From 6392f1f5a89ab4ac94768ce6830ae20f3a6d50f8 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 1 Jul 2013 21:21:41 +0300 Subject: [PATCH 01/61] xbmc-pvr-addons: update iptvsimple --- ...h => xbmc-pvr-addons-frodo-01-PR200.patch} | 0 ...bmc-pvr-addons-frodo-02-PR200-update.patch | 345 ++++++++++++++++++ 2 files changed, 345 insertions(+) rename packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/{xbmc-pvr-addons-frodo-PR200.patch => xbmc-pvr-addons-frodo-01-PR200.patch} (100%) create mode 100644 packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-02-PR200-update.patch diff --git a/packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-PR200.patch b/packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-01-PR200.patch similarity index 100% rename from packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-PR200.patch rename to packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-01-PR200.patch diff --git a/packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-02-PR200-update.patch b/packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-02-PR200-update.patch new file mode 100644 index 0000000000..f74cbb0ebc --- /dev/null +++ b/packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-02-PR200-update.patch @@ -0,0 +1,345 @@ +commit f014d5dcc803d705355148efe2ec720217880d0a +Author: Stefan Saraev +Date: Mon Jul 1 19:57:33 2013 +0300 + + backport latest changes + + added latest changes up to https://github.com/afedchin/xbmc-addon-iptvsimple/commit/a716cdc3cdf44 + + all credit goes to Anton Fedchin + +diff --git a/addons/pvr.iptvsimple/addon/addon.xml.in b/addons/pvr.iptvsimple/addon/addon.xml.in +index 185c3ab..d4692f8 100644 +--- a/addons/pvr.iptvsimple/addon/addon.xml.in ++++ b/addons/pvr.iptvsimple/addon/addon.xml.in +@@ -6,7 +6,7 @@ + provider-name="nightik"> + + +- ++ + + + +- +- +- +- ++ ++ ++ ++ ++ ++ ++ ++ + +- +- +- +- +- +- --> +- ++ ++ ++ ++ ++ ++ ++ ++ --> ++ ++ + +- +- ++ ++ ++ ++ ++ + +diff --git a/addons/pvr.iptvsimple/src/PVRIptvData.cpp b/addons/pvr.iptvsimple/src/PVRIptvData.cpp +index 4ca5265..24e3cee 100644 +--- a/addons/pvr.iptvsimple/src/PVRIptvData.cpp ++++ b/addons/pvr.iptvsimple/src/PVRIptvData.cpp +@@ -155,16 +155,20 @@ bool PVRIptvData::LoadEPG(time_t iStart, time_t iEnd) + if (buffer[0] != '\x3C' || buffer[1] != '\x3F' || buffer[2] != '\x78' || + buffer[3] != '\x6D' || buffer[4] != '\x6C') + { +- // check for tar archive +- if (strcmp(buffer + 0x101, "ustar") || strcmp(buffer + 0x101, "GNUtar")) ++ // check for BOM ++ if (buffer[0] != '\xEF' || buffer[1] != '\xBB' || buffer[2] != '\xBF') + { +- buffer += 0x200; // RECORDSIZE = 512 +- } +- else +- { +- XBMC->Log(LOG_ERROR, "Invalid EPG file '%s': unable to decompress file.", m_strXMLTVUrl.c_str()); +- m_bEGPLoaded = true; +- return false; ++ // check for tar archive ++ if (strcmp(buffer + 0x101, "ustar") || strcmp(buffer + 0x101, "GNUtar")) ++ { ++ buffer += 0x200; // RECORDSIZE = 512 ++ } ++ else ++ { ++ XBMC->Log(LOG_ERROR, "Invalid EPG file '%s': unable to parse file.", m_strXMLTVUrl.c_str()); ++ m_bEGPLoaded = true; ++ return false; ++ } + } + } + +@@ -321,10 +325,10 @@ bool PVRIptvData::LoadPlayList(void) + /* load channels */ + bool bFirst = true; + +- int iUniqueChannelId = 0; ++ int iChannelIndex = 0; + int iUniqueGroupId = 0; + int iCurrentGroupId = 0; +- int iChannelNum = 0; ++ int iChannelNum = g_iStartNumber; + int iEPGTimeShift = 0; + + PVRIptvChannel tmpChannel; +@@ -446,8 +450,8 @@ bool PVRIptvData::LoadPlayList(void) + else if (strLine[0] != '#') + { + PVRIptvChannel channel; +- channel.iUniqueId = ++iUniqueChannelId; +- channel.iChannelNumber = ++iChannelNum; ++ channel.iUniqueId = GetChannelId(tmpChannel.strChannelName.c_str(), strLine); ++ channel.iChannelNumber = iChannelNum++; + channel.strTvgId = tmpChannel.strTvgId; + channel.strChannelName = tmpChannel.strChannelName; + channel.strTvgName = tmpChannel.strTvgName; +@@ -460,10 +464,11 @@ bool PVRIptvData::LoadPlayList(void) + if (iCurrentGroupId > 0) + { + channel.bRadio = m_groups.at(iCurrentGroupId - 1).bRadio; +- m_groups.at(iCurrentGroupId - 1).members.push_back(channel.iChannelNumber); ++ m_groups.at(iCurrentGroupId - 1).members.push_back(iChannelIndex); + } + + m_channels.push_back(channel); ++ iChannelIndex++; + + tmpChannel.strTvgId = ""; + tmpChannel.strChannelName = ""; +@@ -568,26 +573,24 @@ PVR_ERROR PVRIptvData::GetChannelGroups(ADDON_HANDLE handle, bool bRadio) + + PVR_ERROR PVRIptvData::GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) + { +- for (unsigned int iGroupPtr = 0; iGroupPtr < m_groups.size(); iGroupPtr++) ++ PVRIptvChannelGroup *myGroup; ++ if ((myGroup = FindGroup(group.strGroupName)) != NULL) + { +- PVRIptvChannelGroup &myGroup = m_groups.at(iGroupPtr); +- if (!strcmp(myGroup.strGroupName.c_str(),group.strGroupName)) ++ for (unsigned int iPtr = 0; iPtr < myGroup->members.size(); iPtr++) + { +- for (unsigned int iChannelPtr = 0; iChannelPtr < myGroup.members.size(); iChannelPtr++) +- { +- int iId = myGroup.members.at(iChannelPtr) - 1; +- if (iId < 0 || iId > (int)m_channels.size() - 1) +- continue; +- PVRIptvChannel &channel = m_channels.at(iId); +- PVR_CHANNEL_GROUP_MEMBER xbmcGroupMember; +- memset(&xbmcGroupMember, 0, sizeof(PVR_CHANNEL_GROUP_MEMBER)); +- +- strncpy(xbmcGroupMember.strGroupName, group.strGroupName, sizeof(xbmcGroupMember.strGroupName) - 1); +- xbmcGroupMember.iChannelUniqueId = channel.iUniqueId; +- xbmcGroupMember.iChannelNumber = channel.iChannelNumber; +- +- PVR->TransferChannelGroupMember(handle, &xbmcGroupMember); +- } ++ int iIndex = myGroup->members.at(iPtr); ++ if (iIndex < 0 || iIndex >= (int) m_channels.size()) ++ continue; ++ ++ PVRIptvChannel &channel = m_channels.at(iIndex); ++ PVR_CHANNEL_GROUP_MEMBER xbmcGroupMember; ++ memset(&xbmcGroupMember, 0, sizeof(PVR_CHANNEL_GROUP_MEMBER)); ++ ++ strncpy(xbmcGroupMember.strGroupName, group.strGroupName, sizeof(xbmcGroupMember.strGroupName) - 1); ++ xbmcGroupMember.iChannelUniqueId = channel.iUniqueId; ++ xbmcGroupMember.iChannelNumber = channel.iChannelNumber; ++ ++ PVR->TransferChannelGroupMember(handle, &xbmcGroupMember); + } + } + +@@ -891,9 +894,7 @@ int PVRIptvData::GetCachedFileContents(const std::string &strCachedName, const s + void PVRIptvData::ApplyChannelsLogos() + { + if (m_strLogoPath.IsEmpty()) +- { + return; +- } + + vector::iterator channel; + for(channel = m_channels.begin(); channel < m_channels.end(); channel++) +@@ -975,3 +976,17 @@ CStdString PVRIptvData::ReadMarkerValue(std::string &strLine, const char* strMar + + return std::string(""); + } ++ ++int PVRIptvData::GetChannelId(const char * strChannelName, const char * strStreamUrl) ++{ ++ std::string concat(strChannelName); ++ concat.append(strStreamUrl); ++ ++ const char* strString = concat.c_str(); ++ int iId = 0; ++ int c; ++ while (c = *strString++) ++ iId = ((iId << 5) + iId) + c; /* iId * 33 + c */ ++ ++ return abs(iId); ++} +\ No newline at end of file +diff --git a/addons/pvr.iptvsimple/src/PVRIptvData.h b/addons/pvr.iptvsimple/src/PVRIptvData.h +index 944a734..c49b0cc 100644 +--- a/addons/pvr.iptvsimple/src/PVRIptvData.h ++++ b/addons/pvr.iptvsimple/src/PVRIptvData.h +@@ -103,6 +103,7 @@ protected: + virtual int GetCachedFileContents(const std::string &strCachedName, const std::string &strFilePath, std::string &strContent); + virtual void ApplyChannelsLogos(); + virtual CStdString ReadMarkerValue(std::string &strLine, const char * strMarkerName); ++ virtual int GetChannelId(const char * strChannelName, const char * strStreamUrl); + + protected: + virtual void *Process(void); +diff --git a/addons/pvr.iptvsimple/src/client.cpp b/addons/pvr.iptvsimple/src/client.cpp +index b80f483..b8c55b4 100644 +--- a/addons/pvr.iptvsimple/src/client.cpp ++++ b/addons/pvr.iptvsimple/src/client.cpp +@@ -54,6 +54,7 @@ std::string g_strTvgPath = ""; + std::string g_strM3UPath = ""; + std::string g_strLogoPath = ""; + int g_iEPGTimeShift = 0; ++int g_iStartNumber = 1; + bool g_bTSOverride = true; + + extern std::string PathCombine(const std::string &strPath, const std::string &strFileName) +@@ -102,7 +103,10 @@ void ADDON_ReadSettings(void) + { + g_strM3UPath = GetClientFilePath(M3U_FILE_NAME); + } +- ++ if (!XBMC->GetSetting("startNum", &g_iStartNumber)) ++ { ++ g_iStartNumber = 1; ++ } + if (!XBMC->GetSetting("epgPathType", &iPathType)) + { + iPathType = 1; +diff --git a/addons/pvr.iptvsimple/src/client.h b/addons/pvr.iptvsimple/src/client.h +index bc81eeb..89500f1 100644 +--- a/addons/pvr.iptvsimple/src/client.h ++++ b/addons/pvr.iptvsimple/src/client.h +@@ -27,7 +27,7 @@ + #include "libXBMC_pvr.h" + #include "libXBMC_gui.h" + +-#define PVR_CLIENT_VERSION "0.1.3" ++#define PVR_CLIENT_VERSION "1.8.1" + #define M3U_FILE_NAME "iptv.m3u.cache" + #define TVG_FILE_NAME "xmltv.xml.cache" + +@@ -47,6 +47,7 @@ extern std::string g_strM3UPath; + extern std::string g_strTvgPath; + extern std::string g_strLogoPath; + extern int g_iEPGTimeShift; ++extern int g_iStartNumber; + extern bool g_bTSOverride; + + extern std::string PathCombine(const std::string &strPath, const std::string &strFileName); From 22f4612a3822a28a91fc50e49e150740fab05ffa Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 2 Jul 2013 09:15:29 +0200 Subject: [PATCH 02/61] Mesa: update to Mesa-9.1.4 Signed-off-by: Stephan Raue --- packages/graphics/Mesa/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/graphics/Mesa/meta b/packages/graphics/Mesa/meta index a3fdb8b073..3169327517 100644 --- a/packages/graphics/Mesa/meta +++ b/packages/graphics/Mesa/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="Mesa" -PKG_VERSION="9.1.3" +PKG_VERSION="9.1.4" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="OSS" From 6d72b7391109da2f82ccb7a5004778acdb37106e Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 2 Jul 2013 09:15:30 +0200 Subject: [PATCH 03/61] xf86-video-intel: update to xf86-video-intel-2.21.11 Signed-off-by: Stephan Raue --- packages/x11/driver/xf86-video-intel/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x11/driver/xf86-video-intel/meta b/packages/x11/driver/xf86-video-intel/meta index ccb4e8f366..18b0e64ce4 100644 --- a/packages/x11/driver/xf86-video-intel/meta +++ b/packages/x11/driver/xf86-video-intel/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="xf86-video-intel" -PKG_VERSION="2.21.10" +PKG_VERSION="2.21.11" PKG_REV="1" PKG_ARCH="i386 x86_64" PKG_LICENSE="OSS" From 1edf52d75ba22fad136131510e28466916ccf43e Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 2 Jul 2013 09:15:30 +0200 Subject: [PATCH 04/61] libXrender: update to libXrender-0.9.8 Signed-off-by: Stephan Raue --- packages/x11/lib/libXrender/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x11/lib/libXrender/meta b/packages/x11/lib/libXrender/meta index 4c67967dd6..e282cf3a91 100644 --- a/packages/x11/lib/libXrender/meta +++ b/packages/x11/lib/libXrender/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="libXrender" -PKG_VERSION="0.9.7" +PKG_VERSION="0.9.8" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="OSS" From c92d1f9efffb7fd99315f7c3cf548a3092c2cc33 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 1 Jul 2013 23:12:34 +0300 Subject: [PATCH 05/61] linux: update to linux-3.10 TODO: sync configs Signed-off-by: Stephan Raue --- packages/linux/meta | 8 +- .../3.10/linux-003-no_dev_console.patch | 21 + .../3.10/linux-010-perf_crosscompiling.patch | 18 + .../3.10/linux-052-XBOX_remote_support.patch | 1029 ++ .../linux-053-spinelplus-remote-0.2.patch | 161 + ...1056c5564eec8a1b169c6e84ff3.6.114c13.patch | 12 + ...-add_Formosa_eHome_Infrared_Receiver.patch | 11 + ...-add_Adaptec_eHome_Infrared_Receiver.patch | 20 + ...tomer-code-restriction-in-rc6-decode.patch | 22 + ..._Manufacturing_Inc_Infrared_Receiver.patch | 13 + ...nux-058.01-HID-Sony-upstream_patches.patch | 867 + ..._sony-add_autorepeat_for_PS3_remotes.patch | 61 + .../linux-059-remove_some_xpad_pids-0.2.patch | 11 + .../3.10/linux-060-add_AUGUST_DVB-T205.patch | 14 + ...x-203-stb0899_enable_low_symbol_rate.patch | 12 + .../linux/patches/3.10/linux-210-dvbsky.patch | 6161 ++++++++ ...linux-212-mantis_stb0899_faster_lock.patch | 138 + .../3.10/linux-221-ngene-octopus.patch | 12735 +++++++++++++++ .../linux-222-stb0899_signal_quality.patch | 62 + ...-video-artifacts-with-tt-3600-s2-usb.patch | 17 + .../3.10/linux-700-jmicron_1_0_8_5.patch | 1603 ++ .../3.10/linux-900-hide_tsc_error.patch | 12 + ...x-950-saa716x_PCIe_interface_chipset.patch | 13031 ++++++++++++++++ ...utputting-HDMI-audio-before-prepare-.patch | 78 + .../3.10/linux-995-CX24120-13Z_frontend.patch | 1577 ++ .../3.10/linux-996-macmini2012-ethernet.patch | 11 + ...x-997-disable-rc6-on-sandybridge-gt1.patch | 13 + projects/RPi/options | 2 +- 28 files changed, 37717 insertions(+), 3 deletions(-) create mode 100644 packages/linux/patches/3.10/linux-003-no_dev_console.patch create mode 100644 packages/linux/patches/3.10/linux-010-perf_crosscompiling.patch create mode 100644 packages/linux/patches/3.10/linux-052-XBOX_remote_support.patch create mode 100644 packages/linux/patches/3.10/linux-053-spinelplus-remote-0.2.patch create mode 100644 packages/linux/patches/3.10/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch create mode 100644 packages/linux/patches/3.10/linux-055-add_Formosa_eHome_Infrared_Receiver.patch create mode 100644 packages/linux/patches/3.10/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch create mode 100644 packages/linux/patches/3.10/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch create mode 100644 packages/linux/patches/3.10/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch create mode 100644 packages/linux/patches/3.10/linux-058.01-HID-Sony-upstream_patches.patch create mode 100644 packages/linux/patches/3.10/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch create mode 100644 packages/linux/patches/3.10/linux-059-remove_some_xpad_pids-0.2.patch create mode 100644 packages/linux/patches/3.10/linux-060-add_AUGUST_DVB-T205.patch create mode 100644 packages/linux/patches/3.10/linux-203-stb0899_enable_low_symbol_rate.patch create mode 100644 packages/linux/patches/3.10/linux-210-dvbsky.patch create mode 100644 packages/linux/patches/3.10/linux-212-mantis_stb0899_faster_lock.patch create mode 100644 packages/linux/patches/3.10/linux-221-ngene-octopus.patch create mode 100644 packages/linux/patches/3.10/linux-222-stb0899_signal_quality.patch create mode 100644 packages/linux/patches/3.10/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch create mode 100644 packages/linux/patches/3.10/linux-700-jmicron_1_0_8_5.patch create mode 100644 packages/linux/patches/3.10/linux-900-hide_tsc_error.patch create mode 100644 packages/linux/patches/3.10/linux-950-saa716x_PCIe_interface_chipset.patch create mode 100644 packages/linux/patches/3.10/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch create mode 100755 packages/linux/patches/3.10/linux-995-CX24120-13Z_frontend.patch create mode 100644 packages/linux/patches/3.10/linux-996-macmini2012-ethernet.patch create mode 100644 packages/linux/patches/3.10/linux-997-disable-rc6-on-sandybridge-gt1.patch diff --git a/packages/linux/meta b/packages/linux/meta index 8efd30f557..6121a85d53 100644 --- a/packages/linux/meta +++ b/packages/linux/meta @@ -33,10 +33,14 @@ case "$LINUX" in PKG_VERSION="2.6.38-ti-omap4" PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.bz2" ;; - *) + 3.9) PKG_VERSION="3.9.8" PKG_URL="http://www.kernel.org/pub/linux/kernel/v3.x/$PKG_NAME-$PKG_VERSION.tar.xz" ;; + *) + PKG_VERSION="3.10" + PKG_URL="http://www.kernel.org/pub/linux/kernel/v3.x/$PKG_NAME-$PKG_VERSION.tar.xz" + ;; esac PKG_REV="1" @@ -55,5 +59,5 @@ PKG_AUTORECONF="no" if [ "$DEVTOOLS" = "yes" ]; then PKG_DEPENDS="$PKG_DEPENDS Python" - PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS newt slang elfutils Python" + PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS slang elfutils Python" fi diff --git a/packages/linux/patches/3.10/linux-003-no_dev_console.patch b/packages/linux/patches/3.10/linux-003-no_dev_console.patch new file mode 100644 index 0000000000..df35a7ab9a --- /dev/null +++ b/packages/linux/patches/3.10/linux-003-no_dev_console.patch @@ -0,0 +1,21 @@ +diff --git a/init/main.c b/init/main.c +index 9484f4b..db55edd 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -880,8 +880,14 @@ static noinline void __init kernel_init_freeable(void) + do_basic_setup(); + + /* Open the /dev/console on the rootfs, this should never fail */ +- if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) +- pr_err("Warning: unable to open an initial console.\n"); ++ char *console = "/dev_console"; ++ ++ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) { ++ sys_mknod(console, S_IFCHR|0600, (TTYAUX_MAJOR<<8)|1); ++ if (sys_open(console, O_RDWR, 0) < 0) ++ printk(KERN_WARNING "Warning: unable to open an initial console.\n"); ++ sys_unlink(console); ++ } + + (void) sys_dup(0); + (void) sys_dup(0); diff --git a/packages/linux/patches/3.10/linux-010-perf_crosscompiling.patch b/packages/linux/patches/3.10/linux-010-perf_crosscompiling.patch new file mode 100644 index 0000000000..b214488e35 --- /dev/null +++ b/packages/linux/patches/3.10/linux-010-perf_crosscompiling.patch @@ -0,0 +1,18 @@ +diff --git a/tools/perf/Makefile b/tools/perf/Makefile +index b0f164b..ecb1af6 100644 +--- a/tools/perf/Makefile ++++ b/tools/perf/Makefile +@@ -687,12 +687,10 @@ ifndef NO_LIBAUDIT + endif + + ifndef NO_SLANG +- FLAGS_SLANG=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -I/usr/include/slang -lslang ++ FLAGS_SLANG=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lslang + ifneq ($(call try-cc,$(SOURCE_SLANG),$(FLAGS_SLANG),libslang),y) + msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); + else +- # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h +- BASIC_CFLAGS += -I/usr/include/slang + BASIC_CFLAGS += -DSLANG_SUPPORT + EXTLIBS += -lslang + LIB_OBJS += $(OUTPUT)ui/browser.o diff --git a/packages/linux/patches/3.10/linux-052-XBOX_remote_support.patch b/packages/linux/patches/3.10/linux-052-XBOX_remote_support.patch new file mode 100644 index 0000000000..6b43f9b315 --- /dev/null +++ b/packages/linux/patches/3.10/linux-052-XBOX_remote_support.patch @@ -0,0 +1,1029 @@ +diff -Naur linux-3.9.4/drivers/staging/media/lirc/Kconfig linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig +--- linux-3.9.4/drivers/staging/media/lirc/Kconfig 2013-05-24 20:45:59.000000000 +0200 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig 2013-05-30 18:18:57.238957100 +0200 +@@ -63,10 +63,17 @@ + help + Driver for the SIR IrDA port + ++config LIRC_XBOX ++ tristate "XBOX USB IR Remote" ++ depends on LIRC && USB ++ help ++ Driver for the Microsoft XBOX USB IR Remote ++ + config LIRC_ZILOG + tristate "Zilog/Hauppauge IR Transmitter" + depends on LIRC && I2C + help + Driver for the Zilog/Hauppauge IR Transmitter, found on + PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards ++ + endif +diff -Naur linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c +--- linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c 2013-05-30 18:40:22.523775446 +0200 +@@ -0,0 +1,995 @@ ++/* ++ * lirc_xbox - USB remote support for LIRC ++ * (supports Microsoft XBOX DVD Dongle) ++ * ++ * Copyright (C) 2003-2004 Paul Miller ++ * ++ * This driver was derived from: ++ * Vladimir Dergachev 's 2002 ++ * "USB ATI Remote support" (input device) ++ * Adrian Dewhurst 's 2002 ++ * "USB StreamZap remote driver" (LIRC) ++ * Artur Lipowski 's 2002 ++ * "lirc_dev" and "lirc_gpio" LIRC modules ++ * Michael Wojciechowski ++ * initial xbox support ++ * Vassilis Virvilis 2006 ++ * reworked the patch for lirc submission ++ * Paul Miller's 2004 ++ * lirc_atiusb - removed all ati remote support ++ * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $ ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++ ++//#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) ++//#include ++//#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++//#include "drivers/kcompat.h" ++//#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) ++#include ++#include ++//#else ++//#include "drivers/lirc.h" ++//#include "drivers/lirc_dev/lirc_dev.h" ++//#endif ++ ++#define DRIVER_VERSION "$Revision: 0.01 $" ++#define DRIVER_AUTHOR "Jason Martin " ++#define DRIVER_DESC "XBOX DVD Dongle USB remote driver for LIRC" ++#define DRIVER_NAME "lirc_xbox" ++ ++#define CODE_LENGTH 6 ++#define CODE_MIN_LENGTH 6 ++#define DECODE_LENGTH 1 ++ ++#ifndef URB_ASYNC_UNLINK ++#define URB_ASYNC_UNLINK 0 ++#endif ++ ++/* module parameters */ ++#ifdef CONFIG_USB_DEBUG ++static int debug = 1; ++#else ++static int debug; ++#endif ++ ++#define dprintk(fmt, args...) \ ++ do { \ ++ if (debug) \ ++ printk(KERN_DEBUG fmt, ## args); \ ++ } while (0) ++ ++/* ++ * USB_BUFF_LEN must be the maximum value of the code_length array. ++ * It is used for static arrays. ++ */ ++#define USB_BUFF_LEN 6 ++ ++static int mask = 0xFFFF; /* channel acceptance bit mask */ ++static int unique; /* enable channel-specific codes */ ++static int repeat = 10; /* repeat time in 1/100 sec */ ++static unsigned long repeat_jiffies; /* repeat timeout */ ++ ++/* get hi and low bytes of a 16-bits int */ ++#define HI(a) ((unsigned char)((a) >> 8)) ++#define LO(a) ((unsigned char)((a) & 0xff)) ++ ++/* general constants */ ++#define SEND_FLAG_IN_PROGRESS 1 ++#define SEND_FLAG_COMPLETE 2 ++#define FREE_ALL 0xFF ++ ++/* endpoints */ ++#define EP_KEYS 0 ++#define EP_MOUSE 1 ++#define EP_MOUSE_ADDR 0x81 ++#define EP_KEYS_ADDR 0x82 ++ ++/* USB vendor ids for XBOX DVD Dongles */ ++#define VENDOR_MS1 0x040b ++#define VENDOR_MS2 0x045e ++#define VENDOR_MS3 0xFFFF ++ ++static struct usb_device_id usb_remote_table[] = { ++ /* Gamester Xbox DVD Movie Playback Kit IR */ ++ { USB_DEVICE(VENDOR_MS1, 0x6521) }, ++ ++ /* Microsoft Xbox DVD Movie Playback Kit IR */ ++ { USB_DEVICE(VENDOR_MS2, 0x0284) }, ++ ++ /* ++ * Some Chinese manufacturer -- conflicts with the joystick from the ++ * same manufacturer ++ */ ++ { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, ++ ++ /* Terminating entry */ ++ { } ++}; ++ ++/* init strings */ ++#define USB_OUTLEN 7 ++ ++static char init1[] = {0x01, 0x00, 0x20, 0x14}; ++static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; ++ ++struct in_endpt { ++ /* inner link in list of endpoints for the remote specified by ir */ ++ struct list_head iep_list_link; ++ struct xbox_dev *ir; ++ struct urb *urb; ++ struct usb_endpoint_descriptor *ep; ++ ++ /* buffers and dma */ ++ unsigned char *buf; ++ unsigned int len; ++ dma_addr_t dma; ++ ++ /* handle repeats */ ++ unsigned char old[USB_BUFF_LEN]; ++ unsigned long old_jiffies; ++}; ++ ++struct out_endpt { ++ struct xbox_dev *ir; ++ struct urb *urb; ++ struct usb_endpoint_descriptor *ep; ++ ++ /* buffers and dma */ ++ unsigned char *buf; ++ dma_addr_t dma; ++ ++ /* handle sending (init strings) */ ++ int send_flags; ++ wait_queue_head_t wait; ++}; ++ ++ ++/* data structure for each usb remote */ ++struct xbox_dev { ++ /* inner link in list of all remotes managed by this module */ ++ struct list_head remote_list_link; ++ /* Number of usb interfaces associated with this device */ ++ int dev_refcount; ++ ++ /* usb */ ++ struct usb_device *usbdev; ++ /* Head link to list of all inbound endpoints in this remote */ ++ struct list_head iep_listhead; ++ struct out_endpt *out_init; ++ int devnum; ++ ++ /* lirc */ ++ struct lirc_driver *d; ++ int connected; ++ ++ /* locking */ ++ struct mutex lock; ++}; ++ ++/* list of all registered devices via the remote_list_link in xbox_dev */ ++static struct list_head remote_list; ++ ++/* ++ * Convenience macros to retrieve a pointer to the surrounding struct from ++ * the given list_head reference within, pointed at by link. ++ */ ++#define get_iep_from_link(link) \ ++ list_entry((link), struct in_endpt, iep_list_link); ++#define get_irctl_from_link(link) \ ++ list_entry((link), struct xbox_dev, remote_list_link); ++ ++/* send packet - used to initialize remote */ ++static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) ++{ ++ struct xbox_dev *ir = oep->ir; ++ DECLARE_WAITQUEUE(wait, current); ++ int timeout = HZ; /* 1 second */ ++ unsigned char buf[USB_OUTLEN]; ++ ++ dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); ++ ++ mutex_lock(&ir->lock); ++ oep->urb->transfer_buffer_length = LO(cmd) + 1; ++ oep->urb->dev = oep->ir->usbdev; ++ oep->send_flags = SEND_FLAG_IN_PROGRESS; ++ ++ memcpy(buf+1, data, LO(cmd)); ++ buf[0] = HI(cmd); ++ memcpy(oep->buf, buf, LO(cmd)+1); ++ ++ set_current_state(TASK_INTERRUPTIBLE); ++ add_wait_queue(&oep->wait, &wait); ++ ++ if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&oep->wait, &wait); ++ mutex_unlock(&ir->lock); ++ return; ++ } ++ mutex_unlock(&ir->lock); ++ ++ while (timeout && (oep->urb->status == -EINPROGRESS) ++ && !(oep->send_flags & SEND_FLAG_COMPLETE)) { ++ timeout = schedule_timeout(timeout); ++ rmb(); ++ } ++ ++ dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); ++ ++ set_current_state(TASK_RUNNING); ++ remove_wait_queue(&oep->wait, &wait); ++ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(oep->urb); ++} ++ ++static int unregister_from_lirc(struct xbox_dev *ir) ++{ ++ struct lirc_driver *d = ir->d; ++ int devnum; ++ ++ devnum = ir->devnum; ++ dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); ++ ++ lirc_unregister_driver(d->minor); ++ ++ printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); ++ return 0; ++} ++ ++static int set_use_inc(void *data) ++{ ++ struct xbox_dev *ir = data; ++ struct list_head *pos, *n; ++ struct in_endpt *iep; ++ int rtn; ++ ++ if (!ir) { ++ printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); ++ return -EIO; ++ } ++ dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); ++ ++ mutex_lock(&ir->lock); ++ if (!ir->connected) { ++ if (!ir->usbdev) { ++ mutex_unlock(&ir->lock); ++ dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); ++ return -ENOENT; ++ } ++ ++ /* Iterate through the inbound endpoints */ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ /* extract the current in_endpt */ ++ iep = get_iep_from_link(pos); ++ iep->urb->dev = ir->usbdev; ++ dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", ++ ir->devnum, iep->ep->bEndpointAddress, iep); ++ rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); ++ if (rtn) { ++ printk(DRIVER_NAME "[%d]: open result = %d " ++ "error submitting urb\n", ++ ir->devnum, rtn); ++ mutex_unlock(&ir->lock); ++ return -EIO; ++ } ++ } ++ ir->connected = 1; ++ } ++ mutex_unlock(&ir->lock); ++ ++ return 0; ++} ++ ++static void set_use_dec(void *data) ++{ ++ struct xbox_dev *ir = data; ++ struct list_head *pos, *n; ++ struct in_endpt *iep; ++ ++ if (!ir) { ++ printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); ++ return; ++ } ++ dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); ++ ++ mutex_lock(&ir->lock); ++ if (ir->connected) { ++ /* Free inbound usb urbs */ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ iep = get_iep_from_link(pos); ++ dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", ++ ir->devnum, iep->ep->bEndpointAddress, iep); ++ usb_kill_urb(iep->urb); ++ } ++ ir->connected = 0; ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static void print_data(struct in_endpt *iep, char *buf, int len) ++{ ++ const int clen = CODE_LENGTH; ++ char codes[clen * 3 + 1]; ++ int i; ++ ++ if (len <= 0) ++ return; ++ ++ for (i = 0; i < len && i < clen; i++) ++ snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); ++ printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", ++ iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); ++} ++ ++static int code_check_xbox(struct in_endpt *iep, int len) ++{ ++ // struct xbox_dev *ir = iep->ir; ++ const int clen = CODE_LENGTH; ++ ++ if (len != clen) { ++ dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " ++ "ir.. ?\n", len, clen); ++ return -1; ++ } ++ ++ /* check for repeats */ ++ if (memcmp(iep->old, iep->buf, len) == 0) { ++ if (iep->old_jiffies + repeat_jiffies > jiffies) ++ return -1; ++ } else { ++ /* ++ * the third byte of xbox ir packet seems to contain key info ++ * the last two bytes are.. some kind of clock? ++ */ ++ iep->buf[0] = iep->buf[2]; ++ memset(iep->buf + 1, 0, len - 1); ++ memcpy(iep->old, iep->buf, len); ++ } ++ iep->old_jiffies = jiffies; ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) ++#else ++static void usb_remote_recv(struct urb *urb) ++#endif ++{ ++ struct in_endpt *iep; ++ int len, result = -1; ++ ++ if (!urb) ++ return; ++ iep = urb->context; ++ if (!iep) { ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ } ++ if (!iep->ir->usbdev) ++ return; ++ ++ len = urb->actual_length; ++ if (debug) ++ print_data(iep, urb->transfer_buffer, len); ++ ++ switch (urb->status) { ++ ++ case 0: ++ result = code_check_xbox(iep, len); ++ ++ if (result < 0) ++ break; ++ ++ lirc_buffer_write(iep->ir->d->rbuf, iep->buf); ++ wake_up(&iep->ir->d->rbuf->wait_poll); ++ break; ++ ++ case -ECONNRESET: ++ case -ENOENT: ++ case -ESHUTDOWN: ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ ++ case -EPIPE: ++ default: ++ break; ++ } ++ ++ usb_submit_urb(urb, GFP_ATOMIC); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++static void usb_remote_send(struct urb *urb, struct pt_regs *regs) ++#else ++static void usb_remote_send(struct urb *urb) ++#endif ++{ ++ struct out_endpt *oep; ++ ++ if (!urb) ++ return; ++ oep = urb->context; ++ if (!oep) { ++ urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(urb); ++ return; ++ } ++ if (!oep->ir->usbdev) ++ return; ++ ++ dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); ++ ++ if (urb->status) ++ return; ++ ++ oep->send_flags |= SEND_FLAG_COMPLETE; ++ wmb(); ++ if (waitqueue_active(&oep->wait)) ++ wake_up(&oep->wait); ++} ++ ++ ++/* ++ * Initialization and removal ++ */ ++ ++/* ++ * Free iep according to mem_failure which specifies a checkpoint into the ++ * initialization sequence for rollback recovery. ++ */ ++static void free_in_endpt(struct in_endpt *iep, int mem_failure) ++{ ++ struct xbox_dev *ir; ++ dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); ++ if (!iep) ++ return; ++ ++ ir = iep->ir; ++ if (!ir) { ++ dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); ++ return; ++ } ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 5: ++ list_del(&iep->iep_list_link); ++ dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " ++ "from list\n", ir->devnum, iep->ep->bEndpointAddress); ++ case 4: ++ if (iep->urb) { ++ iep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(iep->urb); ++ usb_free_urb(iep->urb); ++ iep->urb = 0; ++ } else ++ dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", ++ ir->devnum); ++ case 3: ++ usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); ++ iep->buf = 0; ++ case 2: ++ kfree(iep); ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++/* ++ * Construct a new inbound endpoint for this remote, and add it to the list of ++ * in_epts in ir. ++ */ ++static struct in_endpt *new_in_endpt(struct xbox_dev *ir, ++ struct usb_endpoint_descriptor *ep) ++{ ++ struct usb_device *dev = ir->usbdev; ++ struct in_endpt *iep; ++ int pipe, maxp, len, addr; ++ int mem_failure; ++ ++ addr = ep->bEndpointAddress; ++ pipe = usb_rcvintpipe(dev, addr); ++ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); ++ ++/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; ++ * len -= (len % CODE_LENGTH); */ ++ len = CODE_LENGTH; ++ ++ dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " ++ "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); ++ ++ mem_failure = 0; ++ iep = kzalloc(sizeof(*iep), GFP_KERNEL); ++ if (!iep) { ++ mem_failure = 1; ++ goto new_in_endpt_failure_check; ++ } ++ iep->ir = ir; ++ iep->ep = ep; ++ iep->len = len; ++ ++ iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); ++ if (!iep->buf) { ++ mem_failure = 2; ++ goto new_in_endpt_failure_check; ++ } ++ ++ iep->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!iep->urb) ++ mem_failure = 3; ++ ++new_in_endpt_failure_check: ++ ++ if (mem_failure) { ++ free_in_endpt(iep, mem_failure); ++ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", ++ ir->devnum, addr, mem_failure); ++ return NULL; ++ } ++ list_add_tail(&iep->iep_list_link, &ir->iep_listhead); ++ dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", ++ ir->devnum, iep->ep->bEndpointAddress); ++ return iep; ++} ++ ++static void free_out_endpt(struct out_endpt *oep, int mem_failure) ++{ ++ struct xbox_dev *ir; ++ dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); ++ if (!oep) ++ return; ++ ++ wake_up_all(&oep->wait); ++ ++ ir = oep->ir; ++ if (!ir) { ++ dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); ++ return; ++ } ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 4: ++ if (oep->urb) { ++ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; ++ usb_unlink_urb(oep->urb); ++ usb_free_urb(oep->urb); ++ oep->urb = 0; ++ } else { ++ dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", ++ ir->devnum); ++ } ++ case 3: ++ usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, ++ oep->buf, oep->dma); ++ oep->buf = 0; ++ case 2: ++ kfree(oep); ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static struct out_endpt *new_out_endpt(struct xbox_dev *ir, ++ struct usb_endpoint_descriptor *ep) ++{ ++ struct usb_device *dev = ir->usbdev; ++ struct out_endpt *oep; ++ int mem_failure; ++ ++ dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", ++ ir->devnum, ep->bEndpointAddress); ++ ++ mem_failure = 0; ++ oep = kzalloc(sizeof(*oep), GFP_KERNEL); ++ if (!oep) ++ mem_failure = 1; ++ else { ++ oep->ir = ir; ++ oep->ep = ep; ++ init_waitqueue_head(&oep->wait); ++ ++ oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, ++ GFP_ATOMIC, &oep->dma); ++ if (!oep->buf) ++ mem_failure = 2; ++ else { ++ oep->urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!oep->urb) ++ mem_failure = 3; ++ } ++ } ++ if (mem_failure) { ++ free_out_endpt(oep, mem_failure); ++ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", ++ ir->devnum, ep->bEndpointAddress, mem_failure); ++ return NULL; ++ } ++ return oep; ++} ++ ++static void free_irctl(struct xbox_dev *ir, int mem_failure) ++{ ++ struct list_head *pos, *n; ++ struct in_endpt *in; ++ dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); ++ ++ if (!ir) ++ return; ++ ++ list_for_each_safe(pos, n, &ir->iep_listhead) { ++ in = get_iep_from_link(pos); ++ free_in_endpt(in, FREE_ALL); ++ } ++ if (ir->out_init) { ++ free_out_endpt(ir->out_init, FREE_ALL); ++ ir->out_init = NULL; ++ } ++ ++ mutex_lock(&ir->lock); ++ switch (mem_failure) { ++ case FREE_ALL: ++ case 6: ++ if (!--ir->dev_refcount) { ++ list_del(&ir->remote_list_link); ++ dprintk(DRIVER_NAME "[%d]: free_irctl: removing " ++ "remote from list\n", ir->devnum); ++ } else { ++ dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," ++ "aborting free_irctl\n", ++ ir->devnum, ir->dev_refcount); ++ mutex_unlock(&ir->lock); ++ return; ++ } ++ case 5: ++ case 4: ++ case 3: ++ if (ir->d) { ++ switch (mem_failure) { ++ case 5: ++ lirc_buffer_free(ir->d->rbuf); ++ case 4: ++ kfree(ir->d->rbuf); ++ case 3: ++ kfree(ir->d); ++ } ++ } else ++ printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n", ++ ir->devnum); ++ case 2: ++ mutex_unlock(&ir->lock); ++ kfree(ir); ++ return; ++ } ++ mutex_unlock(&ir->lock); ++} ++ ++static struct xbox_dev *new_irctl(struct usb_interface *intf) ++{ ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct xbox_dev *ir; ++ struct lirc_driver *driver; ++ int devnum, dclen; ++ int mem_failure; ++ ++ devnum = dev->devnum; ++ ++ dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum); ++ ++ mem_failure = 0; ++ ir = kzalloc(sizeof(*ir), GFP_KERNEL); ++ if (!ir) { ++ mem_failure = 1; ++ goto new_irctl_failure_check; ++ } ++ ++ dclen = DECODE_LENGTH; ++ ++ /* ++ * add this infrared remote struct to remote_list, keeping track ++ * of the number of drivers registered. ++ */ ++ dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); ++ list_add_tail(&ir->remote_list_link, &remote_list); ++ ir->dev_refcount = 1; ++ ++ driver = kzalloc(sizeof(*driver), GFP_KERNEL); ++ if (!driver) { ++ mem_failure = 2; ++ goto new_irctl_failure_check; ++ } ++ ++ ir->d = driver; ++ driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL); ++ if (!driver->rbuf) { ++ mem_failure = 3; ++ goto new_irctl_failure_check; ++ } ++ ++ if (lirc_buffer_init(driver->rbuf, dclen, 2)) { ++ mem_failure = 4; ++ goto new_irctl_failure_check; ++ } ++ ++ strcpy(driver->name, DRIVER_NAME " "); ++ driver->minor = -1; ++ driver->code_length = dclen * 8; ++ driver->features = LIRC_CAN_REC_LIRCCODE; ++ driver->data = ir; ++ driver->set_use_inc = &set_use_inc; ++ driver->set_use_dec = &set_use_dec; ++ driver->dev = &intf->dev; ++ driver->owner = THIS_MODULE; ++ ir->usbdev = dev; ++ ir->devnum = devnum; ++ ++ mutex_init(&ir->lock); ++ INIT_LIST_HEAD(&ir->iep_listhead); ++ ++new_irctl_failure_check: ++ ++ if (mem_failure) { ++ free_irctl(ir, mem_failure); ++ printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", ++ devnum, mem_failure); ++ return NULL; ++ } ++ return ir; ++} ++ ++/* ++ * Scan the global list of remotes to see if the device listed is one of them. ++ * If it is, the corresponding xbox_dev is returned, with its dev_refcount ++ * incremented. Otherwise, returns null. ++ */ ++static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev) ++{ ++ struct list_head *pos; ++ struct xbox_dev *ir = NULL; ++ ++ dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); ++ list_for_each(pos, &remote_list) { ++ ir = get_irctl_from_link(pos); ++ if (ir->usbdev != dev) { ++ dprintk(DRIVER_NAME "[%d]: device %d isn't it...", ++ dev->devnum, ir->devnum); ++ ir = NULL; ++ } else { ++ dprintk(DRIVER_NAME "[%d]: prior instance found.\n", ++ dev->devnum); ++ ir->dev_refcount++; ++ break; ++ } ++ } ++ return ir; ++} ++ ++/* ++ * If the USB interface has an out endpoint for control. ++ */ ++static void send_outbound_init(struct xbox_dev *ir) ++{ ++ if (ir->out_init) { ++ struct out_endpt *oep = ir->out_init; ++ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " ++ "outbound ep\n", ir->devnum); ++ usb_fill_int_urb(oep->urb, ir->usbdev, ++ usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), ++ oep->buf, USB_OUTLEN, usb_remote_send, ++ oep, oep->ep->bInterval); ++ oep->urb->transfer_dma = oep->dma; ++ oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ ++ send_packet(oep, 0x8004, init1); ++ send_packet(oep, 0x8007, init2); ++ } ++} ++ ++/* Log driver and usb info */ ++static void log_usb_dev_info(struct usb_device *dev) ++{ ++ char buf[63], name[128] = ""; ++ ++ if (dev->descriptor.iManufacturer ++ && usb_string(dev, dev->descriptor.iManufacturer, ++ buf, sizeof(buf)) > 0) ++ strlcpy(name, buf, sizeof(name)); ++ if (dev->descriptor.iProduct ++ && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) ++ snprintf(name + strlen(name), sizeof(name) - strlen(name), ++ " %s", buf); ++ printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, ++ dev->bus->busnum, dev->devnum); ++} ++ ++ ++static int usb_remote_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ struct usb_device *dev = interface_to_usbdev(intf); ++ struct usb_host_interface *idesc; ++ struct usb_endpoint_descriptor *ep; ++ struct in_endpt *iep; ++ struct xbox_dev *ir; ++ int i; ++ ++ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", ++ dev->devnum, dev, intf, id); ++ ++ idesc = intf->cur_altsetting; ++ ++ /* Check if a usb remote has already been registered for this device */ ++ ir = get_prior_reg_ir(dev); ++ ++ if (!ir) { ++ ir = new_irctl(intf); ++ if (!ir) ++ return -ENOMEM; ++ } ++ ++ /* ++ * step through the endpoints to find first in and first out endpoint ++ * of type interrupt transfer ++ */ ++ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { ++ ep = &idesc->endpoint[i].desc; ++ dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", ++ dev->devnum, i); ++ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == ++ USB_DIR_IN) && ++ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == ++ USB_ENDPOINT_XFER_INT)) { ++ ++ iep = new_in_endpt(ir, ep); ++ if (iep) ++ { ++ usb_fill_int_urb(iep->urb, dev, ++ usb_rcvintpipe(dev, ++ iep->ep->bEndpointAddress), ++ iep->buf, iep->len, usb_remote_recv, ++ iep, iep->ep->bInterval); ++ iep->urb->transfer_dma = iep->dma; ++ iep->urb->transfer_flags |= ++ URB_NO_TRANSFER_DMA_MAP; ++ } ++ } ++ ++ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == ++ USB_DIR_OUT) && ++ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == ++ USB_ENDPOINT_XFER_INT) && ++ (ir->out_init == NULL)) ++ ir->out_init = new_out_endpt(ir, ep); ++ } ++ if (list_empty(&ir->iep_listhead)) { ++ printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", ++ ir->devnum); ++ free_irctl(ir, FREE_ALL); ++ return -ENODEV; ++ } ++ if (ir->dev_refcount == 1) { ++ ir->d->minor = lirc_register_driver(ir->d); ++ if (ir->d->minor < 0) { ++ free_irctl(ir, FREE_ALL); ++ return -ENODEV; ++ } ++ ++ /* Note new driver registration in kernel logs */ ++ log_usb_dev_info(dev); ++ ++ /* outbound data (initialization) */ ++ send_outbound_init(ir); ++ } ++ ++ usb_set_intfdata(intf, ir); ++ return 0; ++} ++ ++static void usb_remote_disconnect(struct usb_interface *intf) ++{ ++ /* struct usb_device *dev = interface_to_usbdev(intf); */ ++ struct xbox_dev *ir = usb_get_intfdata(intf); ++ usb_set_intfdata(intf, NULL); ++ ++ dprintk(DRIVER_NAME ": disconnecting remote %d:\n", ++ (ir ? ir->devnum : -1)); ++ if (!ir || !ir->d) ++ return; ++ ++ if (ir->usbdev) { ++ /* Only unregister once */ ++ ir->usbdev = NULL; ++ unregister_from_lirc(ir); ++ } ++ ++ /* This also removes the current remote from remote_list */ ++ free_irctl(ir, FREE_ALL); ++} ++ ++static struct usb_driver usb_remote_driver = { ++ .name = DRIVER_NAME, ++ .probe = usb_remote_probe, ++ .disconnect = usb_remote_disconnect, ++ .id_table = usb_remote_table ++}; ++ ++static int __init usb_remote_init(void) ++{ ++ int i; ++ ++ INIT_LIST_HEAD(&remote_list); ++ ++ printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " ++ DRIVER_VERSION "\n"); ++ printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); ++ dprintk(DRIVER_NAME ": debug mode enabled: " ++ "$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n"); ++ ++ repeat_jiffies = repeat*HZ/100; ++ ++ i = usb_register(&usb_remote_driver); ++ if (i) { ++ printk(DRIVER_NAME ": usb register failed, result = %d\n", i); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void __exit usb_remote_exit(void) ++{ ++ usb_deregister(&usb_remote_driver); ++} ++ ++module_init(usb_remote_init); ++module_exit(usb_remote_exit); ++ ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_AUTHOR(DRIVER_AUTHOR); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(usb, usb_remote_table); ++ ++module_param(debug, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); ++ ++module_param(mask, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); ++ ++module_param(unique, bool, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); ++ ++module_param(repeat, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); +diff -Naur linux-3.9.4/drivers/staging/media/lirc/Makefile linux-3.9.4.patch/drivers/staging/media/lirc/Makefile +--- linux-3.9.4/drivers/staging/media/lirc/Makefile 2013-05-24 20:45:59.000000000 +0200 ++++ linux-3.9.4.patch/drivers/staging/media/lirc/Makefile 2013-05-30 18:17:39.163634834 +0200 +@@ -10,4 +10,5 @@ + obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o + obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o + obj-$(CONFIG_LIRC_SIR) += lirc_sir.o ++obj-$(CONFIG_LIRC_XBOX) += lirc_xbox.o + obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o diff --git a/packages/linux/patches/3.10/linux-053-spinelplus-remote-0.2.patch b/packages/linux/patches/3.10/linux-053-spinelplus-remote-0.2.patch new file mode 100644 index 0000000000..f110183d85 --- /dev/null +++ b/packages/linux/patches/3.10/linux-053-spinelplus-remote-0.2.patch @@ -0,0 +1,161 @@ +diff -Naur linux-3.9/drivers/hid/hid-core.c linux-3.9.patch/drivers/hid/hid-core.c +--- linux-3.9/drivers/hid/hid-core.c 2013-04-29 02:36:01.000000000 +0200 ++++ linux-3.9.patch/drivers/hid/hid-core.c 2013-04-29 17:08:40.528324010 +0200 +@@ -1681,6 +1681,9 @@ + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, + #if IS_ENABLED(CONFIG_HID_ROCCAT) + { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, +diff -Naur linux-3.9/drivers/hid/hid-ids.h linux-3.9.patch/drivers/hid/hid-ids.h +--- linux-3.9/drivers/hid/hid-ids.h 2013-04-29 02:36:01.000000000 +0200 ++++ linux-3.9.patch/drivers/hid/hid-ids.h 2013-04-29 17:08:40.537323981 +0200 +@@ -663,6 +663,9 @@ + + #define USB_VENDOR_ID_PHILIPS 0x0471 + #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 ++#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1 0x206c ++#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2 0x20cc ++#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3 0x0613 + + #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 + #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff +diff -Naur linux-3.9/drivers/hid/hid-spinelplus.c linux-3.9.patch/drivers/hid/hid-spinelplus.c +--- linux-3.9/drivers/hid/hid-spinelplus.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.9.patch/drivers/hid/hid-spinelplus.c 2013-04-29 17:08:40.537323981 +0200 +@@ -0,0 +1,104 @@ ++/* ++ * HID driver for "PHILIPS MCE USB IR Receiver- Spinel plus" remotes ++ * ++ * Copyright (c) 2010 Panagiotis Skintzos ++ * ++ * Renamed to Spinel, cleanup and modified to also support ++ * Spinel Plus 0471:20CC by Stephan Raue 2012. ++ */ ++ ++/* ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the Free ++ * Software Foundation; either version 2 of the License, or (at your option) ++ * any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "hid-ids.h" ++ ++#define spinelplus_map_key(c) set_bit(EV_REP, hi->input->evbit); \ ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) ++ ++static int spinelplus_input_mapping(struct hid_device *hdev, ++ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ switch (usage->hid) { ++ case 0xffbc000d: spinelplus_map_key(KEY_MEDIA); break; ++ case 0xffbc0024: spinelplus_map_key(KEY_MEDIA); break; ++ case 0xffbc0027: spinelplus_map_key(KEY_ZOOM); break; ++ case 0xffbc0033: spinelplus_map_key(KEY_HOME); break; ++ case 0xffbc0035: spinelplus_map_key(KEY_CAMERA); break; ++ case 0xffbc0036: spinelplus_map_key(KEY_EPG); break; ++ case 0xffbc0037: spinelplus_map_key(KEY_DVD); break; ++ case 0xffbc0038: spinelplus_map_key(KEY_HOME); break; ++ case 0xffbc0039: spinelplus_map_key(KEY_MP3); break; ++ case 0xffbc003a: spinelplus_map_key(KEY_VIDEO); break; ++ case 0xffbc005a: spinelplus_map_key(KEY_TEXT); break; ++ case 0xffbc005b: spinelplus_map_key(KEY_RED); break; ++ case 0xffbc005c: spinelplus_map_key(KEY_GREEN); break; ++ case 0xffbc005d: spinelplus_map_key(KEY_YELLOW); break; ++ case 0xffbc005e: spinelplus_map_key(KEY_BLUE); break; ++ default: ++ return 0; ++ } ++ return 1; ++} ++ ++static int spinelplus_probe(struct hid_device *hdev, ++ const struct hid_device_id *id) ++{ ++ int ret; ++ /* Connect only to hid input (not hiddev & hidraw)*/ ++ unsigned int cmask = HID_CONNECT_HIDINPUT; ++ ++ ret = hid_parse(hdev); ++ if (ret) { ++ dev_err(&hdev->dev, "parse failed\n"); ++ goto err_free; ++ } ++ ++ ret = hid_hw_start(hdev, cmask); ++ if (ret) { ++ dev_err(&hdev->dev, "hw start failed\n"); ++ goto err_free; ++ } ++ ++ return 0; ++err_free: ++ return ret; ++} ++ ++static const struct hid_device_id spinelplus_devices[] = { ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(hid, spinelplus_devices); ++ ++static struct hid_driver spinelplus_driver = { ++ .name = "SpinelPlus", ++ .id_table = spinelplus_devices, ++ .input_mapping = spinelplus_input_mapping, ++ .probe = spinelplus_probe, ++}; ++ ++static int __init spinelplus_init(void) ++{ ++ return hid_register_driver(&spinelplus_driver); ++} ++ ++static void __exit spinelplus_exit(void) ++{ ++ hid_unregister_driver(&spinelplus_driver); ++} ++ ++module_init(spinelplus_init); ++module_exit(spinelplus_exit); ++MODULE_LICENSE("GPL"); +diff -Naur linux-3.9/drivers/hid/Kconfig linux-3.9.patch/drivers/hid/Kconfig +--- linux-3.9/drivers/hid/Kconfig 2013-04-29 02:36:01.000000000 +0200 ++++ linux-3.9.patch/drivers/hid/Kconfig 2013-04-29 17:08:40.538323977 +0200 +@@ -602,6 +602,12 @@ + ---help--- + Support for Steelseries SRW-S1 steering wheel + ++config HID_SPINELPLUS ++ tristate "Spinel Plus remote control" ++ depends on USB_HID ++ ---help--- ++ Say Y here if you have a Spinel Plus (0471:206c/20cc/0613) remote ++ + config HID_SUNPLUS + tristate "Sunplus wireless desktop" + depends on USB_HID +diff -Naur linux-3.9/drivers/hid/Makefile linux-3.9.patch/drivers/hid/Makefile +--- linux-3.9/drivers/hid/Makefile 2013-04-29 02:36:01.000000000 +0200 ++++ linux-3.9.patch/drivers/hid/Makefile 2013-04-29 17:09:26.744173841 +0200 +@@ -101,6 +101,7 @@ + obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o + obj-$(CONFIG_HID_SONY) += hid-sony.o + obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o ++obj-$(CONFIG_HID_SPINELPLUS) += hid-spinelplus.o + obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o + obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o + obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o diff --git a/packages/linux/patches/3.10/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch b/packages/linux/patches/3.10/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch new file mode 100644 index 0000000000..08566d1f13 --- /dev/null +++ b/packages/linux/patches/3.10/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch @@ -0,0 +1,12 @@ +diff -Naur linux-3.0/drivers/media/rc/nuvoton-cir.c linux-3.0.patch/drivers/media/rc/nuvoton-cir.c +--- linux-3.0/drivers/media/rc/nuvoton-cir.c 2011-07-22 04:17:23.000000000 +0200 ++++ linux-3.0.patch/drivers/media/rc/nuvoton-cir.c 2011-07-22 21:30:48.374591146 +0200 +@@ -1110,7 +1110,7 @@ + rdev->dev.parent = &pdev->dev; + rdev->driver_name = NVT_DRIVER_NAME; + rdev->map_name = RC_MAP_RC6_MCE; +- rdev->timeout = MS_TO_NS(100); ++ rdev->timeout = US_TO_NS(1000); + /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ + rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); + #if 0 diff --git a/packages/linux/patches/3.10/linux-055-add_Formosa_eHome_Infrared_Receiver.patch b/packages/linux/patches/3.10/linux-055-add_Formosa_eHome_Infrared_Receiver.patch new file mode 100644 index 0000000000..e2afb63e3d --- /dev/null +++ b/packages/linux/patches/3.10/linux-055-add_Formosa_eHome_Infrared_Receiver.patch @@ -0,0 +1,11 @@ +--- linux-3.2.2.orig/drivers/media/rc/mceusb.c 2012-01-30 23:37:12.374473509 +0100 ++++ linux-3.2.2/drivers/media/rc/mceusb.c 2012-01-30 23:40:57.989652931 +0100 +@@ -350,6 +350,8 @@ + { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, + /* Formosa21 / eHome Infrared Receiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, ++ /* Formosa21 / eHome Infrared Receiver */ ++ { USB_DEVICE(VENDOR_FORMOSA, 0xe042) }, + /* Formosa aim / Trust MCE Infrared Receiver */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe017), + .driver_info = MCE_GEN2_NO_TX }, diff --git a/packages/linux/patches/3.10/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch b/packages/linux/patches/3.10/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch new file mode 100644 index 0000000000..461a82e4d5 --- /dev/null +++ b/packages/linux/patches/3.10/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch @@ -0,0 +1,20 @@ +diff -Naur linux-3.6.7/drivers/media/rc/mceusb.c linux-3.6.7.patch/drivers/media/rc/mceusb.c +--- linux-3.6.7/drivers/media/rc/mceusb.c 2012-11-29 04:45:51.142129739 +0100 ++++ linux-3.6.7.patch/drivers/media/rc/mceusb.c 2012-11-29 04:51:30.982828558 +0100 +@@ -200,6 +200,7 @@ + #define VENDOR_TIVO 0x105a + #define VENDOR_CONEXANT 0x0572 + #define VENDOR_TWISTEDMELON 0x2596 ++#define VENDOR_ADAPTEC 0x03f3 + + enum mceusb_model_type { + MCE_GEN2 = 0, /* Most boards */ +@@ -400,6 +401,8 @@ + { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8016) }, + /* Twisted Melon Inc. - Manta Transceiver */ + { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8042) }, ++ /* Adaptec / HP eHome Receiver */ ++ { USB_DEVICE(VENDOR_ADAPTEC, 0x0094) }, + /* Terminating entry */ + { } + }; diff --git a/packages/linux/patches/3.10/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch b/packages/linux/patches/3.10/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch new file mode 100644 index 0000000000..9f84e6659f --- /dev/null +++ b/packages/linux/patches/3.10/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch @@ -0,0 +1,22 @@ +--- linux/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:08:13.148418669 -0800 ++++ linux.patch/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:07:48.864417975 -0800 +@@ -39,7 +39,6 @@ + #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ + #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ + #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ +-#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ + #ifndef CHAR_BIT + #define CHAR_BIT 8 /* Normally in */ + #endif +@@ -242,9 +241,8 @@ again: + } + + scancode = data->body; +- if (data->count == RC6_6A_32_NBITS && +- (scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { +- /* MCE RC */ ++ if (data->count == RC6_6A_32_NBITS) { ++ /* MCE compatible RC */ + toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0; + scancode &= ~RC6_6A_MCE_TOGGLE_MASK; + } else { diff --git a/packages/linux/patches/3.10/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch b/packages/linux/patches/3.10/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch new file mode 100644 index 0000000000..67fc7a0de8 --- /dev/null +++ b/packages/linux/patches/3.10/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch @@ -0,0 +1,13 @@ +diff -Naur linux-3.9.4/drivers/media/rc/mceusb.c linux-3.9.4.patch/drivers/media/rc/mceusb.c +--- linux-3.9.4/drivers/media/rc/mceusb.c 2013-05-24 20:45:59.000000000 +0200 ++++ linux-3.9.4.patch/drivers/media/rc/mceusb.c 2013-05-27 12:28:12.811230633 +0200 +@@ -309,6 +309,9 @@ + /* SMK/I-O Data GV-MC7/RCKIT Receiver */ + { USB_DEVICE(VENDOR_SMK, 0x0353), + .driver_info = MCE_GEN2_NO_TX }, ++ /* SMK Manufacturing, Inc. Receiver */ ++ { USB_DEVICE(VENDOR_SMK, 0x0357), ++ .driver_info = MCE_GEN2_NO_TX }, + /* Tatung eHome Infrared Transceiver */ + { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, + /* Shuttle eHome Infrared Transceiver */ diff --git a/packages/linux/patches/3.10/linux-058.01-HID-Sony-upstream_patches.patch b/packages/linux/patches/3.10/linux-058.01-HID-Sony-upstream_patches.patch new file mode 100644 index 0000000000..2995d9d8bb --- /dev/null +++ b/packages/linux/patches/3.10/linux-058.01-HID-Sony-upstream_patches.patch @@ -0,0 +1,867 @@ +diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig +index 427b759..22d320e 100644 +--- a/drivers/hid/Kconfig ++++ b/drivers/hid/Kconfig +@@ -561,15 +561,6 @@ config HID_PRIMAX + Support for Primax devices that are not fully compliant with the + HID standard. + +-config HID_PS3REMOTE +- tristate "Sony PS3 BD Remote Control" +- depends on HID +- ---help--- +- Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech +- Harmony Adapter for PS3, which connect over Bluetooth. +- +- Support for the 6-axis controllers is provided by HID_SONY. +- + config HID_ROCCAT + tristate "Roccat device support" + depends on USB_HID +@@ -594,12 +585,17 @@ config HID_SAMSUNG + Support for Samsung InfraRed remote control or keyboards. + + config HID_SONY +- tristate "Sony PS3 controller" ++ tristate "Sony PS2/3 accessories" + depends on USB_HID ++ depends on NEW_LEDS ++ depends on LEDS_CLASS + ---help--- +- Support for Sony PS3 6-axis controllers. +- +- Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE. ++ Support for ++ ++ * Sony PS3 6-axis controllers ++ * Buzz controllers ++ * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) ++ * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) + + config HID_SPEEDLINK + tristate "Speedlink VAD Cezanne mouse support" +diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile +index b545124..419b7ca 100644 +--- a/drivers/hid/Makefile ++++ b/drivers/hid/Makefile +@@ -92,7 +92,6 @@ hid-picolcd-y += hid-picolcd_debugfs.o + endif + + obj-$(CONFIG_HID_PRIMAX) += hid-primax.o +-obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o + obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ + hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ + hid-roccat-koneplus.o hid-roccat-konepure.o hid-roccat-kovaplus.o \ +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index b885a28..37e35c0 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1683,6 +1683,8 @@ static const struct hid_device_id hid_have_special_driver[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, +diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h +index 56b224e..c11cca1 100644 +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -737,6 +737,8 @@ + #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 + #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 + #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f ++#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 ++#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 + + #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 + #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 +diff --git a/drivers/hid/hid-ps3remote.c b/drivers/hid/hid-ps3remote.c +deleted file mode 100644 +index f1239d3..0000000 +--- a/drivers/hid/hid-ps3remote.c ++++ /dev/null +@@ -1,204 +0,0 @@ +-/* +- * HID driver for Sony PS3 BD Remote Control +- * +- * Copyright (c) 2012 David Dillow +- * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann +- * and other kernel HID drivers. +- */ +- +-/* +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the Free +- * Software Foundation; either version 2 of the License, or (at your option) +- * any later version. +- */ +- +-/* NOTE: in order for the Sony PS3 BD Remote Control to be found by +- * a Bluetooth host, the key combination Start+Enter has to be kept pressed +- * for about 7 seconds with the Bluetooth Host Controller in discovering mode. +- * +- * There will be no PIN request from the device. +- */ +- +-#include +-#include +-#include +- +-#include "hid-ids.h" +- +-static __u8 ps3remote_rdesc[] = { +- 0x05, 0x01, /* GUsagePage Generic Desktop */ +- 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ +- 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ +- +- /* Use collection 1 for joypad buttons */ +- 0xA1, 0x02, /* MCollection Logical (interrelated data) */ +- +- /* Ignore the 1st byte, maybe it is used for a controller +- * number but it's not needed for correct operation */ +- 0x75, 0x08, /* GReportSize 0x08 [8] */ +- 0x95, 0x01, /* GReportCount 0x01 [1] */ +- 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ +- +- /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these +- * buttons multiple keypresses are allowed */ +- 0x05, 0x09, /* GUsagePage Button */ +- 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ +- 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ +- 0x14, /* GLogicalMinimum [0] */ +- 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ +- 0x75, 0x01, /* GReportSize 0x01 [1] */ +- 0x95, 0x18, /* GReportCount 0x18 [24] */ +- 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ +- +- 0xC0, /* MEndCollection */ +- +- /* Use collection 2 for remote control buttons */ +- 0xA1, 0x02, /* MCollection Logical (interrelated data) */ +- +- /* 5th byte is used for remote control buttons */ +- 0x05, 0x09, /* GUsagePage Button */ +- 0x18, /* LUsageMinimum [No button pressed] */ +- 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ +- 0x14, /* GLogicalMinimum [0] */ +- 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ +- 0x75, 0x08, /* GReportSize 0x08 [8] */ +- 0x95, 0x01, /* GReportCount 0x01 [1] */ +- 0x80, /* MInput */ +- +- /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at +- * 0xff and 11th is for press indication */ +- 0x75, 0x08, /* GReportSize 0x08 [8] */ +- 0x95, 0x06, /* GReportCount 0x06 [6] */ +- 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ +- +- /* 12th byte is for battery strength */ +- 0x05, 0x06, /* GUsagePage Generic Device Controls */ +- 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ +- 0x14, /* GLogicalMinimum [0] */ +- 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ +- 0x75, 0x08, /* GReportSize 0x08 [8] */ +- 0x95, 0x01, /* GReportCount 0x01 [1] */ +- 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ +- +- 0xC0, /* MEndCollection */ +- +- 0xC0 /* MEndCollection [Game Pad] */ +-}; +- +-static const unsigned int ps3remote_keymap_joypad_buttons[] = { +- [0x01] = KEY_SELECT, +- [0x02] = BTN_THUMBL, /* L3 */ +- [0x03] = BTN_THUMBR, /* R3 */ +- [0x04] = BTN_START, +- [0x05] = KEY_UP, +- [0x06] = KEY_RIGHT, +- [0x07] = KEY_DOWN, +- [0x08] = KEY_LEFT, +- [0x09] = BTN_TL2, /* L2 */ +- [0x0a] = BTN_TR2, /* R2 */ +- [0x0b] = BTN_TL, /* L1 */ +- [0x0c] = BTN_TR, /* R1 */ +- [0x0d] = KEY_OPTION, /* options/triangle */ +- [0x0e] = KEY_BACK, /* back/circle */ +- [0x0f] = BTN_0, /* cross */ +- [0x10] = KEY_SCREEN, /* view/square */ +- [0x11] = KEY_HOMEPAGE, /* PS button */ +- [0x14] = KEY_ENTER, +-}; +-static const unsigned int ps3remote_keymap_remote_buttons[] = { +- [0x00] = KEY_1, +- [0x01] = KEY_2, +- [0x02] = KEY_3, +- [0x03] = KEY_4, +- [0x04] = KEY_5, +- [0x05] = KEY_6, +- [0x06] = KEY_7, +- [0x07] = KEY_8, +- [0x08] = KEY_9, +- [0x09] = KEY_0, +- [0x0e] = KEY_ESC, /* return */ +- [0x0f] = KEY_CLEAR, +- [0x16] = KEY_EJECTCD, +- [0x1a] = KEY_MENU, /* top menu */ +- [0x28] = KEY_TIME, +- [0x30] = KEY_PREVIOUS, +- [0x31] = KEY_NEXT, +- [0x32] = KEY_PLAY, +- [0x33] = KEY_REWIND, /* scan back */ +- [0x34] = KEY_FORWARD, /* scan forward */ +- [0x38] = KEY_STOP, +- [0x39] = KEY_PAUSE, +- [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ +- [0x60] = KEY_FRAMEBACK, /* slow/step back */ +- [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ +- [0x63] = KEY_SUBTITLE, +- [0x64] = KEY_AUDIO, +- [0x65] = KEY_ANGLE, +- [0x70] = KEY_INFO, /* display */ +- [0x80] = KEY_BLUE, +- [0x81] = KEY_RED, +- [0x82] = KEY_GREEN, +- [0x83] = KEY_YELLOW, +-}; +- +-static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, +- unsigned int *rsize) +-{ +- *rsize = sizeof(ps3remote_rdesc); +- return ps3remote_rdesc; +-} +- +-static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, +- struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- unsigned int key = usage->hid & HID_USAGE; +- +- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) +- return -1; +- +- switch (usage->collection_index) { +- case 1: +- if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) +- return -1; +- +- key = ps3remote_keymap_joypad_buttons[key]; +- if (!key) +- return -1; +- break; +- case 2: +- if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) +- return -1; +- +- key = ps3remote_keymap_remote_buttons[key]; +- if (!key) +- return -1; +- break; +- default: +- return -1; +- } +- +- hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); +- return 1; +-} +- +-static const struct hid_device_id ps3remote_devices[] = { +- /* PS3 BD Remote Control */ +- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, +- /* Logitech Harmony Adapter for PS3 */ +- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, +- { } +-}; +-MODULE_DEVICE_TABLE(hid, ps3remote_devices); +- +-static struct hid_driver ps3remote_driver = { +- .name = "ps3_remote", +- .id_table = ps3remote_devices, +- .report_fixup = ps3remote_fixup, +- .input_mapping = ps3remote_mapping, +-}; +-module_hid_driver(ps3remote_driver); +- +-MODULE_LICENSE("GPL"); +-MODULE_AUTHOR("David Dillow , Antonio Ospite "); +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index 312098e..83f9629 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -1,11 +1,13 @@ + /* +- * HID driver for some sony "special" devices ++ * HID driver for Sony / PS2 / PS3 BD devices. + * + * Copyright (c) 1999 Andreas Gal + * Copyright (c) 2000-2005 Vojtech Pavlik + * Copyright (c) 2005 Michael Haboustak for Concept2, Inc + * Copyright (c) 2008 Jiri Slaby +- * Copyright (c) 2006-2008 Jiri Kosina ++ * Copyright (c) 2012 David Dillow ++ * Copyright (c) 2006-2013 Jiri Kosina ++ * Copyright (c) 2013 Colin Leitner + */ + + /* +@@ -15,17 +17,28 @@ + * any later version. + */ + ++/* NOTE: in order for the Sony PS3 BD Remote Control to be found by ++ * a Bluetooth host, the key combination Start+Enter has to be kept pressed ++ * for about 7 seconds with the Bluetooth Host Controller in discovering mode. ++ * ++ * There will be no PIN request from the device. ++ */ ++ + #include + #include + #include + #include + #include ++#include "usbhid/usbhid.h" ++#include + + #include "hid-ids.h" + + #define VAIO_RDESC_CONSTANT (1 << 0) + #define SIXAXIS_CONTROLLER_USB (1 << 1) + #define SIXAXIS_CONTROLLER_BT (1 << 2) ++#define BUZZ_CONTROLLER (1 << 3) ++#define PS3REMOTE (1 << 4) + + static const u8 sixaxis_rdesc_fixup[] = { + 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, +@@ -55,10 +68,214 @@ static const u8 sixaxis_rdesc_fixup2[] = { + 0xb1, 0x02, 0xc0, 0xc0, + }; + ++static __u8 ps3remote_rdesc[] = { ++ 0x05, 0x01, /* GUsagePage Generic Desktop */ ++ 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ ++ 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ ++ ++ /* Use collection 1 for joypad buttons */ ++ 0xA1, 0x02, /* MCollection Logical (interrelated data) */ ++ ++ /* Ignore the 1st byte, maybe it is used for a controller ++ * number but it's not needed for correct operation */ ++ 0x75, 0x08, /* GReportSize 0x08 [8] */ ++ 0x95, 0x01, /* GReportCount 0x01 [1] */ ++ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ ++ ++ /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these ++ * buttons multiple keypresses are allowed */ ++ 0x05, 0x09, /* GUsagePage Button */ ++ 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ ++ 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ ++ 0x14, /* GLogicalMinimum [0] */ ++ 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ ++ 0x75, 0x01, /* GReportSize 0x01 [1] */ ++ 0x95, 0x18, /* GReportCount 0x18 [24] */ ++ 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ ++ ++ 0xC0, /* MEndCollection */ ++ ++ /* Use collection 2 for remote control buttons */ ++ 0xA1, 0x02, /* MCollection Logical (interrelated data) */ ++ ++ /* 5th byte is used for remote control buttons */ ++ 0x05, 0x09, /* GUsagePage Button */ ++ 0x18, /* LUsageMinimum [No button pressed] */ ++ 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ ++ 0x14, /* GLogicalMinimum [0] */ ++ 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ ++ 0x75, 0x08, /* GReportSize 0x08 [8] */ ++ 0x95, 0x01, /* GReportCount 0x01 [1] */ ++ 0x80, /* MInput */ ++ ++ /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at ++ * 0xff and 11th is for press indication */ ++ 0x75, 0x08, /* GReportSize 0x08 [8] */ ++ 0x95, 0x06, /* GReportCount 0x06 [6] */ ++ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ ++ ++ /* 12th byte is for battery strength */ ++ 0x05, 0x06, /* GUsagePage Generic Device Controls */ ++ 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ ++ 0x14, /* GLogicalMinimum [0] */ ++ 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ ++ 0x75, 0x08, /* GReportSize 0x08 [8] */ ++ 0x95, 0x01, /* GReportCount 0x01 [1] */ ++ 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ ++ ++ 0xC0, /* MEndCollection */ ++ ++ 0xC0 /* MEndCollection [Game Pad] */ ++}; ++ ++static const unsigned int ps3remote_keymap_joypad_buttons[] = { ++ [0x01] = KEY_SELECT, ++ [0x02] = BTN_THUMBL, /* L3 */ ++ [0x03] = BTN_THUMBR, /* R3 */ ++ [0x04] = BTN_START, ++ [0x05] = KEY_UP, ++ [0x06] = KEY_RIGHT, ++ [0x07] = KEY_DOWN, ++ [0x08] = KEY_LEFT, ++ [0x09] = BTN_TL2, /* L2 */ ++ [0x0a] = BTN_TR2, /* R2 */ ++ [0x0b] = BTN_TL, /* L1 */ ++ [0x0c] = BTN_TR, /* R1 */ ++ [0x0d] = KEY_OPTION, /* options/triangle */ ++ [0x0e] = KEY_BACK, /* back/circle */ ++ [0x0f] = BTN_0, /* cross */ ++ [0x10] = KEY_SCREEN, /* view/square */ ++ [0x11] = KEY_HOMEPAGE, /* PS button */ ++ [0x14] = KEY_ENTER, ++}; ++static const unsigned int ps3remote_keymap_remote_buttons[] = { ++ [0x00] = KEY_1, ++ [0x01] = KEY_2, ++ [0x02] = KEY_3, ++ [0x03] = KEY_4, ++ [0x04] = KEY_5, ++ [0x05] = KEY_6, ++ [0x06] = KEY_7, ++ [0x07] = KEY_8, ++ [0x08] = KEY_9, ++ [0x09] = KEY_0, ++ [0x0e] = KEY_ESC, /* return */ ++ [0x0f] = KEY_CLEAR, ++ [0x16] = KEY_EJECTCD, ++ [0x1a] = KEY_MENU, /* top menu */ ++ [0x28] = KEY_TIME, ++ [0x30] = KEY_PREVIOUS, ++ [0x31] = KEY_NEXT, ++ [0x32] = KEY_PLAY, ++ [0x33] = KEY_REWIND, /* scan back */ ++ [0x34] = KEY_FORWARD, /* scan forward */ ++ [0x38] = KEY_STOP, ++ [0x39] = KEY_PAUSE, ++ [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ ++ [0x60] = KEY_FRAMEBACK, /* slow/step back */ ++ [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ ++ [0x63] = KEY_SUBTITLE, ++ [0x64] = KEY_AUDIO, ++ [0x65] = KEY_ANGLE, ++ [0x70] = KEY_INFO, /* display */ ++ [0x80] = KEY_BLUE, ++ [0x81] = KEY_RED, ++ [0x82] = KEY_GREEN, ++ [0x83] = KEY_YELLOW, ++}; ++ ++static const unsigned int buzz_keymap[] = { ++ /* The controller has 4 remote buzzers, each with one LED and 5 ++ * buttons. ++ * ++ * We use the mapping chosen by the controller, which is: ++ * ++ * Key Offset ++ * ------------------- ++ * Buzz 1 ++ * Blue 5 ++ * Orange 4 ++ * Green 3 ++ * Yellow 2 ++ * ++ * So, for example, the orange button on the third buzzer is mapped to ++ * BTN_TRIGGER_HAPPY14 ++ */ ++ [ 1] = BTN_TRIGGER_HAPPY1, ++ [ 2] = BTN_TRIGGER_HAPPY2, ++ [ 3] = BTN_TRIGGER_HAPPY3, ++ [ 4] = BTN_TRIGGER_HAPPY4, ++ [ 5] = BTN_TRIGGER_HAPPY5, ++ [ 6] = BTN_TRIGGER_HAPPY6, ++ [ 7] = BTN_TRIGGER_HAPPY7, ++ [ 8] = BTN_TRIGGER_HAPPY8, ++ [ 9] = BTN_TRIGGER_HAPPY9, ++ [10] = BTN_TRIGGER_HAPPY10, ++ [11] = BTN_TRIGGER_HAPPY11, ++ [12] = BTN_TRIGGER_HAPPY12, ++ [13] = BTN_TRIGGER_HAPPY13, ++ [14] = BTN_TRIGGER_HAPPY14, ++ [15] = BTN_TRIGGER_HAPPY15, ++ [16] = BTN_TRIGGER_HAPPY16, ++ [17] = BTN_TRIGGER_HAPPY17, ++ [18] = BTN_TRIGGER_HAPPY18, ++ [19] = BTN_TRIGGER_HAPPY19, ++ [20] = BTN_TRIGGER_HAPPY20, ++}; ++ + struct sony_sc { + unsigned long quirks; ++ ++ void *extra; + }; + ++struct buzz_extra { ++ int led_state; ++ struct led_classdev *leds[4]; ++}; ++ ++static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, ++ unsigned int *rsize) ++{ ++ *rsize = sizeof(ps3remote_rdesc); ++ return ps3remote_rdesc; ++} ++ ++static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ unsigned int key = usage->hid & HID_USAGE; ++ ++ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) ++ return -1; ++ ++ switch (usage->collection_index) { ++ case 1: ++ if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) ++ return -1; ++ ++ key = ps3remote_keymap_joypad_buttons[key]; ++ if (!key) ++ return -1; ++ break; ++ case 2: ++ if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) ++ return -1; ++ ++ key = ps3remote_keymap_remote_buttons[key]; ++ if (!key) ++ return -1; ++ break; ++ default: ++ return -1; ++ } ++ ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); ++ return 1; ++} ++ ++ + /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ + static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +@@ -95,6 +312,10 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, + *rsize = sizeof(sixaxis_rdesc_fixup2); + memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize); + } ++ ++ if (sc->quirks & PS3REMOTE) ++ return ps3remote_fixup(hdev, rdesc, rsize); ++ + return rdesc; + } + +@@ -117,6 +338,41 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, + return 0; + } + ++static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, ++ struct hid_field *field, struct hid_usage *usage, ++ unsigned long **bit, int *max) ++{ ++ struct sony_sc *sc = hid_get_drvdata(hdev); ++ ++ if (sc->quirks & BUZZ_CONTROLLER) { ++ unsigned int key = usage->hid & HID_USAGE; ++ ++ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) ++ return -1; ++ ++ switch (usage->collection_index) { ++ case 1: ++ if (key >= ARRAY_SIZE(buzz_keymap)) ++ return -1; ++ ++ key = buzz_keymap[key]; ++ if (!key) ++ return -1; ++ break; ++ default: ++ return -1; ++ } ++ ++ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); ++ return 1; ++ } ++ ++ if (sc->quirks & PS3REMOTE) ++ return ps3remote_mapping(hdev, hi, field, usage, bit, max); ++ ++ return -1; ++} ++ + /* + * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP + * like it should according to usbhid/hid-core.c::usbhid_output_raw_report() +@@ -192,11 +448,181 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) + return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); + } + ++static void buzz_set_leds(struct hid_device *hdev, int leds) ++{ ++ struct list_head *report_list = ++ &hdev->report_enum[HID_OUTPUT_REPORT].report_list; ++ struct hid_report *report = list_entry(report_list->next, ++ struct hid_report, list); ++ __s32 *value = report->field[0]->value; ++ ++ value[0] = 0x00; ++ value[1] = (leds & 1) ? 0xff : 0x00; ++ value[2] = (leds & 2) ? 0xff : 0x00; ++ value[3] = (leds & 4) ? 0xff : 0x00; ++ value[4] = (leds & 8) ? 0xff : 0x00; ++ value[5] = 0x00; ++ value[6] = 0x00; ++ hid_hw_request(hdev, report, HID_REQ_SET_REPORT); ++} ++ ++static void buzz_led_set_brightness(struct led_classdev *led, ++ enum led_brightness value) ++{ ++ struct device *dev = led->dev->parent; ++ struct hid_device *hdev = container_of(dev, struct hid_device, dev); ++ struct sony_sc *drv_data; ++ struct buzz_extra *buzz; ++ ++ int n; ++ ++ drv_data = hid_get_drvdata(hdev); ++ if (!drv_data || !drv_data->extra) { ++ hid_err(hdev, "No device data\n"); ++ return; ++ } ++ buzz = drv_data->extra; ++ ++ for (n = 0; n < 4; n++) { ++ if (led == buzz->leds[n]) { ++ int on = !! (buzz->led_state & (1 << n)); ++ if (value == LED_OFF && on) { ++ buzz->led_state &= ~(1 << n); ++ buzz_set_leds(hdev, buzz->led_state); ++ } else if (value != LED_OFF && !on) { ++ buzz->led_state |= (1 << n); ++ buzz_set_leds(hdev, buzz->led_state); ++ } ++ break; ++ } ++ } ++} ++ ++static enum led_brightness buzz_led_get_brightness(struct led_classdev *led) ++{ ++ struct device *dev = led->dev->parent; ++ struct hid_device *hdev = container_of(dev, struct hid_device, dev); ++ struct sony_sc *drv_data; ++ struct buzz_extra *buzz; ++ ++ int n; ++ int on = 0; ++ ++ drv_data = hid_get_drvdata(hdev); ++ if (!drv_data || !drv_data->extra) { ++ hid_err(hdev, "No device data\n"); ++ return LED_OFF; ++ } ++ buzz = drv_data->extra; ++ ++ for (n = 0; n < 4; n++) { ++ if (led == buzz->leds[n]) { ++ on = !! (buzz->led_state & (1 << n)); ++ break; ++ } ++ } ++ ++ return on ? LED_FULL : LED_OFF; ++} ++ ++static int buzz_init(struct hid_device *hdev) ++{ ++ struct sony_sc *drv_data; ++ struct buzz_extra *buzz; ++ int n, ret = 0; ++ struct led_classdev *led; ++ size_t name_sz; ++ char *name; ++ ++ drv_data = hid_get_drvdata(hdev); ++ BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); ++ ++ buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); ++ if (!buzz) { ++ hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); ++ return -ENOMEM; ++ } ++ drv_data->extra = buzz; ++ ++ /* Clear LEDs as we have no way of reading their initial state. This is ++ * only relevant if the driver is loaded after somebody actively set the ++ * LEDs to on */ ++ buzz_set_leds(hdev, 0x00); ++ ++ name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1; ++ ++ for (n = 0; n < 4; n++) { ++ led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); ++ if (!led) { ++ hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); ++ goto error_leds; ++ } ++ ++ name = (void *)(&led[1]); ++ snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1); ++ led->name = name; ++ led->brightness = 0; ++ led->max_brightness = 1; ++ led->brightness_get = buzz_led_get_brightness; ++ led->brightness_set = buzz_led_set_brightness; ++ ++ if (led_classdev_register(&hdev->dev, led)) { ++ hid_err(hdev, "Failed to register LED %d\n", n); ++ kfree(led); ++ goto error_leds; ++ } ++ ++ buzz->leds[n] = led; ++ } ++ ++ return ret; ++ ++error_leds: ++ for (n = 0; n < 4; n++) { ++ led = buzz->leds[n]; ++ buzz->leds[n] = NULL; ++ if (!led) ++ continue; ++ led_classdev_unregister(led); ++ kfree(led); ++ } ++ ++ kfree(drv_data->extra); ++ drv_data->extra = NULL; ++ return ret; ++} ++ ++static void buzz_remove(struct hid_device *hdev) ++{ ++ struct sony_sc *drv_data; ++ struct buzz_extra *buzz; ++ struct led_classdev *led; ++ int n; ++ ++ drv_data = hid_get_drvdata(hdev); ++ BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); ++ ++ buzz = drv_data->extra; ++ ++ for (n = 0; n < 4; n++) { ++ led = buzz->leds[n]; ++ buzz->leds[n] = NULL; ++ if (!led) ++ continue; ++ led_classdev_unregister(led); ++ kfree(led); ++ } ++ ++ kfree(drv_data->extra); ++ drv_data->extra = NULL; ++} ++ + static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + { + int ret; + unsigned long quirks = id->driver_data; + struct sony_sc *sc; ++ unsigned int connect_mask = HID_CONNECT_DEFAULT; + + sc = kzalloc(sizeof(*sc), GFP_KERNEL); + if (sc == NULL) { +@@ -213,8 +639,14 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + goto err_free; + } + +- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | +- HID_CONNECT_HIDDEV_FORCE); ++ if (sc->quirks & VAIO_RDESC_CONSTANT) ++ connect_mask |= HID_CONNECT_HIDDEV_FORCE; ++ else if (sc->quirks & SIXAXIS_CONTROLLER_USB) ++ connect_mask |= HID_CONNECT_HIDDEV_FORCE; ++ else if (sc->quirks & SIXAXIS_CONTROLLER_BT) ++ connect_mask |= HID_CONNECT_HIDDEV_FORCE; ++ ++ ret = hid_hw_start(hdev, connect_mask); + if (ret) { + hid_err(hdev, "hw start failed\n"); + goto err_free; +@@ -226,6 +658,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + } + else if (sc->quirks & SIXAXIS_CONTROLLER_BT) + ret = sixaxis_set_operational_bt(hdev); ++ else if (sc->quirks & BUZZ_CONTROLLER) ++ ret = buzz_init(hdev); + else + ret = 0; + +@@ -242,8 +676,13 @@ err_free: + + static void sony_remove(struct hid_device *hdev) + { ++ struct sony_sc *sc = hid_get_drvdata(hdev); ++ ++ if (sc->quirks & BUZZ_CONTROLLER) ++ buzz_remove(hdev); ++ + hid_hw_stop(hdev); +- kfree(hid_get_drvdata(hdev)); ++ kfree(sc); + } + + static const struct hid_device_id sony_devices[] = { +@@ -257,17 +696,30 @@ static const struct hid_device_id sony_devices[] = { + .driver_data = VAIO_RDESC_CONSTANT }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), + .driver_data = VAIO_RDESC_CONSTANT }, ++ /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as ++ * Logitech joystick from the device descriptor. */ ++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), ++ .driver_data = BUZZ_CONTROLLER }, ++ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), ++ .driver_data = BUZZ_CONTROLLER }, ++ /* PS3 BD Remote Control */ ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), ++ .driver_data = PS3REMOTE }, ++ /* Logitech Harmony Adapter for PS3 */ ++ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), ++ .driver_data = PS3REMOTE }, + { } + }; + MODULE_DEVICE_TABLE(hid, sony_devices); + + static struct hid_driver sony_driver = { +- .name = "sony", +- .id_table = sony_devices, +- .probe = sony_probe, +- .remove = sony_remove, +- .report_fixup = sony_report_fixup, +- .raw_event = sony_raw_event ++ .name = "sony", ++ .id_table = sony_devices, ++ .input_mapping = sony_mapping, ++ .probe = sony_probe, ++ .remove = sony_remove, ++ .report_fixup = sony_report_fixup, ++ .raw_event = sony_raw_event + }; + module_hid_driver(sony_driver); + diff --git a/packages/linux/patches/3.10/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/linux/patches/3.10/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch new file mode 100644 index 0000000000..abdc74f673 --- /dev/null +++ b/packages/linux/patches/3.10/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch @@ -0,0 +1,61 @@ +Betreff: [RFC] hid/sony: add autorepeat for PS3 remotes +Von: David Dillow +Datum: 28.06.2013 04:28 +An: linux-input@vger.kernel.org +Kopie (CC): Stephan Raue + +Some applications using the PS3 remote would like to have autorepeat +from the device. Use the input subsystem's software emulation to provide +this capability, and enable those that don't need it to turn it off. +--- +I'm not sure this is the correct approach, or if it is even appropriate +for a remote to do autorepeat. However, the media/rc subsystem does do +it by default, and it's been requested by users, so there is at least +some demand. + +This compiled against the hid-sony driver with the PS3 remote changes +merged, but I have done no testing of it. If the approach seems +reasonable, I'll try to test it when the MythTV is idle. + + drivers/hid/hid-sony.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index ecbc749..0bbcd07 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -274,6 +274,24 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, + return 1; + } + ++static int ps3remote_setup_repeat(struct hid_device *hdev) ++{ ++ struct hid_input *hidinput = list_first_entry(&hdev->inputs, ++ struct hid_input, list); ++ struct input_dev *input = hidinput->input; ++ ++ /* ++ * Set up autorepeat defaults per the remote control subsystem; ++ * this must be done after hid_hw_start(), as having these non-zero ++ * at the time of input_register_device() tells the input system that ++ * the hardware does the autorepeat, and the PS3 remote does not. ++ */ ++ set_bit(EV_REP, input->evbit); ++ input->rep[REP_DELAY] = 500; ++ input->rep[REP_PERIOD] = 125; ++ ++ return 0; ++} + + /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ + static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, +@@ -659,6 +677,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + ret = sixaxis_set_operational_bt(hdev); + else if (sc->quirks & BUZZ_CONTROLLER) + ret = buzz_init(hdev); ++ else if (sc->quirks & PS3REMOTE) ++ ret = ps3remote_setup_repeat(hdev); + else + ret = 0; + + + diff --git a/packages/linux/patches/3.10/linux-059-remove_some_xpad_pids-0.2.patch b/packages/linux/patches/3.10/linux-059-remove_some_xpad_pids-0.2.patch new file mode 100644 index 0000000000..4a6d1c7a08 --- /dev/null +++ b/packages/linux/patches/3.10/linux-059-remove_some_xpad_pids-0.2.patch @@ -0,0 +1,11 @@ +diff -Naur linux-3.8.4/drivers/input/joystick/xpad.c linux-3.8.4.patch/drivers/input/joystick/xpad.c +--- linux-3.8.4/drivers/input/joystick/xpad.c 2013-03-20 21:11:19.000000000 +0100 ++++ linux-3.8.4.patch/drivers/input/joystick/xpad.c 2013-03-26 20:24:29.273978355 +0100 +@@ -174,7 +174,6 @@ + { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, +- { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, + { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } + }; + diff --git a/packages/linux/patches/3.10/linux-060-add_AUGUST_DVB-T205.patch b/packages/linux/patches/3.10/linux-060-add_AUGUST_DVB-T205.patch new file mode 100644 index 0000000000..8291a9a3eb --- /dev/null +++ b/packages/linux/patches/3.10/linux-060-add_AUGUST_DVB-T205.patch @@ -0,0 +1,14 @@ +diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +index 2cc8ec7..985fa11 100644 +--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c ++++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +@@ -1408,6 +1408,9 @@ static const struct usb_device_id rtl28xxu_id_table[] = { + &rtl2832u_props, "Compro VideoMate U620F", NULL) }, + { DVB_USB_DEVICE(USB_VID_KWORLD_2, 0xd394, + &rtl2832u_props, "MaxMedia HU394-T", NULL) }, ++ { DVB_USB_DEVICE(USB_VID_GTEK, 0xa803, ++ &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, ++ + { } + }; + MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); diff --git a/packages/linux/patches/3.10/linux-203-stb0899_enable_low_symbol_rate.patch b/packages/linux/patches/3.10/linux-203-stb0899_enable_low_symbol_rate.patch new file mode 100644 index 0000000000..f302b6ce1b --- /dev/null +++ b/packages/linux/patches/3.10/linux-203-stb0899_enable_low_symbol_rate.patch @@ -0,0 +1,12 @@ +diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c +--- linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-16 10:25:43.479645317 +0100 +@@ -1581,7 +1581,7 @@ + .frequency_max = 2150000, + .frequency_stepsize = 0, + .frequency_tolerance = 0, +- .symbol_rate_min = 5000000, ++ .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + + .caps = FE_CAN_INVERSION_AUTO | diff --git a/packages/linux/patches/3.10/linux-210-dvbsky.patch b/packages/linux/patches/3.10/linux-210-dvbsky.patch new file mode 100644 index 0000000000..97683e9275 --- /dev/null +++ b/packages/linux/patches/3.10/linux-210-dvbsky.patch @@ -0,0 +1,6161 @@ +diff -urN a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig +--- a/drivers/media/dvb-frontends/Kconfig 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/dvb-frontends/Kconfig 2013-05-03 17:03:57.000000000 +0800 +@@ -200,6 +200,20 @@ + help + A DVB-S/S2 tuner module. Say Y when you want to support this frontend. + ++config DVB_M88DS3103 ++ tristate "Montage M88DS3103 based" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ A DVB-S/S2 tuner module. Say Y when you want to support this frontend. ++ ++config DVB_M88DC2800 ++ tristate "Montage M88DC2800 based" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ A DVB-C tuner module. Say Y when you want to support this frontend. ++ + config DVB_SI21XX + tristate "Silicon Labs SI21XX based" + depends on DVB_CORE && I2C +diff -urN a/drivers/media/dvb-frontends/m88dc2800.c b/drivers/media/dvb-frontends/m88dc2800.c +--- a/drivers/media/dvb-frontends/m88dc2800.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88dc2800.c 2013-01-26 16:03:21.000000000 +0800 +@@ -0,0 +1,2124 @@ ++/* ++ M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage ++ ++ Copyright (C) 2012 Max nibble ++ Copyright (C) 2011 Montage Technology / www.montage-tech.com ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dvb_frontend.h" ++#include "m88dc2800.h" ++ ++struct m88dc2800_state { ++ struct i2c_adapter *i2c; ++ const struct m88dc2800_config *config; ++ struct dvb_frontend frontend; ++ u32 freq; ++ u32 ber; ++ u32 sym; ++ u16 qam; ++ u8 inverted; ++ u32 xtal; ++ /* tuner state */ ++ u8 tuner_init_OK; /* Tuner initialize status */ ++ u8 tuner_dev_addr; /* Tuner device address */ ++ u32 tuner_freq; /* RF frequency to be set, unit: KHz */ ++ u16 tuner_qam; /* Reserved */ ++ u16 tuner_mode; ++ u8 tuner_bandwidth; /* Bandwidth of the channel, unit: MHz, 6/7/8 */ ++ u8 tuner_loopthrough; /* Tuner loop through switch, 0/1 */ ++ u32 tuner_crystal; /* Tuner crystal frequency, unit: KHz */ ++ u32 tuner_dac; /* Tuner DAC frequency, unit: KHz */ ++ u16 tuner_mtt; /* Tuner chip version, D1: 0x0d, E0: 0x0e, E1: 0x8e */ ++ u16 tuner_custom_cfg; ++ u32 tuner_version; /* Tuner driver version number */ ++ u32 tuner_time; ++}; ++ ++static int debug; ++module_param(debug, int, 0644); ++MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); ++ ++#define dprintk(args...) \ ++ do { \ ++ if (debug) \ ++ printk(KERN_INFO "m88dc2800: " args); \ ++ } while (0) ++ ++ ++static int m88dc2800_i2c_write(struct m88dc2800_state *state, u8 addr, ++ u8 * p_data, u8 len) ++{ ++ struct i2c_msg msg = { .flags = 0 }; ++ ++ msg.addr = addr; ++ msg.buf = p_data; ++ msg.len = len; ++ ++ return i2c_transfer(state->i2c, &msg, 1); ++} ++ ++static int m88dc2800_i2c_read(struct m88dc2800_state *state, u8 addr, ++ u8 * p_data, u8 len) ++{ ++ struct i2c_msg msg = { .flags = I2C_M_RD }; ++ ++ msg.addr = addr; ++ msg.buf = p_data; ++ msg.len = len; ++ ++ return i2c_transfer(state->i2c, &msg, 1); ++} ++ ++/*demod register operations.*/ ++static int WriteReg(struct m88dc2800_state *state, u8 reg, u8 data) ++{ ++ u8 buf[] = { reg, data }; ++ u8 addr = state->config->demod_address; ++ int err; ++ ++ dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); ++ ++ err = m88dc2800_i2c_write(state, addr, buf, 2); ++ ++ if (err != 1) { ++ printk(KERN_ERR ++ "%s: writereg error(err == %i, reg == 0x%02x," ++ " value == 0x%02x)\n", __func__, err, reg, data); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int ReadReg(struct m88dc2800_state *state, u8 reg) ++{ ++ int ret; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ u8 addr = state->config->demod_address; ++ ++ ret = m88dc2800_i2c_write(state, addr, b0, 1); ++ ++ if (ret != 1) { ++ printk(KERN_ERR "%s: reg=0x%x (error=%d)\n", ++ __func__, reg, ret); ++ return -EIO; ++ } ++ ++ ret = m88dc2800_i2c_read(state, addr, b1, 1); ++ ++ dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]); ++ return b1[0]; ++} ++ ++static int _mt_fe_tn_set_reg(struct m88dc2800_state *state, u8 reg, ++ u8 data) ++{ ++ int ret; ++ u8 buf[2]; ++ u8 addr = state->tuner_dev_addr; ++ ++ buf[1] = ReadReg(state, 0x86); ++ buf[1] |= 0x80; ++ ret = WriteReg(state, 0x86, buf[1]); ++ ++ buf[0] = reg; ++ buf[1] = data; ++ ++ ret = m88dc2800_i2c_write(state, addr, buf, 2); ++ if (ret != 1) ++ return -EIO; ++ return 0; ++} ++ ++static int _mt_fe_tn_get_reg(struct m88dc2800_state *state, u8 reg, ++ u8 * p_data) ++{ ++ int ret; ++ u8 buf[2]; ++ u8 addr = state->tuner_dev_addr; ++ ++ buf[1] = ReadReg(state, 0x86); ++ buf[1] |= 0x80; ++ ret = WriteReg(state, 0x86, buf[1]); ++ ++ buf[0] = reg; ++ ret = m88dc2800_i2c_write(state, addr, buf, 1); ++ ++ msleep(1); ++ ++ buf[1] = ReadReg(state, 0x86); ++ buf[1] |= 0x80; ++ ret = WriteReg(state, 0x86, buf[1]); ++ ++ return m88dc2800_i2c_read(state, addr, p_data, 1); ++} ++ ++/* Tuner operation functions.*/ ++static int _mt_fe_tn_set_RF_front_tc2800(struct m88dc2800_state *state) ++{ ++ u32 freq_KHz = state->tuner_freq; ++ u8 a, b, c; ++ if (state->tuner_mtt == 0xD1) { /* D1 */ ++ if (freq_KHz <= 123000) { ++ if (freq_KHz <= 56000) { ++ a = 0x00; b = 0x00; c = 0x00; ++ } else if (freq_KHz <= 64000) { ++ a = 0x10; b = 0x01; c = 0x08; ++ } else if (freq_KHz <= 72000) { ++ a = 0x20; b = 0x02; c = 0x10; ++ } else if (freq_KHz <= 80000) { ++ a = 0x30; b = 0x03; c = 0x18; ++ } else if (freq_KHz <= 88000) { ++ a = 0x40; b = 0x04; c = 0x20; ++ } else if (freq_KHz <= 96000) { ++ a = 0x50; b = 0x05; c = 0x28; ++ } else if (freq_KHz <= 104000) { ++ a = 0x60; b = 0x06; c = 0x30; ++ } else { ++ a = 0x70; b = 0x07; c = 0x38; ++ } ++ _mt_fe_tn_set_reg(state, 0x58, 0x9b); ++ _mt_fe_tn_set_reg(state, 0x59, a); ++ _mt_fe_tn_set_reg(state, 0x5d, b); ++ _mt_fe_tn_set_reg(state, 0x5e, c); ++ _mt_fe_tn_set_reg(state, 0x5a, 0x75); ++ _mt_fe_tn_set_reg(state, 0x73, 0x0c); ++ } else { /* if (freq_KHz > 112000) */ ++ _mt_fe_tn_set_reg(state, 0x58, 0x7b); ++ if (freq_KHz <= 304000) { ++ if (freq_KHz <= 136000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x40); ++ } else if (freq_KHz <= 160000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x48); ++ } else if (freq_KHz <= 184000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x50); ++ } else if (freq_KHz <= 208000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x58); ++ } else if (freq_KHz <= 232000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x60); ++ } else if (freq_KHz <= 256000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x68); ++ } else if (freq_KHz <= 280000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x70); ++ } else { /* if (freq_KHz <= 304000) */ ++ _mt_fe_tn_set_reg(state, 0x5e, 0x78); ++ } ++ if (freq_KHz <= 171000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x08); ++ } else if (freq_KHz <= 211000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0a); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0e); ++ } ++ } else { /* if (freq_KHz > 304000) */ ++ _mt_fe_tn_set_reg(state, 0x5e, 0x88); ++ if (freq_KHz <= 400000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0c); ++ } else if (freq_KHz <= 450000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x09); ++ } else if (freq_KHz <= 550000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0e); ++ } else if (freq_KHz <= 650000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0d); ++ } else { /*if (freq_KHz > 650000) */ ++ _mt_fe_tn_set_reg(state, 0x73, 0x0e); ++ } ++ } ++ } ++ if (freq_KHz > 800000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x24); ++ else if (freq_KHz > 700000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x34); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x44); ++ else if (freq_KHz > 300000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x43); ++ else if (freq_KHz > 220000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 110000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ if (freq_KHz > 600000) ++ _mt_fe_tn_set_reg(state, 0x6a, 0x53); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x6a, 0x57); ++ else ++ _mt_fe_tn_set_reg(state, 0x6a, 0x59); ++ if (freq_KHz < 200000) { ++ _mt_fe_tn_set_reg(state, 0x20, 0x5d); ++ } else if (freq_KHz < 500000) { ++ _mt_fe_tn_set_reg(state, 0x20, 0x7d); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x20, 0xfd); ++ } /* end of 0xD1 */ ++ } else if (state->tuner_mtt == 0xE1) { /* E1 */ ++ if (freq_KHz <= 112000) { /* 123MHz */ ++ if (freq_KHz <= 56000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x01); ++ } else if (freq_KHz <= 64000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x09); ++ } else if (freq_KHz <= 72000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x11); ++ } else if (freq_KHz <= 80000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x19); ++ } else if (freq_KHz <= 88000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x21); ++ } else if (freq_KHz <= 96000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x29); ++ } else if (freq_KHz <= 104000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x31); ++ } else { /* if (freq_KHz <= 112000) */ ++ _mt_fe_tn_set_reg(state, 0x5c, 0x39); ++ } ++ _mt_fe_tn_set_reg(state, 0x5b, 0x30); ++ } else { /* if (freq_KHz > 112000) */ ++ if (freq_KHz <= 304000) { ++ if (freq_KHz <= 136000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x41); ++ } else if (freq_KHz <= 160000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x49); ++ } else if (freq_KHz <= 184000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x51); ++ } else if (freq_KHz <= 208000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x59); ++ } else if (freq_KHz <= 232000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x61); ++ } else if (freq_KHz <= 256000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x69); ++ } else if (freq_KHz <= 280000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x71); ++ } else { /* if (freq_KHz <= 304000) */ ++ _mt_fe_tn_set_reg(state, 0x5c, 0x79); ++ } ++ if (freq_KHz <= 150000) { ++ _mt_fe_tn_set_reg(state, 0x5b, 0x28); ++ } else if (freq_KHz <= 256000) { ++ _mt_fe_tn_set_reg(state, 0x5b, 0x29); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x5b, 0x2a); ++ } ++ } else { /* if (freq_KHz > 304000) */ ++ if (freq_KHz <= 400000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x89); ++ } else if (freq_KHz <= 450000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x91); ++ } else if (freq_KHz <= 650000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x98); ++ } else if (freq_KHz <= 850000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0xa0); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x5c, 0xa8); ++ } ++ _mt_fe_tn_set_reg(state, 0x5b, 0x08); ++ } ++ } ++ } /* end of 0xE1 */ ++ return 0; ++} ++ ++static int _mt_fe_tn_cali_PLL_tc2800(struct m88dc2800_state *state, ++ u32 freq_KHz, ++ u32 cali_freq_thres_div2, ++ u32 cali_freq_thres_div3r, ++ u32 cali_freq_thres_div3) ++{ ++ s32 N, F, MUL; ++ u8 buf, tmp, tmp2; ++ s32 M; ++ const s32 crystal_KHz = state->tuner_crystal; ++ if (state->tuner_mtt == 0xD1) { ++ M = state->tuner_crystal / 4000; ++ if (freq_KHz > cali_freq_thres_div2) { ++ MUL = 4; ++ tmp = 2; ++ } else if (freq_KHz > 300000) { ++ MUL = 8; ++ tmp = 3; ++ } else if (freq_KHz > (cali_freq_thres_div2 / 2)) { ++ MUL = 8; ++ tmp = 4; ++ } else if (freq_KHz > (cali_freq_thres_div2 / 4)) { ++ MUL = 16; ++ tmp = 5; ++ } else if (freq_KHz > (cali_freq_thres_div2 / 8)) { ++ MUL = 32; ++ tmp = 6; ++ } else if (freq_KHz > (cali_freq_thres_div2 / 16)) { ++ MUL = 64; ++ tmp = 7; ++ } else { /* invalid */ ++ MUL = 0; ++ tmp = 0; ++ return 1; ++ } ++ } else if (state->tuner_mtt == 0xE1) { ++ M = state->tuner_crystal / 1000; ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x32, 0xe0); ++ _mt_fe_tn_set_reg(state, 0x33, 0x86); ++ _mt_fe_tn_set_reg(state, 0x37, 0x70); ++ _mt_fe_tn_set_reg(state, 0x38, 0x20); ++ _mt_fe_tn_set_reg(state, 0x39, 0x18); ++ _mt_fe_tn_set_reg(state, 0x89, 0x83); ++ if (freq_KHz > cali_freq_thres_div2) { ++ M = M / 4; ++ MUL = 4; ++ tmp = 2; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > cali_freq_thres_div3r) { ++ M = M / 3; ++ MUL = 6; ++ tmp = 2; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > cali_freq_thres_div3) { ++ M = M / 3; ++ MUL = 6; ++ tmp = 2; ++ tmp2 = M; /* 16 */ ++ } else if (freq_KHz > 304000) { ++ M = M / 4; ++ MUL = 8; ++ tmp = 3; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div2 / 2)) { ++ M = M / 4; ++ MUL = 8; ++ tmp = 4; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div3r / 2)) { ++ M = M / 3; ++ MUL = 12; ++ tmp = 4; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > (cali_freq_thres_div3 / 2)) { ++ M = M / 3; ++ MUL = 12; ++ tmp = 4; ++ tmp2 = M; /* 16 */ ++ } else if (freq_KHz > (cali_freq_thres_div2 / 4)) { ++ M = M / 4; ++ MUL = 16; ++ tmp = 5; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div3r / 4)) { ++ M = M / 3; ++ MUL = 24; ++ tmp = 5; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > (cali_freq_thres_div3 / 4)) { ++ M = M / 3; ++ MUL = 24; ++ tmp = 5; ++ tmp2 = M; /* 16 */ ++ } else if (freq_KHz > (cali_freq_thres_div2 / 8)) { ++ M = M / 4; ++ MUL = 32; ++ tmp = 6; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div3r / 8)) { ++ M = M / 3; ++ MUL = 48; ++ tmp = 6; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > (cali_freq_thres_div3 / 8)) { ++ M = M / 3; ++ MUL = 48; ++ tmp = 6; ++ tmp2 = M; /* 16 */ ++ } else if (freq_KHz > (cali_freq_thres_div2 / 16)) { ++ M = M / 4; ++ MUL = 64; ++ tmp = 7; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div3r / 16)) { ++ M = M / 3; ++ MUL = 96; ++ tmp = 7; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > (cali_freq_thres_div3 / 16)) { ++ M = M / 3; ++ MUL = 96; ++ tmp = 7; ++ tmp2 = M; /* 16 */ ++ } else { /* invalid */ ++ M = M / 4; ++ MUL = 0; ++ tmp = 0; ++ tmp2 = 48; ++ return 1; ++ } ++ if (freq_KHz == 291000) { ++ M = state->tuner_crystal / 1000 / 3; ++ MUL = 12; ++ tmp = 4; ++ tmp2 = M + 32; /* 32 */ ++ } ++ /* ++ if (freq_KHz == 578000) { ++ M = state->tuner_crystal / 1000 / 4; ++ MUL = 4; ++ tmp = 2; ++ tmp2 = M + 16; // 48 ++ } ++ */ ++ if (freq_KHz == 690000) { ++ M = state->tuner_crystal / 1000 / 3; ++ MUL = 4; ++ tmp = 2; ++ tmp2 = M + 16; /* 48 */ ++ } ++ _mt_fe_tn_get_reg(state, 0x33, &buf); ++ buf &= 0xc0; ++ buf += tmp2; ++ _mt_fe_tn_set_reg(state, 0x33, buf); ++ } else { ++ return 1; ++ } ++ _mt_fe_tn_get_reg(state, 0x39, &buf); ++ buf &= 0xf8; ++ buf += tmp; ++ _mt_fe_tn_set_reg(state, 0x39, buf); ++ N = (freq_KHz * MUL * M / crystal_KHz) / 2 * 2 - 256; ++ buf = (N >> 8) & 0xcf; ++ if (state->tuner_mtt == 0xE1) { ++ buf |= 0x30; ++ } ++ _mt_fe_tn_set_reg(state, 0x34, buf); ++ buf = N & 0xff; ++ _mt_fe_tn_set_reg(state, 0x35, buf); ++ F = ((freq_KHz * MUL * M / (crystal_KHz / 1000) / 2) - ++ (freq_KHz * MUL * M / crystal_KHz / 2 * 1000)) * 64 / 1000; ++ buf = F & 0xff; ++ _mt_fe_tn_set_reg(state, 0x36, buf); ++ if (F == 0) { ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_set_reg(state, 0x3d, 0xca); ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_reg(state, 0x3d, 0xfe); ++ } else { ++ return 1; ++ } ++ _mt_fe_tn_set_reg(state, 0x3e, 0x9c); ++ _mt_fe_tn_set_reg(state, 0x3f, 0x34); ++ } ++ if (F > 0) { ++ if (state->tuner_mtt == 0xD1) { ++ if ((F == 32) || (F == 16) || (F == 48)) { ++ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); ++ _mt_fe_tn_set_reg(state, 0x3d, 0x4a); ++ _mt_fe_tn_set_reg(state, 0x3f, 0x36); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); ++ _mt_fe_tn_set_reg(state, 0x3d, 0x4a); ++ _mt_fe_tn_set_reg(state, 0x3f, 0x36); ++ } ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); ++ _mt_fe_tn_set_reg(state, 0x3d, 0x7e); ++ _mt_fe_tn_set_reg(state, 0x3f, 0x36); ++ _mt_fe_tn_set_reg(state, 0x89, 0x84); ++ _mt_fe_tn_get_reg(state, 0x39, &buf); ++ buf = buf & 0x1f; ++ _mt_fe_tn_set_reg(state, 0x39, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf | 0x02; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ } else { ++ return 1; ++ } ++ } ++ _mt_fe_tn_set_reg(state, 0x41, 0x00); ++ if (state->tuner_mtt == 0xD1) { ++ msleep(5); ++ } else if (state->tuner_mtt == 0xE1) { ++ msleep(2); ++ } else { ++ return 1; ++ } ++ _mt_fe_tn_set_reg(state, 0x41, 0x02); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x31, 0x80); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ ++ return 0; ++} ++ ++static int _mt_fe_tn_set_PLL_freq_tc2800(struct m88dc2800_state *state) ++{ ++ u8 buf, buf1; ++ u32 freq_thres_div2_KHz, freq_thres_div3r_KHz, ++ freq_thres_div3_KHz; ++ const u32 freq_KHz = state->tuner_freq; ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_set_reg(state, 0x32, 0xe1); ++ _mt_fe_tn_set_reg(state, 0x33, 0xa6); ++ _mt_fe_tn_set_reg(state, 0x37, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x38, 0x20); ++ _mt_fe_tn_set_reg(state, 0x39, 0x18); ++ _mt_fe_tn_set_reg(state, 0x40, 0x40); ++ freq_thres_div2_KHz = 520000; ++ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, ++ freq_thres_div2_KHz, 0, 0); ++ msleep(5); ++ _mt_fe_tn_get_reg(state, 0x3a, &buf); ++ buf1 = buf; ++ buf = buf & 0x03; ++ buf1 = buf1 & 0x01; ++ if ((buf1 == 0) || (buf == 3)) { ++ freq_thres_div2_KHz = 420000; ++ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, ++ freq_thres_div2_KHz, 0, ++ 0); ++ msleep(5); ++ _mt_fe_tn_get_reg(state, 0x3a, &buf); ++ buf = buf & 0x07; ++ if (buf == 5) { ++ freq_thres_div2_KHz = 520000; ++ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, ++ freq_thres_div2_KHz, ++ 0, 0); ++ msleep(5); ++ } ++ } ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ _mt_fe_tn_set_reg(state, 0x38, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf | 0x10; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf & 0xdf; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x40, 0x0); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x31, 0x80); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ msleep(5); ++ _mt_fe_tn_get_reg(state, 0x39, &buf); ++ buf = buf >> 5; ++ if (buf < 5) { ++ _mt_fe_tn_get_reg(state, 0x39, &buf); ++ buf = buf | 0xa0; ++ buf = buf & 0xbf; ++ _mt_fe_tn_set_reg(state, 0x39, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf | 0x02; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ } ++ _mt_fe_tn_get_reg(state, 0x37, &buf); ++ if (buf > 0x70) { ++ buf = 0x7f; ++ _mt_fe_tn_set_reg(state, 0x40, 0x40); ++ } ++ _mt_fe_tn_set_reg(state, 0x37, buf); ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ if (buf < 0x0f) { ++ buf = (buf & 0x0f) << 2; ++ buf = buf + 0x0f; ++ _mt_fe_tn_set_reg(state, 0x37, buf); ++ } else if (buf < 0x1f) { ++ buf = buf + 0x0f; ++ _mt_fe_tn_set_reg(state, 0x37, buf); ++ } ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = (buf | 0x20) & 0xef; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x41, 0x00); ++ msleep(5); ++ _mt_fe_tn_set_reg(state, 0x41, 0x02); ++ } else if (state->tuner_mtt == 0xE1) { ++ freq_thres_div2_KHz = 580000; ++ freq_thres_div3r_KHz = 500000; ++ freq_thres_div3_KHz = 440000; ++ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, ++ freq_thres_div2_KHz, ++ freq_thres_div3r_KHz, ++ freq_thres_div3_KHz); ++ msleep(3); ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ _mt_fe_tn_set_reg(state, 0x38, buf); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x31, 0x80); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ msleep(3); ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ _mt_fe_tn_set_reg(state, 0x38, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf | 0x10; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf & 0xdf; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x31, 0x80); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ msleep(3); ++ _mt_fe_tn_get_reg(state, 0x37, &buf); ++ _mt_fe_tn_set_reg(state, 0x37, buf); ++ /* ++ if ((freq_KHz == 802000) || (freq_KHz == 826000)) { ++ _mt_fe_tn_set_reg(state, 0x37, 0x5e); ++ } ++ */ ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = (buf & 0xef) | 0x30; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x41, 0x00); ++ msleep(2); ++ _mt_fe_tn_set_reg(state, 0x41, 0x02); ++ } else { ++ return 1; ++ } ++ return 0; ++} ++ ++static int _mt_fe_tn_set_BB_tc2800(struct m88dc2800_state *state) ++{ ++ return 0; ++} ++ ++ static int _mt_fe_tn_set_appendix_tc2800(struct m88dc2800_state *state) ++ ++{ ++ u8 buf; ++ const u32 freq_KHz = state->tuner_freq; ++ if (state->tuner_mtt == 0xD1) { ++ if ((freq_KHz == 123000) || (freq_KHz == 147000) || ++ (freq_KHz == 171000) || (freq_KHz == 195000)) { ++ _mt_fe_tn_set_reg(state, 0x20, 0x1b); ++ } ++ if ((freq_KHz == 371000) || (freq_KHz == 419000) || ++ (freq_KHz == 610000) || (freq_KHz == 730000) || ++ (freq_KHz == 754000) || (freq_KHz == 826000)) { ++ _mt_fe_tn_get_reg(state, 0x0d, &buf); ++ _mt_fe_tn_set_reg(state, 0x0d, (u8) (buf + 1)); ++ } ++ if ((freq_KHz == 522000) || (freq_KHz == 578000) || ++ (freq_KHz == 634000) || (freq_KHz == 690000) || ++ (freq_KHz == 834000)) { ++ _mt_fe_tn_get_reg(state, 0x0d, &buf); ++ _mt_fe_tn_set_reg(state, 0x0d, (u8) (buf - 1)); ++ } ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_reg(state, 0x20, 0xfc); ++ if (freq_KHz == 123000 || freq_KHz == 147000 || ++ freq_KHz == 171000 || freq_KHz == 195000 || ++ freq_KHz == 219000 || freq_KHz == 267000 || ++ freq_KHz == 291000 || freq_KHz == 339000 || ++ freq_KHz == 387000 || freq_KHz == 435000 || ++ freq_KHz == 482000 || freq_KHz == 530000 || ++ freq_KHz == 722000 || ++ (state->tuner_custom_cfg == 1 && freq_KHz == 315000)) { ++ _mt_fe_tn_set_reg(state, 0x20, 0x5c); ++ } ++ } ++ return 0; ++} ++ ++ static int _mt_fe_tn_set_DAC_tc2800(struct m88dc2800_state *state) ++{ ++ u8 buf, tempnumber; ++ s32 N; ++ s32 f1f2number, f1, f2, delta1, Totalnum1; ++ s32 cntT, cntin, NCOI, z0, z1, z2, tmp; ++ u32 fc, fadc, fsd, f2d; ++ u32 FreqTrue108_Hz; ++ s32 M = state->tuner_crystal / 4000; ++ /* const u8 bandwidth = state->tuner_bandwidth; */ ++ const u16 DAC_fre = 108; ++ const u32 crystal_KHz = state->tuner_crystal; ++ const u32 DACFreq_KHz = state->tuner_dac; ++ const u32 freq_KHz = state->tuner_freq; ++ ++ if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_get_reg(state, 0x33, &buf); ++ M = buf & 0x0f; ++ if (M == 0) ++ M = 6; ++ } ++ _mt_fe_tn_get_reg(state, 0x34, &buf); ++ N = buf & 0x07; ++ _mt_fe_tn_get_reg(state, 0x35, &buf); ++ N = (N << 8) + buf; ++ buf = ((N + 256) * crystal_KHz / M / DAC_fre + 500) / 1000; ++ if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_appendix_tc2800(state); ++ if (freq_KHz == 187000 || freq_KHz == 195000 || ++ freq_KHz == 131000 || freq_KHz == 211000 || ++ freq_KHz == 219000 || freq_KHz == 227000 || ++ freq_KHz == 267000 || freq_KHz == 299000 || ++ freq_KHz == 347000 || freq_KHz == 363000 || ++ freq_KHz == 395000 || freq_KHz == 403000 || ++ freq_KHz == 435000 || freq_KHz == 482000 || ++ freq_KHz == 474000 || freq_KHz == 490000 || ++ freq_KHz == 610000 || freq_KHz == 642000 || ++ freq_KHz == 666000 || freq_KHz == 722000 || ++ freq_KHz == 754000 || ++ ((freq_KHz == 379000 || freq_KHz == 467000 || ++ freq_KHz == 762000) && state->tuner_custom_cfg != 1)) { ++ buf = buf + 1; ++ } ++ if (freq_KHz == 123000 || freq_KHz == 139000 || ++ freq_KHz == 147000 || freq_KHz == 171000 || ++ freq_KHz == 179000 || freq_KHz == 203000 || ++ freq_KHz == 235000 || freq_KHz == 251000 || ++ freq_KHz == 259000 || freq_KHz == 283000 || ++ freq_KHz == 331000 || freq_KHz == 363000 || ++ freq_KHz == 371000 || freq_KHz == 387000 || ++ freq_KHz == 411000 || freq_KHz == 427000 || ++ freq_KHz == 443000 || freq_KHz == 451000 || ++ freq_KHz == 459000 || freq_KHz == 506000 || ++ freq_KHz == 514000 || freq_KHz == 538000 || ++ freq_KHz == 546000 || freq_KHz == 554000 || ++ freq_KHz == 562000 || freq_KHz == 570000 || ++ freq_KHz == 578000 || freq_KHz == 602000 || ++ freq_KHz == 626000 || freq_KHz == 658000 || ++ freq_KHz == 690000 || freq_KHz == 714000 || ++ freq_KHz == 746000 || freq_KHz == 522000 || ++ freq_KHz == 826000 || freq_KHz == 155000 || ++ freq_KHz == 530000 || ++ ((freq_KHz == 275000 || freq_KHz == 355000) && ++ state->tuner_custom_cfg != 1) || ++ ((freq_KHz == 467000 || freq_KHz == 762000 || ++ freq_KHz == 778000 || freq_KHz == 818000) && ++ state->tuner_custom_cfg == 1)) { ++ buf = buf - 1; ++ } ++ } ++ _mt_fe_tn_set_reg(state, 0x0e, buf); ++ _mt_fe_tn_set_reg(state, 0x0d, buf); ++ f1f2number = ++ (((DACFreq_KHz * M * buf) / crystal_KHz) << 16) / (N + 256) + ++ (((DACFreq_KHz * M * buf) % crystal_KHz) << 16) / ((N + 256) * ++ crystal_KHz); ++ _mt_fe_tn_set_reg(state, 0xf1, (f1f2number & 0xff00) >> 8); ++ _mt_fe_tn_set_reg(state, 0xf2, f1f2number & 0x00ff); ++ FreqTrue108_Hz = ++ (N + 256) * crystal_KHz / (M * buf) * 1000 + ++ (((N + 256) * crystal_KHz) % (M * buf)) * 1000 / (M * buf); ++ f1 = 4096; ++ fc = FreqTrue108_Hz; ++ fadc = fc / 4; ++ fsd = 27000000; ++ f2d = state->tuner_bandwidth * 1000 / 2 - 150; ++ f2 = (fsd / 250) * f2d / ((fc + 500) / 1000); ++ delta1 = ((f1 - f2) << 15) / f2; ++ Totalnum1 = ((f1 - f2) << 15) - delta1 * f2; ++ cntT = f2; ++ cntin = Totalnum1; ++ NCOI = delta1; ++ z0 = cntin; ++ z1 = cntT; ++ z2 = NCOI; ++ tempnumber = (z0 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xc9, (u8) (tempnumber & 0x0f)); ++ tempnumber = (z0 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xca, tempnumber); ++ tempnumber = (z1 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xcb, tempnumber); ++ tempnumber = (z1 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xcc, tempnumber); ++ tempnumber = (z2 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xcd, tempnumber); ++ tempnumber = (z2 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xce, tempnumber); ++ tmp = f1; ++ f1 = f2; ++ f2 = tmp / 2; ++ delta1 = ((f1 - f2) << 15) / f2; ++ Totalnum1 = ((f1 - f2) << 15) - delta1 * f2; ++ NCOI = (f1 << 15) / f2 - (1 << 15); ++ cntT = f2; ++ cntin = Totalnum1; ++ z0 = cntin; ++ z1 = cntT; ++ z2 = NCOI; ++ tempnumber = (z0 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xd9, (u8) (tempnumber & 0x0f)); ++ tempnumber = (z0 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xda, tempnumber); ++ tempnumber = (z1 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xdb, tempnumber); ++ tempnumber = (z1 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xdc, tempnumber); ++ tempnumber = (z2 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xdd, tempnumber); ++ tempnumber = (z2 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xde, tempnumber); ++ ++ return 0; ++} ++ ++static int _mt_fe_tn_preset_tc2800(struct m88dc2800_state *state) ++{ ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_set_reg(state, 0x19, 0x4a); ++ _mt_fe_tn_set_reg(state, 0x1b, 0x4b); ++ _mt_fe_tn_set_reg(state, 0x04, 0x04); ++ _mt_fe_tn_set_reg(state, 0x17, 0x0d); ++ _mt_fe_tn_set_reg(state, 0x62, 0x6c); ++ _mt_fe_tn_set_reg(state, 0x63, 0xf4); ++ _mt_fe_tn_set_reg(state, 0x1f, 0x0e); ++ _mt_fe_tn_set_reg(state, 0x6b, 0xf4); ++ _mt_fe_tn_set_reg(state, 0x14, 0x01); ++ _mt_fe_tn_set_reg(state, 0x5a, 0x75); ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ _mt_fe_tn_set_reg(state, 0x72, 0xe0); ++ _mt_fe_tn_set_reg(state, 0x70, 0x07); ++ _mt_fe_tn_set_reg(state, 0x15, 0x7b); ++ _mt_fe_tn_set_reg(state, 0x55, 0x71); ++ _mt_fe_tn_set_reg(state, 0x75, 0x55); ++ _mt_fe_tn_set_reg(state, 0x76, 0xac); ++ _mt_fe_tn_set_reg(state, 0x77, 0x6c); ++ _mt_fe_tn_set_reg(state, 0x78, 0x8b); ++ _mt_fe_tn_set_reg(state, 0x79, 0x42); ++ _mt_fe_tn_set_reg(state, 0x7a, 0xd2); ++ _mt_fe_tn_set_reg(state, 0x81, 0x01); ++ _mt_fe_tn_set_reg(state, 0x82, 0x00); ++ _mt_fe_tn_set_reg(state, 0x82, 0x02); ++ _mt_fe_tn_set_reg(state, 0x82, 0x04); ++ _mt_fe_tn_set_reg(state, 0x82, 0x06); ++ _mt_fe_tn_set_reg(state, 0x82, 0x08); ++ _mt_fe_tn_set_reg(state, 0x82, 0x09); ++ _mt_fe_tn_set_reg(state, 0x82, 0x29); ++ _mt_fe_tn_set_reg(state, 0x82, 0x49); ++ _mt_fe_tn_set_reg(state, 0x82, 0x58); ++ _mt_fe_tn_set_reg(state, 0x82, 0x59); ++ _mt_fe_tn_set_reg(state, 0x82, 0x98); ++ _mt_fe_tn_set_reg(state, 0x82, 0x99); ++ _mt_fe_tn_set_reg(state, 0x10, 0x05); ++ _mt_fe_tn_set_reg(state, 0x10, 0x0d); ++ _mt_fe_tn_set_reg(state, 0x11, 0x95); ++ _mt_fe_tn_set_reg(state, 0x11, 0x9d); ++ if (state->tuner_loopthrough != 0) { ++ _mt_fe_tn_set_reg(state, 0x67, 0x25); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x67, 0x05); ++ } ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_reg(state, 0x1b, 0x47); ++ if (state->tuner_mode == 0) { /* DVB-C */ ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ _mt_fe_tn_set_reg(state, 0x62, 0x2c); ++ _mt_fe_tn_set_reg(state, 0x63, 0x54); ++ _mt_fe_tn_set_reg(state, 0x68, 0x0b); ++ _mt_fe_tn_set_reg(state, 0x14, 0x00); ++ } else { /* CTTB */ ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ _mt_fe_tn_set_reg(state, 0x62, 0x0c); ++ _mt_fe_tn_set_reg(state, 0x63, 0x54); ++ _mt_fe_tn_set_reg(state, 0x68, 0x0b); ++ _mt_fe_tn_set_reg(state, 0x14, 0x05); ++ } ++ _mt_fe_tn_set_reg(state, 0x6f, 0x00); ++ _mt_fe_tn_set_reg(state, 0x84, 0x04); ++ _mt_fe_tn_set_reg(state, 0x5e, 0xbe); ++ _mt_fe_tn_set_reg(state, 0x87, 0x07); ++ _mt_fe_tn_set_reg(state, 0x8a, 0x1f); ++ _mt_fe_tn_set_reg(state, 0x8b, 0x1f); ++ _mt_fe_tn_set_reg(state, 0x88, 0x30); ++ _mt_fe_tn_set_reg(state, 0x58, 0x34); ++ _mt_fe_tn_set_reg(state, 0x61, 0x8c); ++ _mt_fe_tn_set_reg(state, 0x6a, 0x42); ++ } ++ return 0; ++} ++ ++static int mt_fe_tn_wakeup_tc2800(struct m88dc2800_state *state) ++{ ++ _mt_fe_tn_set_reg(state, 0x16, 0xb1); ++ _mt_fe_tn_set_reg(state, 0x09, 0x7d); ++ return 0; ++} ++ ++ static int mt_fe_tn_sleep_tc2800(struct m88dc2800_state *state) ++{ ++ _mt_fe_tn_set_reg(state, 0x16, 0xb0); ++ _mt_fe_tn_set_reg(state, 0x09, 0x6d); ++ return 0; ++} ++ ++ static int mt_fe_tn_init_tc2800(struct m88dc2800_state *state) ++{ ++ if (state->tuner_init_OK != 1) { ++ state->tuner_dev_addr = 0x61; /* TUNER_I2C_ADDR_TC2800 */ ++ state->tuner_freq = 650000; ++ state->tuner_qam = 0; ++ state->tuner_mode = 0; // 0: DVB-C, 1: CTTB ++ state->tuner_bandwidth = 8; ++ state->tuner_loopthrough = 0; ++ state->tuner_crystal = 24000; ++ state->tuner_dac = 7200; ++ state->tuner_mtt = 0x00; ++ state->tuner_custom_cfg = 0; ++ state->tuner_version = 30022; /* Driver version number */ ++ state->tuner_time = 12092611; ++ state->tuner_init_OK = 1; ++ } ++ _mt_fe_tn_set_reg(state, 0x2b, 0x46); ++ _mt_fe_tn_set_reg(state, 0x2c, 0x75); ++ if (state->tuner_mtt == 0x00) { ++ u8 tmp = 0; ++ _mt_fe_tn_get_reg(state, 0x01, &tmp); ++ printk(KERN_INFO "m88dc2800: tuner id = 0x%02x ", tmp); ++ switch (tmp) { ++ case 0x0d: ++ state->tuner_mtt = 0xD1; ++ break; ++ case 0x8e: ++ default: ++ state->tuner_mtt = 0xE1; ++ break; ++ } ++ } ++ return 0; ++} ++ ++ static int mt_fe_tn_set_freq_tc2800(struct m88dc2800_state *state, ++ u32 freq_KHz) ++{ ++ u8 buf; ++ u8 buf1; ++ ++ mt_fe_tn_init_tc2800(state); ++ state->tuner_freq = freq_KHz; ++ _mt_fe_tn_set_reg(state, 0x21, freq_KHz > 500000 ? 0xb9 : 0x99); ++ mt_fe_tn_wakeup_tc2800(state); ++ _mt_fe_tn_set_reg(state, 0x05, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x06, 0xf8); ++ _mt_fe_tn_set_RF_front_tc2800(state); ++ _mt_fe_tn_set_PLL_freq_tc2800(state); ++ _mt_fe_tn_set_DAC_tc2800(state); ++ _mt_fe_tn_set_BB_tc2800(state); ++ _mt_fe_tn_preset_tc2800(state); ++ _mt_fe_tn_set_reg(state, 0x05, 0x00); ++ _mt_fe_tn_set_reg(state, 0x06, 0x00); ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_set_reg(state, 0x00, 0x01); ++ _mt_fe_tn_set_reg(state, 0x00, 0x00); ++ msleep(5); ++ _mt_fe_tn_set_reg(state, 0x41, 0x00); ++ msleep(5); ++ _mt_fe_tn_set_reg(state, 0x41, 0x02); ++ ++ _mt_fe_tn_get_reg(state, 0x69, &buf1); ++ buf1 = buf1 & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x61, &buf); ++ buf = buf & 0x0f; ++ if (buf == 0x0c) ++ _mt_fe_tn_set_reg(state, 0x6a, 0x59); ++ if (buf1 > 0x02) { ++ if (freq_KHz > 600000) ++ _mt_fe_tn_set_reg(state, 0x66, 0x44); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x66, 0x64); ++ else ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ } ++ if (buf1 < 0x03) { ++ if (freq_KHz > 800000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x64); ++ else if (freq_KHz > 600000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 300000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x43); ++ else if (freq_KHz > 220000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 110000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ msleep(5); ++ } else if (buf < 0x0c) { ++ if (freq_KHz > 800000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else if (freq_KHz > 600000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x34); ++ else if (freq_KHz > 300000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x43); ++ else if (freq_KHz > 220000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 110000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ msleep(5); ++ } ++ } else if ((state->tuner_mtt == 0xE1)) { ++ _mt_fe_tn_set_reg(state, 0x00, 0x01); ++ _mt_fe_tn_set_reg(state, 0x00, 0x00); ++ msleep(20); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = (buf & 0xef) | 0x28; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ msleep(50); ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ _mt_fe_tn_set_reg(state, 0x38, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = (buf & 0xf7) | 0x10; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ msleep(10); ++ _mt_fe_tn_get_reg(state, 0x69, &buf); ++ buf = buf & 0x03; ++ _mt_fe_tn_set_reg(state, 0x2a, buf); ++ if (buf > 0) { ++ msleep(20); ++ _mt_fe_tn_get_reg(state, 0x84, &buf); ++ buf = buf & 0x1f; ++ _mt_fe_tn_set_reg(state, 0x68, 0x0a); ++ _mt_fe_tn_get_reg(state, 0x88, &buf1); ++ buf1 = buf1 & 0x1f; ++ if (buf <= buf1) ++ _mt_fe_tn_set_reg(state, 0x66, 0x44); ++ else ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ } else { ++ if (freq_KHz <= 600000) ++ _mt_fe_tn_set_reg(state, 0x68, 0x0c); ++ else ++ _mt_fe_tn_set_reg(state, 0x68, 0x0e); ++ _mt_fe_tn_set_reg(state, 0x30, 0xfb); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x31, 0x04); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ } ++ if (state->tuner_loopthrough != 0) { ++ _mt_fe_tn_get_reg(state, 0x28, &buf); ++ if (buf == 0) { ++ _mt_fe_tn_set_reg(state, 0x28, 0xff); ++ _mt_fe_tn_get_reg(state, 0x61, &buf); ++ buf = buf & 0x0f; ++ if (buf > 9) ++ _mt_fe_tn_set_reg(state, 0x67, 0x74); ++ else if (buf > 6) ++ _mt_fe_tn_set_reg(state, 0x67, 0x64); ++ else if (buf > 3) ++ _mt_fe_tn_set_reg(state, 0x67, 0x54); ++ else ++ _mt_fe_tn_set_reg(state, 0x67, 0x44); ++ } ++ } else { ++ _mt_fe_tn_set_reg(state, 0x67, 0x34); ++ } ++ } else { ++ return 1; ++ } ++ return 0; ++} ++ ++ ++/* ++static int mt_fe_tn_set_BB_filter_band_tc2800(struct m88dc2800_state *state, ++ u8 bandwidth) ++{ ++ u8 buf, tmp; ++ ++ _mt_fe_tn_get_reg(state, 0x53, &tmp); ++ ++ if (bandwidth == 6) ++ buf = 0x01 << 1; ++ else if (bandwidth == 7) ++ buf = 0x02 << 1; ++ else if (bandwidth == 8) ++ buf = 0x04 << 1; ++ else ++ buf = 0x04 << 1; ++ ++ tmp &= 0xf1; ++ tmp |= buf; ++ _mt_fe_tn_set_reg(state, 0x53, tmp); ++ state->tuner_bandwidth = bandwidth; ++ return 0; ++} ++*/ ++ ++static s32 mt_fe_tn_get_signal_strength_tc2800(struct m88dc2800_state ++ *state) ++{ ++ s32 level = -107; ++ s32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; ++ s32 val1, val2, val; ++ s32 result2, result3, result4, result5, result6; ++ s32 append; ++ u8 tmp; ++ s32 freq_KHz = (s32) state->tuner_freq; ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_get_reg(state, 0x61, &tmp); ++ tmp1 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x69, &tmp); ++ tmp2 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x73, &tmp); ++ tmp3 = tmp & 0x07; ++ _mt_fe_tn_get_reg(state, 0x7c, &tmp); ++ tmp4 = (tmp >> 4) & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x7b, &tmp); ++ tmp5 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x7f, &tmp); ++ tmp6 = (tmp >> 5) & 0x01; ++ if (tmp1 > 6) { ++ val1 = 0; ++ if (freq_KHz <= 200000) { ++ val2 = (tmp1 - 6) * 267; ++ } else if (freq_KHz <= 600000) { ++ val2 = (tmp1 - 6) * 280; ++ } else { ++ val2 = (tmp1 - 6) * 290; ++ } ++ val = val1 + val2; ++ } else { ++ if (tmp1 == 0) { ++ val1 = -550; ++ } else { ++ val1 = 0; ++ } ++ if ((tmp1 < 4) && (freq_KHz >= 506000)) { ++ val1 = -850; ++ } ++ val2 = 0; ++ val = val1 + val2; ++ } ++ if (freq_KHz <= 95000) { ++ result2 = tmp2 * 289; ++ } else if (freq_KHz <= 155000) { ++ result2 = tmp2 * 278; ++ } else if (freq_KHz <= 245000) { ++ result2 = tmp2 * 267; ++ } else if (freq_KHz <= 305000) { ++ result2 = tmp2 * 256; ++ } else if (freq_KHz <= 335000) { ++ result2 = tmp2 * 244; ++ } else if (freq_KHz <= 425000) { ++ result2 = tmp2 * 233; ++ } else if (freq_KHz <= 575000) { ++ result2 = tmp2 * 222; ++ } else if (freq_KHz <= 665000) { ++ result2 = tmp2 * 211; ++ } else { ++ result2 = tmp2 * 200; ++ } ++ result3 = (6 - tmp3) * 100; ++ result4 = 300 * tmp4; ++ result5 = 50 * tmp5; ++ result6 = 300 * tmp6; ++ if (freq_KHz < 105000) { ++ append = -450; ++ } else if (freq_KHz <= 227000) { ++ append = -4 * (freq_KHz / 1000 - 100) + 150; ++ } else if (freq_KHz <= 305000) { ++ append = -4 * (freq_KHz / 1000 - 100); ++ } else if (freq_KHz <= 419000) { ++ append = 500 - 40 * (freq_KHz / 1000 - 300) / 17 + 130; ++ } else if (freq_KHz <= 640000) { ++ append = 500 - 40 * (freq_KHz / 1000 - 300) / 17; ++ } else { ++ append = -500; ++ } ++ level = append - (val + result2 + result3 + result4 + ++ result5 + result6); ++ level /= 100; ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_get_reg(state, 0x61, &tmp); ++ tmp1 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x84, &tmp); ++ tmp2 = tmp & 0x1f; ++ _mt_fe_tn_get_reg(state, 0x69, &tmp); ++ tmp3 = tmp & 0x03; ++ _mt_fe_tn_get_reg(state, 0x73, &tmp); ++ tmp4 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x7c, &tmp); ++ tmp5 = (tmp >> 4) & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x7b, &tmp); ++ tmp6 = tmp & 0x0f; ++ if (freq_KHz < 151000) { ++ result2 = (1150 - freq_KHz / 100) * 163 / 33 + 4230; ++ result3 = (1150 - freq_KHz / 100) * 115 / 33 + 1850; ++ result4 = -3676 * (freq_KHz / 1000) / 100 + 6115; ++ } else if (freq_KHz < 257000) { ++ result2 = (1540 - freq_KHz / 100) * 11 / 4 + 3870; ++ result3 = (1540 - freq_KHz / 100) * 205 / 96 + 2100; ++ result4 = -21 * freq_KHz / 1000 + 5084; ++ } else if (freq_KHz < 305000) { ++ result2 = (2620 - freq_KHz / 100) * 5 / 3 + 2770; ++ result3 = (2620 - freq_KHz / 100) * 10 / 7 + 1700; ++ result4 = 650; ++ } else if (freq_KHz < 449000) { ++ result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270; ++ result3 = (3100 - freq_KHz / 100) * 5 / 3 + 10000; ++ result4 = 134 * freq_KHz / 10000 + 11875; ++ } else { ++ result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270; ++ result3 = 8400; ++ result4 = 5300; ++ } ++ if (tmp1 > 6) { ++ val1 = result2; ++ val2 = 2900; ++ val = 500; ++ } else if (tmp1 > 0) { ++ val1 = result3; ++ val2 = 2700; ++ val = 500; ++ } else { ++ val1 = result4; ++ val2 = 2700; ++ val = 400; ++ } ++ level = val1 - (val2 * tmp1 + 500 * tmp2 + 3000 * tmp3 - ++ 500 * tmp4 + 3000 * tmp5 + val * tmp6) - 1000; ++ level /= 1000; ++ } ++ return level; ++} ++ ++ ++/* m88dc2800 operation functions */ ++u8 M88DC2000GetLock(struct m88dc2800_state * state) ++{ ++ u8 u8ret = 0; ++ if (ReadReg(state, 0x80) < 0x06) { ++ if ((ReadReg(state, 0xdf) & 0x80) == 0x80 ++ &&(ReadReg(state, 0x91) & 0x23) == 0x03 ++ &&(ReadReg(state, 0x43) & 0x08) == 0x08) ++ u8ret = 1; ++ else ++ u8ret = 0; ++ } else { ++ if ((ReadReg(state, 0x85) & 0x08) == 0x08) ++ u8ret = 1; ++ else ++ u8ret = 0; ++ } ++ dprintk("%s, lock=%d\n", __func__, u8ret); ++ return u8ret; ++} ++ ++static int M88DC2000SetTsType(struct m88dc2800_state *state, u8 type) ++{ ++ u8 regC2H; ++ ++ if (type == 3) { ++ WriteReg(state, 0x84, 0x6A); ++ WriteReg(state, 0xC0, 0x43); ++ WriteReg(state, 0xE2, 0x06); ++ regC2H = ReadReg(state, 0xC2); ++ regC2H &= 0xC0; ++ regC2H |= 0x1B; ++ WriteReg(state, 0xC2, regC2H); ++ WriteReg(state, 0xC1, 0x60); /* common interface */ ++ } else if (type == 1) { ++ WriteReg(state, 0x84, 0x6A); ++ WriteReg(state, 0xC0, 0x47); /* serial format */ ++ WriteReg(state, 0xE2, 0x02); ++ regC2H = ReadReg(state, 0xC2); ++ regC2H &= 0xC7; ++ WriteReg(state, 0xC2, regC2H); ++ WriteReg(state, 0xC1, 0x00); ++ } else { ++ WriteReg(state, 0x84, 0x6C); ++ WriteReg(state, 0xC0, 0x43); /* parallel format */ ++ WriteReg(state, 0xE2, 0x06); ++ regC2H = ReadReg(state, 0xC2); ++ regC2H &= 0xC7; ++ WriteReg(state, 0xC2, regC2H); ++ WriteReg(state, 0xC1, 0x00); ++ } ++ return 0; ++} ++ ++static int M88DC2000RegInitial_TC2800(struct m88dc2800_state *state) ++{ ++ u8 RegE3H, RegE4H; ++ ++ WriteReg(state, 0x00, 0x48); ++ WriteReg(state, 0x01, 0x09); ++ WriteReg(state, 0xFB, 0x0A); ++ WriteReg(state, 0xFC, 0x0B); ++ WriteReg(state, 0x02, 0x0B); ++ WriteReg(state, 0x03, 0x18); ++ WriteReg(state, 0x05, 0x0D); ++ WriteReg(state, 0x36, 0x80); ++ WriteReg(state, 0x43, 0x40); ++ WriteReg(state, 0x55, 0x7A); ++ WriteReg(state, 0x56, 0xD9); ++ WriteReg(state, 0x57, 0xDF); ++ WriteReg(state, 0x58, 0x39); ++ WriteReg(state, 0x5A, 0x00); ++ WriteReg(state, 0x5C, 0x71); ++ WriteReg(state, 0x5D, 0x23); ++ WriteReg(state, 0x86, 0x40); ++ WriteReg(state, 0xF9, 0x08); ++ WriteReg(state, 0x61, 0x40); ++ WriteReg(state, 0x62, 0x0A); ++ WriteReg(state, 0x90, 0x06); ++ WriteReg(state, 0xDE, 0x00); ++ WriteReg(state, 0xA0, 0x03); ++ WriteReg(state, 0xDF, 0x81); ++ WriteReg(state, 0xFA, 0x40); ++ WriteReg(state, 0x37, 0x10); ++ WriteReg(state, 0xF0, 0x40); ++ WriteReg(state, 0xF2, 0x9C); ++ WriteReg(state, 0xF3, 0x40); ++ RegE3H = ReadReg(state, 0xE3); ++ RegE4H = ReadReg(state, 0xE4); ++ if (((RegE3H & 0xC0) == 0x00) && ((RegE4H & 0xC0) == 0x00)) { ++ WriteReg(state, 0x30, 0xFF); ++ WriteReg(state, 0x31, 0x00); ++ WriteReg(state, 0x32, 0x00); ++ WriteReg(state, 0x33, 0x00); ++ WriteReg(state, 0x35, 0x32); ++ WriteReg(state, 0x40, 0x00); ++ WriteReg(state, 0x41, 0x10); ++ WriteReg(state, 0xF1, 0x02); ++ WriteReg(state, 0xF4, 0x04); ++ WriteReg(state, 0xF5, 0x00); ++ WriteReg(state, 0x42, 0x14); ++ WriteReg(state, 0xE1, 0x25); ++ } else if (((RegE3H & 0xC0) == 0x80) && ((RegE4H & 0xC0) == 0x40)) { ++ WriteReg(state, 0x30, 0xFF); ++ WriteReg(state, 0x31, 0x00); ++ WriteReg(state, 0x32, 0x00); ++ WriteReg(state, 0x33, 0x00); ++ WriteReg(state, 0x35, 0x32); ++ WriteReg(state, 0x39, 0x00); ++ WriteReg(state, 0x3A, 0x00); ++ WriteReg(state, 0x40, 0x00); ++ WriteReg(state, 0x41, 0x10); ++ WriteReg(state, 0xF1, 0x00); ++ WriteReg(state, 0xF4, 0x00); ++ WriteReg(state, 0xF5, 0x40); ++ WriteReg(state, 0x42, 0x14); ++ WriteReg(state, 0xE1, 0x25); ++ } else if ((RegE3H == 0x80 || RegE3H == 0x81) ++ && (RegE4H == 0x80 || RegE4H == 0x81)) { ++ WriteReg(state, 0x30, 0xFF); ++ WriteReg(state, 0x31, 0x00); ++ WriteReg(state, 0x32, 0x00); ++ WriteReg(state, 0x33, 0x00); ++ WriteReg(state, 0x35, 0x32); ++ WriteReg(state, 0x39, 0x00); ++ WriteReg(state, 0x3A, 0x00); ++ WriteReg(state, 0xF1, 0x00); ++ WriteReg(state, 0xF4, 0x00); ++ WriteReg(state, 0xF5, 0x40); ++ WriteReg(state, 0x42, 0x24); ++ WriteReg(state, 0xE1, 0x25); ++ WriteReg(state, 0x92, 0x7F); ++ WriteReg(state, 0x93, 0x91); ++ WriteReg(state, 0x95, 0x00); ++ WriteReg(state, 0x2B, 0x33); ++ WriteReg(state, 0x2A, 0x2A); ++ WriteReg(state, 0x2E, 0x80); ++ WriteReg(state, 0x25, 0x25); ++ WriteReg(state, 0x2D, 0xFF); ++ WriteReg(state, 0x26, 0xFF); ++ WriteReg(state, 0x27, 0x00); ++ WriteReg(state, 0x24, 0x25); ++ WriteReg(state, 0xA4, 0xFF); ++ WriteReg(state, 0xA3, 0x0D); ++ } else { ++ WriteReg(state, 0x30, 0xFF); ++ WriteReg(state, 0x31, 0x00); ++ WriteReg(state, 0x32, 0x00); ++ WriteReg(state, 0x33, 0x00); ++ WriteReg(state, 0x35, 0x32); ++ WriteReg(state, 0x39, 0x00); ++ WriteReg(state, 0x3A, 0x00); ++ WriteReg(state, 0xF1, 0x00); ++ WriteReg(state, 0xF4, 0x00); ++ WriteReg(state, 0xF5, 0x40); ++ WriteReg(state, 0x42, 0x24); ++ WriteReg(state, 0xE1, 0x27); ++ WriteReg(state, 0x92, 0x7F); ++ WriteReg(state, 0x93, 0x91); ++ WriteReg(state, 0x95, 0x00); ++ WriteReg(state, 0x2B, 0x33); ++ WriteReg(state, 0x2A, 0x2A); ++ WriteReg(state, 0x2E, 0x80); ++ WriteReg(state, 0x25, 0x25); ++ WriteReg(state, 0x2D, 0xFF); ++ WriteReg(state, 0x26, 0xFF); ++ WriteReg(state, 0x27, 0x00); ++ WriteReg(state, 0x24, 0x25); ++ WriteReg(state, 0xA4, 0xFF); ++ WriteReg(state, 0xA3, 0x10); ++ } ++ WriteReg(state, 0xF6, 0x4E); ++ WriteReg(state, 0xF7, 0x20); ++ WriteReg(state, 0x89, 0x02); ++ WriteReg(state, 0x14, 0x08); ++ WriteReg(state, 0x6F, 0x0D); ++ WriteReg(state, 0x10, 0xFF); ++ WriteReg(state, 0x11, 0x00); ++ WriteReg(state, 0x12, 0x30); ++ WriteReg(state, 0x13, 0x23); ++ WriteReg(state, 0x60, 0x00); ++ WriteReg(state, 0x69, 0x00); ++ WriteReg(state, 0x6A, 0x03); ++ WriteReg(state, 0xE0, 0x75); ++ WriteReg(state, 0x8D, 0x29); ++ WriteReg(state, 0x4E, 0xD8); ++ WriteReg(state, 0x88, 0x80); ++ WriteReg(state, 0x52, 0x79); ++ WriteReg(state, 0x53, 0x03); ++ WriteReg(state, 0x59, 0x30); ++ WriteReg(state, 0x5E, 0x02); ++ WriteReg(state, 0x5F, 0x0F); ++ WriteReg(state, 0x71, 0x03); ++ WriteReg(state, 0x72, 0x12); ++ WriteReg(state, 0x73, 0x12); ++ ++ return 0; ++} ++ ++static int M88DC2000AutoTSClock_P(struct m88dc2800_state *state, u32 sym, ++ u16 qam) ++{ ++ u32 dataRate; ++ u8 clk_div, value; ++ printk(KERN_INFO ++ "m88dc2800: M88DC2000AutoTSClock_P, symrate=%d qam=%d\n", ++ sym, qam); ++ switch (qam) { ++ case 16: ++ dataRate = 4; ++ break; ++ case 32: ++ dataRate = 5; ++ break; ++ case 128: ++ dataRate = 7; ++ break; ++ case 256: ++ dataRate = 8; ++ break; ++ case 64: ++ default: ++ dataRate = 6; ++ break; ++ } ++ dataRate *= sym * 105; ++ dataRate /= 800; ++ if (dataRate <= 4115) ++ clk_div = 0x05; ++ else if (dataRate <= 4800) ++ clk_div = 0x04; ++ else if (dataRate <= 5760) ++ clk_div = 0x03; ++ else if (dataRate <= 7200) ++ clk_div = 0x02; ++ else if (dataRate <= 9600) ++ clk_div = 0x01; ++ else ++ clk_div = 0x00; ++ value = ReadReg(state, 0xC2); ++ value &= 0xc0; ++ value |= clk_div; ++ WriteReg(state, 0xC2, value); ++ return 0; ++} ++ ++static int M88DC2000AutoTSClock_C(struct m88dc2800_state *state, u32 sym, ++ u16 qam) ++{ ++ u32 dataRate; ++ u8 clk_div, value; ++ printk(KERN_INFO ++ "m88dc2800: M88DC2000AutoTSClock_C, symrate=%d qam=%d\n", ++ sym, qam); ++ switch (qam) { ++ case 16: ++ dataRate = 4; ++ break; ++ case 32: ++ dataRate = 5; ++ break; ++ case 128: ++ dataRate = 7; ++ break; ++ case 256: ++ dataRate = 8; ++ break; ++ case 64: ++ default: ++ dataRate = 6; ++ break; ++ } ++ dataRate *= sym * 105; ++ dataRate /= 800; ++ if (dataRate <= 4115) ++ clk_div = 0x3F; ++ else if (dataRate <= 4800) ++ clk_div = 0x36; ++ else if (dataRate <= 5760) ++ clk_div = 0x2D; ++ else if (dataRate <= 7200) ++ clk_div = 0x24; ++ else if (dataRate <= 9600) ++ clk_div = 0x1B; ++ else ++ clk_div = 0x12; ++ value = ReadReg(state, 0xC2); ++ value &= 0xc0; ++ value |= clk_div; ++ WriteReg(state, 0xC2, value); ++ return 0; ++} ++ ++static int M88DC2000SetTxMode(struct m88dc2800_state *state, u8 inverted, ++ u8 j83) ++{ ++ u8 value = 0; ++ if (inverted) ++ value |= 0x08; /* spectrum inverted */ ++ if (j83) ++ value |= 0x01; /* J83C */ ++ WriteReg(state, 0x83, value); ++ return 0; ++} ++ ++static int M88DC2000SoftReset(struct m88dc2800_state *state) ++{ ++ WriteReg(state, 0x80, 0x01); ++ WriteReg(state, 0x82, 0x00); ++ msleep(1); ++ WriteReg(state, 0x80, 0x00); ++ return 0; ++} ++ ++static int M88DC2000SetSym(struct m88dc2800_state *state, u32 sym, u32 xtal) ++{ ++ u8 value; ++ u8 reg6FH, reg12H; ++ u64 fValue; ++ u32 dwValue; ++ ++ printk(KERN_INFO "%s, sym=%d, xtal=%d\n", __func__, sym, xtal); ++ fValue = 4294967296 * (sym + 10); ++ do_div(fValue, xtal); ++ ++ /* fValue = 4294967296 * (sym + 10) / xtal; */ ++ dwValue = (u32) fValue; ++ printk(KERN_INFO "%s, fvalue1=%x\n", __func__, dwValue); ++ WriteReg(state, 0x58, (u8) ((dwValue >> 24) & 0xff)); ++ WriteReg(state, 0x57, (u8) ((dwValue >> 16) & 0xff)); ++ WriteReg(state, 0x56, (u8) ((dwValue >> 8) & 0xff)); ++ WriteReg(state, 0x55, (u8) ((dwValue >> 0) & 0xff)); ++ ++ /* fValue = 2048 * xtal / sym; */ ++ fValue = 2048 * xtal; ++ do_div(fValue, sym); ++ dwValue = (u32) fValue; ++ printk(KERN_INFO "%s, fvalue2=%x\n", __func__, dwValue); ++ WriteReg(state, 0x5D, (u8) ((dwValue >> 8) & 0xff)); ++ WriteReg(state, 0x5C, (u8) ((dwValue >> 0) & 0xff)); ++ value = ReadReg(state, 0x5A); ++ if (((dwValue >> 16) & 0x0001) == 0) ++ value &= 0x7F; ++ else ++ value |= 0x80; ++ WriteReg(state, 0x5A, value); ++ value = ReadReg(state, 0x89); ++ if (sym <= 1800) ++ value |= 0x01; ++ else ++ value &= 0xFE; ++ WriteReg(state, 0x89, value); ++ if (sym >= 6700) { ++ reg6FH = 0x0D; ++ reg12H = 0x30; ++ } else if (sym >= 4000) { ++ fValue = 22 * 4096 / sym; ++ reg6FH = (u8) fValue; ++ reg12H = 0x30; ++ } else if (sym >= 2000) { ++ fValue = 14 * 4096 / sym; ++ reg6FH = (u8) fValue; ++ reg12H = 0x20; ++ } else { ++ fValue = 7 * 4096 / sym; ++ reg6FH = (u8) fValue; ++ reg12H = 0x10; ++ } ++ WriteReg(state, 0x6F, reg6FH); ++ WriteReg(state, 0x12, reg12H); ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ if (sym < 3000) { ++ WriteReg(state, 0x6C, 0x16); ++ WriteReg(state, 0x6D, 0x10); ++ WriteReg(state, 0x6E, 0x18); ++ } else { ++ WriteReg(state, 0x6C, 0x14); ++ WriteReg(state, 0x6D, 0x0E); ++ WriteReg(state, 0x6E, 0x36); ++ } ++ } else { ++ WriteReg(state, 0x6C, 0x16); ++ WriteReg(state, 0x6D, 0x10); ++ WriteReg(state, 0x6E, 0x18); ++ } ++ return 0; ++} ++ ++static int M88DC2000SetQAM(struct m88dc2800_state *state, u16 qam) ++{ ++ u8 reg00H, reg4AH, regC2H, reg44H, reg4CH, reg4DH, reg74H, value; ++ u8 reg8BH, reg8EH; ++ printk(KERN_INFO "%s, qam=%d\n", __func__, qam); ++ regC2H = ReadReg(state, 0xC2); ++ regC2H &= 0xF8; ++ switch (qam) { ++ case 16: /* 16 QAM */ ++ reg00H = 0x08; ++ reg4AH = 0x0F; ++ regC2H |= 0x02; ++ reg44H = 0xAA; ++ reg4CH = 0x0C; ++ reg4DH = 0xF7; ++ reg74H = 0x0E; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ reg8BH = 0x5A; ++ reg8EH = 0xBD; ++ } else { ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ } ++ WriteReg(state, 0x6E, 0x18); ++ break; ++ case 32: /* 32 QAM */ ++ reg00H = 0x18; ++ reg4AH = 0xFB; ++ regC2H |= 0x02; ++ reg44H = 0xAA; ++ reg4CH = 0x0C; ++ reg4DH = 0xF7; ++ reg74H = 0x0E; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ reg8BH = 0x5A; ++ reg8EH = 0xBD; ++ } else { ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ } ++ WriteReg(state, 0x6E, 0x18); ++ break; ++ case 64: /* 64 QAM */ ++ reg00H = 0x48; ++ reg4AH = 0xCD; ++ regC2H |= 0x02; ++ reg44H = 0xAA; ++ reg4CH = 0x0C; ++ reg4DH = 0xF7; ++ reg74H = 0x0E; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ reg8BH = 0x5A; ++ reg8EH = 0xBD; ++ } else { ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ } ++ break; ++ case 128: /* 128 QAM */ ++ reg00H = 0x28; ++ reg4AH = 0xFF; ++ regC2H |= 0x02; ++ reg44H = 0xA9; ++ reg4CH = 0x08; ++ reg4DH = 0xF5; ++ reg74H = 0x0E; ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ break; ++ case 256: /* 256 QAM */ ++ reg00H = 0x38; ++ reg4AH = 0xCD; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ regC2H |= 0x02; ++ } else { ++ regC2H |= 0x01; ++ } ++ reg44H = 0xA9; ++ reg4CH = 0x08; ++ reg4DH = 0xF5; ++ reg74H = 0x0E; ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ break; ++ default: /* 64 QAM */ ++ reg00H = 0x48; ++ reg4AH = 0xCD; ++ regC2H |= 0x02; ++ reg44H = 0xAA; ++ reg4CH = 0x0C; ++ reg4DH = 0xF7; ++ reg74H = 0x0E; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ reg8BH = 0x5A; ++ reg8EH = 0xBD; ++ } else { ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ } ++ break; ++ } ++ WriteReg(state, 0x00, reg00H); ++ value = ReadReg(state, 0x88); ++ value |= 0x08; ++ WriteReg(state, 0x88, value); ++ WriteReg(state, 0x4B, 0xFF); ++ WriteReg(state, 0x4A, reg4AH); ++ value &= 0xF7; ++ WriteReg(state, 0x88, value); ++ WriteReg(state, 0xC2, regC2H); ++ WriteReg(state, 0x44, reg44H); ++ WriteReg(state, 0x4C, reg4CH); ++ WriteReg(state, 0x4D, reg4DH); ++ WriteReg(state, 0x74, reg74H); ++ WriteReg(state, 0x8B, reg8BH); ++ WriteReg(state, 0x8E, reg8EH); ++ return 0; ++} ++ ++static int M88DC2000WriteTuner_TC2800(struct m88dc2800_state *state, ++ u32 freq_KHz) ++{ ++ printk(KERN_INFO "%s, freq=%d KHz\n", __func__, freq_KHz); ++ return mt_fe_tn_set_freq_tc2800(state, freq_KHz); ++} ++ ++static int m88dc2800_init(struct dvb_frontend *fe) ++{ ++ dprintk("%s()\n", __func__); ++ return 0; ++} ++ ++static int m88dc2800_set_parameters(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u8 is_annex_c, is_update; ++ u16 temp_qam; ++ s32 waiting_time; ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ ++ is_annex_c = c->delivery_system == SYS_DVBC_ANNEX_C ? 1 : 0; ++ ++ switch (c->modulation) { ++ case QAM_16: ++ temp_qam = 16; ++ break; ++ case QAM_32: ++ temp_qam = 32; ++ break; ++ case QAM_128: ++ temp_qam = 128; ++ break; ++ case QAM_256: ++ temp_qam = 256; ++ break; ++ default: /* QAM_64 */ ++ temp_qam = 64; ++ break; ++ } ++ ++ state->inverted = c->inversion == INVERSION_ON ? 1 : 0; ++ ++ printk(KERN_INFO ++ "m88dc2800: state, freq=%d qam=%d sym=%d inverted=%d xtal=%d\n", ++ state->freq, state->qam, state->sym, state->inverted, ++ state->xtal); ++ printk(KERN_INFO ++ "m88dc2800: set frequency to %d qam=%d symrate=%d annex-c=%d\n", ++ c->frequency, temp_qam, c->symbol_rate, is_annex_c); ++ ++ is_update = 0; ++ WriteReg(state, 0x80, 0x01); ++ if (c->frequency != state->freq) { ++ M88DC2000WriteTuner_TC2800(state, c->frequency / 1000); ++ state->freq = c->frequency; ++ } ++ if (c->symbol_rate != state->sym) { ++ M88DC2000SetSym(state, c->symbol_rate / 1000, state->xtal); ++ state->sym = c->symbol_rate; ++ is_update = 1; ++ } ++ if (temp_qam != state->qam) { ++ M88DC2000SetQAM(state, temp_qam); ++ state->qam = temp_qam; ++ is_update = 1; ++ } ++ ++ if (is_update != 0) { ++ if (state->config->ts_mode == 3) ++ M88DC2000AutoTSClock_C(state, state->sym / 1000, ++ temp_qam); ++ else ++ M88DC2000AutoTSClock_P(state, state->sym / 1000, ++ temp_qam); ++ } ++ ++ M88DC2000SetTxMode(state, state->inverted, is_annex_c); ++ M88DC2000SoftReset(state); ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) ++ waiting_time = 800; ++ else ++ waiting_time = 500; ++ while (waiting_time > 0) { ++ msleep(50); ++ waiting_time -= 50; ++ if (M88DC2000GetLock(state)) ++ return 0; ++ } ++ ++ state->inverted = (state->inverted != 0) ? 0 : 1; ++ M88DC2000SetTxMode(state, state->inverted, is_annex_c); ++ M88DC2000SoftReset(state); ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) && ++ ((ReadReg(state, 0xE4) & 0x80) == 0x80)) ++ waiting_time = 800; ++ else ++ waiting_time = 500; ++ while (waiting_time > 0) { ++ msleep(50); ++ waiting_time -= 50; ++ if (M88DC2000GetLock(state)) ++ return 0; ++ } ++ return 0; ++} ++ ++static int m88dc2800_read_status(struct dvb_frontend *fe, ++ fe_status_t * status) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ *status = 0; ++ ++ if (M88DC2000GetLock(state)) { ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER ++ |FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK; ++ } ++ return 0; ++} ++ ++static int m88dc2800_read_ber(struct dvb_frontend *fe, u32 * ber) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ u16 tmp; ++ ++ if (M88DC2000GetLock(state) == 0) { ++ state->ber = 0; ++ } else if ((ReadReg(state, 0xA0) & 0x80) != 0x80) { ++ tmp = ReadReg(state, 0xA2) << 8; ++ tmp += ReadReg(state, 0xA1); ++ state->ber = tmp; ++ WriteReg(state, 0xA0, 0x05); ++ WriteReg(state, 0xA0, 0x85); ++ } ++ *ber = state->ber; ++ return 0; ++} ++ ++static int m88dc2800_read_signal_strength(struct dvb_frontend *fe, ++ u16 * strength) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ s16 tuner_strength; ++ ++ tuner_strength = mt_fe_tn_get_signal_strength_tc2800(state); ++ *strength = tuner_strength < -107 ? 0 : tuner_strength + 107; ++ ++ return 0; ++} ++ ++static int m88dc2800_read_snr(struct dvb_frontend *fe, u16 * snr) ++{ ++ static const u32 mes_log[] = { ++ 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000, ++ 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788, ++ 13010, 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472, ++ 14624, 14771, 14914, 15052, 15185, 15315, 15441, 15563, 15682, ++ 15798, 15911, 16021, 16128, 16232, 16335, 16435, 16532, 16628, ++ 16721, 16812, 16902, 16990, 17076, 17160, 17243, 17324, 17404, ++ 17482, 17559, 17634, 17709, 17782, 17853, 17924, 17993, 18062, ++ 18129, 18195, 18261, 18325, 18388, 18451, 18513, 18573, 18633, ++ 18692, 18751, 18808, 18865, 18921, 18976, 19031 ++ }; ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ u8 i; ++ u32 _snr, mse; ++ ++ if ((ReadReg(state, 0x91) & 0x23) != 0x03) { ++ *snr = 0; ++ return 0; ++ } ++ mse = 0; ++ for (i = 0; i < 30; i++) { ++ mse += (ReadReg(state, 0x08) << 8) + ReadReg(state, 0x07); ++ } ++ mse /= 30; ++ if (mse > 80) ++ mse = 80; ++ switch (state->qam) { ++ case 16: ++ _snr = 34080; ++ break; /* 16QAM */ ++ case 32: ++ _snr = 37600; ++ break; /* 32QAM */ ++ case 64: ++ _snr = 40310; ++ break; /* 64QAM */ ++ case 128: ++ _snr = 43720; ++ break; /* 128QAM */ ++ case 256: ++ _snr = 46390; ++ break; /* 256QAM */ ++ default: ++ _snr = 40310; ++ break; ++ } ++ _snr -= mes_log[mse - 1]; /* C - 10*log10(MSE) */ ++ _snr /= 1000; ++ if (_snr > 0xff) ++ _snr = 0xff; ++ *snr = _snr; ++ return 0; ++} ++ ++static int m88dc2800_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ u8 u8Value; ++ ++ u8Value = ReadReg(state, 0xdf); ++ u8Value |= 0x02; /* Hold */ ++ WriteReg(state, 0xdf, u8Value); ++ ++ *ucblocks = ReadReg(state, 0xd5); ++ *ucblocks = (*ucblocks << 8) | ReadReg(state, 0xd4); ++ ++ u8Value &= 0xfe; /* Clear */ ++ WriteReg(state, 0xdf, u8Value); ++ u8Value &= 0xfc; /* Update */ ++ u8Value |= 0x01; ++ WriteReg(state, 0xdf, u8Value); ++ ++ return 0; ++} ++ ++static int m88dc2800_sleep(struct dvb_frontend *fe) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ ++ mt_fe_tn_sleep_tc2800(state); ++ state->freq = 0; ++ ++ return 0; ++} ++ ++static void m88dc2800_release(struct dvb_frontend *fe) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ kfree(state); ++} ++ ++static struct dvb_frontend_ops m88dc2800_ops; ++ ++struct dvb_frontend *m88dc2800_attach(const struct m88dc2800_config ++ *config, struct i2c_adapter *i2c) ++{ ++ struct m88dc2800_state *state = NULL; ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct m88dc2800_state), GFP_KERNEL); ++ if (state == NULL) ++ goto error; ++ ++ /* setup the state */ ++ state->config = config; ++ state->i2c = i2c; ++ state->xtal = 28800; ++ ++ WriteReg(state, 0x80, 0x01); ++ M88DC2000RegInitial_TC2800(state); ++ M88DC2000SetTsType(state, state->config->ts_mode); ++ mt_fe_tn_init_tc2800(state); ++ ++ /* create dvb_frontend */ ++ memcpy(&state->frontend.ops, &m88dc2800_ops, ++ sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ return &state->frontend; ++ ++ error: ++ kfree(state); ++ return NULL; ++} ++ ++EXPORT_SYMBOL(m88dc2800_attach); ++ ++static struct dvb_frontend_ops m88dc2800_ops = { ++ .delsys = {SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C}, ++ .info = { ++ .name = "Montage M88DC2800 DVB-C", ++ .frequency_stepsize = 62500, ++ .frequency_min = 48000000, ++ .frequency_max = 870000000, ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 9000000, ++ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO ++ }, ++ .release = m88dc2800_release, ++ .init = m88dc2800_init, ++ .sleep = m88dc2800_sleep, ++ .set_frontend = m88dc2800_set_parameters, ++ .read_status = m88dc2800_read_status, ++ .read_ber = m88dc2800_read_ber, ++ .read_signal_strength = m88dc2800_read_signal_strength, ++ .read_snr = m88dc2800_read_snr, ++ .read_ucblocks = m88dc2800_read_ucblocks, ++}; ++ ++MODULE_DESCRIPTION("Montage DVB-C demodulator driver"); ++MODULE_AUTHOR("Max Nibble "); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.00"); +diff -urN a/drivers/media/dvb-frontends/m88dc2800.h b/drivers/media/dvb-frontends/m88dc2800.h +--- a/drivers/media/dvb-frontends/m88dc2800.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88dc2800.h 2013-01-26 14:57:32.000000000 +0800 +@@ -0,0 +1,43 @@ ++/* ++ M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage ++ ++ Copyright (C) 2012 Max Nibble ++ Copyright (C) 2011 Montage Technology - www.montage-tech.com ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef M88DC2800_H ++#define M88DC2800_H ++ ++#include ++ ++struct m88dc2800_config { ++ u8 demod_address; ++ u8 ts_mode; ++}; ++ ++#if defined(CONFIG_DVB_M88DC2800) || (defined(CONFIG_DVB_M88DC2800_MODULE) && defined(MODULE)) ++extern struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config, ++ struct i2c_adapter* i2c); ++#else ++static inline struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config, ++ struct i2c_adapter* i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_M88DC2800 */ ++#endif /* M88DC2800_H */ +diff -urN a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c +--- a/drivers/media/dvb-frontends/m88ds3103.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88ds3103.c 2013-01-30 12:33:47.000000000 +0800 +@@ -0,0 +1,1710 @@ ++/* ++ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver ++ ++ Copyright (C) 2011 Max nibble ++ Copyright (C) 2010 Montage Technology ++ Copyright (C) 2009 Konstantin Dimitrov. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "m88ds3103.h" ++#include "m88ds3103_priv.h" ++ ++static int debug; ++module_param(debug, int, 0644); ++MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); ++ ++#define dprintk(args...) \ ++ do { \ ++ if (debug) \ ++ printk(KERN_INFO "m88ds3103: " args); \ ++ } while (0) ++ ++/*demod register operations.*/ ++static int m88ds3103_writereg(struct m88ds3103_state *state, int reg, int data) ++{ ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { .addr = state->config->demod_address, ++ .flags = 0, .buf = buf, .len = 2 }; ++ int err; ++ ++ if (debug > 1) ++ printk("m88ds3103: %s: write reg 0x%02x, value 0x%02x\n", ++ __func__, reg, data); ++ ++ err = i2c_transfer(state->i2c, &msg, 1); ++ if (err != 1) { ++ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x," ++ " value == 0x%02x)\n", __func__, err, reg, data); ++ return -EREMOTEIO; ++ } ++ return 0; ++} ++ ++static int m88ds3103_readreg(struct m88ds3103_state *state, u8 reg) ++{ ++ int ret; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ struct i2c_msg msg[] = { ++ { .addr = state->config->demod_address, .flags = 0, ++ .buf = b0, .len = 1 }, ++ { .addr = state->config->demod_address, .flags = I2C_M_RD, ++ .buf = b1, .len = 1 } ++ }; ++ ret = i2c_transfer(state->i2c, msg, 2); ++ ++ if (ret != 2) { ++ printk(KERN_ERR "%s: reg=0x%x (error=%d)\n", ++ __func__, reg, ret); ++ return ret; ++ } ++ ++ if (debug > 1) ++ printk(KERN_INFO "m88ds3103: read reg 0x%02x, value 0x%02x\n", ++ reg, b1[0]); ++ ++ return b1[0]; ++} ++ ++/*tuner register operations.*/ ++static int m88ds3103_tuner_writereg(struct m88ds3103_state *state, int reg, int data) ++{ ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { .addr = 0x60, ++ .flags = 0, .buf = buf, .len = 2 }; ++ int err; ++ ++ m88ds3103_writereg(state, 0x03, 0x11); ++ err = i2c_transfer(state->i2c, &msg, 1); ++ ++ if (err != 1) { ++ printk("%s: writereg error(err == %i, reg == 0x%02x," ++ " value == 0x%02x)\n", __func__, err, reg, data); ++ return -EREMOTEIO; ++ } ++ ++ return 0; ++} ++ ++static int m88ds3103_tuner_readreg(struct m88ds3103_state *state, u8 reg) ++{ ++ int ret; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ struct i2c_msg msg[] = { ++ { .addr = 0x60, .flags = 0, ++ .buf = b0, .len = 1 }, ++ { .addr = 0x60, .flags = I2C_M_RD, ++ .buf = b1, .len = 1 } ++ }; ++ ++ m88ds3103_writereg(state, 0x03, 0x11); ++ ret = i2c_transfer(state->i2c, msg, 2); ++ ++ if (ret != 2) { ++ printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret); ++ return ret; ++ } ++ ++ return b1[0]; ++} ++ ++/* Bulk demod I2C write, for firmware download. */ ++static int m88ds3103_writeregN(struct m88ds3103_state *state, int reg, ++ const u8 *data, u16 len) ++{ ++ int ret = -EREMOTEIO; ++ struct i2c_msg msg; ++ u8 *buf; ++ ++ buf = kmalloc(len + 1, GFP_KERNEL); ++ if (buf == NULL) { ++ printk("Unable to kmalloc\n"); ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ *(buf) = reg; ++ memcpy(buf + 1, data, len); ++ ++ msg.addr = state->config->demod_address; ++ msg.flags = 0; ++ msg.buf = buf; ++ msg.len = len + 1; ++ ++ if (debug > 1) ++ printk(KERN_INFO "m88ds3103: %s: write regN 0x%02x, len = %d\n", ++ __func__, reg, len); ++ ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ if (ret != 1) { ++ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n", ++ __func__, ret, reg); ++ ret = -EREMOTEIO; ++ } ++ ++error: ++ kfree(buf); ++ ++ return ret; ++} ++ ++static int m88ds3103_load_firmware(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ const struct firmware *fw; ++ int i, ret = 0; ++ ++ dprintk("%s()\n", __func__); ++ ++ if (state->skip_fw_load) ++ return 0; ++ /* Load firmware */ ++ /* request the firmware, this will block until someone uploads it */ ++ if(state->demod_id == DS3000_ID){ ++ printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, ++ DS3000_DEFAULT_FIRMWARE); ++ ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE, ++ state->i2c->dev.parent); ++ }else if(state->demod_id == DS3103_ID){ ++ printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, ++ DS3103_DEFAULT_FIRMWARE); ++ ret = request_firmware(&fw, DS3103_DEFAULT_FIRMWARE, ++ state->i2c->dev.parent); ++ } ++ ++ printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); ++ if (ret) { ++ printk(KERN_ERR "%s: No firmware uploaded (timeout or file not " ++ "found?)\n", __func__); ++ return ret; ++ } ++ ++ /* Make sure we don't recurse back through here during loading */ ++ state->skip_fw_load = 1; ++ ++ dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n", ++ fw->size, ++ fw->data[0], ++ fw->data[1], ++ fw->data[fw->size - 2], ++ fw->data[fw->size - 1]); ++ ++ /* stop internal mcu. */ ++ m88ds3103_writereg(state, 0xb2, 0x01); ++ /* split firmware to download.*/ ++ for(i = 0; i < FW_DOWN_LOOP; i++){ ++ ret = m88ds3103_writeregN(state, 0xb0, &(fw->data[FW_DOWN_SIZE*i]), FW_DOWN_SIZE); ++ if(ret != 1) break; ++ } ++ /* start internal mcu. */ ++ if(ret == 1) ++ m88ds3103_writereg(state, 0xb2, 0x00); ++ ++ release_firmware(fw); ++ ++ dprintk("%s: Firmware upload %s\n", __func__, ++ ret == 1 ? "complete" : "failed"); ++ ++ if(ret == 1) ret = 0; ++ ++ /* Ensure firmware is always loaded if required */ ++ state->skip_fw_load = 0; ++ ++ return ret; ++} ++ ++ ++static int m88ds3103_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 data; ++ ++ dprintk("%s(%d)\n", __func__, voltage); ++ ++ dprintk("m88ds3103:pin_ctrl = (%02x)\n", state->config->pin_ctrl); ++ ++ if(state->config->set_voltage) ++ state->config->set_voltage(fe, voltage); ++ ++ data = m88ds3103_readreg(state, 0xa2); ++ ++ if(state->config->pin_ctrl & 0x80){ /*If control pin is assigned.*/ ++ data &= ~0x03; /* bit0 V/H, bit1 off/on */ ++ if(state->config->pin_ctrl & 0x02) ++ data |= 0x02; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_18: ++ if((state->config->pin_ctrl & 0x01) == 0) ++ data |= 0x01; ++ break; ++ case SEC_VOLTAGE_13: ++ if(state->config->pin_ctrl & 0x01) ++ data |= 0x01; ++ break; ++ case SEC_VOLTAGE_OFF: ++ if(state->config->pin_ctrl & 0x02) ++ data &= ~0x02; ++ else ++ data |= 0x02; ++ break; ++ } ++ } ++ ++ m88ds3103_writereg(state, 0xa2, data); ++ ++ return 0; ++} ++ ++static int m88ds3103_read_status(struct dvb_frontend *fe, fe_status_t* status) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ int lock = 0; ++ ++ *status = 0; ++ ++ switch (state->delivery_system){ ++ case SYS_DVBS: ++ lock = m88ds3103_readreg(state, 0xd1); ++ dprintk("%s: SYS_DVBS status=%x.\n", __func__, lock); ++ ++ if ((lock & 0x07) == 0x07){ ++ /*if((m88ds3103_readreg(state, 0x0d) & 0x07) == 0x07)*/ ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER ++ | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ ++ } ++ break; ++ case SYS_DVBS2: ++ lock = m88ds3103_readreg(state, 0x0d); ++ dprintk("%s: SYS_DVBS2 status=%x.\n", __func__, lock); ++ ++ if ((lock & 0x8f) == 0x8f) ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER ++ | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int m88ds3103_read_ber(struct dvb_frontend *fe, u32* ber) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 tmp1, tmp2, tmp3; ++ u32 ldpc_frame_cnt, pre_err_packags, code_rate_fac = 0; ++ ++ dprintk("%s()\n", __func__); ++ ++ switch (state->delivery_system) { ++ case SYS_DVBS: ++ m88ds3103_writereg(state, 0xf9, 0x04); ++ tmp3 = m88ds3103_readreg(state, 0xf8); ++ if ((tmp3&0x10) == 0){ ++ tmp1 = m88ds3103_readreg(state, 0xf7); ++ tmp2 = m88ds3103_readreg(state, 0xf6); ++ tmp3 |= 0x10; ++ m88ds3103_writereg(state, 0xf8, tmp3); ++ state->preBer = (tmp1<<8) | tmp2; ++ } ++ break; ++ case SYS_DVBS2: ++ tmp1 = m88ds3103_readreg(state, 0x7e) & 0x0f; ++ switch(tmp1){ ++ case 0: code_rate_fac = 16008 - 80; break; ++ case 1: code_rate_fac = 21408 - 80; break; ++ case 2: code_rate_fac = 25728 - 80; break; ++ case 3: code_rate_fac = 32208 - 80; break; ++ case 4: code_rate_fac = 38688 - 80; break; ++ case 5: code_rate_fac = 43040 - 80; break; ++ case 6: code_rate_fac = 48408 - 80; break; ++ case 7: code_rate_fac = 51648 - 80; break; ++ case 8: code_rate_fac = 53840 - 80; break; ++ case 9: code_rate_fac = 57472 - 80; break; ++ case 10: code_rate_fac = 58192 - 80; break; ++ } ++ ++ tmp1 = m88ds3103_readreg(state, 0xd7) & 0xff; ++ tmp2 = m88ds3103_readreg(state, 0xd6) & 0xff; ++ tmp3 = m88ds3103_readreg(state, 0xd5) & 0xff; ++ ldpc_frame_cnt = (tmp1 << 16) | (tmp2 << 8) | tmp3; ++ ++ tmp1 = m88ds3103_readreg(state, 0xf8) & 0xff; ++ tmp2 = m88ds3103_readreg(state, 0xf7) & 0xff; ++ pre_err_packags = tmp1<<8 | tmp2; ++ ++ if (ldpc_frame_cnt > 1000){ ++ m88ds3103_writereg(state, 0xd1, 0x01); ++ m88ds3103_writereg(state, 0xf9, 0x01); ++ m88ds3103_writereg(state, 0xf9, 0x00); ++ m88ds3103_writereg(state, 0xd1, 0x00); ++ state->preBer = pre_err_packags; ++ } ++ break; ++ default: ++ break; ++ } ++ *ber = state->preBer; ++ ++ return 0; ++} ++ ++static int m88ds3103_read_signal_strength(struct dvb_frontend *fe, ++ u16 *signal_strength) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u16 gain; ++ u8 gain1, gain2, gain3 = 0; ++ ++ dprintk("%s()\n", __func__); ++ ++ gain1 = m88ds3103_tuner_readreg(state, 0x3d) & 0x1f; ++ dprintk("%s: gain1 = 0x%02x \n", __func__, gain1); ++ ++ if (gain1 > 15) gain1 = 15; ++ gain2 = m88ds3103_tuner_readreg(state, 0x21) & 0x1f; ++ dprintk("%s: gain2 = 0x%02x \n", __func__, gain2); ++ ++ if(state->tuner_id == TS2022_ID){ ++ gain3 = (m88ds3103_tuner_readreg(state, 0x66)>>3) & 0x07; ++ dprintk("%s: gain3 = 0x%02x \n", __func__, gain3); ++ ++ if (gain2 > 16) gain2 = 16; ++ if (gain2 < 2) gain2 = 2; ++ if (gain3 > 6) gain3 = 6; ++ }else{ ++ if (gain2 > 13) gain2 = 13; ++ gain3 = 0; ++ } ++ ++ gain = gain1*23 + gain2*35 + gain3*29; ++ *signal_strength = 60000 - gain*55; ++ ++ return 0; ++} ++ ++ ++static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *p_snr) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 val, npow1, npow2, spow1, cnt; ++ u16 tmp, snr; ++ u32 npow, spow, snr_total; ++ static const u16 mes_log10[] ={ ++ 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000, ++ 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788, 13010, ++ 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472, 14624, 14771, ++ 14914, 15052, 15185, 15315, 15441, 15563, 15682, 15798, 15911, 16021, ++ 16128, 16232, 16335, 16435, 16532, 16628, 16721, 16812, 16902, 16990, ++ 17076, 17160, 17243, 17324, 17404, 17482, 17559, 17634, 17709, 17782, ++ 17853, 17924, 17993, 18062, 18129, 18195, 18261, 18325, 18388, 18451, ++ 18513, 18573, 18633, 18692, 18751, 18808, 18865, 18921, 18976, 19031 ++ }; ++ static const u16 mes_loge[] ={ ++ 0, 6931, 10986, 13863, 16094, 17918, 19459, 20794, 21972, 23026, ++ 23979, 24849, 25649, 26391, 27081, 27726, 28332, 28904, 29444, 29957, ++ 30445, 30910, 31355, 31781, 32189, 32581, 32958, 33322, 33673, 34012, ++ 34340, 34657, ++ }; ++ ++ dprintk("%s()\n", __func__); ++ ++ snr = 0; ++ ++ switch (state->delivery_system){ ++ case SYS_DVBS: ++ cnt = 10; snr_total = 0; ++ while(cnt > 0){ ++ val = m88ds3103_readreg(state, 0xff); ++ snr_total += val; ++ cnt--; ++ } ++ tmp = (u16)(snr_total/80); ++ if(tmp > 0){ ++ if (tmp > 32) tmp = 32; ++ snr = (mes_loge[tmp - 1] * 100) / 45; ++ }else{ ++ snr = 0; ++ } ++ break; ++ case SYS_DVBS2: ++ cnt = 10; npow = 0; spow = 0; ++ while(cnt >0){ ++ npow1 = m88ds3103_readreg(state, 0x8c) & 0xff; ++ npow2 = m88ds3103_readreg(state, 0x8d) & 0xff; ++ npow += (((npow1 & 0x3f) + (u16)(npow2 << 6)) >> 2); ++ ++ spow1 = m88ds3103_readreg(state, 0x8e) & 0xff; ++ spow += ((spow1 * spow1) >> 1); ++ cnt--; ++ } ++ npow /= 10; spow /= 10; ++ if(spow == 0){ ++ snr = 0; ++ }else if(npow == 0){ ++ snr = 19; ++ }else{ ++ if(spow > npow){ ++ tmp = (u16)(spow / npow); ++ if (tmp > 80) tmp = 80; ++ snr = mes_log10[tmp - 1]*3; ++ }else{ ++ tmp = (u16)(npow / spow); ++ if (tmp > 80) tmp = 80; ++ snr = -(mes_log10[tmp - 1] / 1000); ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ *p_snr = snr; ++ ++ return 0; ++} ++ ++ ++static int m88ds3103_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 tmp1, tmp2, tmp3, data; ++ ++ dprintk("%s()\n", __func__); ++ ++ switch (state->delivery_system) { ++ case SYS_DVBS: ++ data = m88ds3103_readreg(state, 0xf8); ++ data |= 0x40; ++ m88ds3103_writereg(state, 0xf8, data); ++ tmp1 = m88ds3103_readreg(state, 0xf5); ++ tmp2 = m88ds3103_readreg(state, 0xf4); ++ *ucblocks = (tmp1 <<8) | tmp2; ++ data &= ~0x20; ++ m88ds3103_writereg(state, 0xf8, data); ++ data |= 0x20; ++ m88ds3103_writereg(state, 0xf8, data); ++ data &= ~0x40; ++ m88ds3103_writereg(state, 0xf8, data); ++ break; ++ case SYS_DVBS2: ++ tmp1 = m88ds3103_readreg(state, 0xda); ++ tmp2 = m88ds3103_readreg(state, 0xd9); ++ tmp3 = m88ds3103_readreg(state, 0xd8); ++ *ucblocks = (tmp1 <<16)|(tmp2 <<8)|tmp3; ++ data = m88ds3103_readreg(state, 0xd1); ++ data |= 0x01; ++ m88ds3103_writereg(state, 0xd1, data); ++ data &= ~0x01; ++ m88ds3103_writereg(state, 0xd1, data); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static int m88ds3103_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 data_a1, data_a2; ++ ++ dprintk("%s(%d)\n", __func__, tone); ++ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { ++ printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone); ++ return -EINVAL; ++ } ++ ++ data_a1 = m88ds3103_readreg(state, 0xa1); ++ data_a2 = m88ds3103_readreg(state, 0xa2); ++ if(state->demod_id == DS3103_ID) ++ data_a2 &= 0xdf; /* Normal mode */ ++ switch (tone) { ++ case SEC_TONE_ON: ++ dprintk("%s: SEC_TONE_ON\n", __func__); ++ data_a1 |= 0x04; ++ data_a1 &= ~0x03; ++ data_a1 &= ~0x40; ++ data_a2 &= ~0xc0; ++ break; ++ case SEC_TONE_OFF: ++ dprintk("%s: SEC_TONE_OFF\n", __func__); ++ data_a2 &= ~0xc0; ++ data_a2 |= 0x80; ++ break; ++ } ++ m88ds3103_writereg(state, 0xa2, data_a2); ++ m88ds3103_writereg(state, 0xa1, data_a1); ++ return 0; ++} ++ ++static int m88ds3103_send_diseqc_msg(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *d) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ int i, ret = 0; ++ u8 tmp, time_out; ++ ++ /* Dump DiSEqC message */ ++ if (debug) { ++ printk(KERN_INFO "m88ds3103: %s(", __func__); ++ for (i = 0 ; i < d->msg_len ;) { ++ printk(KERN_INFO "0x%02x", d->msg[i]); ++ if (++i < d->msg_len) ++ printk(KERN_INFO ", "); ++ } ++ } ++ ++ tmp = m88ds3103_readreg(state, 0xa2); ++ tmp &= ~0xc0; ++ if(state->demod_id == DS3103_ID) ++ tmp &= ~0x20; ++ m88ds3103_writereg(state, 0xa2, tmp); ++ ++ for (i = 0; i < d->msg_len; i ++) ++ m88ds3103_writereg(state, (0xa3+i), d->msg[i]); ++ ++ tmp = m88ds3103_readreg(state, 0xa1); ++ tmp &= ~0x38; ++ tmp &= ~0x40; ++ tmp |= ((d->msg_len-1) << 3) | 0x07; ++ tmp &= ~0x80; ++ m88ds3103_writereg(state, 0xa1, tmp); ++ /* 1.5 * 9 * 8 = 108ms */ ++ time_out = 150; ++ while (time_out > 0){ ++ msleep(10); ++ time_out -= 10; ++ tmp = m88ds3103_readreg(state, 0xa1); ++ if ((tmp & 0x40) == 0) ++ break; ++ } ++ if (time_out == 0){ ++ tmp = m88ds3103_readreg(state, 0xa1); ++ tmp &= ~0x80; ++ tmp |= 0x40; ++ m88ds3103_writereg(state, 0xa1, tmp); ++ ret = 1; ++ } ++ tmp = m88ds3103_readreg(state, 0xa2); ++ tmp &= ~0xc0; ++ tmp |= 0x80; ++ m88ds3103_writereg(state, 0xa2, tmp); ++ return ret; ++} ++ ++ ++static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, ++ fe_sec_mini_cmd_t burst) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 val, time_out; ++ ++ dprintk("%s()\n", __func__); ++ ++ val = m88ds3103_readreg(state, 0xa2); ++ val &= ~0xc0; ++ if(state->demod_id == DS3103_ID) ++ val &= 0xdf; /* Normal mode */ ++ m88ds3103_writereg(state, 0xa2, val); ++ /* DiSEqC burst */ ++ if (burst == SEC_MINI_B) ++ m88ds3103_writereg(state, 0xa1, 0x01); ++ else ++ m88ds3103_writereg(state, 0xa1, 0x02); ++ ++ msleep(13); ++ ++ time_out = 5; ++ do{ ++ val = m88ds3103_readreg(state, 0xa1); ++ if ((val & 0x40) == 0) ++ break; ++ msleep(1); ++ time_out --; ++ } while (time_out > 0); ++ ++ val = m88ds3103_readreg(state, 0xa2); ++ val &= ~0xc0; ++ val |= 0x80; ++ m88ds3103_writereg(state, 0xa2, val); ++ ++ return 0; ++} ++ ++static void m88ds3103_release(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ ++ dprintk("%s\n", __func__); ++ kfree(state); ++} ++ ++static int m88ds3103_check_id(struct m88ds3103_state *state) ++{ ++ int val_00, val_01; ++ ++ /*check demod id*/ ++ val_01 = m88ds3103_readreg(state, 0x01); ++ printk(KERN_INFO "DS3000 chip version: %x attached.\n", val_01); ++ ++ if(val_01 == 0xD0) ++ state->demod_id = DS3103_ID; ++ else if(val_01 == 0xC0) ++ state->demod_id = DS3000_ID; ++ else ++ state->demod_id = UNKNOW_ID; ++ ++ /*check tuner id*/ ++ val_00 = m88ds3103_tuner_readreg(state, 0x00); ++ printk(KERN_INFO "TS202x chip version[1]: %x attached.\n", val_00); ++ val_00 &= 0x03; ++ if(val_00 == 0) ++ { ++ m88ds3103_tuner_writereg(state, 0x00, 0x01); ++ msleep(3); ++ } ++ m88ds3103_tuner_writereg(state, 0x00, 0x03); ++ msleep(5); ++ ++ val_00 = m88ds3103_tuner_readreg(state, 0x00); ++ printk(KERN_INFO "TS202x chip version[2]: %x attached.\n", val_00); ++ val_00 &= 0xff; ++ if((val_00 == 0x01) || (val_00 == 0x41) || (val_00 == 0x81)) ++ state->tuner_id = TS2020_ID; ++ else if(((val_00 & 0xc0)== 0xc0) || (val_00 == 0x83)) ++ state->tuner_id = TS2022_ID; ++ else ++ state->tuner_id = UNKNOW_ID; ++ ++ return state->demod_id; ++} ++ ++static struct dvb_frontend_ops m88ds3103_ops; ++static int m88ds3103_initilaze(struct dvb_frontend *fe); ++ ++struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *config, ++ struct i2c_adapter *i2c) ++{ ++ struct m88ds3103_state *state = NULL; ++ ++ dprintk("%s\n", __func__); ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct m88ds3103_state), GFP_KERNEL); ++ if (state == NULL) { ++ printk(KERN_ERR "Unable to kmalloc\n"); ++ goto error2; ++ } ++ ++ state->config = config; ++ state->i2c = i2c; ++ state->preBer = 0xffff; ++ state->delivery_system = SYS_DVBS; /*Default to DVB-S.*/ ++ ++ /* check demod id */ ++ if(m88ds3103_check_id(state) == UNKNOW_ID){ ++ printk(KERN_ERR "Unable to find Montage chip\n"); ++ goto error3; ++ } ++ ++ memcpy(&state->frontend.ops, &m88ds3103_ops, ++ sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ ++ m88ds3103_initilaze(&state->frontend); ++ ++ return &state->frontend; ++ ++error3: ++ kfree(state); ++error2: ++ return NULL; ++} ++EXPORT_SYMBOL(m88ds3103_attach); ++ ++static int m88ds3103_set_carrier_offset(struct dvb_frontend *fe, ++ s32 carrier_offset_khz) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ s32 tmp; ++ ++ tmp = carrier_offset_khz; ++ tmp *= 65536; ++ ++ tmp = (2*tmp + MT_FE_MCLK_KHZ) / (2*MT_FE_MCLK_KHZ); ++ ++ if (tmp < 0) ++ tmp += 65536; ++ ++ m88ds3103_writereg(state, 0x5f, tmp >> 8); ++ m88ds3103_writereg(state, 0x5e, tmp & 0xff); ++ ++ return 0; ++} ++ ++static int m88ds3103_set_symrate(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u16 value; ++ ++ value = (((c->symbol_rate / 1000) << 15) + (MT_FE_MCLK_KHZ / 4)) / (MT_FE_MCLK_KHZ / 2); ++ m88ds3103_writereg(state, 0x61, value & 0x00ff); ++ m88ds3103_writereg(state, 0x62, (value & 0xff00) >> 8); ++ ++ return 0; ++} ++ ++static int m88ds3103_set_CCI(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 tmp; ++ ++ tmp = m88ds3103_readreg(state, 0x56); ++ tmp &= ~0x01; ++ m88ds3103_writereg(state, 0x56, tmp); ++ ++ tmp = m88ds3103_readreg(state, 0x76); ++ tmp &= ~0x80; ++ m88ds3103_writereg(state, 0x76, tmp); ++ ++ return 0; ++} ++ ++static int m88ds3103_init_reg(struct m88ds3103_state *state, const u8 *p_reg_tab, u32 size) ++{ ++ u32 i; ++ ++ for(i = 0; i < size; i+=2) ++ m88ds3103_writereg(state, p_reg_tab[i], p_reg_tab[i+1]); ++ ++ return 0; ++} ++ ++static int m88ds3103_get_locked_sym_rate(struct m88ds3103_state *state, u32 *sym_rate_KSs) ++{ ++ u16 tmp; ++ u32 sym_rate_tmp; ++ u8 val_0x6d, val_0x6e; ++ ++ val_0x6d = m88ds3103_readreg(state, 0x6d); ++ val_0x6e = m88ds3103_readreg(state, 0x6e); ++ ++ tmp = (u16)((val_0x6e<<8) | val_0x6d); ++ ++ sym_rate_tmp = (u32)(tmp * MT_FE_MCLK_KHZ); ++ sym_rate_tmp = (u32)(sym_rate_tmp / (1<<16)); ++ *sym_rate_KSs = sym_rate_tmp; ++ ++ return 0; ++} ++ ++static int m88ds3103_get_channel_info(struct m88ds3103_state *state, u8 *p_mode, u8 *p_coderate) ++{ ++ u8 tmp, val_0x7E; ++ ++ if(state->delivery_system == SYS_DVBS2){ ++ val_0x7E = m88ds3103_readreg(state, 0x7e); ++ tmp = (u8)((val_0x7E&0xC0) >> 6); ++ *p_mode = tmp; ++ tmp = (u8)(val_0x7E & 0x0f); ++ *p_coderate = tmp; ++ } else { ++ *p_mode = 0; ++ tmp = m88ds3103_readreg(state, 0xe6); ++ tmp = (u8)(tmp >> 5); ++ *p_coderate = tmp; ++ } ++ ++ return 0; ++} ++ ++static int m88ds3103_set_clock_ratio(struct m88ds3103_state *state) ++{ ++ u8 val, mod_fac, tmp1, tmp2; ++ u32 input_datarate, locked_sym_rate_KSs; ++ u32 MClk_KHz = 96000; ++ u8 mod_mode, code_rate, divid_ratio = 0; ++ ++ locked_sym_rate_KSs = 0; ++ m88ds3103_get_locked_sym_rate(state, &locked_sym_rate_KSs); ++ if(locked_sym_rate_KSs == 0) ++ return 0; ++ ++ m88ds3103_get_channel_info(state, &mod_mode, &code_rate); ++ ++ if (state->delivery_system == SYS_DVBS2) ++ { ++ switch(mod_mode) { ++ case 1: mod_fac = 3; break; ++ case 2: mod_fac = 4; break; ++ case 3: mod_fac = 5; break; ++ default: mod_fac = 2; break; ++ } ++ ++ switch(code_rate) { ++ case 0: input_datarate = locked_sym_rate_KSs*mod_fac/8/4; break; ++ case 1: input_datarate = locked_sym_rate_KSs*mod_fac/8/3; break; ++ case 2: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/5; break; ++ case 3: input_datarate = locked_sym_rate_KSs*mod_fac/8/2; break; ++ case 4: input_datarate = locked_sym_rate_KSs*mod_fac*3/8/5; break; ++ case 5: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/3; break; ++ case 6: input_datarate = locked_sym_rate_KSs*mod_fac*3/8/4; break; ++ case 7: input_datarate = locked_sym_rate_KSs*mod_fac*4/8/5; break; ++ case 8: input_datarate = locked_sym_rate_KSs*mod_fac*5/8/6; break; ++ case 9: input_datarate = locked_sym_rate_KSs*mod_fac*8/8/9; break; ++ case 10: input_datarate = locked_sym_rate_KSs*mod_fac*9/8/10; break; ++ default: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/3; break; ++ } ++ ++ if(state->demod_id == DS3000_ID) ++ input_datarate = input_datarate * 115 / 100; ++ ++ if(input_datarate < 4800) {tmp1 = 15;tmp2 = 15;} //4.8MHz TS clock ++ else if(input_datarate < 4966) {tmp1 = 14;tmp2 = 15;} //4.966MHz TS clock ++ else if(input_datarate < 5143) {tmp1 = 14;tmp2 = 14;} //5.143MHz TS clock ++ else if(input_datarate < 5333) {tmp1 = 13;tmp2 = 14;} //5.333MHz TS clock ++ else if(input_datarate < 5538) {tmp1 = 13;tmp2 = 13;} //5.538MHz TS clock ++ else if(input_datarate < 5760) {tmp1 = 12;tmp2 = 13;} //5.76MHz TS clock allan 0809 ++ else if(input_datarate < 6000) {tmp1 = 12;tmp2 = 12;} //6MHz TS clock ++ else if(input_datarate < 6260) {tmp1 = 11;tmp2 = 12;} //6.26MHz TS clock ++ else if(input_datarate < 6545) {tmp1 = 11;tmp2 = 11;} //6.545MHz TS clock ++ else if(input_datarate < 6857) {tmp1 = 10;tmp2 = 11;} //6.857MHz TS clock ++ else if(input_datarate < 7200) {tmp1 = 10;tmp2 = 10;} //7.2MHz TS clock ++ else if(input_datarate < 7578) {tmp1 = 9;tmp2 = 10;} //7.578MHz TS clock ++ else if(input_datarate < 8000) {tmp1 = 9;tmp2 = 9;} //8MHz TS clock ++ else if(input_datarate < 8470) {tmp1 = 8;tmp2 = 9;} //8.47MHz TS clock ++ else if(input_datarate < 9000) {tmp1 = 8;tmp2 = 8;} //9MHz TS clock ++ else if(input_datarate < 9600) {tmp1 = 7;tmp2 = 8;} //9.6MHz TS clock ++ else if(input_datarate < 10285) {tmp1 = 7;tmp2 = 7;} //10.285MHz TS clock ++ else if(input_datarate < 12000) {tmp1 = 6;tmp2 = 6;} //12MHz TS clock ++ else if(input_datarate < 14400) {tmp1 = 5;tmp2 = 5;} //14.4MHz TS clock ++ else if(input_datarate < 18000) {tmp1 = 4;tmp2 = 4;} //18MHz TS clock ++ else {tmp1 = 3;tmp2 = 3;} //24MHz TS clock ++ ++ if(state->demod_id == DS3000_ID) { ++ val = (u8)((tmp1<<4) + tmp2); ++ m88ds3103_writereg(state, 0xfe, val); ++ } else { ++ tmp1 = m88ds3103_readreg(state, 0x22); ++ tmp2 = m88ds3103_readreg(state, 0x24); ++ ++ tmp1 >>= 6; ++ tmp1 &= 0x03; ++ tmp2 >>= 6; ++ tmp2 &= 0x03; ++ ++ if((tmp1 == 0x00) && (tmp2 == 0x01)) ++ MClk_KHz = 144000; ++ else if((tmp1 == 0x00) && (tmp2 == 0x03)) ++ MClk_KHz = 72000; ++ else if((tmp1 == 0x01) && (tmp2 == 0x01)) ++ MClk_KHz = 115200; ++ else if((tmp1 == 0x02) && (tmp2 == 0x01)) ++ MClk_KHz = 96000; ++ else if((tmp1 == 0x03) && (tmp2 == 0x00)) ++ MClk_KHz = 192000; ++ else ++ return 0; ++ ++ if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/ ++ input_datarate = 5200; ++ ++ if(input_datarate != 0) ++ divid_ratio = (u8)(MClk_KHz / input_datarate); ++ else ++ divid_ratio = 0xFF; ++ ++ if(divid_ratio > 128) ++ divid_ratio = 128; ++ ++ if(divid_ratio < 2) ++ divid_ratio = 2; ++ ++ tmp1 = (u8)(divid_ratio / 2); ++ tmp2 = (u8)(divid_ratio / 2); ++ ++ if((divid_ratio % 2) != 0) ++ tmp2 += 1; ++ ++ tmp1 -= 1; ++ tmp2 -= 1; ++ ++ tmp1 &= 0x3f; ++ tmp2 &= 0x3f; ++ ++ val = m88ds3103_readreg(state, 0xfe); ++ val &= 0xF0; ++ val |= (tmp2 >> 2) & 0x0f; ++ m88ds3103_writereg(state, 0xfe, val); ++ ++ val = (u8)((tmp2 & 0x03) << 6); ++ val |= tmp1; ++ m88ds3103_writereg(state, 0xea, val); ++ } ++ } else { ++ mod_fac = 2; ++ ++ switch(code_rate) { ++ case 4: input_datarate = locked_sym_rate_KSs*mod_fac/2/8; break; ++ case 3: input_datarate = locked_sym_rate_KSs*mod_fac*2/3/8; break; ++ case 2: input_datarate = locked_sym_rate_KSs*mod_fac*3/4/8; break; ++ case 1: input_datarate = locked_sym_rate_KSs*mod_fac*5/6/8; break; ++ case 0: input_datarate = locked_sym_rate_KSs*mod_fac*7/8/8; break; ++ default: input_datarate = locked_sym_rate_KSs*mod_fac*3/4/8; break; ++ } ++ ++ if(state->demod_id == DS3000_ID) ++ input_datarate = input_datarate * 115 / 100; ++ ++ if(input_datarate < 6857) {tmp1 = 7;tmp2 = 7;} //6.857MHz TS clock ++ else if(input_datarate < 7384) {tmp1 = 6;tmp2 = 7;} //7.384MHz TS clock ++ else if(input_datarate < 8000) {tmp1 = 6;tmp2 = 6;} //8MHz TS clock ++ else if(input_datarate < 8727) {tmp1 = 5;tmp2 = 6;} //8.727MHz TS clock ++ else if(input_datarate < 9600) {tmp1 = 5;tmp2 = 5;} //9.6MHz TS clock ++ else if(input_datarate < 10666) {tmp1 = 4;tmp2 = 5;} //10.666MHz TS clock ++ else if(input_datarate < 12000) {tmp1 = 4;tmp2 = 4;} //12MHz TS clock ++ else if(input_datarate < 13714) {tmp1 = 3;tmp2 = 4;} //13.714MHz TS clock ++ else if(input_datarate < 16000) {tmp1 = 3;tmp2 = 3;} //16MHz TS clock ++ else if(input_datarate < 19200) {tmp1 = 2;tmp2 = 3;} //19.2MHz TS clock ++ else {tmp1 = 2;tmp2 = 2;} //24MHz TS clock ++ ++ if(state->demod_id == DS3000_ID) { ++ val = m88ds3103_readreg(state, 0xfe); ++ val &= 0xc0; ++ val |= ((u8)((tmp1<<3) + tmp2)); ++ m88ds3103_writereg(state, 0xfe, val); ++ } else { ++ if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/ ++ input_datarate = 5200; ++ ++ if(input_datarate != 0) ++ divid_ratio = (u8)(MClk_KHz / input_datarate); ++ else ++ divid_ratio = 0xFF; ++ ++ if(divid_ratio > 128) ++ divid_ratio = 128; ++ ++ if(divid_ratio < 2) ++ divid_ratio = 2; ++ ++ tmp1 = (u8)(divid_ratio / 2); ++ tmp2 = (u8)(divid_ratio / 2); ++ ++ if((divid_ratio % 2) != 0) ++ tmp2 += 1; ++ ++ tmp1 -= 1; ++ tmp2 -= 1; ++ ++ tmp1 &= 0x3f; ++ tmp2 &= 0x3f; ++ ++ val = m88ds3103_readreg(state, 0xfe); ++ val &= 0xF0; ++ val |= (tmp2 >> 2) & 0x0f; ++ m88ds3103_writereg(state, 0xfe, val); ++ ++ val = (u8)((tmp2 & 0x03) << 6); ++ val |= tmp1; ++ m88ds3103_writereg(state, 0xea, val); ++ } ++ } ++ return 0; ++} ++ ++static int m88ds3103_demod_connect(struct dvb_frontend *fe, s32 carrier_offset_khz) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u16 value; ++ u8 val1,val2,data; ++ ++ dprintk("connect delivery system = %d\n", state->delivery_system); ++ ++ /* ds3000 global reset */ ++ m88ds3103_writereg(state, 0x07, 0x80); ++ m88ds3103_writereg(state, 0x07, 0x00); ++ /* ds3000 build-in uC reset */ ++ m88ds3103_writereg(state, 0xb2, 0x01); ++ /* ds3000 software reset */ ++ m88ds3103_writereg(state, 0x00, 0x01); ++ ++ switch (state->delivery_system) { ++ case SYS_DVBS: ++ /* initialise the demod in DVB-S mode */ ++ if(state->demod_id == DS3000_ID){ ++ m88ds3103_init_reg(state, ds3000_dvbs_init_tab, sizeof(ds3000_dvbs_init_tab)); ++ ++ value = m88ds3103_readreg(state, 0xfe); ++ value &= 0xc0; ++ value |= 0x1b; ++ m88ds3103_writereg(state, 0xfe, value); ++ ++ if(state->config->ci_mode) ++ val1 = 0x80; ++ else if(state->config->ts_mode) ++ val1 = 0x60; ++ else ++ val1 = 0x20; ++ m88ds3103_writereg(state, 0xfd, val1); ++ ++ }else if(state->demod_id == DS3103_ID){ ++ m88ds3103_init_reg(state, ds3103_dvbs_init_tab, sizeof(ds3103_dvbs_init_tab)); ++ ++ /* set ts clock */ ++ if(state->config->ci_mode == 2){ ++ val1 = 6; val2 = 6; ++ }else if(state->config->ts_mode == 0) { ++ val1 = 3; val2 = 3; ++ }else{ ++ val1 = 0; val2 = 0; ++ } ++ val1 -= 1; val2 -= 1; ++ val1 &= 0x3f; val2 &= 0x3f; ++ data = m88ds3103_readreg(state, 0xfe); ++ data &= 0xf0; ++ data |= (val2 >> 2) & 0x0f; ++ m88ds3103_writereg(state, 0xfe, data); ++ data = (val2 & 0x03) << 6; ++ data |= val1; ++ m88ds3103_writereg(state, 0xea, data); ++ ++ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); ++ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); ++ ++ /* set master clock */ ++ val1 = m88ds3103_readreg(state, 0x22); ++ val2 = m88ds3103_readreg(state, 0x24); ++ ++ val1 &= 0x3f; ++ val2 &= 0x3f; ++ val1 |= 0x80; ++ val2 |= 0x40; ++ ++ m88ds3103_writereg(state, 0x22, val1); ++ m88ds3103_writereg(state, 0x24, val2); ++ ++ if(state->config->ci_mode) ++ val1 = 0x03; ++ else if(state->config->ts_mode) ++ val1 = 0x06; ++ else ++ val1 = 0x42; ++ m88ds3103_writereg(state, 0xfd, val1); ++ } ++ break; ++ case SYS_DVBS2: ++ /* initialise the demod in DVB-S2 mode */ ++ if(state->demod_id == DS3000_ID){ ++ m88ds3103_init_reg(state, ds3000_dvbs2_init_tab, sizeof(ds3000_dvbs2_init_tab)); ++ ++ if (c->symbol_rate >= 30000000) ++ m88ds3103_writereg(state, 0xfe, 0x54); ++ else ++ m88ds3103_writereg(state, 0xfe, 0x98); ++ ++ }else if(state->demod_id == DS3103_ID){ ++ m88ds3103_init_reg(state, ds3103_dvbs2_init_tab, sizeof(ds3103_dvbs2_init_tab)); ++ ++ /* set ts clock */ ++ if(state->config->ci_mode == 2){ ++ val1 = 6; val2 = 6; ++ }else if(state->config->ts_mode == 0){ ++ val1 = 5; val2 = 4; ++ }else{ ++ val1 = 0; val2 = 0; ++ } ++ val1 -= 1; val2 -= 1; ++ val1 &= 0x3f; val2 &= 0x3f; ++ data = m88ds3103_readreg(state, 0xfe); ++ data &= 0xf0; ++ data |= (val2 >> 2) & 0x0f; ++ m88ds3103_writereg(state, 0xfe, data); ++ data = (val2 & 0x03) << 6; ++ data |= val1; ++ m88ds3103_writereg(state, 0xea, data); ++ ++ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); ++ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); ++ ++ /* set master clock */ ++ val1 = m88ds3103_readreg(state, 0x22); ++ val2 = m88ds3103_readreg(state, 0x24); ++ ++ val1 &= 0x3f; ++ val2 &= 0x3f; ++ if((state->config->ci_mode == 2) || (state->config->ts_mode == 1)){ ++ val1 |= 0x80; ++ val2 |= 0x40; ++ }else{ ++ if (c->symbol_rate >= 28000000){ ++ val1 |= 0xc0; ++ }else if (c->symbol_rate >= 18000000){ ++ val2 |= 0x40; ++ }else{ ++ val1 |= 0x80; ++ val2 |= 0x40; ++ } ++ } ++ m88ds3103_writereg(state, 0x22, val1); ++ m88ds3103_writereg(state, 0x24, val2); ++ } ++ ++ if(state->config->ci_mode) ++ val1 = 0x03; ++ else if(state->config->ts_mode) ++ val1 = 0x06; ++ else ++ val1 = 0x42; ++ m88ds3103_writereg(state, 0xfd, val1); ++ ++ break; ++ default: ++ return 1; ++ } ++ /* disable 27MHz clock output */ ++ m88ds3103_writereg(state, 0x29, 0x80); ++ /* enable ac coupling */ ++ m88ds3103_writereg(state, 0x25, 0x8a); ++ ++ if ((c->symbol_rate / 1000) <= 3000){ ++ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 32 * 100 / 64 = 400*/ ++ m88ds3103_writereg(state, 0xc8, 0x20); ++ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ ++ m88ds3103_writereg(state, 0xc7, 0x00); ++ }else if((c->symbol_rate / 1000) <= 10000){ ++ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 16 * 100 / 64 = 200*/ ++ m88ds3103_writereg(state, 0xc8, 0x10); ++ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ ++ m88ds3103_writereg(state, 0xc7, 0x00); ++ }else{ ++ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 6 * 100 / 64 = 75*/ ++ m88ds3103_writereg(state, 0xc8, 0x06); ++ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ ++ m88ds3103_writereg(state, 0xc7, 0x00); ++ } ++ ++ m88ds3103_set_symrate(fe); ++ ++ m88ds3103_set_CCI(fe); ++ ++ m88ds3103_set_carrier_offset(fe, carrier_offset_khz); ++ ++ /* ds3000 out of software reset */ ++ m88ds3103_writereg(state, 0x00, 0x00); ++ /* start ds3000 build-in uC */ ++ m88ds3103_writereg(state, 0xb2, 0x00); ++ ++ return 0; ++} ++ ++static int m88ds3103_set_frontend(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ ++ int i; ++ fe_status_t status; ++ u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf, div4, capCode, changePLL; ++ s32 offset_khz, lpf_offset_KHz; ++ u16 value, ndiv, lpf_coeff; ++ u32 f3db, gdiv28, realFreq; ++ u8 RFgain; ++ ++ dprintk("%s() ", __func__); ++ dprintk("c frequency = %d\n", c->frequency); ++ dprintk("symbol rate = %d\n", c->symbol_rate); ++ dprintk("delivery system = %d\n", c->delivery_system); ++ ++ realFreq = c->frequency; ++ lpf_offset_KHz = 0; ++ if(c->symbol_rate < 5000000){ ++ lpf_offset_KHz = FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz; ++ realFreq += FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz; ++ } ++ ++ if (state->config->set_ts_params) ++ state->config->set_ts_params(fe, 0); ++ ++ div4 = 0; ++ RFgain = 0; ++ if(state->tuner_id == TS2022_ID){ ++ m88ds3103_tuner_writereg(state, 0x10, 0x0a); ++ m88ds3103_tuner_writereg(state, 0x11, 0x40); ++ if (realFreq < 1103000) { ++ m88ds3103_tuner_writereg(state, 0x10, 0x1b); ++ div4 = 1; ++ ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ; ++ }else { ++ ndiv = (realFreq * (6 + 8) * 2)/MT_FE_CRYSTAL_KHZ; ++ } ++ ndiv = ndiv + ndiv%2; ++ if(ndiv < 4095) ++ ndiv = ndiv - 1024; ++ else if (ndiv < 6143) ++ ndiv = ndiv + 1024; ++ else ++ ndiv = ndiv + 3072; ++ ++ m88ds3103_tuner_writereg(state, 0x01, (ndiv & 0x3f00) >> 8); ++ }else{ ++ m88ds3103_tuner_writereg(state, 0x10, 0x00); ++ if (realFreq < 1146000){ ++ m88ds3103_tuner_writereg(state, 0x10, 0x11); ++ div4 = 1; ++ ndiv = (realFreq * (6 + 8) * 4) / MT_FE_CRYSTAL_KHZ; ++ }else{ ++ m88ds3103_tuner_writereg(state, 0x10, 0x01); ++ ndiv = (realFreq * (6 + 8) * 2) / MT_FE_CRYSTAL_KHZ; ++ } ++ ndiv = ndiv + ndiv%2; ++ ndiv = ndiv - 1024; ++ m88ds3103_tuner_writereg(state, 0x01, (ndiv>>8)&0x0f); ++ } ++ /* set pll */ ++ m88ds3103_tuner_writereg(state, 0x02, ndiv & 0x00ff); ++ m88ds3103_tuner_writereg(state, 0x03, 0x06); ++ m88ds3103_tuner_writereg(state, 0x51, 0x0f); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x10); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ ++ if(state->tuner_id == TS2022_ID){ ++ if(( realFreq >= 1650000 ) && (realFreq <= 1850000)){ ++ msleep(5); ++ value = m88ds3103_tuner_readreg(state, 0x14); ++ value &= 0x7f; ++ if(value < 64){ ++ m88ds3103_tuner_writereg(state, 0x10, 0x82); ++ m88ds3103_tuner_writereg(state, 0x11, 0x6f); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x0f); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x10); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ } ++ } ++ msleep(5); ++ value = m88ds3103_tuner_readreg(state, 0x14); ++ value &= 0x1f; ++ ++ if(value > 19){ ++ value = m88ds3103_tuner_readreg(state, 0x10); ++ value &= 0x1d; ++ m88ds3103_tuner_writereg(state, 0x10, value); ++ } ++ }else{ ++ msleep(5); ++ value = m88ds3103_tuner_readreg(state, 0x66); ++ changePLL = (((value & 0x80) >> 7) != div4); ++ ++ if(changePLL){ ++ m88ds3103_tuner_writereg(state, 0x10, 0x11); ++ div4 = 1; ++ ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ; ++ ndiv = ndiv + ndiv%2; ++ ndiv = ndiv - 1024; ++ ++ m88ds3103_tuner_writereg(state, 0x01, (ndiv>>8) & 0x0f); ++ m88ds3103_tuner_writereg(state, 0x02, ndiv & 0xff); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x0f); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x10); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ } ++ } ++ /*set the RF gain*/ ++ if(state->tuner_id == TS2020_ID) ++ m88ds3103_tuner_writereg(state, 0x60, 0x79); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x17); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x08); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ msleep(5); ++ ++ if(state->tuner_id == TS2020_ID){ ++ RFgain = m88ds3103_tuner_readreg(state, 0x3d); ++ RFgain &= 0x0f; ++ if(RFgain < 15){ ++ if(RFgain < 4) ++ RFgain = 0; ++ else ++ RFgain = RFgain -3; ++ value = ((RFgain << 3) | 0x01) & 0x79; ++ m88ds3103_tuner_writereg(state, 0x60, value); ++ m88ds3103_tuner_writereg(state, 0x51, 0x17); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x08); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ } ++ } ++ ++ /* set the LPF */ ++ if(state->tuner_id == TS2022_ID){ ++ m88ds3103_tuner_writereg(state, 0x25, 0x00); ++ m88ds3103_tuner_writereg(state, 0x27, 0x70); ++ m88ds3103_tuner_writereg(state, 0x41, 0x09); ++ m88ds3103_tuner_writereg(state, 0x08, 0x0b); ++ } ++ ++ f3db = ((c->symbol_rate / 1000) *135) / 200 + 2000; ++ f3db += lpf_offset_KHz; ++ if (f3db < 7000) ++ f3db = 7000; ++ if (f3db > 40000) ++ f3db = 40000; ++ ++ gdiv28 = (MT_FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000; ++ m88ds3103_tuner_writereg(state, 0x04, gdiv28 & 0xff); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1b); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x04); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ msleep(5); ++ ++ value = m88ds3103_tuner_readreg(state, 0x26); ++ capCode = value & 0x3f; ++ if(state->tuner_id == TS2022_ID){ ++ m88ds3103_tuner_writereg(state, 0x41, 0x0d); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x1b); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x04); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ ++ msleep(2); ++ ++ value = m88ds3103_tuner_readreg(state, 0x26); ++ value &= 0x3f; ++ value = (capCode + value) / 2; ++ } ++ else ++ value = capCode; ++ ++ gdiv28 = gdiv28 * 207 / (value * 2 + 151); ++ mlpf_max = gdiv28 * 135 / 100; ++ mlpf_min = gdiv28 * 78 / 100; ++ if (mlpf_max > 63) ++ mlpf_max = 63; ++ ++ if(state->tuner_id == TS2022_ID) ++ lpf_coeff = 3200; ++ else ++ lpf_coeff = 2766; ++ ++ nlpf = (f3db * gdiv28 * 2 / lpf_coeff / (MT_FE_CRYSTAL_KHZ / 1000) + 1) / 2 ; ++ if (nlpf > 23) nlpf = 23; ++ if (nlpf < 1) nlpf = 1; ++ ++ lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2; ++ ++ if (lpf_mxdiv < mlpf_min){ ++ nlpf++; ++ lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2; ++ } ++ ++ if (lpf_mxdiv > mlpf_max) ++ lpf_mxdiv = mlpf_max; ++ ++ m88ds3103_tuner_writereg(state, 0x04, lpf_mxdiv); ++ m88ds3103_tuner_writereg(state, 0x06, nlpf); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1b); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x04); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ msleep(5); ++ ++ if(state->tuner_id == TS2022_ID){ ++ msleep(2); ++ value = m88ds3103_tuner_readreg(state, 0x26); ++ capCode = value & 0x3f; ++ ++ m88ds3103_tuner_writereg(state, 0x41, 0x09); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x1b); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x04); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ ++ msleep(2); ++ value = m88ds3103_tuner_readreg(state, 0x26); ++ value &= 0x3f; ++ value = (capCode + value) / 2; ++ ++ value = value | 0x80; ++ m88ds3103_tuner_writereg(state, 0x25, value); ++ m88ds3103_tuner_writereg(state, 0x27, 0x30); ++ ++ m88ds3103_tuner_writereg(state, 0x08, 0x09); ++ } ++ ++ /* Set the BB gain */ ++ m88ds3103_tuner_writereg(state, 0x51, 0x1e); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x01); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ if(state->tuner_id == TS2020_ID){ ++ if(RFgain == 15){ ++ msleep(40); ++ value = m88ds3103_tuner_readreg(state, 0x21); ++ value &= 0x0f; ++ if(value < 3){ ++ m88ds3103_tuner_writereg(state, 0x60, 0x61); ++ m88ds3103_tuner_writereg(state, 0x51, 0x17); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x08); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ } ++ } ++ } ++ msleep(60); ++ ++ offset_khz = (ndiv - ndiv % 2 + 1024) * MT_FE_CRYSTAL_KHZ ++ / (6 + 8) / (div4 + 1) / 2 - realFreq; ++ ++ m88ds3103_demod_connect(fe, offset_khz+lpf_offset_KHz); ++ ++ for (i = 0; i < 30 ; i++) { ++ m88ds3103_read_status(fe, &status); ++ if (status & FE_HAS_LOCK){ ++ break; ++ } ++ msleep(20); ++ } ++ ++ if((status & FE_HAS_LOCK) == 0){ ++ state->delivery_system = (state->delivery_system == SYS_DVBS) ? SYS_DVBS2 : SYS_DVBS; ++ m88ds3103_demod_connect(fe, offset_khz); ++ ++ for (i = 0; i < 30 ; i++) { ++ m88ds3103_read_status(fe, &status); ++ if (status & FE_HAS_LOCK){ ++ break; ++ } ++ msleep(20); ++ } ++ } ++ ++ if (status & FE_HAS_LOCK){ ++ if(state->config->ci_mode == 2) ++ m88ds3103_set_clock_ratio(state); ++ if(state->config->start_ctrl){ ++ if(state->first_lock == 0){ ++ state->config->start_ctrl(fe); ++ state->first_lock = 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int m88ds3103_tune(struct dvb_frontend *fe, ++ bool re_tune, ++ unsigned int mode_flags, ++ unsigned int *delay, ++ fe_status_t *status) ++{ ++ *delay = HZ / 5; ++ ++ dprintk("%s() ", __func__); ++ dprintk("re_tune = %d\n", re_tune); ++ ++ if (re_tune) { ++ int ret = m88ds3103_set_frontend(fe); ++ if (ret) ++ return ret; ++ } ++ ++ return m88ds3103_read_status(fe, status); ++} ++ ++static enum dvbfe_algo m88ds3103_get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++ /* ++ * Power config will reset and load initial firmware if required ++ */ ++static int m88ds3103_initilaze(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ int ret; ++ ++ dprintk("%s()\n", __func__); ++ /* hard reset */ ++ m88ds3103_writereg(state, 0x07, 0x80); ++ m88ds3103_writereg(state, 0x07, 0x00); ++ msleep(1); ++ ++ m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08)); ++ msleep(1); ++ ++ if(state->tuner_id == TS2020_ID){ ++ /* TS2020 init */ ++ m88ds3103_tuner_writereg(state, 0x42, 0x73); ++ msleep(2); ++ m88ds3103_tuner_writereg(state, 0x05, 0x01); ++ m88ds3103_tuner_writereg(state, 0x62, 0xb5); ++ m88ds3103_tuner_writereg(state, 0x07, 0x02); ++ m88ds3103_tuner_writereg(state, 0x08, 0x01); ++ } ++ else if(state->tuner_id == TS2022_ID){ ++ /* TS2022 init */ ++ m88ds3103_tuner_writereg(state, 0x62, 0x6c); ++ msleep(2); ++ m88ds3103_tuner_writereg(state, 0x42, 0x6c); ++ msleep(2); ++ m88ds3103_tuner_writereg(state, 0x7d, 0x9d); ++ m88ds3103_tuner_writereg(state, 0x7c, 0x9a); ++ m88ds3103_tuner_writereg(state, 0x7a, 0x76); ++ ++ m88ds3103_tuner_writereg(state, 0x3b, 0x01); ++ m88ds3103_tuner_writereg(state, 0x63, 0x88); ++ ++ m88ds3103_tuner_writereg(state, 0x61, 0x85); ++ m88ds3103_tuner_writereg(state, 0x22, 0x30); ++ m88ds3103_tuner_writereg(state, 0x30, 0x40); ++ m88ds3103_tuner_writereg(state, 0x20, 0x23); ++ m88ds3103_tuner_writereg(state, 0x24, 0x02); ++ m88ds3103_tuner_writereg(state, 0x12, 0xa0); ++ } ++ ++ if(state->demod_id == DS3103_ID){ ++ m88ds3103_writereg(state, 0x07, 0xe0); ++ m88ds3103_writereg(state, 0x07, 0x00); ++ msleep(1); ++ } ++ m88ds3103_writereg(state, 0xb2, 0x01); ++ ++ /* Load the firmware if required */ ++ ret = m88ds3103_load_firmware(fe); ++ if (ret != 0){ ++ printk(KERN_ERR "%s: Unable initialize firmware\n", __func__); ++ return ret; ++ } ++ if(state->demod_id == DS3103_ID){ ++ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); ++ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); ++ } ++ ++ return 0; ++} ++ ++/* ++ * Initialise or wake up device ++ */ ++static int m88ds3103_initfe(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 val; ++ ++ dprintk("%s()\n", __func__); ++ ++ /* 1st step to wake up demod */ ++ m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08)); ++ m88ds3103_writereg(state, 0x04, 0xfe & m88ds3103_readreg(state, 0x04)); ++ m88ds3103_writereg(state, 0x23, 0xef & m88ds3103_readreg(state, 0x23)); ++ ++ /* 2nd step to wake up tuner */ ++ val = m88ds3103_tuner_readreg(state, 0x00) & 0xff; ++ if((val & 0x01) == 0){ ++ m88ds3103_tuner_writereg(state, 0x00, 0x01); ++ msleep(50); ++ } ++ m88ds3103_tuner_writereg(state, 0x00, 0x03); ++ msleep(50); ++ ++ return 0; ++} ++ ++/* Put device to sleep */ ++static int m88ds3103_sleep(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ ++ dprintk("%s()\n", __func__); ++ ++ /* 1st step to sleep tuner */ ++ m88ds3103_tuner_writereg(state, 0x00, 0x00); ++ ++ /* 2nd step to sleep demod */ ++ m88ds3103_writereg(state, 0x08, 0xfe & m88ds3103_readreg(state, 0x08)); ++ m88ds3103_writereg(state, 0x04, 0x01 | m88ds3103_readreg(state, 0x04)); ++ m88ds3103_writereg(state, 0x23, 0x10 | m88ds3103_readreg(state, 0x23)); ++ ++ ++ return 0; ++} ++ ++static struct dvb_frontend_ops m88ds3103_ops = { ++ .delsys = { SYS_DVBS, SYS_DVBS2}, ++ .info = { ++ .name = "Montage DS3103/TS2022", ++ .type = FE_QPSK, ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ ++ .frequency_tolerance = 5000, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .caps = FE_CAN_INVERSION_AUTO | ++ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | ++ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ++ FE_CAN_2G_MODULATION | ++ FE_CAN_QPSK | FE_CAN_RECOVER ++ }, ++ ++ .release = m88ds3103_release, ++ ++ .init = m88ds3103_initfe, ++ .sleep = m88ds3103_sleep, ++ .read_status = m88ds3103_read_status, ++ .read_ber = m88ds3103_read_ber, ++ .read_signal_strength = m88ds3103_read_signal_strength, ++ .read_snr = m88ds3103_read_snr, ++ .read_ucblocks = m88ds3103_read_ucblocks, ++ .set_tone = m88ds3103_set_tone, ++ .set_voltage = m88ds3103_set_voltage, ++ .diseqc_send_master_cmd = m88ds3103_send_diseqc_msg, ++ .diseqc_send_burst = m88ds3103_diseqc_send_burst, ++ .get_frontend_algo = m88ds3103_get_algo, ++ .tune = m88ds3103_tune, ++ .set_frontend = m88ds3103_set_frontend, ++}; ++ ++MODULE_DESCRIPTION("DVB Frontend module for Montage DS3103/TS2022 hardware"); ++MODULE_AUTHOR("Max nibble"); ++MODULE_LICENSE("GPL"); +diff -urN a/drivers/media/dvb-frontends/m88ds3103.h b/drivers/media/dvb-frontends/m88ds3103.h +--- a/drivers/media/dvb-frontends/m88ds3103.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88ds3103.h 2013-01-30 12:33:51.000000000 +0800 +@@ -0,0 +1,53 @@ ++/* ++ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef M88DS3103_H ++#define M88DS3103_H ++ ++#include ++ ++struct m88ds3103_config { ++ /* the demodulator's i2c address */ ++ u8 demod_address; ++ u8 ci_mode; ++ u8 pin_ctrl; ++ u8 ts_mode; /* 0: Parallel, 1: Serial */ ++ ++ /* Set device param to start dma */ ++ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); ++ /* Start to transfer data */ ++ int (*start_ctrl)(struct dvb_frontend *fe); ++ /* Set LNB voltage */ ++ int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); ++}; ++ ++#if defined(CONFIG_DVB_M88DS3103) || \ ++ (defined(CONFIG_DVB_M88DS3103_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *m88ds3103_attach( ++ const struct m88ds3103_config *config, ++ struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *m88ds3103_attach( ++ const struct m88ds3103_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_M88DS3103 */ ++#endif /* M88DS3103_H */ +diff -urN a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h +--- a/drivers/media/dvb-frontends/m88ds3103_priv.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88ds3103_priv.h 2013-01-30 12:33:56.000000000 +0800 +@@ -0,0 +1,403 @@ ++/* ++ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef M88DS3103_PRIV_H ++#define M88DS3103_PRIV_H ++ ++#define FW_DOWN_SIZE 32 ++#define FW_DOWN_LOOP (8192/FW_DOWN_SIZE) ++#define DS3103_DEFAULT_FIRMWARE "dvb-fe-ds3103.fw" ++#define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds300x.fw" ++#define MT_FE_MCLK_KHZ 96000 /* in kHz */ ++#define MT_FE_CRYSTAL_KHZ 27000 /* in kHz */ ++#define FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz 3000 ++#define DS3000_ID 0x3000 ++#define DS3103_ID 0x3103 ++#define TS2020_ID 0x2020 ++#define TS2022_ID 0x2022 ++#define UNKNOW_ID 0x0000 ++ ++struct m88ds3103_state { ++ struct i2c_adapter *i2c; ++ const struct m88ds3103_config *config; ++ ++ struct dvb_frontend frontend; ++ ++ u32 preBer; ++ u8 skip_fw_load; ++ u8 first_lock; /* The first time of signal lock */ ++ u16 demod_id; /* demod chip type */ ++ u16 tuner_id; /* tuner chip type */ ++ fe_delivery_system_t delivery_system; ++}; ++ ++/* For M88DS3103 demod dvbs mode.*/ ++static u8 ds3103_dvbs_init_tab[] = { ++ 0x23, 0x07, ++ 0x08, 0x03, ++ 0x0c, 0x02, ++ 0x21, 0x54, ++ 0x25, 0x82, ++ 0x27, 0x31, ++ 0x30, 0x08, ++ 0x31, 0x40, ++ 0x32, 0x32, ++ 0x33, 0x35, ++ 0x35, 0xff, ++ 0x3a, 0x00, ++ 0x37, 0x10, ++ 0x38, 0x10, ++ 0x39, 0x02, ++ 0x42, 0x60, ++ 0x4a, 0x80, ++ 0x4b, 0x04, ++ 0x4d, 0x91, ++ 0x5d, 0xc8, ++ 0x50, 0x36, ++ 0x51, 0x36, ++ 0x52, 0x36, ++ 0x53, 0x36, ++ 0x63, 0x0f, ++ 0x64, 0x30, ++ 0x65, 0x40, ++ 0x68, 0x26, ++ 0x69, 0x4c, ++ 0x70, 0x20, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x40, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x60, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x80, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0xa0, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x1f, ++ 0x76, 0x38, ++ 0x77, 0xa6, ++ 0x78, 0x0c, ++ 0x79, 0x80, ++ 0x7f, 0x14, ++ 0x7c, 0x00, ++ 0xae, 0x82, ++ 0x80, 0x64, ++ 0x81, 0x66, ++ 0x82, 0x44, ++ 0x85, 0x04, ++ 0xcd, 0xf4, ++ 0x90, 0x33, ++ 0xa0, 0x44, ++ 0xc0, 0x08, ++ 0xc3, 0x10, ++ 0xc4, 0x08, ++ 0xc5, 0xf0, ++ 0xc6, 0xff, ++ 0xc7, 0x00, ++ 0xc8, 0x1a, ++ 0xc9, 0x80, ++ 0xe0, 0xf8, ++ 0xe6, 0x8b, ++ 0xd0, 0x40, ++ 0xf8, 0x20, ++ 0xfa, 0x0f, ++ 0x00, 0x00, ++ 0xbd, 0x01, ++ 0xb8, 0x00, ++}; ++/* For M88DS3103 demod dvbs2 mode.*/ ++static u8 ds3103_dvbs2_init_tab[] = { ++ 0x23, 0x07, ++ 0x08, 0x07, ++ 0x0c, 0x02, ++ 0x21, 0x54, ++ 0x25, 0x82, ++ 0x27, 0x31, ++ 0x30, 0x08, ++ 0x32, 0x32, ++ 0x33, 0x35, ++ 0x35, 0xff, ++ 0x3a, 0x00, ++ 0x37, 0x10, ++ 0x38, 0x10, ++ 0x39, 0x02, ++ 0x42, 0x60, ++ 0x4a, 0x80, ++ 0x4b, 0x04, ++ 0x4d, 0x91, ++ 0x5d, 0xc8, ++ 0x50, 0x36, ++ 0x51, 0x36, ++ 0x52, 0x36, ++ 0x53, 0x36, ++ 0x63, 0x0f, ++ 0x64, 0x10, ++ 0x65, 0x20, ++ 0x68, 0x46, ++ 0x69, 0xcd, ++ 0x70, 0x20, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x40, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x60, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x80, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0xa0, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x1f, ++ 0x76, 0x38, ++ 0x77, 0xa6, ++ 0x78, 0x0c, ++ 0x79, 0x80, ++ 0x7f, 0x14, ++ 0x85, 0x08, ++ 0xcd, 0xf4, ++ 0x90, 0x33, ++ 0x86, 0x00, ++ 0x87, 0x0f, ++ 0x89, 0x00, ++ 0x8b, 0x44, ++ 0x8c, 0x66, ++ 0x9d, 0xc1, ++ 0x8a, 0x10, ++ 0xad, 0x40, ++ 0xa0, 0x44, ++ 0xc0, 0x08, ++ 0xc1, 0x10, ++ 0xc2, 0x08, ++ 0xc3, 0x10, ++ 0xc4, 0x08, ++ 0xc5, 0xf0, ++ 0xc6, 0xff, ++ 0xc7, 0x00, ++ 0xc8, 0x1a, ++ 0xc9, 0x80, ++ 0xca, 0x23, ++ 0xcb, 0x24, ++ 0xcc, 0xf4, ++ 0xce, 0x74, ++ 0x00, 0x00, ++ 0xbd, 0x01, ++ 0xb8, 0x00, ++}; ++ ++/* For M88DS3000 demod dvbs mode.*/ ++static u8 ds3000_dvbs_init_tab[] = { ++ 0x23, 0x05, ++ 0x08, 0x03, ++ 0x0c, 0x02, ++ 0x21, 0x54, ++ 0x25, 0x82, ++ 0x27, 0x31, ++ 0x30, 0x08, ++ 0x31, 0x40, ++ 0x32, 0x32, ++ 0x33, 0x35, ++ 0x35, 0xff, ++ 0x3a, 0x00, ++ 0x37, 0x10, ++ 0x38, 0x10, ++ 0x39, 0x02, ++ 0x42, 0x60, ++ 0x4a, 0x40, ++ 0x4b, 0x04, ++ 0x4d, 0x91, ++ 0x5d, 0xc8, ++ 0x50, 0x77, ++ 0x51, 0x77, ++ 0x52, 0x36, ++ 0x53, 0x36, ++ 0x56, 0x01, ++ 0x63, 0x47, ++ 0x64, 0x30, ++ 0x65, 0x40, ++ 0x68, 0x26, ++ 0x69, 0x4c, ++ 0x70, 0x20, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x40, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x60, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x80, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0xa0, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x1f, ++ 0x76, 0x00, ++ 0x77, 0xd1, ++ 0x78, 0x0c, ++ 0x79, 0x80, ++ 0x7f, 0x04, ++ 0x7c, 0x00, ++ 0x80, 0x86, ++ 0x81, 0xa6, ++ 0x85, 0x04, ++ 0xcd, 0xf4, ++ 0x90, 0x33, ++ 0xa0, 0x44, ++ 0xc0, 0x18, ++ 0xc3, 0x10, ++ 0xc4, 0x08, ++ 0xc5, 0x80, ++ 0xc6, 0x80, ++ 0xc7, 0x0a, ++ 0xc8, 0x1a, ++ 0xc9, 0x80, ++ 0xfe, 0xb6, ++ 0xe0, 0xf8, ++ 0xe6, 0x8b, ++ 0xd0, 0x40, ++ 0xf8, 0x20, ++ 0xfa, 0x0f, ++ 0xad, 0x20, ++ 0xae, 0x07, ++ 0xb8, 0x00, ++}; ++ ++/* For M88DS3000 demod dvbs2 mode.*/ ++static u8 ds3000_dvbs2_init_tab[] = { ++ 0x23, 0x0f, ++ 0x08, 0x07, ++ 0x0c, 0x02, ++ 0x21, 0x54, ++ 0x25, 0x82, ++ 0x27, 0x31, ++ 0x30, 0x08, ++ 0x31, 0x32, ++ 0x32, 0x32, ++ 0x33, 0x35, ++ 0x35, 0xff, ++ 0x3a, 0x00, ++ 0x37, 0x10, ++ 0x38, 0x10, ++ 0x39, 0x02, ++ 0x42, 0x60, ++ 0x4a, 0x80, ++ 0x4b, 0x04, ++ 0x4d, 0x91, ++ 0x5d, 0x88, ++ 0x50, 0x36, ++ 0x51, 0x36, ++ 0x52, 0x36, ++ 0x53, 0x36, ++ 0x63, 0x60, ++ 0x64, 0x10, ++ 0x65, 0x10, ++ 0x68, 0x04, ++ 0x69, 0x29, ++ 0x70, 0x20, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x40, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x60, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x80, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0xa0, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x1f, ++ 0xa0, 0x44, ++ 0xc0, 0x08, ++ 0xc1, 0x10, ++ 0xc2, 0x08, ++ 0xc3, 0x10, ++ 0xc4, 0x08, ++ 0xc5, 0xf0, ++ 0xc6, 0xf0, ++ 0xc7, 0x0a, ++ 0xc8, 0x1a, ++ 0xc9, 0x80, ++ 0xca, 0x23, ++ 0xcb, 0x24, ++ 0xce, 0x74, ++ 0x56, 0x01, ++ 0x90, 0x03, ++ 0x76, 0x80, ++ 0x77, 0x42, ++ 0x78, 0x0a, ++ 0x79, 0x80, ++ 0xad, 0x40, ++ 0xae, 0x07, ++ 0x7f, 0xd4, ++ 0x7c, 0x00, ++ 0x80, 0xa8, ++ 0x81, 0xda, ++ 0x7c, 0x01, ++ 0x80, 0xda, ++ 0x81, 0xec, ++ 0x7c, 0x02, ++ 0x80, 0xca, ++ 0x81, 0xeb, ++ 0x7c, 0x03, ++ 0x80, 0xba, ++ 0x81, 0xdb, ++ 0x85, 0x08, ++ 0x86, 0x00, ++ 0x87, 0x02, ++ 0x89, 0x80, ++ 0x8b, 0x44, ++ 0x8c, 0xaa, ++ 0x8a, 0x10, ++ 0xba, 0x00, ++ 0xf5, 0x04, ++ 0xd2, 0x32, ++ 0xb8, 0x00, ++}; ++ ++#endif /* M88DS3103_PRIV_H */ +diff -urN a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile +--- a/drivers/media/dvb-frontends/Makefile 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/dvb-frontends/Makefile 2013-05-03 17:04:31.000000000 +0800 +@@ -103,4 +103,5 @@ + obj-$(CONFIG_DVB_RTL2832) += rtl2832.o + obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o + obj-$(CONFIG_DVB_AF9033) += af9033.o +- ++obj-$(CONFIG_DVB_M88DS3103) += m88ds3103.o ++obj-$(CONFIG_DVB_M88DC2800) += m88dc2800.o +diff -urN a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c +--- a/drivers/media/pci/cx23885/cimax2.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cimax2.c 2013-03-31 22:03:29.000000000 +0800 +@@ -415,7 +415,7 @@ + return state->status; + } + +-int netup_ci_init(struct cx23885_tsport *port) ++int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky) + { + struct netup_ci_state *state; + u8 cimax_init[34] = { +@@ -464,6 +464,11 @@ + goto err; + } + ++ if(isDVBSky) { ++ cimax_init[32] = 0x22; ++ cimax_init[33] = 0x00; ++ } ++ + port->port_priv = state; + + switch (port->nr) { +@@ -537,3 +542,19 @@ + dvb_ca_en50221_release(&state->ca); + kfree(state); + } ++ ++/* CI irq handler for DVBSky board*/ ++int dvbsky_ci_slot_status(struct cx23885_dev *dev) ++{ ++ struct cx23885_tsport *port = NULL; ++ struct netup_ci_state *state = NULL; ++ ++ ci_dbg_print("%s:\n", __func__); ++ ++ port = &dev->ts1; ++ state = port->port_priv; ++ schedule_work(&state->work); ++ ci_dbg_print("%s: Wakeup CI0\n", __func__); ++ ++ return 1; ++} +diff -urN a/drivers/media/pci/cx23885/cimax2.h b/drivers/media/pci/cx23885/cimax2.h +--- a/drivers/media/pci/cx23885/cimax2.h 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cimax2.h 2013-01-30 12:34:37.000000000 +0800 +@@ -41,7 +41,9 @@ + extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status); + extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, + int slot, int open); +-extern int netup_ci_init(struct cx23885_tsport *port); ++extern int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky); + extern void netup_ci_exit(struct cx23885_tsport *port); + ++extern int dvbsky_ci_slot_status(struct cx23885_dev *dev); ++ + #endif +diff -urN a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c +--- a/drivers/media/pci/cx23885/cx23885-cards.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885-cards.c 2013-05-03 17:34:46.000000000 +0800 +@@ -569,6 +569,34 @@ + .name = "TeVii S471", + .portb = CX23885_MPEG_DVB, + }, ++ [CX23885_BOARD_BST_PS8512] = { ++ .name = "Bestunar PS8512", ++ .portb = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_S950] = { ++ .name = "DVBSKY S950", ++ .portb = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_S952] = { ++ .name = "DVBSKY S952", ++ .portb = CX23885_MPEG_DVB, ++ .portc = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_S950_CI] = { ++ .ci_type = 3, ++ .name = "DVBSKY S950CI DVB-S2 CI", ++ .portb = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_C2800E_CI] = { ++ .ci_type = 3, ++ .name = "DVBSKY C2800E DVB-C CI", ++ .portb = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_T9580] = { ++ .name = "DVBSKY T9580", ++ .portb = CX23885_MPEG_DVB, ++ .portc = CX23885_MPEG_DVB, ++ }, + [CX23885_BOARD_PROF_8000] = { + .name = "Prof Revolution DVB-S2 8000", + .portb = CX23885_MPEG_DVB, +@@ -605,7 +633,7 @@ + CX25840_NONE1_CH3, + .amux = CX25840_AUDIO6, + } }, +- } ++ } + }; + const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); + +@@ -818,6 +846,30 @@ + .subdevice = 0x9022, + .card = CX23885_BOARD_TEVII_S471, + }, { ++ .subvendor = 0x14f1, ++ .subdevice = 0x8512, ++ .card = CX23885_BOARD_BST_PS8512, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x0950, ++ .card = CX23885_BOARD_DVBSKY_S950, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x0952, ++ .card = CX23885_BOARD_DVBSKY_S952, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x950C, ++ .card = CX23885_BOARD_DVBSKY_S950_CI, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x2800, ++ .card = CX23885_BOARD_DVBSKY_C2800E_CI, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x9580, ++ .card = CX23885_BOARD_DVBSKY_T9580, ++ }, { + .subvendor = 0x8000, + .subdevice = 0x3034, + .card = CX23885_BOARD_PROF_8000, +@@ -1224,7 +1276,7 @@ + cx_set(GP0_IO, 0x00040004); + break; + case CX23885_BOARD_TBS_6920: +- case CX23885_BOARD_PROF_8000: ++ case CX23885_BOARD_PROF_8000: + cx_write(MC417_CTL, 0x00000036); + cx_write(MC417_OEN, 0x00001000); + cx_set(MC417_RWD, 0x00000002); +@@ -1394,9 +1446,84 @@ + cx_set(GP0_IO, 0x00040004); + mdelay(60); + break; ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_BST_PS8512: ++ cx23885_gpio_enable(dev, GPIO_2, 1); ++ cx23885_gpio_clear(dev, GPIO_2); ++ msleep(100); ++ cx23885_gpio_set(dev, GPIO_2); ++ break; ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_T9580: ++ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ ++ ++ cx23885_gpio_enable(dev, GPIO_2, 1); ++ cx23885_gpio_enable(dev, GPIO_11, 1); ++ ++ cx23885_gpio_clear(dev, GPIO_2); ++ cx23885_gpio_clear(dev, GPIO_11); ++ msleep(100); ++ cx23885_gpio_set(dev, GPIO_2); ++ cx23885_gpio_set(dev, GPIO_11); ++ break; ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ /* GPIO-0 INTA from CiMax, input ++ GPIO-1 reset CiMax, output, high active ++ GPIO-2 reset demod, output, low active ++ GPIO-3 to GPIO-10 data/addr for CAM ++ GPIO-11 ~CS0 to CiMax1 ++ GPIO-12 ~CS1 to CiMax2 ++ GPIO-13 ADL0 load LSB addr ++ GPIO-14 ADL1 load MSB addr ++ GPIO-15 ~RDY from CiMax ++ GPIO-17 ~RD to CiMax ++ GPIO-18 ~WR to CiMax ++ */ ++ cx_set(GP0_IO, 0x00060002); /* GPIO 1/2 as output */ ++ cx_clear(GP0_IO, 0x00010004); /*GPIO 0 as input*/ ++ mdelay(100);/* reset delay */ ++ cx_set(GP0_IO, 0x00060004); /* GPIO as out, reset high */ ++ cx_clear(GP0_IO, 0x00010002); ++ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ ++ /* GPIO-15 IN as ~ACK, rest as OUT */ ++ cx_write(MC417_OEN, 0x00001000); ++ /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */ ++ cx_write(MC417_RWD, 0x0000c300); ++ /* enable irq */ ++ cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ ++ break; + } + } + ++static int cx23885_ir_patch(struct i2c_adapter *i2c, u8 reg, u8 mask) ++{ ++ struct i2c_msg msgs[2]; ++ u8 tx_buf[2], rx_buf[1]; ++ /* Write register address */ ++ tx_buf[0] = reg; ++ msgs[0].addr = 0x4c; ++ msgs[0].flags = 0; ++ msgs[0].len = 1; ++ msgs[0].buf = (char *) tx_buf; ++ /* Read data from register */ ++ msgs[1].addr = 0x4c; ++ msgs[1].flags = I2C_M_RD; ++ msgs[1].len = 1; ++ msgs[1].buf = (char *) rx_buf; ++ ++ i2c_transfer(i2c, msgs, 2); ++ ++ tx_buf[0] = reg; ++ tx_buf[1] = rx_buf[0] | mask; ++ msgs[0].addr = 0x4c; ++ msgs[0].flags = 0; ++ msgs[0].len = 2; ++ msgs[0].buf = (char *) tx_buf; ++ ++ return i2c_transfer(i2c, msgs, 1); ++} ++ + int cx23885_ir_init(struct cx23885_dev *dev) + { + static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = { +@@ -1482,6 +1609,23 @@ + v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, + ir_rx_pin_cfg_count, ir_rx_pin_cfg); + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: ++ dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE); ++ if (dev->sd_ir == NULL) { ++ ret = -ENODEV; ++ break; ++ } ++ v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, ++ ir_rx_pin_cfg_count, ir_rx_pin_cfg); ++ ++ cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x1f,0x80); ++ cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x23,0x80); ++ break; + case CX23885_BOARD_HAUPPAUGE_HVR1250: + if (!enable_885_ir) + break; +@@ -1511,9 +1655,15 @@ + cx23888_ir_remove(dev); + dev->sd_ir = NULL; + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: + case CX23885_BOARD_TEVII_S470: +- case CX23885_BOARD_HAUPPAUGE_HVR1250: ++ case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_MYGICA_X8507: + cx23885_irq_remove(dev, PCI_MSK_AV_CORE); + /* sd_ir is a duplicate pointer to the AV Core, just clear it */ +@@ -1556,6 +1706,12 @@ + if (dev->sd_ir) + cx23885_irq_add_enable(dev, PCI_MSK_IR); + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_HAUPPAUGE_HVR1250: +@@ -1657,6 +1813,10 @@ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_TEVII_S471: + case CX23885_BOARD_DVBWORLD_2005: +@@ -1694,6 +1854,22 @@ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; ++ case CX23885_BOARD_DVBSKY_S952: ++ ts1->gen_ctrl_val = 0x5; /* Parallel */ ++ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ++ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ++ ts2->gen_ctrl_val = 0xe; /* Serial bus + punctured clock */ ++ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ++ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ++ break; ++ case CX23885_BOARD_DVBSKY_T9580: ++ ts1->gen_ctrl_val = 0x5; /* Parallel */ ++ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ++ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ++ ts2->gen_ctrl_val = 0x8; /* Serial bus */ ++ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ++ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ++ break; + case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_HAUPPAUGE_HVR1500: + case CX23885_BOARD_HAUPPAUGE_HVR1500Q: +@@ -1749,6 +1925,12 @@ + case CX23885_BOARD_MPX885: + case CX23885_BOARD_MYGICA_X8507: + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_AVERMEDIA_HC81R: + dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[2].i2c_adap, +diff -urN a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c +--- a/drivers/media/pci/cx23885/cx23885-core.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885-core.c 2013-05-03 17:36:31.000000000 +0800 +@@ -1909,6 +1909,10 @@ + (pci_status & PCI_MSK_GPIO0)) + handled += altera_ci_irq(dev); + ++ if (cx23885_boards[dev->board].ci_type == 3 && ++ (pci_status & PCI_MSK_GPIO0)) ++ handled += dvbsky_ci_slot_status(dev); ++ + if (ts1_status) { + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) + handled += cx23885_irq_ts(ts1, ts1_status); +@@ -2144,6 +2148,8 @@ + cx23885_irq_add_enable(dev, PCI_MSK_GPIO1 | PCI_MSK_GPIO0); + break; + case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: + cx23885_irq_add_enable(dev, PCI_MSK_GPIO0); + break; + } +diff -urN a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c +--- a/drivers/media/pci/cx23885/cx23885-dvb.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885-dvb.c 2013-05-03 17:38:34.000000000 +0800 +@@ -51,6 +51,8 @@ + #include "stv6110.h" + #include "lnbh24.h" + #include "cx24116.h" ++#include "m88ds3103.h" ++#include "m88dc2800.h" + #include "cimax2.h" + #include "lgs8gxx.h" + #include "netup-eeprom.h" +@@ -64,8 +66,8 @@ + #include "stv0367.h" + #include "drxk.h" + #include "mt2063.h" +-#include "stv090x.h" +-#include "stb6100.h" ++#include "stv090x.h" ++#include "stb6100.h" + #include "stb6100_cfg.h" + #include "tda10071.h" + #include "a8293.h" +@@ -500,42 +502,130 @@ + .if_khz = 5380, + }; + +-static struct stv090x_config prof_8000_stv090x_config = { +- .device = STV0903, +- .demod_mode = STV090x_SINGLE, +- .clk_mode = STV090x_CLK_EXT, +- .xtal = 27000000, +- .address = 0x6A, +- .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, +- .repeater_level = STV090x_RPTLEVEL_64, +- .adc1_range = STV090x_ADC_2Vpp, +- .diseqc_envelope_mode = false, +- +- .tuner_get_frequency = stb6100_get_frequency, +- .tuner_set_frequency = stb6100_set_frequency, +- .tuner_set_bandwidth = stb6100_set_bandwidth, +- .tuner_get_bandwidth = stb6100_get_bandwidth, +-}; + +-static struct stb6100_config prof_8000_stb6100_config = { +- .tuner_address = 0x60, +- .refclock = 27000000, +-}; +- +-static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++/* bst control */ ++int bst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) + { + struct cx23885_tsport *port = fe->dvb->priv; + struct cx23885_dev *dev = port->dev; ++ ++ cx23885_gpio_enable(dev, GPIO_1, 1); ++ cx23885_gpio_enable(dev, GPIO_0, 1); ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cx23885_gpio_set(dev, GPIO_1); ++ cx23885_gpio_clear(dev, GPIO_0); ++ break; ++ case SEC_VOLTAGE_18: ++ cx23885_gpio_set(dev, GPIO_1); ++ cx23885_gpio_set(dev, GPIO_0); ++ break; ++ case SEC_VOLTAGE_OFF: ++ cx23885_gpio_clear(dev, GPIO_1); ++ cx23885_gpio_clear(dev, GPIO_0); ++ break; ++ } ++ return 0; ++} + +- if (voltage == SEC_VOLTAGE_18) +- cx_write(MC417_RWD, 0x00001e00); +- else if (voltage == SEC_VOLTAGE_13) +- cx_write(MC417_RWD, 0x00001a00); +- else +- cx_write(MC417_RWD, 0x00001800); ++int dvbsky_set_voltage_sec(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct cx23885_tsport *port = fe->dvb->priv; ++ struct cx23885_dev *dev = port->dev; ++ ++ cx23885_gpio_enable(dev, GPIO_12, 1); ++ cx23885_gpio_enable(dev, GPIO_13, 1); ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cx23885_gpio_set(dev, GPIO_13); ++ cx23885_gpio_clear(dev, GPIO_12); ++ break; ++ case SEC_VOLTAGE_18: ++ cx23885_gpio_set(dev, GPIO_13); ++ cx23885_gpio_set(dev, GPIO_12); ++ break; ++ case SEC_VOLTAGE_OFF: ++ cx23885_gpio_clear(dev, GPIO_13); ++ cx23885_gpio_clear(dev, GPIO_12); ++ break; ++ } + return 0; + } + ++/* bestunar single dvb-s2 */ ++static struct m88ds3103_config bst_ds3103_config = { ++ .demod_address = 0x68, ++ .ci_mode = 0, ++ .pin_ctrl = 0x82, ++ .ts_mode = 0, ++ .set_voltage = bst_set_voltage, ++}; ++/* DVBSKY dual dvb-s2 */ ++static struct m88ds3103_config dvbsky_ds3103_config_pri = { ++ .demod_address = 0x68, ++ .ci_mode = 0, ++ .pin_ctrl = 0x82, ++ .ts_mode = 0, ++ .set_voltage = bst_set_voltage, ++}; ++static struct m88ds3103_config dvbsky_ds3103_config_sec = { ++ .demod_address = 0x68, ++ .ci_mode = 0, ++ .pin_ctrl = 0x82, ++ .ts_mode = 1, ++ .set_voltage = dvbsky_set_voltage_sec, ++}; ++ ++static struct m88ds3103_config dvbsky_ds3103_ci_config = { ++ .demod_address = 0x68, ++ .ci_mode = 2, ++ .pin_ctrl = 0x82, ++ .ts_mode = 0, ++}; ++ ++static struct m88dc2800_config dvbsky_dc2800_config = { ++ .demod_address = 0x1c, ++ .ts_mode = 3, ++}; ++ ++static struct stv090x_config prof_8000_stv090x_config = { ++ .device = STV0903, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ .xtal = 27000000, ++ .address = 0x6A, ++ .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, ++ .repeater_level = STV090x_RPTLEVEL_64, ++ .adc1_range = STV090x_ADC_2Vpp, ++ .diseqc_envelope_mode = false, ++ ++ .tuner_get_frequency = stb6100_get_frequency, ++ .tuner_set_frequency = stb6100_set_frequency, ++ .tuner_set_bandwidth = stb6100_set_bandwidth, ++ .tuner_get_bandwidth = stb6100_get_bandwidth, ++}; ++ ++static struct stb6100_config prof_8000_stb6100_config = { ++ .tuner_address = 0x60, ++ .refclock = 27000000, ++}; ++ ++static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct cx23885_tsport *port = fe->dvb->priv; ++ struct cx23885_dev *dev = port->dev; ++ ++ if (voltage == SEC_VOLTAGE_18) ++ cx_write(MC417_RWD, 0x00001e00); ++ else if (voltage == SEC_VOLTAGE_13) ++ cx_write(MC417_RWD, 0x00001a00); ++ else ++ cx_write(MC417_RWD, 0x00001800); ++ return 0; ++} ++ + static int cx23885_dvb_set_frontend(struct dvb_frontend *fe) + { + struct dtv_frontend_properties *p = &fe->dtv_property_cache; +@@ -1250,23 +1340,79 @@ + &tevii_ds3000_config, + &i2c_bus->i2c_adap); + break; +- case CX23885_BOARD_PROF_8000: +- i2c_bus = &dev->i2c_bus[0]; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &bst_ds3103_config, ++ &i2c_bus->i2c_adap); ++ break; ++ ++ case CX23885_BOARD_DVBSKY_S952: ++ switch (port->nr) { ++ /* port B */ ++ case 1: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_config_pri, ++ &i2c_bus->i2c_adap); ++ break; ++ /* port C */ ++ case 2: ++ i2c_bus = &dev->i2c_bus[0]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_config_sec, ++ &i2c_bus->i2c_adap); ++ break; ++ } ++ break; + +- fe0->dvb.frontend = dvb_attach(stv090x_attach, +- &prof_8000_stv090x_config, +- &i2c_bus->i2c_adap, +- STV090x_DEMODULATOR_0); +- if (fe0->dvb.frontend != NULL) { +- if (!dvb_attach(stb6100_attach, +- fe0->dvb.frontend, +- &prof_8000_stb6100_config, +- &i2c_bus->i2c_adap)) +- goto frontend_detach; ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_ci_config, ++ &i2c_bus->i2c_adap); ++ break; ++ ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88dc2800_attach, ++ &dvbsky_dc2800_config, ++ &i2c_bus->i2c_adap); ++ break; + +- fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; ++ case CX23885_BOARD_DVBSKY_T9580: ++ switch (port->nr) { ++ /* port B */ ++ case 1: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_config_pri, ++ &i2c_bus->i2c_adap); ++ break; ++ /* port C */ ++ case 2: ++ break; + } + break; ++ ++ case CX23885_BOARD_PROF_8000: ++ i2c_bus = &dev->i2c_bus[0]; ++ ++ fe0->dvb.frontend = dvb_attach(stv090x_attach, ++ &prof_8000_stv090x_config, ++ &i2c_bus->i2c_adap, ++ STV090x_DEMODULATOR_0); ++ if (fe0->dvb.frontend != NULL) { ++ if (!dvb_attach(stb6100_attach, ++ fe0->dvb.frontend, ++ &prof_8000_stb6100_config, ++ &i2c_bus->i2c_adap)) ++ goto frontend_detach; ++ ++ fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; ++ } ++ break; + case CX23885_BOARD_HAUPPAUGE_HVR4400: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(tda10071_attach, +@@ -1325,7 +1471,7 @@ + printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n", + port->nr, port->frontends.adapter.proposed_mac); + +- netup_ci_init(port); ++ netup_ci_init(port, false); + break; + } + case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: { +@@ -1352,6 +1498,41 @@ + memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); + break; + } ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_T9580:{ ++ u8 eeprom[256]; /* 24C02 i2c eeprom */ ++ ++ if(port->nr > 2) ++ break; ++ ++ dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; ++ tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); ++ printk(KERN_INFO "DVBSKY PCIe MAC= %pM\n", eeprom + 0xc0+(port->nr-1)*8); ++ memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 + ++ (port->nr-1)*8, 6); ++ break; ++ } ++ case CX23885_BOARD_DVBSKY_S950_CI: { ++ u8 eeprom[256]; /* 24C02 i2c eeprom */ ++ ++ if(port->nr > 2) ++ break; ++ ++ dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; ++ tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); ++ printk(KERN_INFO "DVBSKY PCIe MAC= %pM\n", eeprom + 0xc0+(port->nr-1)*8); ++ memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 + ++ (port->nr-1)*8, 6); ++ ++ netup_ci_init(port, true); ++ break; ++ } ++ case CX23885_BOARD_DVBSKY_C2800E_CI: { ++ netup_ci_init(port, true); ++ break; ++ } + } + + return ret; +@@ -1434,6 +1615,8 @@ + + switch (port->dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: + netup_ci_exit(port); + break; + case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: +diff -urN a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h +--- a/drivers/media/pci/cx23885/cx23885.h 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885.h 2013-05-03 17:14:20.000000000 +0800 +@@ -94,6 +94,14 @@ + #define CX23885_BOARD_HAUPPAUGE_HVR4400 38 + #define CX23885_BOARD_AVERMEDIA_HC81R 39 + ++#define CX23885_BOARD_BASE_INDEX 40 ++#define CX23885_BOARD_BST_PS8512 (CX23885_BOARD_BASE_INDEX) ++#define CX23885_BOARD_DVBSKY_S952 (CX23885_BOARD_BASE_INDEX+1) ++#define CX23885_BOARD_DVBSKY_S950 (CX23885_BOARD_BASE_INDEX+2) ++#define CX23885_BOARD_DVBSKY_S950_CI (CX23885_BOARD_BASE_INDEX+3) ++#define CX23885_BOARD_DVBSKY_C2800E_CI (CX23885_BOARD_BASE_INDEX+4) ++#define CX23885_BOARD_DVBSKY_T9580 (CX23885_BOARD_BASE_INDEX+5) ++ + #define GPIO_0 0x00000001 + #define GPIO_1 0x00000002 + #define GPIO_2 0x00000004 +@@ -231,7 +239,7 @@ + */ + u32 clk_freq; + struct cx23885_input input[MAX_CX23885_INPUT]; +- int ci_type; /* for NetUP */ ++ int ci_type; /* 1 and 2 for NetUP, 3 for DVBSky. */ + /* Force bottom field first during DMA (888 workaround) */ + u32 force_bff; + }; +diff -urN a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c +--- a/drivers/media/pci/cx23885/cx23885-input.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885-input.c 2013-05-03 17:42:09.000000000 +0800 +@@ -89,6 +89,12 @@ + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_HAUPPAUGE_HVR1250: ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_MYGICA_X8507: + /* + * The only boards we handle right now. However other boards +@@ -141,6 +147,12 @@ + case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: + case CX23885_BOARD_HAUPPAUGE_HVR1250: ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_MYGICA_X8507: + /* + * The IR controller on this board only returns pulse widths. +@@ -291,6 +303,18 @@ + /* A guess at the remote */ + rc_map = RC_MAP_TEVII_NEC; + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: ++ /* Integrated CX2388[58] IR controller */ ++ driver_type = RC_DRIVER_IR_RAW; ++ allowed_protos = RC_BIT_ALL; ++ /* A guess at the remote */ ++ rc_map = RC_MAP_DVBSKY; ++ break; + case CX23885_BOARD_MYGICA_X8507: + /* Integrated CX23885 IR controller */ + driver_type = RC_DRIVER_IR_RAW; +diff -urN a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig +--- a/drivers/media/pci/cx23885/Kconfig 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/Kconfig 2013-05-03 17:43:05.000000000 +0800 +@@ -23,6 +23,8 @@ + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_M88DC2800 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT +diff -urN a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c +--- a/drivers/media/pci/cx88/cx88-cards.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/cx88-cards.c 2013-05-03 17:06:55.000000000 +0800 +@@ -2309,6 +2309,18 @@ + } }, + .mpeg = CX88_MPEG_DVB, + }, ++ [CX88_BOARD_BST_PS8312] = { ++ .name = "Bestunar PS8312 DVB-S/S2", ++ .tuner_type = UNSET, ++ .radio_type = UNSET, ++ .tuner_addr = ADDR_UNSET, ++ .radio_addr = ADDR_UNSET, ++ .input = { { ++ .type = CX88_VMUX_DVB, ++ .vmux = 0, ++ } }, ++ .mpeg = CX88_MPEG_DVB, ++ }, + }; + + /* ------------------------------------------------------------------ */ +@@ -2813,6 +2825,10 @@ + .subvendor = 0x1822, + .subdevice = 0x0023, + .card = CX88_BOARD_TWINHAN_VP1027_DVBS, ++ }, { ++ .subvendor = 0x14f1, ++ .subdevice = 0x8312, ++ .card = CX88_BOARD_BST_PS8312, + }, + }; + +@@ -3547,6 +3563,12 @@ + cx_write(MO_SRST_IO, 1); + msleep(100); + break; ++ case CX88_BOARD_BST_PS8312: ++ cx_write(MO_GP1_IO, 0x808000); ++ msleep(100); ++ cx_write(MO_GP1_IO, 0x808080); ++ msleep(100); ++ break; + } /*end switch() */ + + +diff -urN a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c +--- a/drivers/media/pci/cx88/cx88-dvb.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/cx88-dvb.c 2013-05-03 17:09:09.000000000 +0800 +@@ -54,6 +54,7 @@ + #include "stv0288.h" + #include "stb6000.h" + #include "cx24116.h" ++#include "m88ds3103.h" + #include "stv0900.h" + #include "stb6100.h" + #include "stb6100_proc.h" +@@ -459,6 +460,56 @@ + return core->prev_set_voltage(fe, voltage); + return 0; + } ++/*CX88_BOARD_BST_PS8312*/ ++static int bst_dvbs_set_voltage(struct dvb_frontend *fe, ++ fe_sec_voltage_t voltage) ++{ ++ struct cx8802_dev *dev= fe->dvb->priv; ++ struct cx88_core *core = dev->core; ++ ++ cx_write(MO_GP1_IO, 0x111111); ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cx_write(MO_GP1_IO, 0x020200); ++ break; ++ case SEC_VOLTAGE_18: ++ cx_write(MO_GP1_IO, 0x020202); ++ break; ++ case SEC_VOLTAGE_OFF: ++ cx_write(MO_GP1_IO, 0x111100); ++ break; ++ } ++ ++ if (core->prev_set_voltage) ++ return core->prev_set_voltage(fe, voltage); ++ return 0; ++} ++ ++static int bst_dvbs_set_voltage_v2(struct dvb_frontend *fe, ++ fe_sec_voltage_t voltage) ++{ ++ struct cx8802_dev *dev= fe->dvb->priv; ++ struct cx88_core *core = dev->core; ++ ++ cx_write(MO_GP1_IO, 0x111101); ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cx_write(MO_GP1_IO, 0x020200); ++ break; ++ case SEC_VOLTAGE_18: ++ ++ cx_write(MO_GP1_IO, 0x020202); ++ break; ++ case SEC_VOLTAGE_OFF: ++ ++ cx_write(MO_GP1_IO, 0x111110); ++ break; ++ } ++ ++ if (core->prev_set_voltage) ++ return core->prev_set_voltage(fe, voltage); ++ return 0; ++} + + static int vp1027_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t voltage) +@@ -706,6 +757,11 @@ + .clk_out_div = 1, + }; + ++static struct m88ds3103_config dvbsky_ds3103_config = { ++ .demod_address = 0x68, ++ .set_ts_params = ds3000_set_ts_param, ++}; ++ + static const struct stv0900_config prof_7301_stv0900_config = { + .demod_address = 0x6a, + /* demod_mode = 0,*/ +@@ -1477,6 +1533,35 @@ + &tevii_ts2020_config, &core->i2c_adap); + fe0->dvb.frontend->ops.set_voltage = + tevii_dvbs_set_voltage; ++ } ++ break; ++ case CX88_BOARD_BST_PS8312: ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_config, ++ &core->i2c_adap); ++ if (fe0->dvb.frontend != NULL){ ++ int ret; ++ u8 b0[] = { 0x60 }; ++ u8 b1[2] = { 0 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = 0x50, ++ .flags = 0, ++ .buf = b0, ++ .len = 1 ++ }, { ++ .addr = 0x50, ++ .flags = I2C_M_RD, ++ .buf = b1, ++ .len = 2 ++ } ++ }; ++ ret = i2c_transfer(&core->i2c_adap, msg, 2); ++ printk("PS8312: config = %02x, %02x", b1[0],b1[1]); ++ if(b1[0] == 0xaa) ++ fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage_v2; ++ else ++ fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage; + } + break; + case CX88_BOARD_OMICOM_SS4_PCI: +diff -urN a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h +--- a/drivers/media/pci/cx88/cx88.h 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/cx88.h 2013-05-03 17:05:57.000000000 +0800 +@@ -238,6 +238,7 @@ + #define CX88_BOARD_WINFAST_DTV1800H_XC4000 88 + #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89 + #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90 ++#define CX88_BOARD_BST_PS8312 91 + + enum cx88_itype { + CX88_VMUX_COMPOSITE1 = 1, +diff -urN a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c +--- a/drivers/media/pci/cx88/cx88-input.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/cx88-input.c 2013-01-26 14:52:03.000000000 +0800 +@@ -419,6 +419,10 @@ + rc_type = RC_BIT_NEC; + ir->sampling = 0xff00; /* address */ + break; ++ case CX88_BOARD_BST_PS8312: ++ ir_codes = RC_MAP_DVBSKY; ++ ir->sampling = 0xff00; /* address */ ++ break; + } + + if (!ir_codes) { +diff -urN a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig +--- a/drivers/media/pci/cx88/Kconfig 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/Kconfig 2013-05-03 17:10:41.000000000 +0800 +@@ -57,6 +57,7 @@ + select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT +diff -urN a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile +--- a/drivers/media/rc/keymaps/Makefile 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/rc/keymaps/Makefile 2013-05-03 17:43:41.000000000 +0800 +@@ -27,6 +27,7 @@ + rc-dm1105-nec.o \ + rc-dntv-live-dvb-t.o \ + rc-dntv-live-dvbt-pro.o \ ++ rc-dvbsky.o \ + rc-em-terratec.o \ + rc-encore-enltv2.o \ + rc-encore-enltv.o \ +diff -urN a/drivers/media/rc/keymaps/rc-dvbsky.c b/drivers/media/rc/keymaps/rc-dvbsky.c +--- a/drivers/media/rc/keymaps/rc-dvbsky.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/rc/keymaps/rc-dvbsky.c 2013-01-26 14:52:49.000000000 +0800 +@@ -0,0 +1,78 @@ ++/* rc-dvbsky.c - Keytable for Dvbsky Remote Controllers ++ * ++ * keymap imported from ir-keymaps.c ++ * ++ * ++ * Copyright (c) 2010-2012 by Nibble Max ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++/* ++ * This table contains the complete RC5 code, instead of just the data part ++ */ ++ ++static struct rc_map_table rc5_dvbsky[] = { ++ { 0x0000, KEY_0 }, ++ { 0x0001, KEY_1 }, ++ { 0x0002, KEY_2 }, ++ { 0x0003, KEY_3 }, ++ { 0x0004, KEY_4 }, ++ { 0x0005, KEY_5 }, ++ { 0x0006, KEY_6 }, ++ { 0x0007, KEY_7 }, ++ { 0x0008, KEY_8 }, ++ { 0x0009, KEY_9 }, ++ { 0x000a, KEY_MUTE }, ++ { 0x000d, KEY_OK }, ++ { 0x000b, KEY_STOP }, ++ { 0x000c, KEY_EXIT }, ++ { 0x000e, KEY_CAMERA }, /*Snap shot*/ ++ { 0x000f, KEY_SUBTITLE }, /*PIP*/ ++ { 0x0010, KEY_VOLUMEUP }, ++ { 0x0011, KEY_VOLUMEDOWN }, ++ { 0x0012, KEY_FAVORITES }, ++ { 0x0013, KEY_LIST }, /*Info*/ ++ { 0x0016, KEY_PAUSE }, ++ { 0x0017, KEY_PLAY }, ++ { 0x001f, KEY_RECORD }, ++ { 0x0020, KEY_CHANNELDOWN }, ++ { 0x0021, KEY_CHANNELUP }, ++ { 0x0025, KEY_POWER2 }, ++ { 0x0026, KEY_REWIND }, ++ { 0x0027, KEY_FASTFORWARD }, ++ { 0x0029, KEY_LAST }, ++ { 0x002b, KEY_MENU }, ++ { 0x002c, KEY_EPG }, ++ { 0x002d, KEY_ZOOM }, ++}; ++ ++static struct rc_map_list rc5_dvbsky_map = { ++ .map = { ++ .scan = rc5_dvbsky, ++ .size = ARRAY_SIZE(rc5_dvbsky), ++ .rc_type = RC_TYPE_RC5, ++ .name = RC_MAP_DVBSKY, ++ } ++}; ++ ++static int __init init_rc_map_rc5_dvbsky(void) ++{ ++ return rc_map_register(&rc5_dvbsky_map); ++} ++ ++static void __exit exit_rc_map_rc5_dvbsky(void) ++{ ++ rc_map_unregister(&rc5_dvbsky_map); ++} ++ ++module_init(init_rc_map_rc5_dvbsky) ++module_exit(exit_rc_map_rc5_dvbsky) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Nibble Max "); +diff -urN a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c +--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c 2013-05-03 17:47:38.000000000 +0800 +@@ -0,0 +1,665 @@ ++/* ++ * Driver for DVBSky USB2.0 receiver ++ * ++ * Copyright (C) 2013 Max nibble ++ * ++ * CIMax code is copied and modified from: ++ * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card ++ * Copyright (C) 2009 NetUP Inc. ++ * Copyright (C) 2009 Igor M. Liplianin ++ * Copyright (C) 2009 Abylay Ospan ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include "dvb_ca_en50221.h" ++#include "dvb_usb.h" ++#include "m88ds3103.h" ++ ++static int dvbsky_debug; ++module_param(dvbsky_debug, int, 0644); ++MODULE_PARM_DESC(dvbsky_debug, "Activates dvbsky usb debugging (default:0)"); ++ ++#define DVBSKY_CI_CTL 0x04 ++#define DVBSKY_CI_RD 1 ++ ++#define dprintk(args...) \ ++ do { \ ++ if (dvbsky_debug) \ ++ printk(KERN_INFO "dvbsky_usb: " args); \ ++ } while (0) ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++struct dvbsky_state { ++ struct mutex stream_mutex; ++ u8 has_ci; ++ u8 ci_attached; ++ struct dvb_ca_en50221 ci; ++ unsigned long next_status_checked_time; ++ u8 ci_i2c_addr; ++ u8 current_ci_flag; ++ int ci_status; ++}; ++ ++static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) ++{ ++ struct dvbsky_state *state = d_to_priv(d); ++ int ret; ++ u8 obuf_pre[3] = { 0x37, 0, 0 }; ++ u8 obuf_post[3] = { 0x36, 3, 0 }; ++ dprintk("%s() -off \n", __func__); ++ mutex_lock(&state->stream_mutex); ++ ret = dvb_usbv2_generic_write(d, obuf_pre, 3); ++ if (!ret && onoff) { ++ msleep(10); ++ ret = dvb_usbv2_generic_write(d, obuf_post, 3); ++ dprintk("%s() -on \n", __func__); ++ } ++ mutex_unlock(&state->stream_mutex); ++ return ret; ++} ++ ++/* CI opertaions */ ++static int dvbsky_ci_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, ++ u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg[] = { ++ { ++ .addr = addr, ++ .flags = 0, ++ .buf = ®, ++ .len = 1 ++ }, { ++ .addr = addr, ++ .flags = I2C_M_RD, ++ .buf = buf, ++ .len = len ++ } ++ }; ++ ++ ret = i2c_transfer(i2c_adap, msg, 2); ++ ++ if (ret != 2) { ++ dprintk("%s: error, Reg = 0x%02x, Status = %d\n", __func__, reg, ret); ++ return -1; ++ } ++ return 0; ++} ++ ++static int dvbsky_ci_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, ++ u8 *buf, int len) ++{ ++ int ret; ++ u8 buffer[len + 1]; ++ ++ struct i2c_msg msg = { ++ .addr = addr, ++ .flags = 0, ++ .buf = &buffer[0], ++ .len = len + 1 ++ }; ++ ++ buffer[0] = reg; ++ memcpy(&buffer[1], buf, len); ++ ++ ret = i2c_transfer(i2c_adap, &msg, 1); ++ ++ if (ret != 1) { ++ dprintk("%s: error, Reg=[0x%02x], Status=%d\n", __func__, reg, ret); ++ return -1; ++ } ++ return 0; ++} ++ ++static int dvbsky_ci_op_cam(struct dvb_ca_en50221 *ci, int slot, ++ u8 flag, u8 read, int addr, u8 data) ++{ ++ struct dvb_usb_device *d = ci->data; ++ struct dvbsky_state *state = d_to_priv(d); ++ u8 store; ++ int ret; ++ u8 command[4], respond[2], command_size, respond_size; ++ ++ /*dprintk("%s()\n", __func__);*/ ++ if (0 != slot) ++ return -EINVAL; ++ ++ if (state->current_ci_flag != flag) { ++ ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &store, 1); ++ if (ret != 0) ++ return ret; ++ ++ store &= ~0x0c; ++ store |= flag; ++ ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &store, 1); ++ if (ret != 0) ++ return ret; ++ } ++ state->current_ci_flag = flag; ++ ++ command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/ ++ command[2] = (u8)(addr & 0xff); /*low part of address*/ ++ if (read) { ++ command[0] = 0x71; ++ command_size = 3; ++ respond_size = 2; ++ } else { ++ command[0] = 0x70; ++ command[3] = data; ++ command_size = 4; ++ respond_size = 1; ++ } ++ ret = dvb_usbv2_generic_rw(d, command, command_size, respond, respond_size); ++ ++ return (read) ? respond[1] : 0; ++} ++ ++static int dvbsky_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, ++ int slot, int addr) ++{ ++ return dvbsky_ci_op_cam(ci, slot, 0, DVBSKY_CI_RD, addr, 0); ++} ++ ++static int dvbsky_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, ++ int slot, int addr, u8 data) ++{ ++ return dvbsky_ci_op_cam(ci, slot, 0, 0, addr, data); ++} ++ ++static int dvbsky_ci_read_cam_ctl(struct dvb_ca_en50221 *ci, int slot, u8 addr) ++{ ++ return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, DVBSKY_CI_RD, addr, 0); ++} ++ ++static int dvbsky_ci_write_cam_ctl(struct dvb_ca_en50221 *ci, int slot, ++ u8 addr, u8 data) ++{ ++ return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, 0, addr, data); ++} ++ ++static int dvbsky_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot) ++{ ++ struct dvb_usb_device *d = ci->data; ++ struct dvbsky_state *state = d_to_priv(d); ++ u8 buf = 0x80; ++ int ret; ++ dprintk("%s() slot=%d\n", __func__, slot); ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ udelay(500); ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ ++ if (ret != 0) ++ return ret; ++ ++ udelay(500); ++ ++ buf = 0x00; ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ msleep(1000); ++ dprintk("%s() slot=%d complete\n", __func__, slot); ++ return 0; ++ ++} ++ ++static int dvbsky_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot) ++{ ++ /* not implemented */ ++ dprintk("%s()\n", __func__); ++ return 0; ++} ++ ++static int dvbsky_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot) ++{ ++ struct dvb_usb_device *d = ci->data; ++ struct dvbsky_state *state = d_to_priv(d); ++ u8 buf; ++ int ret; ++ ++ dprintk("%s()\n", __func__); ++ if (0 != slot) ++ return -EINVAL; ++ ++ dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ buf |= 0x60; ++ ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ return ret; ++} ++ ++static int dvbsky_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, ++ int open) ++{ ++ struct dvb_usb_device *d = ci->data; ++ struct dvbsky_state *state = d_to_priv(d); ++ int ret = 0; ++ u8 buf = 0; ++ /*dprintk("%s()\n", __func__);*/ ++ ++ /* CAM module INSERT/REMOVE processing. slow operation because of i2c ++ * transfers */ ++ if (time_after(jiffies, state->next_status_checked_time)) { ++ ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ ++ /*dprintk("%s() status=%x\n", __func__, buf);*/ ++ ++ state->next_status_checked_time = jiffies ++ + msecs_to_jiffies(1000); ++ ++ if (ret != 0) ++ return 0; ++ ++ if (buf & 1) { ++ state->ci_status = DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY; ++ } ++ else ++ state->ci_status = 0; ++ } ++ /*dprintk("%s() ret=%x\n", __func__, state->ci_status);*/ ++ return state->ci_status; ++} ++ ++static int dvbsky_ci_init(struct dvb_usb_device *d) ++{ ++ struct dvbsky_state *state = d_to_priv(d); ++ int ret; ++ u8 cimax_init[34] = { ++ 0x00, /* module A control*/ ++ 0x00, /* auto select mask high A */ ++ 0x00, /* auto select mask low A */ ++ 0x00, /* auto select pattern high A */ ++ 0x00, /* auto select pattern low A */ ++ 0x44, /* memory access time A */ ++ 0x00, /* invert input A */ ++ 0x00, /* RFU */ ++ 0x00, /* RFU */ ++ 0x00, /* module B control*/ ++ 0x00, /* auto select mask high B */ ++ 0x00, /* auto select mask low B */ ++ 0x00, /* auto select pattern high B */ ++ 0x00, /* auto select pattern low B */ ++ 0x44, /* memory access time B */ ++ 0x00, /* invert input B */ ++ 0x00, /* RFU */ ++ 0x00, /* RFU */ ++ 0x00, /* auto select mask high Ext */ ++ 0x00, /* auto select mask low Ext */ ++ 0x00, /* auto select pattern high Ext */ ++ 0x00, /* auto select pattern low Ext */ ++ 0x00, /* RFU */ ++ 0x02, /* destination - module A */ ++ 0x01, /* power on (use it like store place) */ ++ 0x00, /* RFU */ ++ 0x00, /* int status read only */ ++ 0x00, /* Max: Disable the interrupt in USB solution.*/ ++ 0x05, /* EXTINT=active-high, INT=push-pull */ ++ 0x00, /* USCG1 */ ++ 0x04, /* ack active low */ ++ 0x00, /* LOCK = 0 */ ++ 0x22, /* serial mode, rising in, rising out, MSB first*/ ++ 0x00 /* synchronization */ ++ }; ++ dprintk("%s()\n", __func__); ++ state->current_ci_flag = 0xff; ++ state->ci_status = 0; ++ state->next_status_checked_time = jiffies + msecs_to_jiffies(1000); ++ state->ci_i2c_addr = 0x40; ++ ++ state->ci.owner = THIS_MODULE; ++ state->ci.read_attribute_mem = dvbsky_ci_read_attribute_mem; ++ state->ci.write_attribute_mem = dvbsky_ci_write_attribute_mem; ++ state->ci.read_cam_control = dvbsky_ci_read_cam_ctl; ++ state->ci.write_cam_control = dvbsky_ci_write_cam_ctl; ++ state->ci.slot_reset = dvbsky_ci_slot_reset; ++ state->ci.slot_shutdown = dvbsky_ci_slot_shutdown; ++ state->ci.slot_ts_enable = dvbsky_ci_slot_ts_enable; ++ state->ci.poll_slot_status = dvbsky_ci_poll_slot_status; ++ state->ci.data = d; ++ ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &cimax_init[0], 34); ++ /* lock registers */ ++ ret |= dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0x1f, &cimax_init[0x18], 1); ++ /* power on slots */ ++ ret |= dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0x18, &cimax_init[0x18], 1); ++ if (0 != ret) ++ return ret; ++ ++ ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1); ++ if (ret) ++ return ret; ++ state->ci_attached = 1; ++ dprintk("%s() complete.\n", __func__); ++ return 0; ++} ++ ++static void dvbsky_ci_release(struct dvb_usb_device *d) ++{ ++ struct dvbsky_state *state = d_to_priv(d); ++ ++ /* detach CI */ ++ if (state->ci_attached) ++ dvb_ca_en50221_release(&state->ci); ++ ++ return; ++} ++ ++static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff) ++{ ++ struct dvb_usb_device *d = fe_to_d(fe); ++ /*dprintk("%s() %d\n", __func__, onoff);*/ ++ return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1); ++} ++ ++/* GPIO */ ++static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value) ++{ ++ u8 obuf[64], ibuf[64]; ++ obuf[0] = 0x0e; ++ obuf[1] = gport; ++ obuf[2] = value; ++ return dvb_usbv2_generic_rw(d, obuf, 3, ibuf, 1); ++} ++ ++/* I2C */ ++static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int ret = 0; ++ u8 ibuf[64], obuf[64]; ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ if (num > 2) { ++ printk(KERN_ERR "dvbsky_usb: too many i2c messages[%d] than 2.", num); ++ ret = -EOPNOTSUPP; ++ goto i2c_error; ++ } ++ ++ if(num == 1) { ++ if (msg[0].len > 60) { ++ printk(KERN_ERR "dvbsky_usb: too many i2c bytes[%d] than 60.", msg[0].len); ++ ret = -EOPNOTSUPP; ++ goto i2c_error; ++ } ++ if (msg[0].flags & I2C_M_RD) { ++ /* single read */ ++ obuf[0] = 0x09; ++ obuf[1] = 0; ++ obuf[2] = msg[0].len; ++ obuf[3] = msg[0].addr; ++ ret = dvb_usbv2_generic_rw(d, obuf, 4, ibuf, msg[0].len + 1); ++ /*dprintk("%s(): read status = %d\n", __func__, ibuf[0]);*/ ++ if (!ret) ++ memcpy(msg[0].buf, &ibuf[1], msg[0].len); ++ } else { ++ /* write */ ++ obuf[0] = 0x08; ++ obuf[1] = msg[0].addr; ++ obuf[2] = msg[0].len; ++ memcpy(&obuf[3], msg[0].buf, msg[0].len); ++ ret = dvb_usbv2_generic_rw(d, obuf, msg[0].len + 3, ibuf, 1); ++ /*dprintk("%s(): write status = %d\n", __func__, ibuf[0]);*/ ++ } ++ } else { ++ if ((msg[0].len > 60) || (msg[1].len > 60)) { ++ printk(KERN_ERR "dvbsky_usb: too many i2c bytes[w-%d][r-%d] than 60.", msg[0].len, msg[1].len); ++ ret = -EOPNOTSUPP; ++ goto i2c_error; ++ } ++ /* write then read */ ++ obuf[0] = 0x09; ++ obuf[1] = msg[0].len; ++ obuf[2] = msg[1].len; ++ obuf[3] = msg[0].addr; ++ memcpy(&obuf[4], msg[0].buf, msg[0].len); ++ ret = dvb_usbv2_generic_rw(d, obuf, msg[0].len + 4, ibuf, msg[1].len + 1); ++ /*dprintk("%s(): write then read status = %d\n", __func__, ibuf[0]);*/ ++ if (!ret) ++ memcpy(msg[1].buf, &ibuf[1], msg[1].len); ++ } ++i2c_error: ++ mutex_unlock(&d->i2c_mutex); ++ return (ret) ? ret : num; ++} ++ ++static u32 dvbsky_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm dvbsky_i2c_algo = { ++ .master_xfer = dvbsky_i2c_xfer, ++ .functionality = dvbsky_i2c_func, ++}; ++ ++#if IS_ENABLED(CONFIG_RC_CORE) ++static int dvbsky_rc_query(struct dvb_usb_device *d) ++{ ++ u32 code = 0xffff; ++ u8 obuf[2], ibuf[2], toggle; ++ int ret; ++ obuf[0] = 0x10; ++ ret = dvb_usbv2_generic_rw(d, obuf, 1, ibuf, 2); ++ if(ret == 0) ++ code = (ibuf[0] << 8) | ibuf[1]; ++ ++ if (code != 0xffff) { ++ dprintk("rc code: %x", code); ++ toggle = (code & 0x800) ? 1 : 0; ++ code &= 0x3f; ++ rc_keydown(d->rc_dev, code, toggle); ++ } ++ return 0; ++} ++ ++static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) ++{ ++ rc->allowed_protos = RC_BIT_RC5; ++ rc->query = dvbsky_rc_query; ++ rc->interval = 300; ++ return 0; ++} ++#else ++ #define dvbsky_get_rc_config NULL ++#endif ++ ++static int dvbsky_sync_ctrl(struct dvb_frontend *fe) ++{ ++ struct dvb_usb_device *d = fe_to_d(fe); ++ return dvbsky_stream_ctrl(d, 1); ++} ++ ++static int dvbsky_usb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct dvb_usb_device *d = fe_to_d(fe); ++ u8 value; ++ ++ if (voltage == SEC_VOLTAGE_OFF) ++ value = 0; ++ else ++ value = 1; ++ return dvbsky_gpio_ctrl(d, 0x80, value); ++} ++ ++static int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6]) ++{ ++ struct dvb_usb_device *d = adap_to_d(adap); ++ u8 obuf[] = { 0x1e, 0x00 }; ++ u8 ibuf[6] = { 0 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = 0x51, ++ .flags = 0, ++ .buf = obuf, ++ .len = 2, ++ }, { ++ .addr = 0x51, ++ .flags = I2C_M_RD, ++ .buf = ibuf, ++ .len = 6, ++ ++ } ++ }; ++ ++ if (i2c_transfer(&d->i2c_adap, msg, 2) == 2) ++ memcpy(mac, ibuf, 6); ++ ++ printk(KERN_INFO "dvbsky_usb MAC address=%pM\n", mac); ++ ++ return 0; ++} ++ ++static struct m88ds3103_config dvbsky_usb_ds3103_config = { ++ .demod_address = 0x68, ++ .ci_mode = 1, ++ .pin_ctrl = 0x83, ++ .ts_mode = 0, ++ .start_ctrl = dvbsky_sync_ctrl, ++ .set_voltage = dvbsky_usb_set_voltage, ++}; ++ ++static int dvbsky_s960_attach(struct dvb_usb_adapter *adap) ++{ ++ struct dvbsky_state *state = adap_to_priv(adap); ++ struct dvb_usb_device *d = adap_to_d(adap); ++ int ret = 0; ++ ++ dprintk("%s()\n", __func__); ++ ++ dvbsky_gpio_ctrl(d, 0x04, 1); ++ ++ dvbsky_gpio_ctrl(d, 0x83, 0); ++ msleep(50); ++ dvbsky_gpio_ctrl(d, 0x83, 1); ++ msleep(20); ++ ++ adap->fe[0] = dvb_attach(m88ds3103_attach, ++ &dvbsky_usb_ds3103_config, ++ &d->i2c_adap); ++ if (!adap->fe[0]) { ++ printk(KERN_ERR "dvbsky_s960_attach fail."); ++ ret = -ENODEV; ++ } ++ ++ state->has_ci = 0; ++ ++ return ret; ++} ++ ++static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name) ++{ ++ return WARM; ++} ++ ++static int dvbsky_init(struct dvb_usb_device *d) ++{ ++ struct dvbsky_state *state = d_to_priv(d); ++ int ret; ++ ++ /* use default interface */ ++ ret = usb_set_interface(d->udev, 0, 0); ++ if (ret) ++ return ret; ++ ++ mutex_init(&state->stream_mutex); ++ ++ /* attach CI */ ++ if (state->has_ci) { ++ dvbsky_gpio_ctrl(d, 0xc0, 1); ++ msleep(100); ++ dvbsky_gpio_ctrl(d, 0xc0, 0); ++ msleep(50); ++ state->ci_attached = 0; ++ ret = dvbsky_ci_init(d); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++ ++static void dvbsky_exit(struct dvb_usb_device *d) ++{ ++ return dvbsky_ci_release(d); ++} ++ ++/* DVB USB Driver stuff */ ++static struct dvb_usb_device_properties dvbsky_s960_props = { ++ .driver_name = KBUILD_MODNAME, ++ .owner = THIS_MODULE, ++ .adapter_nr = adapter_nr, ++ .size_of_priv = sizeof(struct dvbsky_state), ++ ++ .generic_bulk_ctrl_endpoint = 0x01, ++ .generic_bulk_ctrl_endpoint_response = 0x81, ++ ++ .i2c_algo = &dvbsky_i2c_algo, ++ .frontend_attach = dvbsky_s960_attach, ++ .init = dvbsky_init, ++ .get_rc_config = dvbsky_get_rc_config, ++ .streaming_ctrl = dvbsky_streaming_ctrl, ++ .identify_state = dvbsky_identify_state, ++ .exit = dvbsky_exit, ++ .read_mac_address = dvbsky_read_mac_addr, ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), ++ } ++ } ++}; ++ ++static const struct usb_device_id dvbsky_id_table[] = { ++ { DVB_USB_DEVICE(0x0572, 0x6831, ++ &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(usb, dvbsky_id_table); ++ ++static struct usb_driver dvbsky_usb_driver = { ++ .name = KBUILD_MODNAME, ++ .id_table = dvbsky_id_table, ++ .probe = dvb_usbv2_probe, ++ .disconnect = dvb_usbv2_disconnect, ++ .suspend = dvb_usbv2_suspend, ++ .resume = dvb_usbv2_resume, ++ .reset_resume = dvb_usbv2_reset_resume, ++ .no_dynamic_id = 1, ++ .soft_unbind = 1, ++}; ++ ++module_usb_driver(dvbsky_usb_driver); ++ ++MODULE_AUTHOR("Max nibble "); ++MODULE_DESCRIPTION("Driver for DVBSky USB2.0"); ++MODULE_LICENSE("GPL"); +diff -urN a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig +--- a/drivers/media/usb/dvb-usb-v2/Kconfig 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/usb/dvb-usb-v2/Kconfig 2013-05-03 17:45:35.000000000 +0800 +@@ -149,3 +149,10 @@ + help + Say Y here to support the Realtek RTL28xxU DVB USB receiver. + ++config DVB_USB_DVBSKY ++ tristate "DVBSky USB2.0 support" ++ depends on DVB_USB_V2 ++ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the USB receivers from DVBSky. ++ +diff -urN a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile +--- a/drivers/media/usb/dvb-usb-v2/Makefile 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/usb/dvb-usb-v2/Makefile 2013-02-17 12:03:00.000000000 +0800 +@@ -43,6 +43,9 @@ + dvb-usb-rtl28xxu-objs := rtl28xxu.o + obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o + ++dvb-usb-dvbsky-objs := dvbsky.o ++obj-$(CONFIG_DVB_USB_DVBSKY) += dvb-usb-dvbsky.o ++ + ccflags-y += -I$(srctree)/drivers/media/dvb-core + ccflags-y += -I$(srctree)/drivers/media/dvb-frontends + ccflags-y += -I$(srctree)/drivers/media/tuners +diff -urN a/include/media/rc-map.h b/include/media/rc-map.h +--- a/include/media/rc-map.h 2013-04-29 08:36:01.000000000 +0800 ++++ b/include/media/rc-map.h 2013-05-03 17:02:46.000000000 +0800 +@@ -118,6 +118,7 @@ + #define RC_MAP_DM1105_NEC "rc-dm1105-nec" + #define RC_MAP_DNTV_LIVE_DVBT_PRO "rc-dntv-live-dvbt-pro" + #define RC_MAP_DNTV_LIVE_DVB_T "rc-dntv-live-dvb-t" ++#define RC_MAP_DVBSKY "rc-dvbsky" + #define RC_MAP_EMPTY "rc-empty" + #define RC_MAP_EM_TERRATEC "rc-em-terratec" + #define RC_MAP_ENCORE_ENLTV2 "rc-encore-enltv2" diff --git a/packages/linux/patches/3.10/linux-212-mantis_stb0899_faster_lock.patch b/packages/linux/patches/3.10/linux-212-mantis_stb0899_faster_lock.patch new file mode 100644 index 0000000000..eef4e1effc --- /dev/null +++ b/packages/linux/patches/3.10/linux-212-mantis_stb0899_faster_lock.patch @@ -0,0 +1,138 @@ +diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_algo.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_algo.c +--- linux-3.7.2/drivers/media/dvb-frontends/stb0899_algo.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_algo.c 2013-01-16 10:28:33.633409961 +0100 +@@ -206,7 +206,6 @@ + static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) + { + struct stb0899_internal *internal = &state->internal; +- struct stb0899_params *params = &state->params; + + short int derot_step, derot_freq = 0, derot_limit, next_loop = 3; + int index = 0; +@@ -216,10 +215,9 @@ + + /* timing loop computation & symbol rate optimisation */ + derot_limit = (internal->sub_range / 2L) / internal->mclk; +- derot_step = (params->srate / 2L) / internal->mclk; ++ derot_step = internal->derot_step * 4; /* dertot_step = decreasing delta */ + + while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { +- index++; + derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ + + if (abs(derot_freq) > derot_limit) +@@ -230,6 +228,7 @@ + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ + } ++ index++; + internal->direction = -internal->direction; /* Change zigzag direction */ + } + +@@ -278,14 +277,18 @@ + { + struct stb0899_internal *internal = &state->internal; + +- short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3; ++ short int derot_freq = 0, last_derot_freq = 0, derot_limit, derot_step, next_loop = 3; + int index = 0; ++ int base_freq; + u8 cfr[2]; + u8 reg; + + internal->status = NOCARRIER; + derot_limit = (internal->sub_range / 2L) / internal->mclk; + derot_freq = internal->derot_freq; ++ derot_step = internal->derot_step * 2; ++ last_derot_freq = internal->derot_freq; ++ base_freq = internal->derot_freq; + + reg = stb0899_read_reg(state, STB0899_CFD); + STB0899_SETFIELD_VAL(CFD_ON, reg, 1); +@@ -294,11 +297,10 @@ + do { + dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk); + if (stb0899_check_carrier(state) == NOCARRIER) { +- index++; + last_derot_freq = derot_freq; +- derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ ++ derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ + +- if(abs(derot_freq) > derot_limit) ++ if (derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) + next_loop--; + + if (next_loop) { +@@ -310,9 +312,10 @@ + STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); + stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ + } ++ index++; ++ internal->direction = -internal->direction; /* Change zigzag direction */ + } + +- internal->direction = -internal->direction; /* Change zigzag direction */ + } while ((internal->status != CARRIEROK) && next_loop); + + if (internal->status == CARRIEROK) { +@@ -338,6 +341,7 @@ + int lock = 0, index = 0, dataTime = 500, loop; + u8 reg; + ++ msleep(1); + internal->status = NODATA; + + /* RESET FEC */ +@@ -348,6 +352,7 @@ + reg = stb0899_read_reg(state, STB0899_TSTRES); + STB0899_SETFIELD_VAL(FRESACS, reg, 0); + stb0899_write_reg(state, STB0899_TSTRES, reg); ++ msleep(1); + + if (params->srate <= 2000000) + dataTime = 2000; +@@ -363,6 +368,7 @@ + + stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */ + while (1) { ++ msleep(1); // Alex: added 1 mSec + /* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */ + reg = stb0899_read_reg(state, STB0899_VSTATUS); + lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg); +@@ -390,20 +396,21 @@ + short int derot_freq, derot_step, derot_limit, next_loop = 3; + u8 cfr[2]; + u8 reg; +- int index = 1; ++ int index = 0; ++ int base_freq; + + struct stb0899_internal *internal = &state->internal; +- struct stb0899_params *params = &state->params; + +- derot_step = (params->srate / 4L) / internal->mclk; ++ derot_step = internal->derot_step; + derot_limit = (internal->sub_range / 2L) / internal->mclk; + derot_freq = internal->derot_freq; ++ base_freq = internal->derot_freq; + + do { + if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { + + derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ +- if (abs(derot_freq) > derot_limit) ++ if (derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) + next_loop--; + + if (next_loop) { +@@ -417,9 +424,9 @@ + stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ + + stb0899_check_carrier(state); +- index++; + } + } ++ index++; + internal->direction = -internal->direction; /* change zig zag direction */ + } while ((internal->status != DATAOK) && next_loop); + diff --git a/packages/linux/patches/3.10/linux-221-ngene-octopus.patch b/packages/linux/patches/3.10/linux-221-ngene-octopus.patch new file mode 100644 index 0000000000..ea092a58f9 --- /dev/null +++ b/packages/linux/patches/3.10/linux-221-ngene-octopus.patch @@ -0,0 +1,12735 @@ +From c5891c83d5777a2e691c2a452a7f57a6b6a13344 Mon Sep 17 00:00:00 2001 +From: Stefan Saraev +Date: Sun, 12 May 2013 23:47:07 +0300 +Subject: [PATCH] dvb: ngene/octopus + +--- + drivers/media/dvb-frontends/Kconfig | 26 + + drivers/media/dvb-frontends/Makefile | 2 + + drivers/media/dvb-frontends/stv0367dd.c | 2269 +++++++++++++++++ + drivers/media/dvb-frontends/stv0367dd.h | 17 + + drivers/media/dvb-frontends/stv0367dd_regs.h | 3431 ++++++++++++++++++++++++++ + drivers/media/dvb-frontends/tda18212dd.c | 906 +++++++ + drivers/media/dvb-frontends/tda18212dd.h | 5 + + drivers/media/pci/ddbridge/Kconfig | 14 +- + drivers/media/pci/ddbridge/ddbridge-core.c | 1947 ++++++++++++---- + drivers/media/pci/ddbridge/ddbridge-regs.h | 56 +- + drivers/media/pci/ddbridge/ddbridge.h | 97 +- + drivers/media/pci/ngene/Kconfig | 17 +- + drivers/media/pci/ngene/Makefile | 3 +- + drivers/media/pci/ngene/ngene-av.c | 348 +++ + drivers/media/pci/ngene/ngene-cards.c | 778 +++++-- + drivers/media/pci/ngene/ngene-core.c | 378 +++- + drivers/media/pci/ngene/ngene-dvb.c | 372 +++ + drivers/media/pci/ngene/ngene-eeprom.c | 284 +++ + drivers/media/pci/ngene/ngene-i2c.c | 113 + + drivers/media/pci/ngene/ngene.h | 40 + + drivers/staging/media/cxd2099/TODO | 12 - + drivers/staging/media/cxd2099/cxd2099.c | 47 +- + drivers/staging/media/cxd2099/cxd2099.h | 2 +- + 23 files changed, 10416 insertions(+), 748 deletions(-) + create mode 100644 drivers/media/dvb-frontends/stv0367dd.c + create mode 100644 drivers/media/dvb-frontends/stv0367dd.h + create mode 100644 drivers/media/dvb-frontends/stv0367dd_regs.h + create mode 100644 drivers/media/dvb-frontends/tda18212dd.c + create mode 100644 drivers/media/dvb-frontends/tda18212dd.h + create mode 100644 drivers/media/pci/ngene/ngene-av.c + create mode 100644 drivers/media/pci/ngene/ngene-eeprom.c + delete mode 100644 drivers/staging/media/cxd2099/TODO + +diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig +index 05cf66f..1e0275f 100644 +--- a/drivers/media/dvb-frontends/Kconfig ++++ b/drivers/media/dvb-frontends/Kconfig +@@ -19,6 +19,14 @@ config DVB_STB0899 + A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want + to support this demodulator based frontends + ++config DVB_CXD2099 ++ tristate "CXD2099AR Common Interface driver" ++ depends on DVB_CORE && PCI && I2C ++ ---help--- ++ Support for the CI module found on cards based on ++ - Micronas ngene PCIe bridge: cineS2 etc. ++ - Digital Devices PCIe bridge: Octopus series ++ + config DVB_STB6100 + tristate "STB6100 based tuners" + depends on DVB_CORE && I2C +@@ -63,6 +71,24 @@ config DVB_TDA18271C2DD + + Say Y when you want to support this tuner. + ++config DVB_STV0367DD ++ tristate "STV 0367 (DD)" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ STV 0367 DVB-C/T demodulator (Digital Devices driver). ++ ++ Say Y when you want to support this frontend. ++ ++config DVB_TDA18212DD ++ tristate "NXP TDA18212 silicon tuner (DD)" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ NXP TDA18212 silicon tuner (Digital Devices driver). ++ ++ Say Y when you want to support this tuner. ++ + comment "DVB-S (satellite) frontends" + depends on DVB_CORE + +diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile +index 75440de..25ab5f8 100644 +--- a/drivers/media/dvb-frontends/Makefile ++++ b/drivers/media/dvb-frontends/Makefile +@@ -100,6 +100,8 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o + obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o + obj-$(CONFIG_DVB_DRXK) += drxk.o + obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o ++obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o ++obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o + obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o + obj-$(CONFIG_DVB_A8293) += a8293.o + obj-$(CONFIG_DVB_TDA10071) += tda10071.o +diff --git a/drivers/media/dvb-frontends/stv0367dd.c b/drivers/media/dvb-frontends/stv0367dd.c +new file mode 100644 +index 0000000..34a38cf +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0367dd.c +@@ -0,0 +1,2269 @@ ++/* ++ * stv0367dd: STV0367 DVB-C/T demodulator driver ++ * ++ * Copyright (C) 2011 Digital Devices GmbH ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "stv0367dd.h" ++#include "stv0367dd_regs.h" ++ ++enum omode { OM_NONE, OM_DVBT, OM_DVBC, OM_QAM_ITU_C }; ++enum { QAM_MOD_QAM4 = 0, ++ QAM_MOD_QAM16, ++ QAM_MOD_QAM32, ++ QAM_MOD_QAM64, ++ QAM_MOD_QAM128, ++ QAM_MOD_QAM256, ++ QAM_MOD_QAM512, ++ QAM_MOD_QAM1024 ++}; ++ ++enum {QAM_SPECT_NORMAL, QAM_SPECT_INVERTED }; ++ ++enum { ++ QAM_FEC_A = 1, /* J83 Annex A */ ++ QAM_FEC_B = (1<<1), /* J83 Annex B */ ++ QAM_FEC_C = (1<<2) /* J83 Annex C */ ++}; ++ ++enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted }; ++ ++struct stv_state { ++#ifdef USE_API3 ++ struct dvb_frontend c_frontend; ++ struct dvb_frontend t_frontend; ++#else ++ struct dvb_frontend frontend; ++#endif ++ fe_modulation_t modulation; ++ u32 symbol_rate; ++ u32 bandwidth; ++ struct device *dev; ++ ++ struct i2c_adapter *i2c; ++ u8 adr; ++ void *priv; ++ ++ struct mutex mutex; ++ struct mutex ctlock; ++ ++ u32 master_clock; ++ u32 adc_clock; ++ u8 ID; ++ u8 I2CRPT; ++ u32 omode; ++ u8 qam_inversion; ++ ++ s32 IF; ++ ++ s32 m_FECTimeOut; ++ s32 m_DemodTimeOut; ++ s32 m_SignalTimeOut; ++ s32 m_DemodLockTime; ++ s32 m_FFTTimeOut; ++ s32 m_TSTimeOut; ++ ++ bool m_bFirstTimeLock; ++ ++ u8 m_Save_QAM_AGC_CTL; ++ ++ enum EDemodState demod_state; ++ ++ u8 m_OFDM_FFTMode; // 0 = 2k, 1 = 8k, 2 = 4k ++ u8 m_OFDM_Modulation; // ++ u8 m_OFDM_FEC; // ++ u8 m_OFDM_Guard; ++ ++ u32 ucblocks; ++}; ++ ++struct init_table { ++ u16 adr; ++ u8 data; ++}; ++ ++struct init_table base_init[] = { ++ { R367_IOCFG0, 0x80 }, ++ { R367_DAC0R, 0x00 }, ++ { R367_IOCFG1, 0x00 }, ++ { R367_DAC1R, 0x00 }, ++ { R367_IOCFG2, 0x00 }, ++ { R367_SDFR, 0x00 }, ++ { R367_AUX_CLK, 0x00 }, ++ { R367_FREESYS1, 0x00 }, ++ { R367_FREESYS2, 0x00 }, ++ { R367_FREESYS3, 0x00 }, ++ { R367_GPIO_CFG, 0x55 }, ++ { R367_GPIO_CMD, 0x01 }, ++ { R367_TSTRES, 0x00 }, ++ { R367_ANACTRL, 0x00 }, ++ { R367_TSTBUS, 0x00 }, ++ { R367_RF_AGC2, 0x20 }, ++ { R367_ANADIGCTRL, 0x0b }, ++ { R367_PLLMDIV, 0x01 }, ++ { R367_PLLNDIV, 0x08 }, ++ { R367_PLLSETUP, 0x18 }, ++ { R367_DUAL_AD12, 0x04 }, ++ { R367_TSTBIST, 0x00 }, ++ { 0x0000, 0x00 } ++}; ++ ++struct init_table qam_init[] = { ++ { R367_QAM_CTRL_1, 0x06 },// Orginal 0x04 ++ { R367_QAM_CTRL_2, 0x03 }, ++ { R367_QAM_IT_STATUS1, 0x2b }, ++ { R367_QAM_IT_STATUS2, 0x08 }, ++ { R367_QAM_IT_EN1, 0x00 }, ++ { R367_QAM_IT_EN2, 0x00 }, ++ { R367_QAM_CTRL_STATUS, 0x04 }, ++ { R367_QAM_TEST_CTL, 0x00 }, ++ { R367_QAM_AGC_CTL, 0x73 }, ++ { R367_QAM_AGC_IF_CFG, 0x50 }, ++ { R367_QAM_AGC_RF_CFG, 0x02 },// RF Freeze ++ { R367_QAM_AGC_PWM_CFG, 0x03 }, ++ { R367_QAM_AGC_PWR_REF_L, 0x5a }, ++ { R367_QAM_AGC_PWR_REF_H, 0x00 }, ++ { R367_QAM_AGC_RF_TH_L, 0xff }, ++ { R367_QAM_AGC_RF_TH_H, 0x07 }, ++ { R367_QAM_AGC_IF_LTH_L, 0x00 }, ++ { R367_QAM_AGC_IF_LTH_H, 0x08 }, ++ { R367_QAM_AGC_IF_HTH_L, 0xff }, ++ { R367_QAM_AGC_IF_HTH_H, 0x07 }, ++ { R367_QAM_AGC_PWR_RD_L, 0xa0 }, ++ { R367_QAM_AGC_PWR_RD_M, 0xe9 }, ++ { R367_QAM_AGC_PWR_RD_H, 0x03 }, ++ { R367_QAM_AGC_PWM_IFCMD_L, 0xe4 }, ++ { R367_QAM_AGC_PWM_IFCMD_H, 0x00 }, ++ { R367_QAM_AGC_PWM_RFCMD_L, 0xff }, ++ { R367_QAM_AGC_PWM_RFCMD_H, 0x07 }, ++ { R367_QAM_IQDEM_CFG, 0x01 }, ++ { R367_QAM_MIX_NCO_LL, 0x22 }, ++ { R367_QAM_MIX_NCO_HL, 0x96 }, ++ { R367_QAM_MIX_NCO_HH, 0x55 }, ++ { R367_QAM_SRC_NCO_LL, 0xff }, ++ { R367_QAM_SRC_NCO_LH, 0x0c }, ++ { R367_QAM_SRC_NCO_HL, 0xf5 }, ++ { R367_QAM_SRC_NCO_HH, 0x20 }, ++ { R367_QAM_IQDEM_GAIN_SRC_L, 0x06 }, ++ { R367_QAM_IQDEM_GAIN_SRC_H, 0x01 }, ++ { R367_QAM_IQDEM_DCRM_CFG_LL, 0xfe }, ++ { R367_QAM_IQDEM_DCRM_CFG_LH, 0xff }, ++ { R367_QAM_IQDEM_DCRM_CFG_HL, 0x0f }, ++ { R367_QAM_IQDEM_DCRM_CFG_HH, 0x00 }, ++ { R367_QAM_IQDEM_ADJ_COEFF0, 0x34 }, ++ { R367_QAM_IQDEM_ADJ_COEFF1, 0xae }, ++ { R367_QAM_IQDEM_ADJ_COEFF2, 0x46 }, ++ { R367_QAM_IQDEM_ADJ_COEFF3, 0x77 }, ++ { R367_QAM_IQDEM_ADJ_COEFF4, 0x96 }, ++ { R367_QAM_IQDEM_ADJ_COEFF5, 0x69 }, ++ { R367_QAM_IQDEM_ADJ_COEFF6, 0xc7 }, ++ { R367_QAM_IQDEM_ADJ_COEFF7, 0x01 }, ++ { R367_QAM_IQDEM_ADJ_EN, 0x04 }, ++ { R367_QAM_IQDEM_ADJ_AGC_REF, 0x94 }, ++ { R367_QAM_ALLPASSFILT1, 0xc9 }, ++ { R367_QAM_ALLPASSFILT2, 0x2d }, ++ { R367_QAM_ALLPASSFILT3, 0xa3 }, ++ { R367_QAM_ALLPASSFILT4, 0xfb }, ++ { R367_QAM_ALLPASSFILT5, 0xf6 }, ++ { R367_QAM_ALLPASSFILT6, 0x45 }, ++ { R367_QAM_ALLPASSFILT7, 0x6f }, ++ { R367_QAM_ALLPASSFILT8, 0x7e }, ++ { R367_QAM_ALLPASSFILT9, 0x05 }, ++ { R367_QAM_ALLPASSFILT10, 0x0a }, ++ { R367_QAM_ALLPASSFILT11, 0x51 }, ++ { R367_QAM_TRL_AGC_CFG, 0x20 }, ++ { R367_QAM_TRL_LPF_CFG, 0x28 }, ++ { R367_QAM_TRL_LPF_ACQ_GAIN, 0x44 }, ++ { R367_QAM_TRL_LPF_TRK_GAIN, 0x22 }, ++ { R367_QAM_TRL_LPF_OUT_GAIN, 0x03 }, ++ { R367_QAM_TRL_LOCKDET_LTH, 0x04 }, ++ { R367_QAM_TRL_LOCKDET_HTH, 0x11 }, ++ { R367_QAM_TRL_LOCKDET_TRGVAL, 0x20 }, ++ { R367_QAM_IQ_QAM, 0x01 }, ++ { R367_QAM_FSM_STATE, 0xa0 }, ++ { R367_QAM_FSM_CTL, 0x08 }, ++ { R367_QAM_FSM_STS, 0x0c }, ++ { R367_QAM_FSM_SNR0_HTH, 0x00 }, ++ { R367_QAM_FSM_SNR1_HTH, 0x00 }, ++ { R367_QAM_FSM_SNR2_HTH, 0x00 }, ++ { R367_QAM_FSM_SNR0_LTH, 0x00 }, ++ { R367_QAM_FSM_SNR1_LTH, 0x00 }, ++ { R367_QAM_FSM_EQA1_HTH, 0x00 }, ++ { R367_QAM_FSM_TEMPO, 0x32 }, ++ { R367_QAM_FSM_CONFIG, 0x03 }, ++ { R367_QAM_EQU_I_TESTTAP_L, 0x11 }, ++ { R367_QAM_EQU_I_TESTTAP_M, 0x00 }, ++ { R367_QAM_EQU_I_TESTTAP_H, 0x00 }, ++ { R367_QAM_EQU_TESTAP_CFG, 0x00 }, ++ { R367_QAM_EQU_Q_TESTTAP_L, 0xff }, ++ { R367_QAM_EQU_Q_TESTTAP_M, 0x00 }, ++ { R367_QAM_EQU_Q_TESTTAP_H, 0x00 }, ++ { R367_QAM_EQU_TAP_CTRL, 0x00 }, ++ { R367_QAM_EQU_CTR_CRL_CONTROL_L, 0x11 }, ++ { R367_QAM_EQU_CTR_CRL_CONTROL_H, 0x05 }, ++ { R367_QAM_EQU_CTR_HIPOW_L, 0x00 }, ++ { R367_QAM_EQU_CTR_HIPOW_H, 0x00 }, ++ { R367_QAM_EQU_I_EQU_LO, 0xef }, ++ { R367_QAM_EQU_I_EQU_HI, 0x00 }, ++ { R367_QAM_EQU_Q_EQU_LO, 0xee }, ++ { R367_QAM_EQU_Q_EQU_HI, 0x00 }, ++ { R367_QAM_EQU_MAPPER, 0xc5 }, ++ { R367_QAM_EQU_SWEEP_RATE, 0x80 }, ++ { R367_QAM_EQU_SNR_LO, 0x64 }, ++ { R367_QAM_EQU_SNR_HI, 0x03 }, ++ { R367_QAM_EQU_GAMMA_LO, 0x00 }, ++ { R367_QAM_EQU_GAMMA_HI, 0x00 }, ++ { R367_QAM_EQU_ERR_GAIN, 0x36 }, ++ { R367_QAM_EQU_RADIUS, 0xaa }, ++ { R367_QAM_EQU_FFE_MAINTAP, 0x00 }, ++ { R367_QAM_EQU_FFE_LEAKAGE, 0x63 }, ++ { R367_QAM_EQU_FFE_MAINTAP_POS, 0xdf }, ++ { R367_QAM_EQU_GAIN_WIDE, 0x88 }, ++ { R367_QAM_EQU_GAIN_NARROW, 0x41 }, ++ { R367_QAM_EQU_CTR_LPF_GAIN, 0xd1 }, ++ { R367_QAM_EQU_CRL_LPF_GAIN, 0xa7 }, ++ { R367_QAM_EQU_GLOBAL_GAIN, 0x06 }, ++ { R367_QAM_EQU_CRL_LD_SEN, 0x85 }, ++ { R367_QAM_EQU_CRL_LD_VAL, 0xe2 }, ++ { R367_QAM_EQU_CRL_TFR, 0x20 }, ++ { R367_QAM_EQU_CRL_BISTH_LO, 0x00 }, ++ { R367_QAM_EQU_CRL_BISTH_HI, 0x00 }, ++ { R367_QAM_EQU_SWEEP_RANGE_LO, 0x00 }, ++ { R367_QAM_EQU_SWEEP_RANGE_HI, 0x00 }, ++ { R367_QAM_EQU_CRL_LIMITER, 0x40 }, ++ { R367_QAM_EQU_MODULUS_MAP, 0x90 }, ++ { R367_QAM_EQU_PNT_GAIN, 0xa7 }, ++ { R367_QAM_FEC_AC_CTR_0, 0x16 }, ++ { R367_QAM_FEC_AC_CTR_1, 0x0b }, ++ { R367_QAM_FEC_AC_CTR_2, 0x88 }, ++ { R367_QAM_FEC_AC_CTR_3, 0x02 }, ++ { R367_QAM_FEC_STATUS, 0x12 }, ++ { R367_QAM_RS_COUNTER_0, 0x7d }, ++ { R367_QAM_RS_COUNTER_1, 0xd0 }, ++ { R367_QAM_RS_COUNTER_2, 0x19 }, ++ { R367_QAM_RS_COUNTER_3, 0x0b }, ++ { R367_QAM_RS_COUNTER_4, 0xa3 }, ++ { R367_QAM_RS_COUNTER_5, 0x00 }, ++ { R367_QAM_BERT_0, 0x01 }, ++ { R367_QAM_BERT_1, 0x25 }, ++ { R367_QAM_BERT_2, 0x41 }, ++ { R367_QAM_BERT_3, 0x39 }, ++ { R367_QAM_OUTFORMAT_0, 0xc2 }, ++ { R367_QAM_OUTFORMAT_1, 0x22 }, ++ { R367_QAM_SMOOTHER_2, 0x28 }, ++ { R367_QAM_TSMF_CTRL_0, 0x01 }, ++ { R367_QAM_TSMF_CTRL_1, 0xc6 }, ++ { R367_QAM_TSMF_CTRL_3, 0x43 }, ++ { R367_QAM_TS_ON_ID_0, 0x00 }, ++ { R367_QAM_TS_ON_ID_1, 0x00 }, ++ { R367_QAM_TS_ON_ID_2, 0x00 }, ++ { R367_QAM_TS_ON_ID_3, 0x00 }, ++ { R367_QAM_RE_STATUS_0, 0x00 }, ++ { R367_QAM_RE_STATUS_1, 0x00 }, ++ { R367_QAM_RE_STATUS_2, 0x00 }, ++ { R367_QAM_RE_STATUS_3, 0x00 }, ++ { R367_QAM_TS_STATUS_0, 0x00 }, ++ { R367_QAM_TS_STATUS_1, 0x00 }, ++ { R367_QAM_TS_STATUS_2, 0xa0 }, ++ { R367_QAM_TS_STATUS_3, 0x00 }, ++ { R367_QAM_T_O_ID_0, 0x00 }, ++ { R367_QAM_T_O_ID_1, 0x00 }, ++ { R367_QAM_T_O_ID_2, 0x00 }, ++ { R367_QAM_T_O_ID_3, 0x00 }, ++ { 0x0000, 0x00 } // EOT ++}; ++ ++struct init_table ofdm_init[] = { ++ //{R367_OFDM_ID ,0x60}, ++ //{R367_OFDM_I2CRPT ,0x22}, ++ //{R367_OFDM_TOPCTRL ,0x02}, ++ //{R367_OFDM_IOCFG0 ,0x40}, ++ //{R367_OFDM_DAC0R ,0x00}, ++ //{R367_OFDM_IOCFG1 ,0x00}, ++ //{R367_OFDM_DAC1R ,0x00}, ++ //{R367_OFDM_IOCFG2 ,0x62}, ++ //{R367_OFDM_SDFR ,0x00}, ++ //{R367_OFDM_STATUS ,0xf8}, ++ //{R367_OFDM_AUX_CLK ,0x0a}, ++ //{R367_OFDM_FREESYS1 ,0x00}, ++ //{R367_OFDM_FREESYS2 ,0x00}, ++ //{R367_OFDM_FREESYS3 ,0x00}, ++ //{R367_OFDM_GPIO_CFG ,0x55}, ++ //{R367_OFDM_GPIO_CMD ,0x00}, ++ {R367_OFDM_AGC2MAX ,0xff}, ++ {R367_OFDM_AGC2MIN ,0x00}, ++ {R367_OFDM_AGC1MAX ,0xff}, ++ {R367_OFDM_AGC1MIN ,0x00}, ++ {R367_OFDM_AGCR ,0xbc}, ++ {R367_OFDM_AGC2TH ,0x00}, ++ //{R367_OFDM_AGC12C ,0x01}, //Note: This defines AGC pins, also needed for QAM ++ {R367_OFDM_AGCCTRL1 ,0x85}, ++ {R367_OFDM_AGCCTRL2 ,0x1f}, ++ {R367_OFDM_AGC1VAL1 ,0x00}, ++ {R367_OFDM_AGC1VAL2 ,0x00}, ++ {R367_OFDM_AGC2VAL1 ,0x6f}, ++ {R367_OFDM_AGC2VAL2 ,0x05}, ++ {R367_OFDM_AGC2PGA ,0x00}, ++ {R367_OFDM_OVF_RATE1 ,0x00}, ++ {R367_OFDM_OVF_RATE2 ,0x00}, ++ {R367_OFDM_GAIN_SRC1 ,0x2b}, ++ {R367_OFDM_GAIN_SRC2 ,0x04}, ++ {R367_OFDM_INC_DEROT1 ,0x55}, ++ {R367_OFDM_INC_DEROT2 ,0x55}, ++ {R367_OFDM_PPM_CPAMP_DIR ,0x2c}, ++ {R367_OFDM_PPM_CPAMP_INV ,0x00}, ++ {R367_OFDM_FREESTFE_1 ,0x00}, ++ {R367_OFDM_FREESTFE_2 ,0x1c}, ++ {R367_OFDM_DCOFFSET ,0x00}, ++ {R367_OFDM_EN_PROCESS ,0x05}, ++ {R367_OFDM_SDI_SMOOTHER ,0x80}, ++ {R367_OFDM_FE_LOOP_OPEN ,0x1c}, ++ {R367_OFDM_FREQOFF1 ,0x00}, ++ {R367_OFDM_FREQOFF2 ,0x00}, ++ {R367_OFDM_FREQOFF3 ,0x00}, ++ {R367_OFDM_TIMOFF1 ,0x00}, ++ {R367_OFDM_TIMOFF2 ,0x00}, ++ {R367_OFDM_EPQ ,0x02}, ++ {R367_OFDM_EPQAUTO ,0x01}, ++ {R367_OFDM_SYR_UPDATE ,0xf5}, ++ {R367_OFDM_CHPFREE ,0x00}, ++ {R367_OFDM_PPM_STATE_MAC ,0x23}, ++ {R367_OFDM_INR_THRESHOLD ,0xff}, ++ {R367_OFDM_EPQ_TPS_ID_CELL ,0xf9}, ++ {R367_OFDM_EPQ_CFG ,0x00}, ++ {R367_OFDM_EPQ_STATUS ,0x01}, ++ {R367_OFDM_AUTORELOCK ,0x81}, ++ {R367_OFDM_BER_THR_VMSB ,0x00}, ++ {R367_OFDM_BER_THR_MSB ,0x00}, ++ {R367_OFDM_BER_THR_LSB ,0x00}, ++ {R367_OFDM_CCD ,0x83}, ++ {R367_OFDM_SPECTR_CFG ,0x00}, ++ {R367_OFDM_CHC_DUMMY ,0x18}, ++ {R367_OFDM_INC_CTL ,0x88}, ++ {R367_OFDM_INCTHRES_COR1 ,0xb4}, ++ {R367_OFDM_INCTHRES_COR2 ,0x96}, ++ {R367_OFDM_INCTHRES_DET1 ,0x0e}, ++ {R367_OFDM_INCTHRES_DET2 ,0x11}, ++ {R367_OFDM_IIR_CELLNB ,0x8d}, ++ {R367_OFDM_IIRCX_COEFF1_MSB ,0x00}, ++ {R367_OFDM_IIRCX_COEFF1_LSB ,0x00}, ++ {R367_OFDM_IIRCX_COEFF2_MSB ,0x09}, ++ {R367_OFDM_IIRCX_COEFF2_LSB ,0x18}, ++ {R367_OFDM_IIRCX_COEFF3_MSB ,0x14}, ++ {R367_OFDM_IIRCX_COEFF3_LSB ,0x9c}, ++ {R367_OFDM_IIRCX_COEFF4_MSB ,0x00}, ++ {R367_OFDM_IIRCX_COEFF4_LSB ,0x00}, ++ {R367_OFDM_IIRCX_COEFF5_MSB ,0x36}, ++ {R367_OFDM_IIRCX_COEFF5_LSB ,0x42}, ++ {R367_OFDM_FEPATH_CFG ,0x00}, ++ {R367_OFDM_PMC1_FUNC ,0x65}, ++ {R367_OFDM_PMC1_FOR ,0x00}, ++ {R367_OFDM_PMC2_FUNC ,0x00}, ++ {R367_OFDM_STATUS_ERR_DA ,0xe0}, ++ {R367_OFDM_DIG_AGC_R ,0xfe}, ++ {R367_OFDM_COMAGC_TARMSB ,0x0b}, ++ {R367_OFDM_COM_AGC_TAR_ENMODE ,0x41}, ++ {R367_OFDM_COM_AGC_CFG ,0x3e}, ++ {R367_OFDM_COM_AGC_GAIN1 ,0x39}, ++ {R367_OFDM_AUT_AGC_TARGETMSB ,0x0b}, ++ {R367_OFDM_LOCK_DET_MSB ,0x01}, ++ {R367_OFDM_AGCTAR_LOCK_LSBS ,0x40}, ++ {R367_OFDM_AUT_GAIN_EN ,0xf4}, ++ {R367_OFDM_AUT_CFG ,0xf0}, ++ {R367_OFDM_LOCKN ,0x23}, ++ {R367_OFDM_INT_X_3 ,0x00}, ++ {R367_OFDM_INT_X_2 ,0x03}, ++ {R367_OFDM_INT_X_1 ,0x8d}, ++ {R367_OFDM_INT_X_0 ,0xa0}, ++ {R367_OFDM_MIN_ERRX_MSB ,0x00}, ++ {R367_OFDM_COR_CTL ,0x00}, ++ {R367_OFDM_COR_STAT ,0xf6}, ++ {R367_OFDM_COR_INTEN ,0x00}, ++ {R367_OFDM_COR_INTSTAT ,0x3f}, ++ {R367_OFDM_COR_MODEGUARD ,0x03}, ++ {R367_OFDM_AGC_CTL ,0x08}, ++ {R367_OFDM_AGC_MANUAL1 ,0x00}, ++ {R367_OFDM_AGC_MANUAL2 ,0x00}, ++ {R367_OFDM_AGC_TARG ,0x16}, ++ {R367_OFDM_AGC_GAIN1 ,0x53}, ++ {R367_OFDM_AGC_GAIN2 ,0x1d}, ++ {R367_OFDM_RESERVED_1 ,0x00}, ++ {R367_OFDM_RESERVED_2 ,0x00}, ++ {R367_OFDM_RESERVED_3 ,0x00}, ++ {R367_OFDM_CAS_CTL ,0x44}, ++ {R367_OFDM_CAS_FREQ ,0xb3}, ++ {R367_OFDM_CAS_DAGCGAIN ,0x12}, ++ {R367_OFDM_SYR_CTL ,0x04}, ++ {R367_OFDM_SYR_STAT ,0x10}, ++ {R367_OFDM_SYR_NCO1 ,0x00}, ++ {R367_OFDM_SYR_NCO2 ,0x00}, ++ {R367_OFDM_SYR_OFFSET1 ,0x00}, ++ {R367_OFDM_SYR_OFFSET2 ,0x00}, ++ {R367_OFDM_FFT_CTL ,0x00}, ++ {R367_OFDM_SCR_CTL ,0x70}, ++ {R367_OFDM_PPM_CTL1 ,0xf8}, ++ {R367_OFDM_TRL_CTL ,0xac}, ++ {R367_OFDM_TRL_NOMRATE1 ,0x1e}, ++ {R367_OFDM_TRL_NOMRATE2 ,0x58}, ++ {R367_OFDM_TRL_TIME1 ,0x1d}, ++ {R367_OFDM_TRL_TIME2 ,0xfc}, ++ {R367_OFDM_CRL_CTL ,0x24}, ++ {R367_OFDM_CRL_FREQ1 ,0xad}, ++ {R367_OFDM_CRL_FREQ2 ,0x9d}, ++ {R367_OFDM_CRL_FREQ3 ,0xff}, ++ {R367_OFDM_CHC_CTL ,0x01}, ++ {R367_OFDM_CHC_SNR ,0xf0}, ++ {R367_OFDM_BDI_CTL ,0x00}, ++ {R367_OFDM_DMP_CTL ,0x00}, ++ {R367_OFDM_TPS_RCVD1 ,0x30}, ++ {R367_OFDM_TPS_RCVD2 ,0x02}, ++ {R367_OFDM_TPS_RCVD3 ,0x01}, ++ {R367_OFDM_TPS_RCVD4 ,0x00}, ++ {R367_OFDM_TPS_ID_CELL1 ,0x00}, ++ {R367_OFDM_TPS_ID_CELL2 ,0x00}, ++ {R367_OFDM_TPS_RCVD5_SET1 ,0x02}, ++ {R367_OFDM_TPS_SET2 ,0x02}, ++ {R367_OFDM_TPS_SET3 ,0x01}, ++ {R367_OFDM_TPS_CTL ,0x00}, ++ {R367_OFDM_CTL_FFTOSNUM ,0x34}, ++ {R367_OFDM_TESTSELECT ,0x09}, ++ {R367_OFDM_MSC_REV ,0x0a}, ++ {R367_OFDM_PIR_CTL ,0x00}, ++ {R367_OFDM_SNR_CARRIER1 ,0xa1}, ++ {R367_OFDM_SNR_CARRIER2 ,0x9a}, ++ {R367_OFDM_PPM_CPAMP ,0x2c}, ++ {R367_OFDM_TSM_AP0 ,0x00}, ++ {R367_OFDM_TSM_AP1 ,0x00}, ++ {R367_OFDM_TSM_AP2 ,0x00}, ++ {R367_OFDM_TSM_AP3 ,0x00}, ++ {R367_OFDM_TSM_AP4 ,0x00}, ++ {R367_OFDM_TSM_AP5 ,0x00}, ++ {R367_OFDM_TSM_AP6 ,0x00}, ++ {R367_OFDM_TSM_AP7 ,0x00}, ++ //{R367_OFDM_TSTRES ,0x00}, ++ //{R367_OFDM_ANACTRL ,0x0D},/*caution PLL stopped, to be restarted at init!!!*/ ++ //{R367_OFDM_TSTBUS ,0x00}, ++ //{R367_OFDM_TSTRATE ,0x00}, ++ {R367_OFDM_CONSTMODE ,0x01}, ++ {R367_OFDM_CONSTCARR1 ,0x00}, ++ {R367_OFDM_CONSTCARR2 ,0x00}, ++ {R367_OFDM_ICONSTEL ,0x0a}, ++ {R367_OFDM_QCONSTEL ,0x15}, ++ {R367_OFDM_TSTBISTRES0 ,0x00}, ++ {R367_OFDM_TSTBISTRES1 ,0x00}, ++ {R367_OFDM_TSTBISTRES2 ,0x28}, ++ {R367_OFDM_TSTBISTRES3 ,0x00}, ++ //{R367_OFDM_RF_AGC1 ,0xff}, ++ //{R367_OFDM_RF_AGC2 ,0x83}, ++ //{R367_OFDM_ANADIGCTRL ,0x19}, ++ //{R367_OFDM_PLLMDIV ,0x0c}, ++ //{R367_OFDM_PLLNDIV ,0x55}, ++ //{R367_OFDM_PLLSETUP ,0x18}, ++ //{R367_OFDM_DUAL_AD12 ,0x00}, ++ //{R367_OFDM_TSTBIST ,0x00}, ++ //{R367_OFDM_PAD_COMP_CTRL ,0x00}, ++ //{R367_OFDM_PAD_COMP_WR ,0x00}, ++ //{R367_OFDM_PAD_COMP_RD ,0xe0}, ++ {R367_OFDM_SYR_TARGET_FFTADJT_MSB ,0x00}, ++ {R367_OFDM_SYR_TARGET_FFTADJT_LSB ,0x00}, ++ {R367_OFDM_SYR_TARGET_CHCADJT_MSB ,0x00}, ++ {R367_OFDM_SYR_TARGET_CHCADJT_LSB ,0x00}, ++ {R367_OFDM_SYR_FLAG ,0x00}, ++ {R367_OFDM_CRL_TARGET1 ,0x00}, ++ {R367_OFDM_CRL_TARGET2 ,0x00}, ++ {R367_OFDM_CRL_TARGET3 ,0x00}, ++ {R367_OFDM_CRL_TARGET4 ,0x00}, ++ {R367_OFDM_CRL_FLAG ,0x00}, ++ {R367_OFDM_TRL_TARGET1 ,0x00}, ++ {R367_OFDM_TRL_TARGET2 ,0x00}, ++ {R367_OFDM_TRL_CHC ,0x00}, ++ {R367_OFDM_CHC_SNR_TARG ,0x00}, ++ {R367_OFDM_TOP_TRACK ,0x00}, ++ {R367_OFDM_TRACKER_FREE1 ,0x00}, ++ {R367_OFDM_ERROR_CRL1 ,0x00}, ++ {R367_OFDM_ERROR_CRL2 ,0x00}, ++ {R367_OFDM_ERROR_CRL3 ,0x00}, ++ {R367_OFDM_ERROR_CRL4 ,0x00}, ++ {R367_OFDM_DEC_NCO1 ,0x2c}, ++ {R367_OFDM_DEC_NCO2 ,0x0f}, ++ {R367_OFDM_DEC_NCO3 ,0x20}, ++ {R367_OFDM_SNR ,0xf1}, ++ {R367_OFDM_SYR_FFTADJ1 ,0x00}, ++ {R367_OFDM_SYR_FFTADJ2 ,0x00}, ++ {R367_OFDM_SYR_CHCADJ1 ,0x00}, ++ {R367_OFDM_SYR_CHCADJ2 ,0x00}, ++ {R367_OFDM_SYR_OFF ,0x00}, ++ {R367_OFDM_PPM_OFFSET1 ,0x00}, ++ {R367_OFDM_PPM_OFFSET2 ,0x03}, ++ {R367_OFDM_TRACKER_FREE2 ,0x00}, ++ {R367_OFDM_DEBG_LT10 ,0x00}, ++ {R367_OFDM_DEBG_LT11 ,0x00}, ++ {R367_OFDM_DEBG_LT12 ,0x00}, ++ {R367_OFDM_DEBG_LT13 ,0x00}, ++ {R367_OFDM_DEBG_LT14 ,0x00}, ++ {R367_OFDM_DEBG_LT15 ,0x00}, ++ {R367_OFDM_DEBG_LT16 ,0x00}, ++ {R367_OFDM_DEBG_LT17 ,0x00}, ++ {R367_OFDM_DEBG_LT18 ,0x00}, ++ {R367_OFDM_DEBG_LT19 ,0x00}, ++ {R367_OFDM_DEBG_LT1A ,0x00}, ++ {R367_OFDM_DEBG_LT1B ,0x00}, ++ {R367_OFDM_DEBG_LT1C ,0x00}, ++ {R367_OFDM_DEBG_LT1D ,0x00}, ++ {R367_OFDM_DEBG_LT1E ,0x00}, ++ {R367_OFDM_DEBG_LT1F ,0x00}, ++ {R367_OFDM_RCCFGH ,0x00}, ++ {R367_OFDM_RCCFGM ,0x00}, ++ {R367_OFDM_RCCFGL ,0x00}, ++ {R367_OFDM_RCINSDELH ,0x00}, ++ {R367_OFDM_RCINSDELM ,0x00}, ++ {R367_OFDM_RCINSDELL ,0x00}, ++ {R367_OFDM_RCSTATUS ,0x00}, ++ {R367_OFDM_RCSPEED ,0x6f}, ++ {R367_OFDM_RCDEBUGM ,0xe7}, ++ {R367_OFDM_RCDEBUGL ,0x9b}, ++ {R367_OFDM_RCOBSCFG ,0x00}, ++ {R367_OFDM_RCOBSM ,0x00}, ++ {R367_OFDM_RCOBSL ,0x00}, ++ {R367_OFDM_RCFECSPY ,0x00}, ++ {R367_OFDM_RCFSPYCFG ,0x00}, ++ {R367_OFDM_RCFSPYDATA ,0x00}, ++ {R367_OFDM_RCFSPYOUT ,0x00}, ++ {R367_OFDM_RCFSTATUS ,0x00}, ++ {R367_OFDM_RCFGOODPACK ,0x00}, ++ {R367_OFDM_RCFPACKCNT ,0x00}, ++ {R367_OFDM_RCFSPYMISC ,0x00}, ++ {R367_OFDM_RCFBERCPT4 ,0x00}, ++ {R367_OFDM_RCFBERCPT3 ,0x00}, ++ {R367_OFDM_RCFBERCPT2 ,0x00}, ++ {R367_OFDM_RCFBERCPT1 ,0x00}, ++ {R367_OFDM_RCFBERCPT0 ,0x00}, ++ {R367_OFDM_RCFBERERR2 ,0x00}, ++ {R367_OFDM_RCFBERERR1 ,0x00}, ++ {R367_OFDM_RCFBERERR0 ,0x00}, ++ {R367_OFDM_RCFSTATESM ,0x00}, ++ {R367_OFDM_RCFSTATESL ,0x00}, ++ {R367_OFDM_RCFSPYBER ,0x00}, ++ {R367_OFDM_RCFSPYDISTM ,0x00}, ++ {R367_OFDM_RCFSPYDISTL ,0x00}, ++ {R367_OFDM_RCFSPYOBS7 ,0x00}, ++ {R367_OFDM_RCFSPYOBS6 ,0x00}, ++ {R367_OFDM_RCFSPYOBS5 ,0x00}, ++ {R367_OFDM_RCFSPYOBS4 ,0x00}, ++ {R367_OFDM_RCFSPYOBS3 ,0x00}, ++ {R367_OFDM_RCFSPYOBS2 ,0x00}, ++ {R367_OFDM_RCFSPYOBS1 ,0x00}, ++ {R367_OFDM_RCFSPYOBS0 ,0x00}, ++ //{R367_OFDM_TSGENERAL ,0x00}, ++ //{R367_OFDM_RC1SPEED ,0x6f}, ++ //{R367_OFDM_TSGSTATUS ,0x18}, ++ {R367_OFDM_FECM ,0x01}, ++ {R367_OFDM_VTH12 ,0xff}, ++ {R367_OFDM_VTH23 ,0xa1}, ++ {R367_OFDM_VTH34 ,0x64}, ++ {R367_OFDM_VTH56 ,0x40}, ++ {R367_OFDM_VTH67 ,0x00}, ++ {R367_OFDM_VTH78 ,0x2c}, ++ {R367_OFDM_VITCURPUN ,0x12}, ++ {R367_OFDM_VERROR ,0x01}, ++ {R367_OFDM_PRVIT ,0x3f}, ++ {R367_OFDM_VAVSRVIT ,0x00}, ++ {R367_OFDM_VSTATUSVIT ,0xbd}, ++ {R367_OFDM_VTHINUSE ,0xa1}, ++ {R367_OFDM_KDIV12 ,0x20}, ++ {R367_OFDM_KDIV23 ,0x40}, ++ {R367_OFDM_KDIV34 ,0x20}, ++ {R367_OFDM_KDIV56 ,0x30}, ++ {R367_OFDM_KDIV67 ,0x00}, ++ {R367_OFDM_KDIV78 ,0x30}, ++ {R367_OFDM_SIGPOWER ,0x54}, ++ {R367_OFDM_DEMAPVIT ,0x40}, ++ {R367_OFDM_VITSCALE ,0x00}, ++ {R367_OFDM_FFEC1PRG ,0x00}, ++ {R367_OFDM_FVITCURPUN ,0x12}, ++ {R367_OFDM_FVERROR ,0x01}, ++ {R367_OFDM_FVSTATUSVIT ,0xbd}, ++ {R367_OFDM_DEBUG_LT1 ,0x00}, ++ {R367_OFDM_DEBUG_LT2 ,0x00}, ++ {R367_OFDM_DEBUG_LT3 ,0x00}, ++ {R367_OFDM_TSTSFMET ,0x00}, ++ {R367_OFDM_SELOUT ,0x00}, ++ {R367_OFDM_TSYNC ,0x00}, ++ {R367_OFDM_TSTERR ,0x00}, ++ {R367_OFDM_TSFSYNC ,0x00}, ++ {R367_OFDM_TSTSFERR ,0x00}, ++ {R367_OFDM_TSTTSSF1 ,0x01}, ++ {R367_OFDM_TSTTSSF2 ,0x1f}, ++ {R367_OFDM_TSTTSSF3 ,0x00}, ++ {R367_OFDM_TSTTS1 ,0x00}, ++ {R367_OFDM_TSTTS2 ,0x1f}, ++ {R367_OFDM_TSTTS3 ,0x01}, ++ {R367_OFDM_TSTTS4 ,0x00}, ++ {R367_OFDM_TSTTSRC ,0x00}, ++ {R367_OFDM_TSTTSRS ,0x00}, ++ {R367_OFDM_TSSTATEM ,0xb0}, ++ {R367_OFDM_TSSTATEL ,0x40}, ++ {R367_OFDM_TSCFGH ,0x80}, ++ {R367_OFDM_TSCFGM ,0x00}, ++ {R367_OFDM_TSCFGL ,0x20}, ++ {R367_OFDM_TSSYNC ,0x00}, ++ {R367_OFDM_TSINSDELH ,0x00}, ++ {R367_OFDM_TSINSDELM ,0x00}, ++ {R367_OFDM_TSINSDELL ,0x00}, ++ {R367_OFDM_TSDIVN ,0x03}, ++ {R367_OFDM_TSDIVPM ,0x00}, ++ {R367_OFDM_TSDIVPL ,0x00}, ++ {R367_OFDM_TSDIVQM ,0x00}, ++ {R367_OFDM_TSDIVQL ,0x00}, ++ {R367_OFDM_TSDILSTKM ,0x00}, ++ {R367_OFDM_TSDILSTKL ,0x00}, ++ {R367_OFDM_TSSPEED ,0x6f}, ++ {R367_OFDM_TSSTATUS ,0x81}, ++ {R367_OFDM_TSSTATUS2 ,0x6a}, ++ {R367_OFDM_TSBITRATEM ,0x0f}, ++ {R367_OFDM_TSBITRATEL ,0xc6}, ++ {R367_OFDM_TSPACKLENM ,0x00}, ++ {R367_OFDM_TSPACKLENL ,0xfc}, ++ {R367_OFDM_TSBLOCLENM ,0x0a}, ++ {R367_OFDM_TSBLOCLENL ,0x80}, ++ {R367_OFDM_TSDLYH ,0x90}, ++ {R367_OFDM_TSDLYM ,0x68}, ++ {R367_OFDM_TSDLYL ,0x01}, ++ {R367_OFDM_TSNPDAV ,0x00}, ++ {R367_OFDM_TSBUFSTATH ,0x00}, ++ {R367_OFDM_TSBUFSTATM ,0x00}, ++ {R367_OFDM_TSBUFSTATL ,0x00}, ++ {R367_OFDM_TSDEBUGM ,0xcf}, ++ {R367_OFDM_TSDEBUGL ,0x1e}, ++ {R367_OFDM_TSDLYSETH ,0x00}, ++ {R367_OFDM_TSDLYSETM ,0x68}, ++ {R367_OFDM_TSDLYSETL ,0x00}, ++ {R367_OFDM_TSOBSCFG ,0x00}, ++ {R367_OFDM_TSOBSM ,0x47}, ++ {R367_OFDM_TSOBSL ,0x1f}, ++ {R367_OFDM_ERRCTRL1 ,0x95}, ++ {R367_OFDM_ERRCNT1H ,0x80}, ++ {R367_OFDM_ERRCNT1M ,0x00}, ++ {R367_OFDM_ERRCNT1L ,0x00}, ++ {R367_OFDM_ERRCTRL2 ,0x95}, ++ {R367_OFDM_ERRCNT2H ,0x00}, ++ {R367_OFDM_ERRCNT2M ,0x00}, ++ {R367_OFDM_ERRCNT2L ,0x00}, ++ {R367_OFDM_FECSPY ,0x88}, ++ {R367_OFDM_FSPYCFG ,0x2c}, ++ {R367_OFDM_FSPYDATA ,0x3a}, ++ {R367_OFDM_FSPYOUT ,0x06}, ++ {R367_OFDM_FSTATUS ,0x61}, ++ {R367_OFDM_FGOODPACK ,0xff}, ++ {R367_OFDM_FPACKCNT ,0xff}, ++ {R367_OFDM_FSPYMISC ,0x66}, ++ {R367_OFDM_FBERCPT4 ,0x00}, ++ {R367_OFDM_FBERCPT3 ,0x00}, ++ {R367_OFDM_FBERCPT2 ,0x36}, ++ {R367_OFDM_FBERCPT1 ,0x36}, ++ {R367_OFDM_FBERCPT0 ,0x14}, ++ {R367_OFDM_FBERERR2 ,0x00}, ++ {R367_OFDM_FBERERR1 ,0x03}, ++ {R367_OFDM_FBERERR0 ,0x28}, ++ {R367_OFDM_FSTATESM ,0x00}, ++ {R367_OFDM_FSTATESL ,0x02}, ++ {R367_OFDM_FSPYBER ,0x00}, ++ {R367_OFDM_FSPYDISTM ,0x01}, ++ {R367_OFDM_FSPYDISTL ,0x9f}, ++ {R367_OFDM_FSPYOBS7 ,0xc9}, ++ {R367_OFDM_FSPYOBS6 ,0x99}, ++ {R367_OFDM_FSPYOBS5 ,0x08}, ++ {R367_OFDM_FSPYOBS4 ,0xec}, ++ {R367_OFDM_FSPYOBS3 ,0x01}, ++ {R367_OFDM_FSPYOBS2 ,0x0f}, ++ {R367_OFDM_FSPYOBS1 ,0xf5}, ++ {R367_OFDM_FSPYOBS0 ,0x08}, ++ {R367_OFDM_SFDEMAP ,0x40}, ++ {R367_OFDM_SFERROR ,0x00}, ++ {R367_OFDM_SFAVSR ,0x30}, ++ {R367_OFDM_SFECSTATUS ,0xcc}, ++ {R367_OFDM_SFKDIV12 ,0x20}, ++ {R367_OFDM_SFKDIV23 ,0x40}, ++ {R367_OFDM_SFKDIV34 ,0x20}, ++ {R367_OFDM_SFKDIV56 ,0x20}, ++ {R367_OFDM_SFKDIV67 ,0x00}, ++ {R367_OFDM_SFKDIV78 ,0x20}, ++ {R367_OFDM_SFDILSTKM ,0x00}, ++ {R367_OFDM_SFDILSTKL ,0x00}, ++ {R367_OFDM_SFSTATUS ,0xb5}, ++ {R367_OFDM_SFDLYH ,0x90}, ++ {R367_OFDM_SFDLYM ,0x60}, ++ {R367_OFDM_SFDLYL ,0x01}, ++ {R367_OFDM_SFDLYSETH ,0xc0}, ++ {R367_OFDM_SFDLYSETM ,0x60}, ++ {R367_OFDM_SFDLYSETL ,0x00}, ++ {R367_OFDM_SFOBSCFG ,0x00}, ++ {R367_OFDM_SFOBSM ,0x47}, ++ {R367_OFDM_SFOBSL ,0x05}, ++ {R367_OFDM_SFECINFO ,0x40}, ++ {R367_OFDM_SFERRCTRL ,0x74}, ++ {R367_OFDM_SFERRCNTH ,0x80}, ++ {R367_OFDM_SFERRCNTM ,0x00}, ++ {R367_OFDM_SFERRCNTL ,0x00}, ++ {R367_OFDM_SYMBRATEM ,0x2f}, ++ {R367_OFDM_SYMBRATEL ,0x50}, ++ {R367_OFDM_SYMBSTATUS ,0x7f}, ++ {R367_OFDM_SYMBCFG ,0x00}, ++ {R367_OFDM_SYMBFIFOM ,0xf4}, ++ {R367_OFDM_SYMBFIFOL ,0x0d}, ++ {R367_OFDM_SYMBOFFSM ,0xf0}, ++ {R367_OFDM_SYMBOFFSL ,0x2d}, ++ //{R367_OFDM_DEBUG_LT4 ,0x00}, ++ //{R367_OFDM_DEBUG_LT5 ,0x00}, ++ //{R367_OFDM_DEBUG_LT6 ,0x00}, ++ //{R367_OFDM_DEBUG_LT7 ,0x00}, ++ //{R367_OFDM_DEBUG_LT8 ,0x00}, ++ //{R367_OFDM_DEBUG_LT9 ,0x00}, ++ { 0x0000, 0x00 } // EOT ++}; ++ ++inline u32 MulDiv32(u32 a, u32 b, u32 c) ++{ ++ u64 tmp64; ++ ++ tmp64 = (u64)a * (u64)b; ++ do_div(tmp64, c); ++ ++ return (u32) tmp64; ++} ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = ++ {.addr = adr, .flags = 0, .buf = data, .len = len}; ++ ++ if (i2c_transfer(adap, &msg, 1) != 1) { ++ printk("stv0367: i2c_write error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++#if 0 ++static int i2c_read(struct i2c_adapter *adap, ++ u8 adr, u8 *msg, int len, u8 *answ, int alen) ++{ ++ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, ++ .buf = msg, .len = len}, ++ { .addr = adr, .flags = I2C_M_RD, ++ .buf = answ, .len = alen } }; ++ if (i2c_transfer(adap, msgs, 2) != 2) { ++ printk("stv0367: i2c_read error\n"); ++ return -1; ++ } ++ return 0; ++} ++#endif ++ ++static int writereg(struct stv_state *state, u16 reg, u8 dat) ++{ ++ u8 mm[3] = { (reg >> 8), reg & 0xff, dat }; ++ ++ return i2c_write(state->i2c, state->adr, mm, 3); ++} ++ ++static int readreg(struct stv_state *state, u16 reg, u8 *val) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = state->adr, .flags = I2C_M_RD, ++ .buf = val, .len = 1}}; ++ return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int readregs(struct stv_state *state, u16 reg, u8 *val, int count) ++{ ++ u8 msg[2] = {reg >> 8, reg & 0xff}; ++ struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0, ++ .buf = msg, .len = 2}, ++ {.addr = state->adr, .flags = I2C_M_RD, ++ .buf = val, .len = count}}; ++ return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int write_init_table(struct stv_state *state, struct init_table *tab) ++{ ++ while (1) { ++ if (!tab->adr) ++ break; ++ if (writereg(state, tab->adr, tab->data) < 0) ++ return -1; ++ tab++; ++ } ++ return 0; ++} ++ ++static int qam_set_modulation(struct stv_state *state) ++{ ++ int stat = 0; ++ ++ switch(state->modulation) { ++ case QAM_16: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM16 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x64); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ ++ writereg(state, R367_QAM_FSM_STATE,0x90); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0x8a); ++ break; ++ case QAM_32: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM32 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x6e); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ ++ writereg(state, R367_QAM_FSM_STATE,0xb0); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xb7); ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x9d); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); ++ break; ++ case QAM_64: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM64 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x82); /* Set digital AGC reference */ ++ if(state->symbol_rate>4500000) ++ { ++ writereg(state, R367_QAM_FSM_STATE,0xb0); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa5); ++ } ++ else if(state->symbol_rate>2500000) // 25000000 ++ { ++ writereg(state, R367_QAM_FSM_STATE,0xa0); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6); ++ } ++ else ++ { ++ writereg(state, R367_QAM_FSM_STATE,0xa0); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1); ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); ++ } ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0x99); ++ break; ++ case QAM_128: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM128 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x76); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ ++ writereg(state, R367_QAM_FSM_STATE,0x90); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xb1); ++ if(state->symbol_rate>4500000) // 45000000 ++ { ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); ++ } ++ else if(state->symbol_rate>2500000) // 25000000 ++ { ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6); ++ } ++ else ++ { ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0x97); ++ } ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x8e); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); ++ break; ++ case QAM_256: ++ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM256 ); ++ writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a); /* Set analog AGC reference */ ++ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x94); /* Set digital AGC reference */ ++ writereg(state, R367_QAM_FSM_STATE,0xa0); ++ if(state->symbol_rate>4500000) // 45000000 ++ { ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ } ++ else if(state->symbol_rate>2500000) // 25000000 ++ { ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); ++ } ++ else ++ { ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1); ++ } ++ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); ++ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x85); ++ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); ++ break; ++ default: ++ stat = -EINVAL; ++ break; ++ } ++ return stat; ++} ++ ++ ++static int QAM_SetSymbolRate(struct stv_state *state) ++{ ++ int status = 0; ++ u32 sr = state->symbol_rate; ++ u32 Corr = 0; ++ u32 Temp, Temp1, AdpClk; ++ ++ switch(state->modulation) { ++ default: ++ case QAM_16: Corr = 1032; break; ++ case QAM_32: Corr = 954; break; ++ case QAM_64: Corr = 983; break; ++ case QAM_128: Corr = 957; break; ++ case QAM_256: Corr = 948; break; ++ } ++ ++ // Transfer ration ++ Temp = (256*sr) / state->adc_clock; ++ writereg(state, R367_QAM_EQU_CRL_TFR,(Temp)); ++ ++ /* Symbol rate and SRC gain calculation */ ++ AdpClk = (state->master_clock)/2000; /* TRL works at half the system clock */ ++ ++ Temp = state->symbol_rate; ++ Temp1 = sr; ++ ++ if(sr < 2097152) /* 2097152 = 2^21 */ ++ { ++ Temp = ((((sr * 2048) / AdpClk) * 16384 ) / 125 ) * 8; ++ Temp1 = (((((sr * 2048) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 10000000; ++ } ++ else if(sr < 4194304) /* 4194304 = 2**22 */ ++ { ++ Temp = ((((sr * 1024) / AdpClk) * 16384 ) / 125 ) * 16; ++ Temp1 = (((((sr * 1024) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 5000000; ++ } ++ else if(sr < 8388608) /* 8388608 = 2**23 */ ++ { ++ Temp = ((((sr * 512) / AdpClk) * 16384 ) / 125 ) * 32; ++ Temp1 = (((((sr * 512) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 2500000; ++ } ++ else ++ { ++ Temp = ((((sr * 256) / AdpClk) * 16384 ) / 125 ) * 64; ++ Temp1 = (((((sr * 256) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 1250000; ++ } ++ ++ ///* Filters' coefficients are calculated and written into registers only if the filters are enabled */ ++ //if (ChipGetField(hChip,F367qam_ADJ_EN)) // Is disabled from init! ++ //{ ++ // FE_367qam_SetIirAdjacentcoefficient(hChip, MasterClk_Hz, SymbolRate); ++ //} ++ ///* AllPass filter is never used on this IC */ ++ //ChipSetField(hChip,F367qam_ALLPASSFILT_EN,0); // should be disabled from init! ++ ++ writereg(state, R367_QAM_SRC_NCO_LL,(Temp)); ++ writereg(state, R367_QAM_SRC_NCO_LH,(Temp>>8)); ++ writereg(state, R367_QAM_SRC_NCO_HL,(Temp>>16)); ++ writereg(state, R367_QAM_SRC_NCO_HH,(Temp>>24)); ++ ++ writereg(state, R367_QAM_IQDEM_GAIN_SRC_L,(Temp1)); ++ writereg(state, R367_QAM_IQDEM_GAIN_SRC_H,(Temp1>>8)); ++ return status; ++} ++ ++ ++static int QAM_SetDerotFrequency(struct stv_state *state, u32 DerotFrequency) ++{ ++ int status = 0; ++ u32 Sampled_IF; ++ ++ do { ++ //if (DerotFrequency < 1000000) ++ // DerotFrequency = state->adc_clock/4; /* ZIF operation */ ++ if (DerotFrequency > state->adc_clock) ++ DerotFrequency = DerotFrequency - state->adc_clock; // User Alias ++ ++ Sampled_IF = ((32768 * (DerotFrequency/1000)) / (state->adc_clock/1000)) * 256; ++ if(Sampled_IF > 8388607) ++ Sampled_IF = 8388607; ++ ++ writereg(state, R367_QAM_MIX_NCO_LL, (Sampled_IF)); ++ writereg(state, R367_QAM_MIX_NCO_HL, (Sampled_IF>>8)); ++ writereg(state, R367_QAM_MIX_NCO_HH, (Sampled_IF>>16)); ++ } while(0); ++ ++ return status; ++} ++ ++ ++ ++static int QAM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency) ++{ ++ int status = 0; ++ u32 AGCTimeOut = 25; ++ u32 TRLTimeOut = 100000000 / state->symbol_rate; ++ u32 CRLSymbols = 0; ++ u32 EQLTimeOut = 100; ++ u32 SearchRange = state->symbol_rate / 25; ++ u32 CRLTimeOut; ++ u8 Temp; ++ ++ if( state->demod_state != QAMSet ) { ++ writereg(state, R367_DEBUG_LT4,0x00); ++ writereg(state, R367_DEBUG_LT5,0x01); ++ writereg(state, R367_DEBUG_LT6,0x06);// R367_QAM_CTRL_1 ++ writereg(state, R367_DEBUG_LT7,0x03);// R367_QAM_CTRL_2 ++ writereg(state, R367_DEBUG_LT8,0x00); ++ writereg(state, R367_DEBUG_LT9,0x00); ++ ++ // Tuner Setup ++ writereg(state, R367_ANADIGCTRL,0x8B); /* Buffer Q disabled, I Enabled, signed ADC */ ++ writereg(state, R367_DUAL_AD12,0x04); /* ADCQ disabled */ ++ ++ // Clock setup ++ writereg(state, R367_ANACTRL,0x0D); /* PLL bypassed and disabled */ ++ writereg(state, R367_TOPCTRL,0x10); // Set QAM ++ ++ writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */ ++ writereg(state, R367_PLLNDIV,232); ++ writereg(state, R367_PLLSETUP,0x18); /* ADC clock is equal to system clock */ ++ ++ msleep(50); ++ writereg(state, R367_ANACTRL,0x00); /* PLL enabled and used */ ++ ++ state->master_clock = 58000000; ++ state->adc_clock = 58000000; ++ ++ state->demod_state = QAMSet; ++ } ++ ++ state->m_bFirstTimeLock = true; ++ state->m_DemodLockTime = -1; ++ ++ qam_set_modulation(state); ++ QAM_SetSymbolRate(state); ++ ++ // Will make problems on low symbol rates ( < 2500000 ) ++ ++ switch(state->modulation) { ++ default: ++ case QAM_16: CRLSymbols = 150000; break; ++ case QAM_32: CRLSymbols = 250000; break; ++ case QAM_64: CRLSymbols = 200000; break; ++ case QAM_128: CRLSymbols = 250000; break; ++ case QAM_256: CRLSymbols = 250000; break; ++ } ++ ++ CRLTimeOut = (25 * CRLSymbols * (SearchRange/1000)) / (state->symbol_rate/1000); ++ CRLTimeOut = (1000 * CRLTimeOut) / state->symbol_rate; ++ if( CRLTimeOut < 50 ) CRLTimeOut = 50; ++ ++ state->m_FECTimeOut = 20; ++ state->m_DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut; ++ state->m_SignalTimeOut = AGCTimeOut + TRLTimeOut; ++ ++ // QAM_AGC_ACCUMRSTSEL = 0; ++ readreg(state, R367_QAM_AGC_CTL,&state->m_Save_QAM_AGC_CTL); ++ writereg(state, R367_QAM_AGC_CTL,state->m_Save_QAM_AGC_CTL & ~0x0F); ++ ++ // QAM_MODULUSMAP_EN = 0 ++ readreg(state, R367_QAM_EQU_PNT_GAIN,&Temp); ++ writereg(state, R367_QAM_EQU_PNT_GAIN,Temp & ~0x40); ++ ++ // QAM_SWEEP_EN = 0 ++ readreg(state, R367_QAM_EQU_CTR_LPF_GAIN,&Temp); ++ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,Temp & ~0x08); ++ ++ QAM_SetDerotFrequency(state, IntermediateFrequency); ++ ++ // Release TRL ++ writereg(state, R367_QAM_CTRL_1,0x00); ++ ++ state->IF = IntermediateFrequency; ++ state->demod_state = QAMStarted; ++ ++ return status; ++} ++ ++static int OFDM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency) ++{ ++ int status = 0; ++ u8 GAIN_SRC1; ++ u32 Derot; ++ u8 SYR_CTL; ++ u8 tmp1; ++ u8 tmp2; ++ ++ if ( state->demod_state != OFDMSet ) { ++ // QAM Disable ++ writereg(state, R367_DEBUG_LT4, 0x00); ++ writereg(state, R367_DEBUG_LT5, 0x00); ++ writereg(state, R367_DEBUG_LT6, 0x00);// R367_QAM_CTRL_1 ++ writereg(state, R367_DEBUG_LT7, 0x00);// R367_QAM_CTRL_2 ++ writereg(state, R367_DEBUG_LT8, 0x00); ++ writereg(state, R367_DEBUG_LT9, 0x00); ++ ++ // Tuner Setup ++ writereg(state, R367_ANADIGCTRL, 0x89); /* Buffer Q disabled, I Enabled, unsigned ADC */ ++ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ ++ ++ // Clock setup ++ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ ++ writereg(state, R367_TOPCTRL, 0x00); // Set OFDM ++ ++ writereg(state, R367_PLLMDIV, 1); /* IC runs at 54 MHz with a 27 MHz crystal */ ++ writereg(state, R367_PLLNDIV, 8); ++ writereg(state, R367_PLLSETUP, 0x18); /* ADC clock is equal to system clock */ ++ ++ msleep(50); ++ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ ++ ++ state->master_clock = 54000000; ++ state->adc_clock = 54000000; ++ ++ state->demod_state = OFDMSet; ++ } ++ ++ state->m_bFirstTimeLock = true; ++ state->m_DemodLockTime = -1; ++ ++ // Set inversion in GAIN_SRC1 (fixed from init) ++ // is in GAIN_SRC1, see below ++ ++ GAIN_SRC1 = 0xA0; ++ // Bandwidth ++ ++ // Fixed values for 54 MHz ++ switch(state->bandwidth) { ++ case 0: ++ case 8000000: ++ // Normrate = 44384; ++ writereg(state, R367_OFDM_TRL_CTL,0x14); ++ writereg(state, R367_OFDM_TRL_NOMRATE1,0xB0); ++ writereg(state, R367_OFDM_TRL_NOMRATE2,0x56); ++ // Gain SRC = 2774 ++ writereg(state, R367_OFDM_GAIN_SRC1,0x0A | GAIN_SRC1); ++ writereg(state, R367_OFDM_GAIN_SRC2,0xD6); ++ break; ++ case 7000000: ++ // Normrate = 38836; ++ writereg(state, R367_OFDM_TRL_CTL,0x14); ++ writereg(state, R367_OFDM_TRL_NOMRATE1,0xDA); ++ writereg(state, R367_OFDM_TRL_NOMRATE2,0x4B); ++ // Gain SRC = 2427 ++ writereg(state, R367_OFDM_GAIN_SRC1,0x09 | GAIN_SRC1); ++ writereg(state, R367_OFDM_GAIN_SRC2,0x7B); ++ break; ++ case 6000000: ++ // Normrate = 33288; ++ writereg(state, R367_OFDM_TRL_CTL,0x14); ++ writereg(state, R367_OFDM_TRL_NOMRATE1,0x04); ++ writereg(state, R367_OFDM_TRL_NOMRATE2,0x41); ++ // Gain SRC = 2080 ++ writereg(state, R367_OFDM_GAIN_SRC1,0x08 | GAIN_SRC1); ++ writereg(state, R367_OFDM_GAIN_SRC2,0x20); ++ break; ++ default: ++ return -EINVAL; ++ break; ++ } ++ ++ Derot = ((IntermediateFrequency/1000) * 65536) / (state->master_clock / 1000); ++ ++ writereg(state, R367_OFDM_INC_DEROT1,(Derot>>8)); ++ writereg(state, R367_OFDM_INC_DEROT2,(Derot)); ++ ++ readreg(state, R367_OFDM_SYR_CTL,&SYR_CTL); ++ SYR_CTL &= ~0x78; ++ writereg(state, R367_OFDM_SYR_CTL,SYR_CTL); // EchoPos = 0 ++ ++ ++ writereg(state, R367_OFDM_COR_MODEGUARD,0x03); // Force = 0, Mode = 0, Guard = 3 ++ SYR_CTL &= 0x01; ++ writereg(state, R367_OFDM_SYR_CTL,SYR_CTL); // SYR_TR_DIS = 0 ++ ++ msleep(5); ++ ++ writereg(state, R367_OFDM_COR_CTL,0x20); // Start core ++ ++ // -- Begin M.V. ++ // Reset FEC and Read Solomon ++ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); ++ readreg(state, R367_TSGENERAL,&tmp2); ++ writereg(state, R367_OFDM_SFDLYSETH,tmp1 | 0x08); ++ writereg(state, R367_TSGENERAL,tmp2 | 0x01); ++ // -- End M.V. ++ ++ state->m_SignalTimeOut = 200; ++ state->IF = IntermediateFrequency; ++ state->demod_state = OFDMStarted; ++ state->m_DemodTimeOut = 0; ++ state->m_FECTimeOut = 0; ++ state->m_TSTimeOut = 0; ++ ++ return status; ++} ++ ++#if 0 ++static int Stop(struct stv_state *state) ++{ ++ int status = 0; ++ ++ switch(state->demod_state) ++ { ++ case QAMStarted: ++ status = writereg(state, R367_QAM_CTRL_1,0x06); ++ state->demod_state = QAMSet; ++ break; ++ case OFDMStarted: ++ status = writereg(state, R367_OFDM_COR_CTL,0x00); ++ state->demod_state = OFDMSet; ++ break; ++ default: ++ break; ++ } ++ return status; ++} ++#endif ++ ++static s32 Log10x100(u32 x) ++{ ++ static u32 LookupTable[100] = { ++ 101157945, 103514217, 105925373, 108392691, 110917482, ++ 113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5 ++ 127350308, 130316678, 133352143, 136458314, 139636836, ++ 142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5 ++ 160324539, 164058977, 167880402, 171790839, 175792361, ++ 179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5 ++ 201836636, 206538016, 211348904, 216271852, 221309471, ++ 226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5 ++ 254097271, 260015956, 266072506, 272270131, 278612117, ++ 285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5 ++ 319889511, 327340695, 334965439, 342767787, 350751874, ++ 358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5 ++ 402717034, 412097519, 421696503, 431519077, 441570447, ++ 451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5 ++ 506990708, 518800039, 530884444, 543250331, 555904257, ++ 568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5 ++ 638263486, 653130553, 668343918, 683911647, 699841996, ++ 716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5 ++ 803526122, 822242650, 841395142, 860993752, 881048873, ++ 901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5 ++ }; ++ s32 y; ++ int i; ++ ++ if (x == 0) ++ return 0; ++ y = 800; ++ if (x >= 1000000000) { ++ x /= 10; ++ y += 100; ++ } ++ ++ while (x < 100000000) { ++ x *= 10; ++ y -= 100; ++ } ++ i = 0; ++ while (i < 100 && x > LookupTable[i]) ++ i += 1; ++ y += i; ++ return y; ++} ++ ++static int QAM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise) ++{ ++ u32 RegValAvg = 0; ++ u8 RegVal[2]; ++ int status = 0, i; ++ ++ *pSignalToNoise = 0; ++ for (i = 0; i < 10; i += 1 ) { ++ readregs(state, R367_QAM_EQU_SNR_LO, RegVal, 2); ++ RegValAvg += RegVal[0] + 256 * RegVal[1]; ++ } ++ if (RegValAvg != 0) { ++ s32 Power = 1; ++ switch(state->modulation) { ++ case QAM_16: ++ Power = 20480; ++ break; ++ case QAM_32: ++ Power = 23040; ++ break; ++ case QAM_64: ++ Power = 21504; ++ break; ++ case QAM_128: ++ Power = 23616; break; ++ case QAM_256: ++ Power = 21760; break; ++ default: ++ break; ++ } ++ *pSignalToNoise = Log10x100((Power * 320) / RegValAvg); ++ } else { ++ *pSignalToNoise = 380; ++ } ++ return status; ++} ++ ++static int OFDM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise) ++{ ++ u8 CHC_SNR = 0; ++ ++ int status = readreg(state, R367_OFDM_CHC_SNR, &CHC_SNR); ++ if (status >= 0) { ++ // Note: very unclear documentation on this. ++ // Datasheet states snr = CHC_SNR/4 dB -> way to high values! ++ // Software snr = ( 1000 * CHC_SNR ) / 8 / 32 / 10; -> to low values ++ // Comment in SW states this should be ( 1000 * CHC_SNR ) / 4 / 32 / 10; for the 367 ++ // 361/362 Datasheet: snr = CHC_SNR/8 dB -> this looks best ++ *pSignalToNoise = ( (s32)CHC_SNR * 10) / 8; ++ } ++ //printk("SNR %d\n", *pSignalToNoise); ++ return status; ++} ++ ++#if 0 ++static int DVBC_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) ++{ ++ *pQuality = 100; ++ return 0; ++}; ++ ++static int DVBT_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) ++{ ++ static s32 QE_SN[] = { ++ 51, // QPSK 1/2 ++ 69, // QPSK 2/3 ++ 79, // QPSK 3/4 ++ 89, // QPSK 5/6 ++ 97, // QPSK 7/8 ++ 108, // 16-QAM 1/2 ++ 131, // 16-QAM 2/3 ++ 146, // 16-QAM 3/4 ++ 156, // 16-QAM 5/6 ++ 160, // 16-QAM 7/8 ++ 165, // 64-QAM 1/2 ++ 187, // 64-QAM 2/3 ++ 202, // 64-QAM 3/4 ++ 216, // 64-QAM 5/6 ++ 225, // 64-QAM 7/8 ++ }; ++ u8 TPS_Received[2]; ++ int Constellation; ++ int CodeRate; ++ s32 SignalToNoiseRel, BERQuality; ++ ++ *pQuality = 0; ++ readregs(state, R367_OFDM_TPS_RCVD2, TPS_Received, sizeof(TPS_Received)); ++ Constellation = TPS_Received[0] & 0x03; ++ CodeRate = TPS_Received[1] & 0x07; ++ ++ if( Constellation > 2 || CodeRate > 5 ) ++ return -1; ++ SignalToNoiseRel = SignalToNoise - QE_SN[Constellation * 5 + CodeRate]; ++ BERQuality = 100; ++ ++ if( SignalToNoiseRel < -70 ) ++ *pQuality = 0; ++ else if( SignalToNoiseRel < 30 ) { ++ *pQuality = ((SignalToNoiseRel + 70) * BERQuality)/100; ++ } else ++ *pQuality = BERQuality; ++ return 0; ++}; ++ ++static s32 DVBCQuality(struct stv_state *state, s32 SignalToNoise) ++{ ++ s32 SignalToNoiseRel = 0; ++ s32 Quality = 0; ++ s32 BERQuality = 100; ++ ++ switch(state->modulation) { ++ case QAM_16: SignalToNoiseRel = SignalToNoise - 200 ; break; ++ case QAM_32: SignalToNoiseRel = SignalToNoise - 230 ; break; // Not in NorDig ++ case QAM_64: SignalToNoiseRel = SignalToNoise - 260 ; break; ++ case QAM_128: SignalToNoiseRel = SignalToNoise - 290 ; break; ++ case QAM_256: SignalToNoiseRel = SignalToNoise - 320 ; break; ++ } ++ ++ if( SignalToNoiseRel < -70 ) Quality = 0; ++ else if( SignalToNoiseRel < 30 ) ++ { ++ Quality = ((SignalToNoiseRel + 70) * BERQuality)/100; ++ } ++ else ++ Quality = BERQuality; ++ ++ return Quality; ++} ++ ++static int GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) ++{ ++ *pQuality = 0; ++ switch(state->demod_state) ++ { ++ case QAMStarted: ++ *pQuality = DVBCQuality(state, SignalToNoise); ++ break; ++ case OFDMStarted: ++ return DVBT_GetQuality(state, SignalToNoise, pQuality); ++ } ++ return 0; ++}; ++#endif ++ ++static int attach_init(struct stv_state *state) ++{ ++ int stat = 0; ++ ++ stat = readreg(state, R367_ID, &state->ID); ++ if ( stat < 0 || state->ID != 0x60 ) ++ return -ENODEV; ++ printk("stv0367 found\n"); ++ ++ writereg(state, R367_TOPCTRL, 0x10); ++ write_init_table(state, base_init); ++ write_init_table(state, qam_init); ++ ++ writereg(state, R367_TOPCTRL, 0x00); ++ write_init_table(state, ofdm_init); ++ ++ writereg(state, R367_OFDM_GAIN_SRC1, 0x2A); ++ writereg(state, R367_OFDM_GAIN_SRC2, 0xD6); ++ writereg(state, R367_OFDM_INC_DEROT1, 0x55); ++ writereg(state, R367_OFDM_INC_DEROT2, 0x55); ++ writereg(state, R367_OFDM_TRL_CTL, 0x14); ++ writereg(state, R367_OFDM_TRL_NOMRATE1, 0xAE); ++ writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56); ++ writereg(state, R367_OFDM_FEPATH_CFG, 0x0); ++ ++ // OFDM TS Setup ++ ++ writereg(state, R367_OFDM_TSCFGH, 0x70); ++ writereg(state, R367_OFDM_TSCFGM, 0xC0); ++ writereg(state, R367_OFDM_TSCFGL, 0x20); ++ writereg(state, R367_OFDM_TSSPEED, 0x40); // Fixed at 54 MHz ++ //writereg(state, R367_TSTBUS, 0x80); // Invert CLK ++ ++ writereg(state, R367_OFDM_TSCFGH, 0x71); ++ writereg(state, R367_OFDM_TSCFGH, 0x70); ++ ++ writereg(state, R367_TOPCTRL, 0x10); ++ ++ // Also needed for QAM ++ writereg(state, R367_OFDM_AGC12C, 0x01); // AGC Pin setup ++ ++ writereg(state, R367_OFDM_AGCCTRL1, 0x8A); // ++ ++ // QAM TS setup, note exact format also depends on descrambler settings ++ writereg(state, R367_QAM_OUTFORMAT_0, 0x85); // Inverted Clock, Swap, serial ++ // writereg(state, R367_QAM_OUTFORMAT_1, 0x00); // ++ ++ // Clock setup ++ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ ++ ++ if( state->master_clock == 58000000 ) { ++ writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */ ++ writereg(state, R367_PLLNDIV,232); ++ } else { ++ writereg(state, R367_PLLMDIV,1); /* IC runs at 54 MHz with a 27 MHz crystal */ ++ writereg(state, R367_PLLNDIV,8); ++ } ++ writereg(state, R367_PLLSETUP, 0x18); /* ADC clock is equal to system clock */ ++ ++ // Tuner setup ++ writereg(state, R367_ANADIGCTRL, 0x8b); /* Buffer Q disabled, I Enabled, signed ADC */ ++ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ ++ ++ writereg(state, R367_QAM_FSM_SNR2_HTH, 0x23); /* Improves the C/N lock limit */ ++ writereg(state, R367_QAM_IQ_QAM, 0x01); /* ZIF/IF Automatic mode */ ++ writereg(state, R367_QAM_EQU_FFE_LEAKAGE, 0x83); /* Improving burst noise performances */ ++ writereg(state, R367_QAM_IQDEM_ADJ_EN, 0x05); /* Improving ACI performances */ ++ ++ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ ++ ++ writereg(state, R367_I2CRPT, state->I2CRPT); ++ state->demod_state = QAMSet; ++ return stat; ++} ++ ++#ifdef USE_API3 ++static void c_release(struct dvb_frontend* fe) ++#else ++static void release(struct dvb_frontend* fe) ++#endif ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ printk("%s\n", __FUNCTION__); ++ kfree(state); ++} ++ ++#ifdef USE_API3 ++static int c_init (struct dvb_frontend *fe) ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ ++ if (mutex_trylock(&state->ctlock)==0) ++ return -EBUSY; ++ state->omode = OM_DVBC; ++ return 0; ++} ++ ++static int c_sleep(struct dvb_frontend* fe) ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ ++ mutex_unlock(&state->ctlock); ++ return 0; ++} ++#endif ++ ++static int gate_ctrl(struct dvb_frontend* fe, int enable) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ u8 i2crpt = state->I2CRPT & ~0x80; ++ ++ if (enable) ++ i2crpt |= 0x80; ++ if (writereg(state, R367_I2CRPT, i2crpt) < 0) ++ return -1; ++ state->I2CRPT = i2crpt; ++ return 0; ++} ++ ++#if 0 ++static int c_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) ++{ ++ return DVBFE_ALGO_SEARCH_AGAIN; ++} ++#endif ++ ++#if 0 ++int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); ++int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); ++#endif ++ ++static int ofdm_lock(struct stv_state *state) ++{ ++ int status = 0; ++ u8 OFDM_Status; ++ s32 DemodTimeOut = 10; ++ s32 FECTimeOut = 0; ++ s32 TSTimeOut = 0; ++ u8 CPAMPMin = 255; ++ u8 CPAMPValue; ++ u8 SYR_STAT; ++ u8 FFTMode; ++ u8 TSStatus; ++ ++ msleep(state->m_SignalTimeOut); ++ readreg(state, R367_OFDM_STATUS,&OFDM_Status); ++ ++ if (!(OFDM_Status & 0x40)) ++ return -1; ++ //printk("lock 1\n"); ++ ++ readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); ++ FFTMode = (SYR_STAT & 0x0C) >> 2; ++ ++ switch(FFTMode) ++ { ++ case 0: // 2K ++ DemodTimeOut = 10; ++ FECTimeOut = 150; ++ TSTimeOut = 125; ++ CPAMPMin = 20; ++ break; ++ case 1: // 8K ++ DemodTimeOut = 55; ++ FECTimeOut = 600; ++ TSTimeOut = 500; ++ CPAMPMin = 80; ++ break; ++ case 2: // 4K ++ DemodTimeOut = 40; ++ FECTimeOut = 300; ++ TSTimeOut = 250; ++ CPAMPMin = 30; ++ break; ++ } ++ state->m_OFDM_FFTMode = FFTMode; ++ readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue); ++ msleep(DemodTimeOut); ++ { ++ // Release FEC and Read Solomon Reset ++ u8 tmp1; ++ u8 tmp2; ++ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); ++ readreg(state, R367_TSGENERAL,&tmp2); ++ writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08); ++ writereg(state, R367_TSGENERAL,tmp2 & ~0x01); ++ } ++ msleep(FECTimeOut); ++ if( (OFDM_Status & 0x98) != 0x98 ) ++ ;//return -1; ++ //printk("lock 2\n"); ++ ++ { ++ u8 Guard = (SYR_STAT & 0x03); ++ if(Guard < 2) ++ { ++ u8 tmp; ++ readreg(state, R367_OFDM_SYR_CTL,&tmp); ++ writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN ++ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); ++ writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER ++ } else { ++ u8 tmp; ++ readreg(state, R367_OFDM_SYR_CTL,&tmp); ++ writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN ++ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); ++ writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER ++ } ++ ++ // apply Sfec workaround if 8K 64QAM CR!=1/2 ++ if( FFTMode == 1) ++ { ++ u8 tmp[2]; ++ readregs(state, R367_OFDM_TPS_RCVD2, tmp, 2); ++ if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) ) ++ { ++ writereg(state, R367_OFDM_SFDLYSETH,0xc0); ++ writereg(state, R367_OFDM_SFDLYSETM,0x60); ++ writereg(state, R367_OFDM_SFDLYSETL,0x00); ++ } ++ else ++ { ++ writereg(state, R367_OFDM_SFDLYSETH,0x00); ++ } ++ } ++ } ++ msleep(TSTimeOut); ++ readreg(state, R367_OFDM_TSSTATUS,&TSStatus); ++ if( (TSStatus & 0x80) != 0x80 ) ++ return -1; ++ //printk("lock 3\n"); ++ return status; ++} ++ ++ ++ ++#ifdef USE_API3 ++static int set_parameters(struct dvb_frontend *fe, ++ struct dvb_frontend_parameters *p) ++{ ++ int stat; ++ struct stv_state *state = fe->demodulator_priv; ++ u32 OF = 0; ++ u32 IF; ++ ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe, p); ++ ++ switch (state->omode) { ++ case OM_DVBC: ++ case OM_QAM_ITU_C: ++ state->modulation = p->u.qam.modulation; ++ state->symbol_rate = p->u.qam.symbol_rate; ++ break; ++ case OM_DVBT: ++ switch (p->u.ofdm.bandwidth) { ++ case BANDWIDTH_AUTO: ++ case BANDWIDTH_8_MHZ: ++ state->bandwidth = 8000000; ++ break; ++ case BANDWIDTH_7_MHZ: ++ state->bandwidth = 7000000; ++ break; ++ case BANDWIDTH_6_MHZ: ++ state->bandwidth = 6000000; ++ break; ++ default: ++ return -EINVAL; ++ } ++ break; ++ default: ++ return -EINVAL; ++ } ++#else ++static int set_parameters(struct dvb_frontend *fe) ++{ ++ int stat; ++ struct stv_state *state = fe->demodulator_priv; ++ u32 OF = 0; ++ u32 IF; ++ ++ switch (fe->dtv_property_cache.delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ state->omode = OM_DVBC; ++ /* symbol rate 0 might cause an oops */ ++ if (fe->dtv_property_cache.symbol_rate == 0) { ++ printk(KERN_ERR "stv0367dd: Invalid symbol rate\n"); ++ return -EINVAL; ++ } ++ break; ++ case SYS_DVBT: ++ state->omode = OM_DVBT; ++ break; ++ default: ++ return -EINVAL; ++ } ++ if (fe->ops.tuner_ops.set_params) ++ fe->ops.tuner_ops.set_params(fe); ++ state->modulation = fe->dtv_property_cache.modulation; ++ state->symbol_rate = fe->dtv_property_cache.symbol_rate; ++ state->bandwidth = fe->dtv_property_cache.bandwidth_hz; ++#endif ++ fe->ops.tuner_ops.get_if_frequency(fe, &IF); ++ //fe->ops.tuner_ops.get_frequency(fe, &IF); ++ ++ switch(state->omode) { ++ case OM_DVBT: ++ stat = OFDM_Start(state, OF, IF); ++ ofdm_lock(state); ++ break; ++ case OM_DVBC: ++ case OM_QAM_ITU_C: ++ stat = QAM_Start(state, OF, IF); ++ break; ++ default: ++ stat = -EINVAL; ++ } ++ //printk("%s IF=%d OF=%d done\n", __FUNCTION__, IF, OF); ++ return stat; ++} ++ ++#if 0 ++static int c_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) ++{ ++ //struct stv_state *state = fe->demodulator_priv; ++ //printk("%s\n", __FUNCTION__); ++ return 0; ++} ++ ++static int OFDM_GetLockStatus(struct stv_state *state, LOCK_STATUS* pLockStatus, s32 Time) ++{ ++ int status = STATUS_SUCCESS; ++ u8 OFDM_Status; ++ s32 DemodTimeOut = 0; ++ s32 FECTimeOut = 0; ++ s32 TSTimeOut = 0; ++ u8 CPAMPMin = 255; ++ u8 CPAMPValue; ++ bool SYRLock; ++ u8 SYR_STAT; ++ u8 FFTMode; ++ u8 TSStatus; ++ ++ readreg(state, R367_OFDM_STATUS,&OFDM_Status); ++ ++ SYRLock = (OFDM_Status & 0x40) != 0; ++ ++ if( Time > m_SignalTimeOut && !SYRLock ) ++ { ++ *pLockStatus = NEVER_LOCK; ++ break; ++ } ++ ++ if( !SYRLock ) break; ++ ++ *pLockStatus = SIGNAL_PRESENT; ++ ++ // Check Mode ++ ++ readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); ++ FFTMode = (SYR_STAT & 0x0C) >> 2; ++ ++ switch(FFTMode) ++ { ++ case 0: // 2K ++ DemodTimeOut = 10; ++ FECTimeOut = 150; ++ TSTimeOut = 125; ++ CPAMPMin = 20; ++ break; ++ case 1: // 8K ++ DemodTimeOut = 55; ++ FECTimeOut = 600; ++ TSTimeOut = 500; ++ CPAMPMin = 80; ++ break; ++ case 2: // 4K ++ DemodTimeOut = 40; ++ FECTimeOut = 300; ++ TSTimeOut = 250; ++ CPAMPMin = 30; ++ break; ++ } ++ ++ m_OFDM_FFTMode = FFTMode; ++ ++ if( m_DemodTimeOut == 0 && m_bFirstTimeLock ) ++ { ++ m_DemodTimeOut = Time + DemodTimeOut; ++ //break; ++ } ++ ++ readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue); ++ ++ if( Time <= m_DemodTimeOut && CPAMPValue < CPAMPMin ) ++ { ++ break; ++ } ++ ++ if( CPAMPValue < CPAMPMin && m_bFirstTimeLock ) ++ { ++ // initiate retry ++ *pLockStatus = NEVER_LOCK; ++ break; ++ } ++ ++ if( CPAMPValue < CPAMPMin ) break; ++ ++ *pLockStatus = DEMOD_LOCK; ++ ++ if( m_FECTimeOut == 0 && m_bFirstTimeLock ) ++ { ++ // Release FEC and Read Solomon Reset ++ u8 tmp1; ++ u8 tmp2; ++ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); ++ readreg(state, R367_TSGENERAL,&tmp2); ++ writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08); ++ writereg(state, R367_TSGENERAL,tmp2 & ~0x01); ++ ++ m_FECTimeOut = Time + FECTimeOut; ++ } ++ ++ // Wait for TSP_LOCK, LK, PRF ++ if( (OFDM_Status & 0x98) != 0x98 ) ++ { ++ if( Time > m_FECTimeOut ) *pLockStatus = NEVER_LOCK; ++ break; ++ } ++ ++ if( m_bFirstTimeLock && m_TSTimeOut == 0) ++ { ++ u8 Guard = (SYR_STAT & 0x03); ++ if(Guard < 2) ++ { ++ u8 tmp; ++ readreg(state, R367_OFDM_SYR_CTL,&tmp); ++ writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN ++ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); ++ writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER ++ } else { ++ u8 tmp; ++ readreg(state, R367_OFDM_SYR_CTL,&tmp); ++ writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN ++ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); ++ writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER ++ } ++ ++ // apply Sfec workaround if 8K 64QAM CR!=1/2 ++ if( FFTMode == 1) ++ { ++ u8 tmp[2]; ++ readreg(state, R367_OFDM_TPS_RCVD2,tmp,2); ++ if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) ) ++ { ++ writereg(state, R367_OFDM_SFDLYSETH,0xc0); ++ writereg(state, R367_OFDM_SFDLYSETM,0x60); ++ writereg(state, R367_OFDM_SFDLYSETL,0x00); ++ } ++ else ++ { ++ writereg(state, R367_OFDM_SFDLYSETH,0x00); ++ } ++ } ++ ++ m_TSTimeOut = Time + TSTimeOut; ++ } ++ readreg(state, R367_OFDM_TSSTATUS,&TSStatus); ++ if( (TSStatus & 0x80) != 0x80 ) ++ { ++ if( Time > m_TSTimeOut ) *pLockStatus = NEVER_LOCK; ++ break; ++ } ++ *pLockStatus = MPEG_LOCK; ++ m_bFirstTimeLock = false; ++ return status; ++} ++ ++#endif ++ ++static int read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ *status=0; ++ ++ switch(state->demod_state) { ++ case QAMStarted: ++ { ++ u8 FEC_Lock; ++ u8 QAM_Lock; ++ ++ readreg(state, R367_QAM_FSM_STS, &QAM_Lock); ++ QAM_Lock &= 0x0F; ++ if (QAM_Lock >10) ++ *status|=0x07; ++ readreg(state, R367_QAM_FEC_STATUS,&FEC_Lock); ++ if (FEC_Lock&2) ++ *status|=0x1f; ++ if (state->m_bFirstTimeLock) { ++ state->m_bFirstTimeLock = false; ++ // QAM_AGC_ACCUMRSTSEL to Tracking; ++ writereg(state, R367_QAM_AGC_CTL, state->m_Save_QAM_AGC_CTL); ++ } ++ break; ++ } ++ case OFDMStarted: ++ { ++ u8 OFDM_Status; ++ u8 TSStatus; ++ ++ readreg(state, R367_OFDM_TSSTATUS, &TSStatus); ++ ++ readreg(state, R367_OFDM_STATUS, &OFDM_Status); ++ if (OFDM_Status & 0x40) ++ *status |= FE_HAS_SIGNAL; ++ ++ if ((OFDM_Status & 0x98) == 0x98) ++ *status|=0x0f; ++ ++ if (TSStatus & 0x80) ++ *status |= 0x1f; ++ break; ++ } ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static int read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ //struct stv_state *state = fe->demodulator_priv; ++ *ber=0; ++ return 0; ++} ++ ++static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) ++{ ++ if (fe->ops.tuner_ops.get_rf_strength) ++ fe->ops.tuner_ops.get_rf_strength(fe, strength); ++ else ++ *strength = 0; ++ return 0; ++} ++ ++static int read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ s32 snr2 = 0; ++ ++ switch(state->demod_state) { ++ case QAMStarted: ++ QAM_GetSignalToNoise(state, &snr2); ++ break; ++ case OFDMStarted: ++ OFDM_GetSignalToNoise(state, &snr2); ++ break; ++ default: ++ break; ++ } ++ *snr = snr2&0xffff; ++ return 0; ++} ++ ++static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct stv_state *state = fe->demodulator_priv; ++ u8 errl, errm, errh; ++ u8 val; ++ ++ switch(state->demod_state) { ++ case QAMStarted: ++ readreg(state, R367_QAM_RS_COUNTER_4, &errl); ++ readreg(state, R367_QAM_RS_COUNTER_5, &errm); ++ *ucblocks = (errm << 8) | errl; ++ break; ++ case OFDMStarted: ++ readreg(state, R367_OFDM_SFERRCNTH, &val); ++ if ((val & 0x80) == 0) { ++ readreg(state, R367_OFDM_ERRCNT1H, &errh); ++ readreg(state, R367_OFDM_ERRCNT1M, &errl); ++ readreg(state, R367_OFDM_ERRCNT1L, &errm); ++ state->ucblocks = (errh <<16) | (errm << 8) | errl; ++ } ++ *ucblocks = state->ucblocks; ++ break; ++ default: ++ *ucblocks = 0; ++ break; ++ } ++ return 0; ++} ++ ++static int c_get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *sets) ++{ ++ sets->min_delay_ms=3000; ++ sets->max_drift=0; ++ sets->step_size=0; ++ return 0; ++} ++ ++#ifndef USE_API3 ++static int get_tune_settings(struct dvb_frontend *fe, ++ struct dvb_frontend_tune_settings *sets) ++{ ++ switch (fe->dtv_property_cache.delivery_system) { ++ case SYS_DVBC_ANNEX_A: ++ case SYS_DVBC_ANNEX_C: ++ return c_get_tune_settings(fe, sets); ++ default: ++ /* DVB-T: Use info.frequency_stepsize. */ ++ return -EINVAL; ++ } ++} ++#endif ++ ++#ifdef USE_API3 ++static void t_release(struct dvb_frontend* fe) ++{ ++ //struct stv_state *state=fe->demodulator_priv; ++ //printk("%s\n", __FUNCTION__); ++ //kfree(state); ++} ++ ++static int t_init (struct dvb_frontend *fe) ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ if (mutex_trylock(&state->ctlock)==0) ++ return -EBUSY; ++ state->omode = OM_DVBT; ++ return 0; ++} ++ ++static int t_sleep(struct dvb_frontend* fe) ++{ ++ struct stv_state *state=fe->demodulator_priv; ++ mutex_unlock(&state->ctlock); ++ return 0; ++} ++#endif ++ ++#if 0 ++static int t_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) ++{ ++ //struct stv_state *state = fe->demodulator_priv; ++ //printk("%s\n", __FUNCTION__); ++ return 0; ++} ++ ++static enum dvbfe_algo algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_CUSTOM; ++} ++#endif ++ ++#ifdef USE_API3 ++static struct dvb_frontend_ops c_ops = { ++ .info = { ++ .name = "STV0367 DVB-C", ++ .type = FE_QAM, ++ .frequency_stepsize = 62500, ++ .frequency_min = 47000000, ++ .frequency_max = 862000000, ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 11700000, ++ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO ++ }, ++ .release = c_release, ++ .init = c_init, ++ .sleep = c_sleep, ++ .i2c_gate_ctrl = gate_ctrl, ++ ++ .get_tune_settings = c_get_tune_settings, ++ ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++ ++#if 1 ++ .set_frontend = set_parameters, ++#else ++ .get_frontend_algo = algo, ++ .search = search, ++#endif ++}; ++ ++static struct dvb_frontend_ops t_ops = { ++ .info = { ++ .name = "STV0367 DVB-T", ++ .type = FE_OFDM, ++ .frequency_min = 47125000, ++ .frequency_max = 865000000, ++ .frequency_stepsize = 166667, ++ .frequency_tolerance = 0, ++ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | ++ FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | ++ FE_CAN_FEC_AUTO | ++ FE_CAN_QAM_16 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | ++ FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | ++ FE_CAN_MUTE_TS ++ }, ++ .release = t_release, ++ .init = t_init, ++ .sleep = t_sleep, ++ .i2c_gate_ctrl = gate_ctrl, ++ ++ .set_frontend = set_parameters, ++ ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++}; ++ ++#else ++ ++static struct dvb_frontend_ops common_ops = { ++ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT }, ++ .info = { ++ .name = "STV0367 DVB-C DVB-T", ++ .frequency_stepsize = 166667, /* DVB-T only */ ++ .frequency_min = 47000000, /* DVB-T: 47125000 */ ++ .frequency_max = 865000000, /* DVB-C: 862000000 */ ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 11700000, ++ .caps = /* DVB-C */ ++ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | FE_CAN_QAM_256 | ++ FE_CAN_FEC_AUTO | ++ /* DVB-T */ ++ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | ++ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ++ FE_CAN_TRANSMISSION_MODE_AUTO | ++ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | ++ FE_CAN_RECOVER | FE_CAN_MUTE_TS ++ }, ++ .release = release, ++ .i2c_gate_ctrl = gate_ctrl, ++ ++ .get_tune_settings = get_tune_settings, ++ ++ .set_frontend = set_parameters, ++ ++ .read_status = read_status, ++ .read_ber = read_ber, ++ .read_signal_strength = read_signal_strength, ++ .read_snr = read_snr, ++ .read_ucblocks = read_ucblocks, ++}; ++#endif ++ ++ ++static void init_state(struct stv_state *state, struct stv0367_cfg *cfg) ++{ ++ u32 ulENARPTLEVEL = 5; ++ u32 ulQAMInversion = 2; ++ state->omode = OM_NONE; ++ state->adr = cfg->adr; ++ ++ mutex_init(&state->mutex); ++ mutex_init(&state->ctlock); ++ ++#ifdef USE_API3 ++ memcpy(&state->c_frontend.ops, &c_ops, sizeof(struct dvb_frontend_ops)); ++ memcpy(&state->t_frontend.ops, &t_ops, sizeof(struct dvb_frontend_ops)); ++ state->c_frontend.demodulator_priv = state; ++ state->t_frontend.demodulator_priv = state; ++#else ++ memcpy(&state->frontend.ops, &common_ops, sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++#endif ++ ++ state->master_clock = 58000000; ++ state->adc_clock = 58000000; ++ state->I2CRPT = 0x08 | ((ulENARPTLEVEL & 0x07) << 4); ++ state->qam_inversion = ((ulQAMInversion & 3) << 6 ); ++ state->demod_state = Off; ++} ++ ++ ++struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, struct stv0367_cfg *cfg, ++ struct dvb_frontend **fe_t) ++{ ++ struct stv_state *state = NULL; ++ ++ state = kzalloc(sizeof(struct stv_state), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ ++ state->i2c = i2c; ++ init_state(state, cfg); ++ ++ if (attach_init(state)<0) ++ goto error; ++#ifdef USE_API3 ++ *fe_t = &state->t_frontend; ++ return &state->c_frontend; ++#else ++ return &state->frontend; ++#endif ++ ++error: ++ printk("stv0367: not found\n"); ++ kfree(state); ++ return NULL; ++} ++ ++ ++MODULE_DESCRIPTION("STV0367DD driver"); ++MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); ++MODULE_LICENSE("GPL"); ++ ++EXPORT_SYMBOL(stv0367_attach); ++ ++ ++ +diff --git a/drivers/media/dvb-frontends/stv0367dd.h b/drivers/media/dvb-frontends/stv0367dd.h +new file mode 100644 +index 0000000..665d4c8 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0367dd.h +@@ -0,0 +1,17 @@ ++#ifndef _STV0367DD_H_ ++#define _STV0367DD_H_ ++ ++#include ++#include ++ ++struct stv0367_cfg { ++ u8 adr; ++ u32 xtal; ++ u32 ts_mode; ++}; ++ ++ ++extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, ++ struct stv0367_cfg *cfg, ++ struct dvb_frontend **fe_t); ++#endif +diff --git a/drivers/media/dvb-frontends/stv0367dd_regs.h b/drivers/media/dvb-frontends/stv0367dd_regs.h +new file mode 100644 +index 0000000..f33e787 +--- /dev/null ++++ b/drivers/media/dvb-frontends/stv0367dd_regs.h +@@ -0,0 +1,3431 @@ ++// @DVB-C/DVB-T STMicroelectronics STV0367 register defintions ++// Author Manfred Vlkel, Februar 2011 ++// (c) 2010 DigitalDevices GmbH Germany. All rights reserved ++ ++// $Id: DD_STV0367Register.h 357 2011-04-27 02:39:13Z manfred $ ++ ++/* ======================================================================= ++ -- Registers Declaration ++ -- ------------------------- ++ -- Each register (R367_XXXXX) is defined by its address (2 bytes). ++ -- ++ -- Each field (F367_XXXXX)is defined as follow: ++ -- [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte] ++ ======================================================================= */ ++ ++/* ID */ ++#define R367_ID 0xF000 ++#define F367_IDENTIFICATIONREG 0xF00000FF ++ ++/* I2CRPT */ ++#define R367_I2CRPT 0xF001 ++#define F367_I2CT_ON 0xF0010080 ++#define F367_ENARPT_LEVEL 0xF0010070 ++#define F367_SCLT_DELAY 0xF0010008 ++#define F367_SCLT_NOD 0xF0010004 ++#define F367_STOP_ENABLE 0xF0010002 ++#define F367_SDAT_NOD 0xF0010001 ++ ++/* TOPCTRL */ ++#define R367_TOPCTRL 0xF002 ++#define F367_STDBY 0xF0020080 ++#define F367_STDBY_FEC 0xF0020040 ++#define F367_STDBY_CORE 0xF0020020 ++#define F367_QAM_COFDM 0xF0020010 ++#define F367_TS_DIS 0xF0020008 ++#define F367_DIR_CLK_216 0xF0020004 ++#define F367_TUNER_BB 0xF0020002 ++#define F367_DVBT_H 0xF0020001 ++ ++/* IOCFG0 */ ++#define R367_IOCFG0 0xF003 ++#define F367_OP0_SD 0xF0030080 ++#define F367_OP0_VAL 0xF0030040 ++#define F367_OP0_OD 0xF0030020 ++#define F367_OP0_INV 0xF0030010 ++#define F367_OP0_DACVALUE_HI 0xF003000F ++ ++/* DAC0R */ ++#define R367_DAC0R 0xF004 ++#define F367_OP0_DACVALUE_LO 0xF00400FF ++ ++/* IOCFG1 */ ++#define R367_IOCFG1 0xF005 ++#define F367_IP0 0xF0050040 ++#define F367_OP1_OD 0xF0050020 ++#define F367_OP1_INV 0xF0050010 ++#define F367_OP1_DACVALUE_HI 0xF005000F ++ ++/* DAC1R */ ++#define R367_DAC1R 0xF006 ++#define F367_OP1_DACVALUE_LO 0xF00600FF ++ ++/* IOCFG2 */ ++#define R367_IOCFG2 0xF007 ++#define F367_OP2_LOCK_CONF 0xF00700E0 ++#define F367_OP2_OD 0xF0070010 ++#define F367_OP2_VAL 0xF0070008 ++#define F367_OP1_LOCK_CONF 0xF0070007 ++ ++/* SDFR */ ++#define R367_SDFR 0xF008 ++#define F367_OP0_FREQ 0xF00800F0 ++#define F367_OP1_FREQ 0xF008000F ++ ++/* STATUS */ ++#define R367_OFDM_STATUS 0xF009 ++#define F367_TPS_LOCK 0xF0090080 ++#define F367_SYR_LOCK 0xF0090040 ++#define F367_AGC_LOCK 0xF0090020 ++#define F367_PRF 0xF0090010 ++#define F367_LK 0xF0090008 ++#define F367_PR 0xF0090007 ++ ++/* AUX_CLK */ ++#define R367_AUX_CLK 0xF00A ++#define F367_AUXFEC_CTL 0xF00A00C0 ++#define F367_DIS_CKX4 0xF00A0020 ++#define F367_CKSEL 0xF00A0018 ++#define F367_CKDIV_PROG 0xF00A0006 ++#define F367_AUXCLK_ENA 0xF00A0001 ++ ++/* FREESYS1 */ ++#define R367_FREESYS1 0xF00B ++#define F367_FREE_SYS1 0xF00B00FF ++ ++/* FREESYS2 */ ++#define R367_FREESYS2 0xF00C ++#define F367_FREE_SYS2 0xF00C00FF ++ ++/* FREESYS3 */ ++#define R367_FREESYS3 0xF00D ++#define F367_FREE_SYS3 0xF00D00FF ++ ++/* GPIO_CFG */ ++#define R367_GPIO_CFG 0xF00E ++#define F367_GPIO7_NOD 0xF00E0080 ++#define F367_GPIO7_CFG 0xF00E0040 ++#define F367_GPIO6_NOD 0xF00E0020 ++#define F367_GPIO6_CFG 0xF00E0010 ++#define F367_GPIO5_NOD 0xF00E0008 ++#define F367_GPIO5_CFG 0xF00E0004 ++#define F367_GPIO4_NOD 0xF00E0002 ++#define F367_GPIO4_CFG 0xF00E0001 ++ ++/* GPIO_CMD */ ++#define R367_GPIO_CMD 0xF00F ++#define F367_GPIO7_VAL 0xF00F0008 ++#define F367_GPIO6_VAL 0xF00F0004 ++#define F367_GPIO5_VAL 0xF00F0002 ++#define F367_GPIO4_VAL 0xF00F0001 ++ ++/* AGC2MAX */ ++#define R367_OFDM_AGC2MAX 0xF010 ++#define F367_OFDM_AGC2_MAX 0xF01000FF ++ ++/* AGC2MIN */ ++#define R367_OFDM_AGC2MIN 0xF011 ++#define F367_OFDM_AGC2_MIN 0xF01100FF ++ ++/* AGC1MAX */ ++#define R367_OFDM_AGC1MAX 0xF012 ++#define F367_OFDM_AGC1_MAX 0xF01200FF ++ ++/* AGC1MIN */ ++#define R367_OFDM_AGC1MIN 0xF013 ++#define F367_OFDM_AGC1_MIN 0xF01300FF ++ ++/* AGCR */ ++#define R367_OFDM_AGCR 0xF014 ++#define F367_OFDM_RATIO_A 0xF01400E0 ++#define F367_OFDM_RATIO_B 0xF0140018 ++#define F367_OFDM_RATIO_C 0xF0140007 ++ ++/* AGC2TH */ ++#define R367_OFDM_AGC2TH 0xF015 ++#define F367_OFDM_AGC2_THRES 0xF01500FF ++ ++/* AGC12C */ ++#define R367_OFDM_AGC12C 0xF016 ++#define F367_OFDM_AGC1_IV 0xF0160080 ++#define F367_OFDM_AGC1_OD 0xF0160040 ++#define F367_OFDM_AGC1_LOAD 0xF0160020 ++#define F367_OFDM_AGC2_IV 0xF0160010 ++#define F367_OFDM_AGC2_OD 0xF0160008 ++#define F367_OFDM_AGC2_LOAD 0xF0160004 ++#define F367_OFDM_AGC12_MODE 0xF0160003 ++ ++/* AGCCTRL1 */ ++#define R367_OFDM_AGCCTRL1 0xF017 ++#define F367_OFDM_DAGC_ON 0xF0170080 ++#define F367_OFDM_INVERT_AGC12 0xF0170040 ++#define F367_OFDM_AGC1_MODE 0xF0170008 ++#define F367_OFDM_AGC2_MODE 0xF0170007 ++ ++/* AGCCTRL2 */ ++#define R367_OFDM_AGCCTRL2 0xF018 ++#define F367_OFDM_FRZ2_CTRL 0xF0180060 ++#define F367_OFDM_FRZ1_CTRL 0xF0180018 ++#define F367_OFDM_TIME_CST 0xF0180007 ++ ++/* AGC1VAL1 */ ++#define R367_OFDM_AGC1VAL1 0xF019 ++#define F367_OFDM_AGC1_VAL_LO 0xF01900FF ++ ++/* AGC1VAL2 */ ++#define R367_OFDM_AGC1VAL2 0xF01A ++#define F367_OFDM_AGC1_VAL_HI 0xF01A000F ++ ++/* AGC2VAL1 */ ++#define R367_OFDM_AGC2VAL1 0xF01B ++#define F367_OFDM_AGC2_VAL_LO 0xF01B00FF ++ ++/* AGC2VAL2 */ ++#define R367_OFDM_AGC2VAL2 0xF01C ++#define F367_OFDM_AGC2_VAL_HI 0xF01C000F ++ ++/* AGC2PGA */ ++#define R367_OFDM_AGC2PGA 0xF01D ++#define F367_OFDM_AGC2_PGA 0xF01D00FF ++ ++/* OVF_RATE1 */ ++#define R367_OFDM_OVF_RATE1 0xF01E ++#define F367_OFDM_OVF_RATE_HI 0xF01E000F ++ ++/* OVF_RATE2 */ ++#define R367_OFDM_OVF_RATE2 0xF01F ++#define F367_OFDM_OVF_RATE_LO 0xF01F00FF ++ ++/* GAIN_SRC1 */ ++#define R367_OFDM_GAIN_SRC1 0xF020 ++#define F367_OFDM_INV_SPECTR 0xF0200080 ++#define F367_OFDM_IQ_INVERT 0xF0200040 ++#define F367_OFDM_INR_BYPASS 0xF0200020 ++#define F367_OFDM_STATUS_INV_SPECRUM 0xF0200010 ++#define F367_OFDM_GAIN_SRC_HI 0xF020000F ++ ++/* GAIN_SRC2 */ ++#define R367_OFDM_GAIN_SRC2 0xF021 ++#define F367_OFDM_GAIN_SRC_LO 0xF02100FF ++ ++/* INC_DEROT1 */ ++#define R367_OFDM_INC_DEROT1 0xF022 ++#define F367_OFDM_INC_DEROT_HI 0xF02200FF ++ ++/* INC_DEROT2 */ ++#define R367_OFDM_INC_DEROT2 0xF023 ++#define F367_OFDM_INC_DEROT_LO 0xF02300FF ++ ++/* PPM_CPAMP_DIR */ ++#define R367_OFDM_PPM_CPAMP_DIR 0xF024 ++#define F367_OFDM_PPM_CPAMP_DIRECT 0xF02400FF ++ ++/* PPM_CPAMP_INV */ ++#define R367_OFDM_PPM_CPAMP_INV 0xF025 ++#define F367_OFDM_PPM_CPAMP_INVER 0xF02500FF ++ ++/* FREESTFE_1 */ ++#define R367_OFDM_FREESTFE_1 0xF026 ++#define F367_OFDM_SYMBOL_NUMBER_INC 0xF02600C0 ++#define F367_OFDM_SEL_LSB 0xF0260004 ++#define F367_OFDM_AVERAGE_ON 0xF0260002 ++#define F367_OFDM_DC_ADJ 0xF0260001 ++ ++/* FREESTFE_2 */ ++#define R367_OFDM_FREESTFE_2 0xF027 ++#define F367_OFDM_SEL_SRCOUT 0xF02700C0 ++#define F367_OFDM_SEL_SYRTHR 0xF027001F ++ ++/* DCOFFSET */ ++#define R367_OFDM_DCOFFSET 0xF028 ++#define F367_OFDM_SELECT_I_Q 0xF0280080 ++#define F367_OFDM_DC_OFFSET 0xF028007F ++ ++/* EN_PROCESS */ ++#define R367_OFDM_EN_PROCESS 0xF029 ++#define F367_OFDM_FREE 0xF02900F0 ++#define F367_OFDM_ENAB_MANUAL 0xF0290001 ++ ++/* SDI_SMOOTHER */ ++#define R367_OFDM_SDI_SMOOTHER 0xF02A ++#define F367_OFDM_DIS_SMOOTH 0xF02A0080 ++#define F367_OFDM_SDI_INC_SMOOTHER 0xF02A007F ++ ++/* FE_LOOP_OPEN */ ++#define R367_OFDM_FE_LOOP_OPEN 0xF02B ++#define F367_OFDM_TRL_LOOP_OP 0xF02B0002 ++#define F367_OFDM_CRL_LOOP_OP 0xF02B0001 ++ ++/* FREQOFF1 */ ++#define R367_OFDM_FREQOFF1 0xF02C ++#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_VHI 0xF02C00FF ++ ++/* FREQOFF2 */ ++#define R367_OFDM_FREQOFF2 0xF02D ++#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_HI 0xF02D00FF ++ ++/* FREQOFF3 */ ++#define R367_OFDM_FREQOFF3 0xF02E ++#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_LO 0xF02E00FF ++ ++/* TIMOFF1 */ ++#define R367_OFDM_TIMOFF1 0xF02F ++#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_HI 0xF02F00FF ++ ++/* TIMOFF2 */ ++#define R367_OFDM_TIMOFF2 0xF030 ++#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_LO 0xF03000FF ++ ++/* EPQ */ ++#define R367_OFDM_EPQ 0xF031 ++#define F367_OFDM_EPQ1 0xF03100FF ++ ++/* EPQAUTO */ ++#define R367_OFDM_EPQAUTO 0xF032 ++#define F367_OFDM_EPQ2 0xF03200FF ++ ++/* SYR_UPDATE */ ++#define R367_OFDM_SYR_UPDATE 0xF033 ++#define F367_OFDM_SYR_PROTV 0xF0330080 ++#define F367_OFDM_SYR_PROTV_GAIN 0xF0330060 ++#define F367_OFDM_SYR_FILTER 0xF0330010 ++#define F367_OFDM_SYR_TRACK_THRES 0xF033000C ++ ++/* CHPFREE */ ++#define R367_OFDM_CHPFREE 0xF034 ++#define F367_OFDM_CHP_FREE 0xF03400FF ++ ++/* PPM_STATE_MAC */ ++#define R367_OFDM_PPM_STATE_MAC 0xF035 ++#define F367_OFDM_PPM_STATE_MACHINE_DECODER 0xF035003F ++ ++/* INR_THRESHOLD */ ++#define R367_OFDM_INR_THRESHOLD 0xF036 ++#define F367_OFDM_INR_THRESH 0xF03600FF ++ ++/* EPQ_TPS_ID_CELL */ ++#define R367_OFDM_EPQ_TPS_ID_CELL 0xF037 ++#define F367_OFDM_ENABLE_LGTH_TO_CF 0xF0370080 ++#define F367_OFDM_DIS_TPS_RSVD 0xF0370040 ++#define F367_OFDM_DIS_BCH 0xF0370020 ++#define F367_OFDM_DIS_ID_CEL 0xF0370010 ++#define F367_OFDM_TPS_ADJUST_SYM 0xF037000F ++ ++/* EPQ_CFG */ ++#define R367_OFDM_EPQ_CFG 0xF038 ++#define F367_OFDM_EPQ_RANGE 0xF0380002 ++#define F367_OFDM_EPQ_SOFT 0xF0380001 ++ ++/* EPQ_STATUS */ ++#define R367_OFDM_EPQ_STATUS 0xF039 ++#define F367_OFDM_SLOPE_INC 0xF03900FC ++#define F367_OFDM_TPS_FIELD 0xF0390003 ++ ++/* AUTORELOCK */ ++#define R367_OFDM_AUTORELOCK 0xF03A ++#define F367_OFDM_BYPASS_BER_TEMPO 0xF03A0080 ++#define F367_OFDM_BER_TEMPO 0xF03A0070 ++#define F367_OFDM_BYPASS_COFDM_TEMPO 0xF03A0008 ++#define F367_OFDM_COFDM_TEMPO 0xF03A0007 ++ ++/* BER_THR_VMSB */ ++#define R367_OFDM_BER_THR_VMSB 0xF03B ++#define F367_OFDM_BER_THRESHOLD_HI 0xF03B00FF ++ ++/* BER_THR_MSB */ ++#define R367_OFDM_BER_THR_MSB 0xF03C ++#define F367_OFDM_BER_THRESHOLD_MID 0xF03C00FF ++ ++/* BER_THR_LSB */ ++#define R367_OFDM_BER_THR_LSB 0xF03D ++#define F367_OFDM_BER_THRESHOLD_LO 0xF03D00FF ++ ++/* CCD */ ++#define R367_OFDM_CCD 0xF03E ++#define F367_OFDM_CCD_DETECTED 0xF03E0080 ++#define F367_OFDM_CCD_RESET 0xF03E0040 ++#define F367_OFDM_CCD_THRESHOLD 0xF03E000F ++ ++/* SPECTR_CFG */ ++#define R367_OFDM_SPECTR_CFG 0xF03F ++#define F367_OFDM_SPECT_CFG 0xF03F0003 ++ ++/* CONSTMU_MSB */ ++#define R367_OFDM_CONSTMU_MSB 0xF040 ++#define F367_OFDM_CONSTMU_FREEZE 0xF0400080 ++#define F367_OFDM_CONSTNU_FORCE_EN 0xF0400040 ++#define F367_OFDM_CONST_MU_MSB 0xF040003F ++ ++/* CONSTMU_LSB */ ++#define R367_OFDM_CONSTMU_LSB 0xF041 ++#define F367_OFDM_CONST_MU_LSB 0xF04100FF ++ ++/* CONSTMU_MAX_MSB */ ++#define R367_OFDM_CONSTMU_MAX_MSB 0xF042 ++#define F367_OFDM_CONST_MU_MAX_MSB 0xF042003F ++ ++/* CONSTMU_MAX_LSB */ ++#define R367_OFDM_CONSTMU_MAX_LSB 0xF043 ++#define F367_OFDM_CONST_MU_MAX_LSB 0xF04300FF ++ ++/* ALPHANOISE */ ++#define R367_OFDM_ALPHANOISE 0xF044 ++#define F367_OFDM_USE_ALLFILTER 0xF0440080 ++#define F367_OFDM_INTER_ON 0xF0440040 ++#define F367_OFDM_ALPHA_NOISE 0xF044001F ++ ++/* MAXGP_MSB */ ++#define R367_OFDM_MAXGP_MSB 0xF045 ++#define F367_OFDM_MUFILTER_LENGTH 0xF04500F0 ++#define F367_OFDM_MAX_GP_MSB 0xF045000F ++ ++/* MAXGP_LSB */ ++#define R367_OFDM_MAXGP_LSB 0xF046 ++#define F367_OFDM_MAX_GP_LSB 0xF04600FF ++ ++/* ALPHAMSB */ ++#define R367_OFDM_ALPHAMSB 0xF047 ++#define F367_OFDM_CHC_DATARATE 0xF04700C0 ++#define F367_OFDM_ALPHA_MSB 0xF047003F ++ ++/* ALPHALSB */ ++#define R367_OFDM_ALPHALSB 0xF048 ++#define F367_OFDM_ALPHA_LSB 0xF04800FF ++ ++/* PILOT_ACCU */ ++#define R367_OFDM_PILOT_ACCU 0xF049 ++#define F367_OFDM_USE_SCAT4ADDAPT 0xF0490080 ++#define F367_OFDM_PILOT_ACC 0xF049001F ++ ++/* PILOTMU_ACCU */ ++#define R367_OFDM_PILOTMU_ACCU 0xF04A ++#define F367_OFDM_DISCARD_BAD_SP 0xF04A0080 ++#define F367_OFDM_DISCARD_BAD_CP 0xF04A0040 ++#define F367_OFDM_PILOT_MU_ACCU 0xF04A001F ++ ++/* FILT_CHANNEL_EST */ ++#define R367_OFDM_FILT_CHANNEL_EST 0xF04B ++#define F367_OFDM_USE_FILT_PILOT 0xF04B0080 ++#define F367_OFDM_FILT_CHANNEL 0xF04B007F ++ ++/* ALPHA_NOPISE_FREQ */ ++#define R367_OFDM_ALPHA_NOPISE_FREQ 0xF04C ++#define F367_OFDM_NOISE_FREQ_FILT 0xF04C0040 ++#define F367_OFDM_ALPHA_NOISE_FREQ 0xF04C003F ++ ++/* RATIO_PILOT */ ++#define R367_OFDM_RATIO_PILOT 0xF04D ++#define F367_OFDM_RATIO_MEAN_SP 0xF04D00F0 ++#define F367_OFDM_RATIO_MEAN_CP 0xF04D000F ++ ++/* CHC_CTL */ ++#define R367_OFDM_CHC_CTL 0xF04E ++#define F367_OFDM_TRACK_EN 0xF04E0080 ++#define F367_OFDM_NOISE_NORM_EN 0xF04E0040 ++#define F367_OFDM_FORCE_CHC_RESET 0xF04E0020 ++#define F367_OFDM_SHORT_TIME 0xF04E0010 ++#define F367_OFDM_FORCE_STATE_EN 0xF04E0008 ++#define F367_OFDM_FORCE_STATE 0xF04E0007 ++ ++/* EPQ_ADJUST */ ++#define R367_OFDM_EPQ_ADJUST 0xF04F ++#define F367_OFDM_ADJUST_SCAT_IND 0xF04F00C0 ++#define F367_OFDM_ONE_SYMBOL 0xF04F0010 ++#define F367_OFDM_EPQ_DECAY 0xF04F000E ++#define F367_OFDM_HOLD_SLOPE 0xF04F0001 ++ ++/* EPQ_THRES */ ++#define R367_OFDM_EPQ_THRES 0xF050 ++#define F367_OFDM_EPQ_THR 0xF05000FF ++ ++/* OMEGA_CTL */ ++#define R367_OFDM_OMEGA_CTL 0xF051 ++#define F367_OFDM_OMEGA_RST 0xF0510080 ++#define F367_OFDM_FREEZE_OMEGA 0xF0510040 ++#define F367_OFDM_OMEGA_SEL 0xF051003F ++ ++/* GP_CTL */ ++#define R367_OFDM_GP_CTL 0xF052 ++#define F367_OFDM_CHC_STATE 0xF05200E0 ++#define F367_OFDM_FREEZE_GP 0xF0520010 ++#define F367_OFDM_GP_SEL 0xF052000F ++ ++/* MUMSB */ ++#define R367_OFDM_MUMSB 0xF053 ++#define F367_OFDM_MU_MSB 0xF053007F ++ ++/* MULSB */ ++#define R367_OFDM_MULSB 0xF054 ++#define F367_OFDM_MU_LSB 0xF05400FF ++ ++/* GPMSB */ ++#define R367_OFDM_GPMSB 0xF055 ++#define F367_OFDM_CSI_THRESHOLD 0xF05500E0 ++#define F367_OFDM_GP_MSB 0xF055000F ++ ++/* GPLSB */ ++#define R367_OFDM_GPLSB 0xF056 ++#define F367_OFDM_GP_LSB 0xF05600FF ++ ++/* OMEGAMSB */ ++#define R367_OFDM_OMEGAMSB 0xF057 ++#define F367_OFDM_OMEGA_MSB 0xF057007F ++ ++/* OMEGALSB */ ++#define R367_OFDM_OMEGALSB 0xF058 ++#define F367_OFDM_OMEGA_LSB 0xF05800FF ++ ++/* SCAT_NB */ ++#define R367_OFDM_SCAT_NB 0xF059 ++#define F367_OFDM_CHC_TEST 0xF05900F8 ++#define F367_OFDM_SCAT_NUMB 0xF0590003 ++ ++/* CHC_DUMMY */ ++#define R367_OFDM_CHC_DUMMY 0xF05A ++#define F367_OFDM_CHC_DUM 0xF05A00FF ++ ++/* INC_CTL */ ++#define R367_OFDM_INC_CTL 0xF05B ++#define F367_OFDM_INC_BYPASS 0xF05B0080 ++#define F367_OFDM_INC_NDEPTH 0xF05B000C ++#define F367_OFDM_INC_MADEPTH 0xF05B0003 ++ ++/* INCTHRES_COR1 */ ++#define R367_OFDM_INCTHRES_COR1 0xF05C ++#define F367_OFDM_INC_THRES_COR1 0xF05C00FF ++ ++/* INCTHRES_COR2 */ ++#define R367_OFDM_INCTHRES_COR2 0xF05D ++#define F367_OFDM_INC_THRES_COR2 0xF05D00FF ++ ++/* INCTHRES_DET1 */ ++#define R367_OFDM_INCTHRES_DET1 0xF05E ++#define F367_OFDM_INC_THRES_DET1 0xF05E003F ++ ++/* INCTHRES_DET2 */ ++#define R367_OFDM_INCTHRES_DET2 0xF05F ++#define F367_OFDM_INC_THRES_DET2 0xF05F003F ++ ++/* IIR_CELLNB */ ++#define R367_OFDM_IIR_CELLNB 0xF060 ++#define F367_OFDM_NRST_IIR 0xF0600080 ++#define F367_OFDM_IIR_CELL_NB 0xF0600007 ++ ++/* IIRCX_COEFF1_MSB */ ++#define R367_OFDM_IIRCX_COEFF1_MSB 0xF061 ++#define F367_OFDM_IIR_CX_COEFF1_MSB 0xF06100FF ++ ++/* IIRCX_COEFF1_LSB */ ++#define R367_OFDM_IIRCX_COEFF1_LSB 0xF062 ++#define F367_OFDM_IIR_CX_COEFF1_LSB 0xF06200FF ++ ++/* IIRCX_COEFF2_MSB */ ++#define R367_OFDM_IIRCX_COEFF2_MSB 0xF063 ++#define F367_OFDM_IIR_CX_COEFF2_MSB 0xF06300FF ++ ++/* IIRCX_COEFF2_LSB */ ++#define R367_OFDM_IIRCX_COEFF2_LSB 0xF064 ++#define F367_OFDM_IIR_CX_COEFF2_LSB 0xF06400FF ++ ++/* IIRCX_COEFF3_MSB */ ++#define R367_OFDM_IIRCX_COEFF3_MSB 0xF065 ++#define F367_OFDM_IIR_CX_COEFF3_MSB 0xF06500FF ++ ++/* IIRCX_COEFF3_LSB */ ++#define R367_OFDM_IIRCX_COEFF3_LSB 0xF066 ++#define F367_OFDM_IIR_CX_COEFF3_LSB 0xF06600FF ++ ++/* IIRCX_COEFF4_MSB */ ++#define R367_OFDM_IIRCX_COEFF4_MSB 0xF067 ++#define F367_OFDM_IIR_CX_COEFF4_MSB 0xF06700FF ++ ++/* IIRCX_COEFF4_LSB */ ++#define R367_OFDM_IIRCX_COEFF4_LSB 0xF068 ++#define F367_OFDM_IIR_CX_COEFF4_LSB 0xF06800FF ++ ++/* IIRCX_COEFF5_MSB */ ++#define R367_OFDM_IIRCX_COEFF5_MSB 0xF069 ++#define F367_OFDM_IIR_CX_COEFF5_MSB 0xF06900FF ++ ++/* IIRCX_COEFF5_LSB */ ++#define R367_OFDM_IIRCX_COEFF5_LSB 0xF06A ++#define F367_OFDM_IIR_CX_COEFF5_LSB 0xF06A00FF ++ ++/* FEPATH_CFG */ ++#define R367_OFDM_FEPATH_CFG 0xF06B ++#define F367_OFDM_DEMUX_SWAP 0xF06B0004 ++#define F367_OFDM_DIGAGC_SWAP 0xF06B0002 ++#define F367_OFDM_LONGPATH_IF 0xF06B0001 ++ ++/* PMC1_FUNC */ ++#define R367_OFDM_PMC1_FUNC 0xF06C ++#define F367_OFDM_SOFT_RSTN 0xF06C0080 ++#define F367_OFDM_PMC1_AVERAGE_TIME 0xF06C0078 ++#define F367_OFDM_PMC1_WAIT_TIME 0xF06C0006 ++#define F367_OFDM_PMC1_2N_SEL 0xF06C0001 ++ ++/* PMC1_FOR */ ++#define R367_OFDM_PMC1_FOR 0xF06D ++#define F367_OFDM_PMC1_FORCE 0xF06D0080 ++#define F367_OFDM_PMC1_FORCE_VALUE 0xF06D007C ++ ++/* PMC2_FUNC */ ++#define R367_OFDM_PMC2_FUNC 0xF06E ++#define F367_OFDM_PMC2_SOFT_STN 0xF06E0080 ++#define F367_OFDM_PMC2_ACCU_TIME 0xF06E0070 ++#define F367_OFDM_PMC2_CMDP_MN 0xF06E0008 ++#define F367_OFDM_PMC2_SWAP 0xF06E0004 ++ ++/* STATUS_ERR_DA */ ++#define R367_OFDM_STATUS_ERR_DA 0xF06F ++#define F367_OFDM_COM_USEGAINTRK 0xF06F0080 ++#define F367_OFDM_COM_AGCLOCK 0xF06F0040 ++#define F367_OFDM_AUT_AGCLOCK 0xF06F0020 ++#define F367_OFDM_MIN_ERR_X_LSB 0xF06F000F ++ ++/* DIG_AGC_R */ ++#define R367_OFDM_DIG_AGC_R 0xF070 ++#define F367_OFDM_COM_SOFT_RSTN 0xF0700080 ++#define F367_OFDM_COM_AGC_ON 0xF0700040 ++#define F367_OFDM_COM_EARLY 0xF0700020 ++#define F367_OFDM_AUT_SOFT_RESETN 0xF0700010 ++#define F367_OFDM_AUT_AGC_ON 0xF0700008 ++#define F367_OFDM_AUT_EARLY 0xF0700004 ++#define F367_OFDM_AUT_ROT_EN 0xF0700002 ++#define F367_OFDM_LOCK_SOFT_RESETN 0xF0700001 ++ ++/* COMAGC_TARMSB */ ++#define R367_OFDM_COMAGC_TARMSB 0xF071 ++#define F367_OFDM_COM_AGC_TARGET_MSB 0xF07100FF ++ ++/* COM_AGC_TAR_ENMODE */ ++#define R367_OFDM_COM_AGC_TAR_ENMODE 0xF072 ++#define F367_OFDM_COM_AGC_TARGET_LSB 0xF07200F0 ++#define F367_OFDM_COM_ENMODE 0xF072000F ++ ++/* COM_AGC_CFG */ ++#define R367_OFDM_COM_AGC_CFG 0xF073 ++#define F367_OFDM_COM_N 0xF07300F8 ++#define F367_OFDM_COM_STABMODE 0xF0730006 ++#define F367_OFDM_ERR_SEL 0xF0730001 ++ ++/* COM_AGC_GAIN1 */ ++#define R367_OFDM_COM_AGC_GAIN1 0xF074 ++#define F367_OFDM_COM_GAIN1ACK 0xF07400F0 ++#define F367_OFDM_COM_GAIN1TRK 0xF074000F ++ ++/* AUT_AGC_TARGETMSB */ ++#define R367_OFDM_AUT_AGC_TARGETMSB 0xF075 ++#define F367_OFDM_AUT_AGC_TARGET_MSB 0xF07500FF ++ ++/* LOCK_DET_MSB */ ++#define R367_OFDM_LOCK_DET_MSB 0xF076 ++#define F367_OFDM_LOCK_DETECT_MSB 0xF07600FF ++ ++/* AGCTAR_LOCK_LSBS */ ++#define R367_OFDM_AGCTAR_LOCK_LSBS 0xF077 ++#define F367_OFDM_AUT_AGC_TARGET_LSB 0xF07700F0 ++#define F367_OFDM_LOCK_DETECT_LSB 0xF077000F ++ ++/* AUT_GAIN_EN */ ++#define R367_OFDM_AUT_GAIN_EN 0xF078 ++#define F367_OFDM_AUT_ENMODE 0xF07800F0 ++#define F367_OFDM_AUT_GAIN2 0xF078000F ++ ++/* AUT_CFG */ ++#define R367_OFDM_AUT_CFG 0xF079 ++#define F367_OFDM_AUT_N 0xF07900F8 ++#define F367_OFDM_INT_CHOICE 0xF0790006 ++#define F367_OFDM_INT_LOAD 0xF0790001 ++ ++/* LOCKN */ ++#define R367_OFDM_LOCKN 0xF07A ++#define F367_OFDM_LOCK_N 0xF07A00F8 ++#define F367_OFDM_SEL_IQNTAR 0xF07A0004 ++#define F367_OFDM_LOCK_DETECT_CHOICE 0xF07A0003 ++ ++/* INT_X_3 */ ++#define R367_OFDM_INT_X_3 0xF07B ++#define F367_OFDM_INT_X3 0xF07B00FF ++ ++/* INT_X_2 */ ++#define R367_OFDM_INT_X_2 0xF07C ++#define F367_OFDM_INT_X2 0xF07C00FF ++ ++/* INT_X_1 */ ++#define R367_OFDM_INT_X_1 0xF07D ++#define F367_OFDM_INT_X1 0xF07D00FF ++ ++/* INT_X_0 */ ++#define R367_OFDM_INT_X_0 0xF07E ++#define F367_OFDM_INT_X0 0xF07E00FF ++ ++/* MIN_ERRX_MSB */ ++#define R367_OFDM_MIN_ERRX_MSB 0xF07F ++#define F367_OFDM_MIN_ERR_X_MSB 0xF07F00FF ++ ++/* COR_CTL */ ++#define R367_OFDM_COR_CTL 0xF080 ++#define F367_OFDM_CORE_ACTIVE 0xF0800020 ++#define F367_OFDM_HOLD 0xF0800010 ++#define F367_OFDM_CORE_STATE_CTL 0xF080000F ++ ++/* COR_STAT */ ++#define R367_OFDM_COR_STAT 0xF081 ++#define F367_OFDM_SCATT_LOCKED 0xF0810080 ++#define F367_OFDM_TPS_LOCKED 0xF0810040 ++#define F367_OFDM_SYR_LOCKED_COR 0xF0810020 ++#define F367_OFDM_AGC_LOCKED_STAT 0xF0810010 ++#define F367_OFDM_CORE_STATE_STAT 0xF081000F ++ ++/* COR_INTEN */ ++#define R367_OFDM_COR_INTEN 0xF082 ++#define F367_OFDM_INTEN 0xF0820080 ++#define F367_OFDM_INTEN_SYR 0xF0820020 ++#define F367_OFDM_INTEN_FFT 0xF0820010 ++#define F367_OFDM_INTEN_AGC 0xF0820008 ++#define F367_OFDM_INTEN_TPS1 0xF0820004 ++#define F367_OFDM_INTEN_TPS2 0xF0820002 ++#define F367_OFDM_INTEN_TPS3 0xF0820001 ++ ++/* COR_INTSTAT */ ++#define R367_OFDM_COR_INTSTAT 0xF083 ++#define F367_OFDM_INTSTAT_SYR 0xF0830020 ++#define F367_OFDM_INTSTAT_FFT 0xF0830010 ++#define F367_OFDM_INTSAT_AGC 0xF0830008 ++#define F367_OFDM_INTSTAT_TPS1 0xF0830004 ++#define F367_OFDM_INTSTAT_TPS2 0xF0830002 ++#define F367_OFDM_INTSTAT_TPS3 0xF0830001 ++ ++/* COR_MODEGUARD */ ++#define R367_OFDM_COR_MODEGUARD 0xF084 ++#define F367_OFDM_FORCE 0xF0840010 ++#define F367_OFDM_MODE 0xF084000C ++#define F367_OFDM_GUARD 0xF0840003 ++ ++/* AGC_CTL */ ++#define R367_OFDM_AGC_CTL 0xF085 ++#define F367_OFDM_AGC_TIMING_FACTOR 0xF08500E0 ++#define F367_OFDM_AGC_LAST 0xF0850010 ++#define F367_OFDM_AGC_GAIN 0xF085000C ++#define F367_OFDM_AGC_NEG 0xF0850002 ++#define F367_OFDM_AGC_SET 0xF0850001 ++ ++/* AGC_MANUAL1 */ ++#define R367_OFDM_AGC_MANUAL1 0xF086 ++#define F367_OFDM_AGC_VAL_LO 0xF08600FF ++ ++/* AGC_MANUAL2 */ ++#define R367_OFDM_AGC_MANUAL2 0xF087 ++#define F367_OFDM_AGC_VAL_HI 0xF087000F ++ ++/* AGC_TARG */ ++#define R367_OFDM_AGC_TARG 0xF088 ++#define F367_OFDM_AGC_TARGET 0xF08800FF ++ ++/* AGC_GAIN1 */ ++#define R367_OFDM_AGC_GAIN1 0xF089 ++#define F367_OFDM_AGC_GAIN_LO 0xF08900FF ++ ++/* AGC_GAIN2 */ ++#define R367_OFDM_AGC_GAIN2 0xF08A ++#define F367_OFDM_AGC_LOCKED_GAIN2 0xF08A0010 ++#define F367_OFDM_AGC_GAIN_HI 0xF08A000F ++ ++/* RESERVED_1 */ ++#define R367_OFDM_RESERVED_1 0xF08B ++#define F367_OFDM_RESERVED1 0xF08B00FF ++ ++/* RESERVED_2 */ ++#define R367_OFDM_RESERVED_2 0xF08C ++#define F367_OFDM_RESERVED2 0xF08C00FF ++ ++/* RESERVED_3 */ ++#define R367_OFDM_RESERVED_3 0xF08D ++#define F367_OFDM_RESERVED3 0xF08D00FF ++ ++/* CAS_CTL */ ++#define R367_OFDM_CAS_CTL 0xF08E ++#define F367_OFDM_CCS_ENABLE 0xF08E0080 ++#define F367_OFDM_ACS_DISABLE 0xF08E0040 ++#define F367_OFDM_DAGC_DIS 0xF08E0020 ++#define F367_OFDM_DAGC_GAIN 0xF08E0018 ++#define F367_OFDM_CCSMU 0xF08E0007 ++ ++/* CAS_FREQ */ ++#define R367_OFDM_CAS_FREQ 0xF08F ++#define F367_OFDM_CCS_FREQ 0xF08F00FF ++ ++/* CAS_DAGCGAIN */ ++#define R367_OFDM_CAS_DAGCGAIN 0xF090 ++#define F367_OFDM_CAS_DAGC_GAIN 0xF09000FF ++ ++/* SYR_CTL */ ++#define R367_OFDM_SYR_CTL 0xF091 ++#define F367_OFDM_SICTH_ENABLE 0xF0910080 ++#define F367_OFDM_LONG_ECHO 0xF0910078 ++#define F367_OFDM_AUTO_LE_EN 0xF0910004 ++#define F367_OFDM_SYR_BYPASS 0xF0910002 ++#define F367_OFDM_SYR_TR_DIS 0xF0910001 ++ ++/* SYR_STAT */ ++#define R367_OFDM_SYR_STAT 0xF092 ++#define F367_OFDM_SYR_LOCKED_STAT 0xF0920010 ++#define F367_OFDM_SYR_MODE 0xF092000C ++#define F367_OFDM_SYR_GUARD 0xF0920003 ++ ++/* SYR_NCO1 */ ++#define R367_OFDM_SYR_NCO1 0xF093 ++#define F367_OFDM_SYR_NCO_LO 0xF09300FF ++ ++/* SYR_NCO2 */ ++#define R367_OFDM_SYR_NCO2 0xF094 ++#define F367_OFDM_SYR_NCO_HI 0xF094003F ++ ++/* SYR_OFFSET1 */ ++#define R367_OFDM_SYR_OFFSET1 0xF095 ++#define F367_OFDM_SYR_OFFSET_LO 0xF09500FF ++ ++/* SYR_OFFSET2 */ ++#define R367_OFDM_SYR_OFFSET2 0xF096 ++#define F367_OFDM_SYR_OFFSET_HI 0xF096003F ++ ++/* FFT_CTL */ ++#define R367_OFDM_FFT_CTL 0xF097 ++#define F367_OFDM_SHIFT_FFT_TRIG 0xF0970018 ++#define F367_OFDM_FFT_TRIGGER 0xF0970004 ++#define F367_OFDM_FFT_MANUAL 0xF0970002 ++#define F367_OFDM_IFFT_MODE 0xF0970001 ++ ++/* SCR_CTL */ ++#define R367_OFDM_SCR_CTL 0xF098 ++#define F367_OFDM_SYRADJDECAY 0xF0980070 ++#define F367_OFDM_SCR_CPEDIS 0xF0980002 ++#define F367_OFDM_SCR_DIS 0xF0980001 ++ ++/* PPM_CTL1 */ ++#define R367_OFDM_PPM_CTL1 0xF099 ++#define F367_OFDM_PPM_MAXFREQ 0xF0990030 ++#define F367_OFDM_PPM_MAXTIM 0xF0990008 ++#define F367_OFDM_PPM_INVSEL 0xF0990004 ++#define F367_OFDM_PPM_SCATDIS 0xF0990002 ++#define F367_OFDM_PPM_BYP 0xF0990001 ++ ++/* TRL_CTL */ ++#define R367_OFDM_TRL_CTL 0xF09A ++#define F367_OFDM_TRL_NOMRATE_LSB 0xF09A0080 ++#define F367_OFDM_TRL_GAIN_FACTOR 0xF09A0078 ++#define F367_OFDM_TRL_LOOPGAIN 0xF09A0007 ++ ++/* TRL_NOMRATE1 */ ++#define R367_OFDM_TRL_NOMRATE1 0xF09B ++#define F367_OFDM_TRL_NOMRATE_LO 0xF09B00FF ++ ++/* TRL_NOMRATE2 */ ++#define R367_OFDM_TRL_NOMRATE2 0xF09C ++#define F367_OFDM_TRL_NOMRATE_HI 0xF09C00FF ++ ++/* TRL_TIME1 */ ++#define R367_OFDM_TRL_TIME1 0xF09D ++#define F367_OFDM_TRL_TOFFSET_LO 0xF09D00FF ++ ++/* TRL_TIME2 */ ++#define R367_OFDM_TRL_TIME2 0xF09E ++#define F367_OFDM_TRL_TOFFSET_HI 0xF09E00FF ++ ++/* CRL_CTL */ ++#define R367_OFDM_CRL_CTL 0xF09F ++#define F367_OFDM_CRL_DIS 0xF09F0080 ++#define F367_OFDM_CRL_GAIN_FACTOR 0xF09F0078 ++#define F367_OFDM_CRL_LOOPGAIN 0xF09F0007 ++ ++/* CRL_FREQ1 */ ++#define R367_OFDM_CRL_FREQ1 0xF0A0 ++#define F367_OFDM_CRL_FOFFSET_LO 0xF0A000FF ++ ++/* CRL_FREQ2 */ ++#define R367_OFDM_CRL_FREQ2 0xF0A1 ++#define F367_OFDM_CRL_FOFFSET_HI 0xF0A100FF ++ ++/* CRL_FREQ3 */ ++#define R367_OFDM_CRL_FREQ3 0xF0A2 ++#define F367_OFDM_CRL_FOFFSET_VHI 0xF0A200FF ++ ++/* TPS_SFRAME_CTL */ ++#define R367_OFDM_TPS_SFRAME_CTL 0xF0A3 ++#define F367_OFDM_TPS_SFRAME_SYNC 0xF0A30001 ++ ++/* CHC_SNR */ ++#define R367_OFDM_CHC_SNR 0xF0A4 ++#define F367_OFDM_CHCSNR 0xF0A400FF ++ ++/* BDI_CTL */ ++#define R367_OFDM_BDI_CTL 0xF0A5 ++#define F367_OFDM_BDI_LPSEL 0xF0A50002 ++#define F367_OFDM_BDI_SERIAL 0xF0A50001 ++ ++/* DMP_CTL */ ++#define R367_OFDM_DMP_CTL 0xF0A6 ++#define F367_OFDM_DMP_SCALING_FACTOR 0xF0A6001E ++#define F367_OFDM_DMP_SDDIS 0xF0A60001 ++ ++/* TPS_RCVD1 */ ++#define R367_OFDM_TPS_RCVD1 0xF0A7 ++#define F367_OFDM_TPS_CHANGE 0xF0A70040 ++#define F367_OFDM_BCH_OK 0xF0A70020 ++#define F367_OFDM_TPS_SYNC 0xF0A70010 ++#define F367_OFDM_TPS_FRAME 0xF0A70003 ++ ++/* TPS_RCVD2 */ ++#define R367_OFDM_TPS_RCVD2 0xF0A8 ++#define F367_OFDM_TPS_HIERMODE 0xF0A80070 ++#define F367_OFDM_TPS_CONST 0xF0A80003 ++ ++/* TPS_RCVD3 */ ++#define R367_OFDM_TPS_RCVD3 0xF0A9 ++#define F367_OFDM_TPS_LPCODE 0xF0A90070 ++#define F367_OFDM_TPS_HPCODE 0xF0A90007 ++ ++/* TPS_RCVD4 */ ++#define R367_OFDM_TPS_RCVD4 0xF0AA ++#define F367_OFDM_TPS_GUARD 0xF0AA0030 ++#define F367_OFDM_TPS_MODE 0xF0AA0003 ++ ++/* TPS_ID_CELL1 */ ++#define R367_OFDM_TPS_ID_CELL1 0xF0AB ++#define F367_OFDM_TPS_ID_CELL_LO 0xF0AB00FF ++ ++/* TPS_ID_CELL2 */ ++#define R367_OFDM_TPS_ID_CELL2 0xF0AC ++#define F367_OFDM_TPS_ID_CELL_HI 0xF0AC00FF ++ ++/* TPS_RCVD5_SET1 */ ++#define R367_OFDM_TPS_RCVD5_SET1 0xF0AD ++#define F367_OFDM_TPS_NA 0xF0AD00FC ++#define F367_OFDM_TPS_SETFRAME 0xF0AD0003 ++ ++/* TPS_SET2 */ ++#define R367_OFDM_TPS_SET2 0xF0AE ++#define F367_OFDM_TPS_SETHIERMODE 0xF0AE0070 ++#define F367_OFDM_TPS_SETCONST 0xF0AE0003 ++ ++/* TPS_SET3 */ ++#define R367_OFDM_TPS_SET3 0xF0AF ++#define F367_OFDM_TPS_SETLPCODE 0xF0AF0070 ++#define F367_OFDM_TPS_SETHPCODE 0xF0AF0007 ++ ++/* TPS_CTL */ ++#define R367_OFDM_TPS_CTL 0xF0B0 ++#define F367_OFDM_TPS_IMM 0xF0B00004 ++#define F367_OFDM_TPS_BCHDIS 0xF0B00002 ++#define F367_OFDM_TPS_UPDDIS 0xF0B00001 ++ ++/* CTL_FFTOSNUM */ ++#define R367_OFDM_CTL_FFTOSNUM 0xF0B1 ++#define F367_OFDM_SYMBOL_NUMBER 0xF0B1007F ++ ++/* TESTSELECT */ ++#define R367_OFDM_TESTSELECT 0xF0B2 ++#define F367_OFDM_TEST_SELECT 0xF0B2001F ++ ++/* MSC_REV */ ++#define R367_OFDM_MSC_REV 0xF0B3 ++#define F367_OFDM_REV_NUMBER 0xF0B300FF ++ ++/* PIR_CTL */ ++#define R367_OFDM_PIR_CTL 0xF0B4 ++#define F367_OFDM_FREEZE 0xF0B40001 ++ ++/* SNR_CARRIER1 */ ++#define R367_OFDM_SNR_CARRIER1 0xF0B5 ++#define F367_OFDM_SNR_CARRIER_LO 0xF0B500FF ++ ++/* SNR_CARRIER2 */ ++#define R367_OFDM_SNR_CARRIER2 0xF0B6 ++#define F367_OFDM_MEAN 0xF0B600C0 ++#define F367_OFDM_SNR_CARRIER_HI 0xF0B6001F ++ ++/* PPM_CPAMP */ ++#define R367_OFDM_PPM_CPAMP 0xF0B7 ++#define F367_OFDM_PPM_CPC 0xF0B700FF ++ ++/* TSM_AP0 */ ++#define R367_OFDM_TSM_AP0 0xF0B8 ++#define F367_OFDM_ADDRESS_BYTE_0 0xF0B800FF ++ ++/* TSM_AP1 */ ++#define R367_OFDM_TSM_AP1 0xF0B9 ++#define F367_OFDM_ADDRESS_BYTE_1 0xF0B900FF ++ ++/* TSM_AP2 */ ++#define R367_OFDM_TSM_AP2 0xF0BA ++#define F367_OFDM_DATA_BYTE_0 0xF0BA00FF ++ ++/* TSM_AP3 */ ++#define R367_OFDM_TSM_AP3 0xF0BB ++#define F367_OFDM_DATA_BYTE_1 0xF0BB00FF ++ ++/* TSM_AP4 */ ++#define R367_OFDM_TSM_AP4 0xF0BC ++#define F367_OFDM_DATA_BYTE_2 0xF0BC00FF ++ ++/* TSM_AP5 */ ++#define R367_OFDM_TSM_AP5 0xF0BD ++#define F367_OFDM_DATA_BYTE_3 0xF0BD00FF ++ ++/* TSM_AP6 */ ++#define R367_OFDM_TSM_AP6 0xF0BE ++#define F367_OFDM_TSM_AP_6 0xF0BE00FF ++ ++/* TSM_AP7 */ ++#define R367_OFDM_TSM_AP7 0xF0BF ++#define F367_OFDM_MEM_SELECT_BYTE 0xF0BF00FF ++ ++/* TSTRES */ ++#define R367_TSTRES 0xF0C0 ++#define F367_FRES_DISPLAY 0xF0C00080 ++#define F367_FRES_FIFO_AD 0xF0C00020 ++#define F367_FRESRS 0xF0C00010 ++#define F367_FRESACS 0xF0C00008 ++#define F367_FRESFEC 0xF0C00004 ++#define F367_FRES_PRIF 0xF0C00002 ++#define F367_FRESCORE 0xF0C00001 ++ ++/* ANACTRL */ ++#define R367_ANACTRL 0xF0C1 ++#define F367_BYPASS_XTAL 0xF0C10040 ++#define F367_BYPASS_PLLXN 0xF0C1000C ++#define F367_DIS_PAD_OSC 0xF0C10002 ++#define F367_STDBY_PLLXN 0xF0C10001 ++ ++/* TSTBUS */ ++#define R367_TSTBUS 0xF0C2 ++#define F367_TS_BYTE_CLK_INV 0xF0C20080 ++#define F367_CFG_IP 0xF0C20070 ++#define F367_CFG_TST 0xF0C2000F ++ ++/* TSTRATE */ ++#define R367_TSTRATE 0xF0C6 ++#define F367_FORCEPHA 0xF0C60080 ++#define F367_FNEWPHA 0xF0C60010 ++#define F367_FROT90 0xF0C60008 ++#define F367_FR 0xF0C60007 ++ ++/* CONSTMODE */ ++#define R367_OFDM_CONSTMODE 0xF0CB ++#define F367_OFDM_TST_PRIF 0xF0CB00E0 ++#define F367_OFDM_CAR_TYPE 0xF0CB0018 ++#define F367_OFDM_CONST_MODE 0xF0CB0003 ++ ++/* CONSTCARR1 */ ++#define R367_OFDM_CONSTCARR1 0xF0CC ++#define F367_OFDM_CONST_CARR_LO 0xF0CC00FF ++ ++/* CONSTCARR2 */ ++#define R367_OFDM_CONSTCARR2 0xF0CD ++#define F367_OFDM_CONST_CARR_HI 0xF0CD001F ++ ++/* ICONSTEL */ ++#define R367_OFDM_ICONSTEL 0xF0CE ++#define F367_OFDM_PICONSTEL 0xF0CE00FF ++ ++/* QCONSTEL */ ++#define R367_OFDM_QCONSTEL 0xF0CF ++#define F367_OFDM_PQCONSTEL 0xF0CF00FF ++ ++/* TSTBISTRES0 */ ++#define R367_OFDM_TSTBISTRES0 0xF0D0 ++#define F367_OFDM_BEND_PPM 0xF0D00080 ++#define F367_OFDM_BBAD_PPM 0xF0D00040 ++#define F367_OFDM_BEND_FFTW 0xF0D00020 ++#define F367_OFDM_BBAD_FFTW 0xF0D00010 ++#define F367_OFDM_BEND_FFT_BUF 0xF0D00008 ++#define F367_OFDM_BBAD_FFT_BUF 0xF0D00004 ++#define F367_OFDM_BEND_SYR 0xF0D00002 ++#define F367_OFDM_BBAD_SYR 0xF0D00001 ++ ++/* TSTBISTRES1 */ ++#define R367_OFDM_TSTBISTRES1 0xF0D1 ++#define F367_OFDM_BEND_CHC_CP 0xF0D10080 ++#define F367_OFDM_BBAD_CHC_CP 0xF0D10040 ++#define F367_OFDM_BEND_CHCI 0xF0D10020 ++#define F367_OFDM_BBAD_CHCI 0xF0D10010 ++#define F367_OFDM_BEND_BDI 0xF0D10008 ++#define F367_OFDM_BBAD_BDI 0xF0D10004 ++#define F367_OFDM_BEND_SDI 0xF0D10002 ++#define F367_OFDM_BBAD_SDI 0xF0D10001 ++ ++/* TSTBISTRES2 */ ++#define R367_OFDM_TSTBISTRES2 0xF0D2 ++#define F367_OFDM_BEND_CHC_INC 0xF0D20080 ++#define F367_OFDM_BBAD_CHC_INC 0xF0D20040 ++#define F367_OFDM_BEND_CHC_SPP 0xF0D20020 ++#define F367_OFDM_BBAD_CHC_SPP 0xF0D20010 ++#define F367_OFDM_BEND_CHC_CPP 0xF0D20008 ++#define F367_OFDM_BBAD_CHC_CPP 0xF0D20004 ++#define F367_OFDM_BEND_CHC_SP 0xF0D20002 ++#define F367_OFDM_BBAD_CHC_SP 0xF0D20001 ++ ++/* TSTBISTRES3 */ ++#define R367_OFDM_TSTBISTRES3 0xF0D3 ++#define F367_OFDM_BEND_QAM 0xF0D30080 ++#define F367_OFDM_BBAD_QAM 0xF0D30040 ++#define F367_OFDM_BEND_SFEC_VIT 0xF0D30020 ++#define F367_OFDM_BBAD_SFEC_VIT 0xF0D30010 ++#define F367_OFDM_BEND_SFEC_DLINE 0xF0D30008 ++#define F367_OFDM_BBAD_SFEC_DLINE 0xF0D30004 ++#define F367_OFDM_BEND_SFEC_HW 0xF0D30002 ++#define F367_OFDM_BBAD_SFEC_HW 0xF0D30001 ++ ++/* RF_AGC1 */ ++#define R367_RF_AGC1 0xF0D4 ++#define F367_RF_AGC1_LEVEL_HI 0xF0D400FF ++ ++/* RF_AGC2 */ ++#define R367_RF_AGC2 0xF0D5 ++#define F367_REF_ADGP 0xF0D50080 ++#define F367_STDBY_ADCGP 0xF0D50020 ++#define F367_CHANNEL_SEL 0xF0D5001C ++#define F367_RF_AGC1_LEVEL_LO 0xF0D50003 ++ ++/* ANADIGCTRL */ ++#define R367_ANADIGCTRL 0xF0D7 ++#define F367_SEL_CLKDEM 0xF0D70020 ++#define F367_EN_BUFFER_Q 0xF0D70010 ++#define F367_EN_BUFFER_I 0xF0D70008 ++#define F367_ADC_RIS_EGDE 0xF0D70004 ++#define F367_SGN_ADC 0xF0D70002 ++#define F367_SEL_AD12_SYNC 0xF0D70001 ++ ++/* PLLMDIV */ ++#define R367_PLLMDIV 0xF0D8 ++#define F367_PLL_MDIV 0xF0D800FF ++ ++/* PLLNDIV */ ++#define R367_PLLNDIV 0xF0D9 ++#define F367_PLL_NDIV 0xF0D900FF ++ ++/* PLLSETUP */ ++#define R367_PLLSETUP 0xF0DA ++#define F367_PLL_PDIV 0xF0DA0070 ++#define F367_PLL_KDIV 0xF0DA000F ++ ++/* DUAL_AD12 */ ++#define R367_DUAL_AD12 0xF0DB ++#define F367_FS20M 0xF0DB0020 ++#define F367_FS50M 0xF0DB0010 ++#define F367_INMODE0 0xF0DB0008 ++#define F367_POFFQ 0xF0DB0004 ++#define F367_POFFI 0xF0DB0002 ++#define F367_INMODE1 0xF0DB0001 ++ ++/* TSTBIST */ ++#define R367_TSTBIST 0xF0DC ++#define F367_TST_BYP_CLK 0xF0DC0080 ++#define F367_TST_GCLKENA_STD 0xF0DC0040 ++#define F367_TST_GCLKENA 0xF0DC0020 ++#define F367_TST_MEMBIST 0xF0DC001F ++ ++/* PAD_COMP_CTRL */ ++#define R367_PAD_COMP_CTRL 0xF0DD ++#define F367_COMPTQ 0xF0DD0010 ++#define F367_COMPEN 0xF0DD0008 ++#define F367_FREEZE2 0xF0DD0004 ++#define F367_SLEEP_INHBT 0xF0DD0002 ++#define F367_CHIP_SLEEP 0xF0DD0001 ++ ++/* PAD_COMP_WR */ ++#define R367_PAD_COMP_WR 0xF0DE ++#define F367_WR_ASRC 0xF0DE007F ++ ++/* PAD_COMP_RD */ ++#define R367_PAD_COMP_RD 0xF0DF ++#define F367_COMPOK 0xF0DF0080 ++#define F367_RD_ASRC 0xF0DF007F ++ ++/* SYR_TARGET_FFTADJT_MSB */ ++#define R367_OFDM_SYR_TARGET_FFTADJT_MSB 0xF100 ++#define F367_OFDM_SYR_START 0xF1000080 ++#define F367_OFDM_SYR_TARGET_FFTADJ_HI 0xF100000F ++ ++/* SYR_TARGET_FFTADJT_LSB */ ++#define R367_OFDM_SYR_TARGET_FFTADJT_LSB 0xF101 ++#define F367_OFDM_SYR_TARGET_FFTADJ_LO 0xF10100FF ++ ++/* SYR_TARGET_CHCADJT_MSB */ ++#define R367_OFDM_SYR_TARGET_CHCADJT_MSB 0xF102 ++#define F367_OFDM_SYR_TARGET_CHCADJ_HI 0xF102000F ++ ++/* SYR_TARGET_CHCADJT_LSB */ ++#define R367_OFDM_SYR_TARGET_CHCADJT_LSB 0xF103 ++#define F367_OFDM_SYR_TARGET_CHCADJ_LO 0xF10300FF ++ ++/* SYR_FLAG */ ++#define R367_OFDM_SYR_FLAG 0xF104 ++#define F367_OFDM_TRIG_FLG1 0xF1040080 ++#define F367_OFDM_TRIG_FLG0 0xF1040040 ++#define F367_OFDM_FFT_FLG1 0xF1040008 ++#define F367_OFDM_FFT_FLG0 0xF1040004 ++#define F367_OFDM_CHC_FLG1 0xF1040002 ++#define F367_OFDM_CHC_FLG0 0xF1040001 ++ ++/* CRL_TARGET1 */ ++#define R367_OFDM_CRL_TARGET1 0xF105 ++#define F367_OFDM_CRL_START 0xF1050080 ++#define F367_OFDM_CRL_TARGET_VHI 0xF105000F ++ ++/* CRL_TARGET2 */ ++#define R367_OFDM_CRL_TARGET2 0xF106 ++#define F367_OFDM_CRL_TARGET_HI 0xF10600FF ++ ++/* CRL_TARGET3 */ ++#define R367_OFDM_CRL_TARGET3 0xF107 ++#define F367_OFDM_CRL_TARGET_LO 0xF10700FF ++ ++/* CRL_TARGET4 */ ++#define R367_OFDM_CRL_TARGET4 0xF108 ++#define F367_OFDM_CRL_TARGET_VLO 0xF10800FF ++ ++/* CRL_FLAG */ ++#define R367_OFDM_CRL_FLAG 0xF109 ++#define F367_OFDM_CRL_FLAG1 0xF1090002 ++#define F367_OFDM_CRL_FLAG0 0xF1090001 ++ ++/* TRL_TARGET1 */ ++#define R367_OFDM_TRL_TARGET1 0xF10A ++#define F367_OFDM_TRL_TARGET_HI 0xF10A00FF ++ ++/* TRL_TARGET2 */ ++#define R367_OFDM_TRL_TARGET2 0xF10B ++#define F367_OFDM_TRL_TARGET_LO 0xF10B00FF ++ ++/* TRL_CHC */ ++#define R367_OFDM_TRL_CHC 0xF10C ++#define F367_OFDM_TRL_START 0xF10C0080 ++#define F367_OFDM_CHC_START 0xF10C0040 ++#define F367_OFDM_TRL_FLAG1 0xF10C0002 ++#define F367_OFDM_TRL_FLAG0 0xF10C0001 ++ ++/* CHC_SNR_TARG */ ++#define R367_OFDM_CHC_SNR_TARG 0xF10D ++#define F367_OFDM_CHC_SNR_TARGET 0xF10D00FF ++ ++/* TOP_TRACK */ ++#define R367_OFDM_TOP_TRACK 0xF10E ++#define F367_OFDM_TOP_START 0xF10E0080 ++#define F367_OFDM_FIRST_FLAG 0xF10E0070 ++#define F367_OFDM_TOP_FLAG1 0xF10E0008 ++#define F367_OFDM_TOP_FLAG0 0xF10E0004 ++#define F367_OFDM_CHC_FLAG1 0xF10E0002 ++#define F367_OFDM_CHC_FLAG0 0xF10E0001 ++ ++/* TRACKER_FREE1 */ ++#define R367_OFDM_TRACKER_FREE1 0xF10F ++#define F367_OFDM_TRACKER_FREE_1 0xF10F00FF ++ ++/* ERROR_CRL1 */ ++#define R367_OFDM_ERROR_CRL1 0xF110 ++#define F367_OFDM_ERROR_CRL_VHI 0xF11000FF ++ ++/* ERROR_CRL2 */ ++#define R367_OFDM_ERROR_CRL2 0xF111 ++#define F367_OFDM_ERROR_CRL_HI 0xF11100FF ++ ++/* ERROR_CRL3 */ ++#define R367_OFDM_ERROR_CRL3 0xF112 ++#define F367_OFDM_ERROR_CRL_LOI 0xF11200FF ++ ++/* ERROR_CRL4 */ ++#define R367_OFDM_ERROR_CRL4 0xF113 ++#define F367_OFDM_ERROR_CRL_VLO 0xF11300FF ++ ++/* DEC_NCO1 */ ++#define R367_OFDM_DEC_NCO1 0xF114 ++#define F367_OFDM_DEC_NCO_VHI 0xF11400FF ++ ++/* DEC_NCO2 */ ++#define R367_OFDM_DEC_NCO2 0xF115 ++#define F367_OFDM_DEC_NCO_HI 0xF11500FF ++ ++/* DEC_NCO3 */ ++#define R367_OFDM_DEC_NCO3 0xF116 ++#define F367_OFDM_DEC_NCO_LO 0xF11600FF ++ ++/* SNR */ ++#define R367_OFDM_SNR 0xF117 ++#define F367_OFDM_SNRATIO 0xF11700FF ++ ++/* SYR_FFTADJ1 */ ++#define R367_OFDM_SYR_FFTADJ1 0xF118 ++#define F367_OFDM_SYR_FFTADJ_HI 0xF11800FF ++ ++/* SYR_FFTADJ2 */ ++#define R367_OFDM_SYR_FFTADJ2 0xF119 ++#define F367_OFDM_SYR_FFTADJ_LO 0xF11900FF ++ ++/* SYR_CHCADJ1 */ ++#define R367_OFDM_SYR_CHCADJ1 0xF11A ++#define F367_OFDM_SYR_CHCADJ_HI 0xF11A00FF ++ ++/* SYR_CHCADJ2 */ ++#define R367_OFDM_SYR_CHCADJ2 0xF11B ++#define F367_OFDM_SYR_CHCADJ_LO 0xF11B00FF ++ ++/* SYR_OFF */ ++#define R367_OFDM_SYR_OFF 0xF11C ++#define F367_OFDM_SYR_OFFSET 0xF11C00FF ++ ++/* PPM_OFFSET1 */ ++#define R367_OFDM_PPM_OFFSET1 0xF11D ++#define F367_OFDM_PPM_OFFSET_HI 0xF11D00FF ++ ++/* PPM_OFFSET2 */ ++#define R367_OFDM_PPM_OFFSET2 0xF11E ++#define F367_OFDM_PPM_OFFSET_LO 0xF11E00FF ++ ++/* TRACKER_FREE2 */ ++#define R367_OFDM_TRACKER_FREE2 0xF11F ++#define F367_OFDM_TRACKER_FREE_2 0xF11F00FF ++ ++/* DEBG_LT10 */ ++#define R367_OFDM_DEBG_LT10 0xF120 ++#define F367_OFDM_DEBUG_LT10 0xF12000FF ++ ++/* DEBG_LT11 */ ++#define R367_OFDM_DEBG_LT11 0xF121 ++#define F367_OFDM_DEBUG_LT11 0xF12100FF ++ ++/* DEBG_LT12 */ ++#define R367_OFDM_DEBG_LT12 0xF122 ++#define F367_OFDM_DEBUG_LT12 0xF12200FF ++ ++/* DEBG_LT13 */ ++#define R367_OFDM_DEBG_LT13 0xF123 ++#define F367_OFDM_DEBUG_LT13 0xF12300FF ++ ++/* DEBG_LT14 */ ++#define R367_OFDM_DEBG_LT14 0xF124 ++#define F367_OFDM_DEBUG_LT14 0xF12400FF ++ ++/* DEBG_LT15 */ ++#define R367_OFDM_DEBG_LT15 0xF125 ++#define F367_OFDM_DEBUG_LT15 0xF12500FF ++ ++/* DEBG_LT16 */ ++#define R367_OFDM_DEBG_LT16 0xF126 ++#define F367_OFDM_DEBUG_LT16 0xF12600FF ++ ++/* DEBG_LT17 */ ++#define R367_OFDM_DEBG_LT17 0xF127 ++#define F367_OFDM_DEBUG_LT17 0xF12700FF ++ ++/* DEBG_LT18 */ ++#define R367_OFDM_DEBG_LT18 0xF128 ++#define F367_OFDM_DEBUG_LT18 0xF12800FF ++ ++/* DEBG_LT19 */ ++#define R367_OFDM_DEBG_LT19 0xF129 ++#define F367_OFDM_DEBUG_LT19 0xF12900FF ++ ++/* DEBG_LT1A */ ++#define R367_OFDM_DEBG_LT1A 0xF12A ++#define F367_OFDM_DEBUG_LT1A 0xF12A00FF ++ ++/* DEBG_LT1B */ ++#define R367_OFDM_DEBG_LT1B 0xF12B ++#define F367_OFDM_DEBUG_LT1B 0xF12B00FF ++ ++/* DEBG_LT1C */ ++#define R367_OFDM_DEBG_LT1C 0xF12C ++#define F367_OFDM_DEBUG_LT1C 0xF12C00FF ++ ++/* DEBG_LT1D */ ++#define R367_OFDM_DEBG_LT1D 0xF12D ++#define F367_OFDM_DEBUG_LT1D 0xF12D00FF ++ ++/* DEBG_LT1E */ ++#define R367_OFDM_DEBG_LT1E 0xF12E ++#define F367_OFDM_DEBUG_LT1E 0xF12E00FF ++ ++/* DEBG_LT1F */ ++#define R367_OFDM_DEBG_LT1F 0xF12F ++#define F367_OFDM_DEBUG_LT1F 0xF12F00FF ++ ++/* RCCFGH */ ++#define R367_OFDM_RCCFGH 0xF200 ++#define F367_OFDM_TSRCFIFO_DVBCI 0xF2000080 ++#define F367_OFDM_TSRCFIFO_SERIAL 0xF2000040 ++#define F367_OFDM_TSRCFIFO_DISABLE 0xF2000020 ++#define F367_OFDM_TSFIFO_2TORC 0xF2000010 ++#define F367_OFDM_TSRCFIFO_HSGNLOUT 0xF2000008 ++#define F367_OFDM_TSRCFIFO_ERRMODE 0xF2000006 ++#define F367_OFDM_RCCFGH_0 0xF2000001 ++ ++/* RCCFGM */ ++#define R367_OFDM_RCCFGM 0xF201 ++#define F367_OFDM_TSRCFIFO_MANSPEED 0xF20100C0 ++#define F367_OFDM_TSRCFIFO_PERMDATA 0xF2010020 ++#define F367_OFDM_TSRCFIFO_NONEWSGNL 0xF2010010 ++#define F367_OFDM_RCBYTE_OVERSAMPLING 0xF201000E ++#define F367_OFDM_TSRCFIFO_INVDATA 0xF2010001 ++ ++/* RCCFGL */ ++#define R367_OFDM_RCCFGL 0xF202 ++#define F367_OFDM_TSRCFIFO_BCLKDEL1CK 0xF20200C0 ++#define F367_OFDM_RCCFGL_5 0xF2020020 ++#define F367_OFDM_TSRCFIFO_DUTY50 0xF2020010 ++#define F367_OFDM_TSRCFIFO_NSGNL2DATA 0xF2020008 ++#define F367_OFDM_TSRCFIFO_DISSERMUX 0xF2020004 ++#define F367_OFDM_RCCFGL_1 0xF2020002 ++#define F367_OFDM_TSRCFIFO_STOPCKDIS 0xF2020001 ++ ++/* RCINSDELH */ ++#define R367_OFDM_RCINSDELH 0xF203 ++#define F367_OFDM_TSRCDEL_SYNCBYTE 0xF2030080 ++#define F367_OFDM_TSRCDEL_XXHEADER 0xF2030040 ++#define F367_OFDM_TSRCDEL_BBHEADER 0xF2030020 ++#define F367_OFDM_TSRCDEL_DATAFIELD 0xF2030010 ++#define F367_OFDM_TSRCINSDEL_ISCR 0xF2030008 ++#define F367_OFDM_TSRCINSDEL_NPD 0xF2030004 ++#define F367_OFDM_TSRCINSDEL_RSPARITY 0xF2030002 ++#define F367_OFDM_TSRCINSDEL_CRC8 0xF2030001 ++ ++/* RCINSDELM */ ++#define R367_OFDM_RCINSDELM 0xF204 ++#define F367_OFDM_TSRCINS_BBPADDING 0xF2040080 ++#define F367_OFDM_TSRCINS_BCHFEC 0xF2040040 ++#define F367_OFDM_TSRCINS_LDPCFEC 0xF2040020 ++#define F367_OFDM_TSRCINS_EMODCOD 0xF2040010 ++#define F367_OFDM_TSRCINS_TOKEN 0xF2040008 ++#define F367_OFDM_TSRCINS_XXXERR 0xF2040004 ++#define F367_OFDM_TSRCINS_MATYPE 0xF2040002 ++#define F367_OFDM_TSRCINS_UPL 0xF2040001 ++ ++/* RCINSDELL */ ++#define R367_OFDM_RCINSDELL 0xF205 ++#define F367_OFDM_TSRCINS_DFL 0xF2050080 ++#define F367_OFDM_TSRCINS_SYNCD 0xF2050040 ++#define F367_OFDM_TSRCINS_BLOCLEN 0xF2050020 ++#define F367_OFDM_TSRCINS_SIGPCOUNT 0xF2050010 ++#define F367_OFDM_TSRCINS_FIFO 0xF2050008 ++#define F367_OFDM_TSRCINS_REALPACK 0xF2050004 ++#define F367_OFDM_TSRCINS_TSCONFIG 0xF2050002 ++#define F367_OFDM_TSRCINS_LATENCY 0xF2050001 ++ ++/* RCSTATUS */ ++#define R367_OFDM_RCSTATUS 0xF206 ++#define F367_OFDM_TSRCFIFO_LINEOK 0xF2060080 ++#define F367_OFDM_TSRCFIFO_ERROR 0xF2060040 ++#define F367_OFDM_TSRCFIFO_DATA7 0xF2060020 ++#define F367_OFDM_RCSTATUS_4 0xF2060010 ++#define F367_OFDM_TSRCFIFO_DEMODSEL 0xF2060008 ++#define F367_OFDM_TSRC1FIFOSPEED_STORE 0xF2060004 ++#define F367_OFDM_RCSTATUS_1 0xF2060002 ++#define F367_OFDM_TSRCSERIAL_IMPOSSIBLE 0xF2060001 ++ ++/* RCSPEED */ ++#define R367_OFDM_RCSPEED 0xF207 ++#define F367_OFDM_TSRCFIFO_OUTSPEED 0xF20700FF ++ ++/* RCDEBUGM */ ++#define R367_OFDM_RCDEBUGM 0xF208 ++#define F367_OFDM_SD_UNSYNC 0xF2080080 ++#define F367_OFDM_ULFLOCK_DETECTM 0xF2080040 ++#define F367_OFDM_SUL_SELECTOS 0xF2080020 ++#define F367_OFDM_DILUL_NOSCRBLE 0xF2080010 ++#define F367_OFDM_NUL_SCRB 0xF2080008 ++#define F367_OFDM_UL_SCRB 0xF2080004 ++#define F367_OFDM_SCRAULBAD 0xF2080002 ++#define F367_OFDM_SCRAUL_UNSYNC 0xF2080001 ++ ++/* RCDEBUGL */ ++#define R367_OFDM_RCDEBUGL 0xF209 ++#define F367_OFDM_RS_ERR 0xF2090080 ++#define F367_OFDM_LLFLOCK_DETECTM 0xF2090040 ++#define F367_OFDM_NOT_SUL_SELECTOS 0xF2090020 ++#define F367_OFDM_DILLL_NOSCRBLE 0xF2090010 ++#define F367_OFDM_NLL_SCRB 0xF2090008 ++#define F367_OFDM_LL_SCRB 0xF2090004 ++#define F367_OFDM_SCRALLBAD 0xF2090002 ++#define F367_OFDM_SCRALL_UNSYNC 0xF2090001 ++ ++/* RCOBSCFG */ ++#define R367_OFDM_RCOBSCFG 0xF20A ++#define F367_OFDM_TSRCFIFO_OBSCFG 0xF20A00FF ++ ++/* RCOBSM */ ++#define R367_OFDM_RCOBSM 0xF20B ++#define F367_OFDM_TSRCFIFO_OBSDATA_HI 0xF20B00FF ++ ++/* RCOBSL */ ++#define R367_OFDM_RCOBSL 0xF20C ++#define F367_OFDM_TSRCFIFO_OBSDATA_LO 0xF20C00FF ++ ++/* RCFECSPY */ ++#define R367_OFDM_RCFECSPY 0xF210 ++#define F367_OFDM_SPYRC_ENABLE 0xF2100080 ++#define F367_OFDM_RCNO_SYNCBYTE 0xF2100040 ++#define F367_OFDM_RCSERIAL_MODE 0xF2100020 ++#define F367_OFDM_RCUNUSUAL_PACKET 0xF2100010 ++#define F367_OFDM_BERRCMETER_DATAMODE 0xF210000C ++#define F367_OFDM_BERRCMETER_LMODE 0xF2100002 ++#define F367_OFDM_BERRCMETER_RESET 0xF2100001 ++ ++/* RCFSPYCFG */ ++#define R367_OFDM_RCFSPYCFG 0xF211 ++#define F367_OFDM_FECSPYRC_INPUT 0xF21100C0 ++#define F367_OFDM_RCRST_ON_ERROR 0xF2110020 ++#define F367_OFDM_RCONE_SHOT 0xF2110010 ++#define F367_OFDM_RCI2C_MODE 0xF211000C ++#define F367_OFDM_SPYRC_HSTERESIS 0xF2110003 ++ ++/* RCFSPYDATA */ ++#define R367_OFDM_RCFSPYDATA 0xF212 ++#define F367_OFDM_SPYRC_STUFFING 0xF2120080 ++#define F367_OFDM_RCNOERR_PKTJITTER 0xF2120040 ++#define F367_OFDM_SPYRC_CNULLPKT 0xF2120020 ++#define F367_OFDM_SPYRC_OUTDATA_MODE 0xF212001F ++ ++/* RCFSPYOUT */ ++#define R367_OFDM_RCFSPYOUT 0xF213 ++#define F367_OFDM_FSPYRC_DIRECT 0xF2130080 ++#define F367_OFDM_RCFSPYOUT_6 0xF2130040 ++#define F367_OFDM_SPYRC_OUTDATA_BUS 0xF2130038 ++#define F367_OFDM_RCSTUFF_MODE 0xF2130007 ++ ++/* RCFSTATUS */ ++#define R367_OFDM_RCFSTATUS 0xF214 ++#define F367_OFDM_SPYRC_ENDSIM 0xF2140080 ++#define F367_OFDM_RCVALID_SIM 0xF2140040 ++#define F367_OFDM_RCFOUND_SIGNAL 0xF2140020 ++#define F367_OFDM_RCDSS_SYNCBYTE 0xF2140010 ++#define F367_OFDM_RCRESULT_STATE 0xF214000F ++ ++/* RCFGOODPACK */ ++#define R367_OFDM_RCFGOODPACK 0xF215 ++#define F367_OFDM_RCGOOD_PACKET 0xF21500FF ++ ++/* RCFPACKCNT */ ++#define R367_OFDM_RCFPACKCNT 0xF216 ++#define F367_OFDM_RCPACKET_COUNTER 0xF21600FF ++ ++/* RCFSPYMISC */ ++#define R367_OFDM_RCFSPYMISC 0xF217 ++#define F367_OFDM_RCLABEL_COUNTER 0xF21700FF ++ ++/* RCFBERCPT4 */ ++#define R367_OFDM_RCFBERCPT4 0xF218 ++#define F367_OFDM_FBERRCMETER_CPT_MMMMSB 0xF21800FF ++ ++/* RCFBERCPT3 */ ++#define R367_OFDM_RCFBERCPT3 0xF219 ++#define F367_OFDM_FBERRCMETER_CPT_MMMSB 0xF21900FF ++ ++/* RCFBERCPT2 */ ++#define R367_OFDM_RCFBERCPT2 0xF21A ++#define F367_OFDM_FBERRCMETER_CPT_MMSB 0xF21A00FF ++ ++/* RCFBERCPT1 */ ++#define R367_OFDM_RCFBERCPT1 0xF21B ++#define F367_OFDM_FBERRCMETER_CPT_MSB 0xF21B00FF ++ ++/* RCFBERCPT0 */ ++#define R367_OFDM_RCFBERCPT0 0xF21C ++#define F367_OFDM_FBERRCMETER_CPT_LSB 0xF21C00FF ++ ++/* RCFBERERR2 */ ++#define R367_OFDM_RCFBERERR2 0xF21D ++#define F367_OFDM_FBERRCMETER_ERR_HI 0xF21D00FF ++ ++/* RCFBERERR1 */ ++#define R367_OFDM_RCFBERERR1 0xF21E ++#define F367_OFDM_FBERRCMETER_ERR 0xF21E00FF ++ ++/* RCFBERERR0 */ ++#define R367_OFDM_RCFBERERR0 0xF21F ++#define F367_OFDM_FBERRCMETER_ERR_LO 0xF21F00FF ++ ++/* RCFSTATESM */ ++#define R367_OFDM_RCFSTATESM 0xF220 ++#define F367_OFDM_RCRSTATE_F 0xF2200080 ++#define F367_OFDM_RCRSTATE_E 0xF2200040 ++#define F367_OFDM_RCRSTATE_D 0xF2200020 ++#define F367_OFDM_RCRSTATE_C 0xF2200010 ++#define F367_OFDM_RCRSTATE_B 0xF2200008 ++#define F367_OFDM_RCRSTATE_A 0xF2200004 ++#define F367_OFDM_RCRSTATE_9 0xF2200002 ++#define F367_OFDM_RCRSTATE_8 0xF2200001 ++ ++/* RCFSTATESL */ ++#define R367_OFDM_RCFSTATESL 0xF221 ++#define F367_OFDM_RCRSTATE_7 0xF2210080 ++#define F367_OFDM_RCRSTATE_6 0xF2210040 ++#define F367_OFDM_RCRSTATE_5 0xF2210020 ++#define F367_OFDM_RCRSTATE_4 0xF2210010 ++#define F367_OFDM_RCRSTATE_3 0xF2210008 ++#define F367_OFDM_RCRSTATE_2 0xF2210004 ++#define F367_OFDM_RCRSTATE_1 0xF2210002 ++#define F367_OFDM_RCRSTATE_0 0xF2210001 ++ ++/* RCFSPYBER */ ++#define R367_OFDM_RCFSPYBER 0xF222 ++#define F367_OFDM_RCFSPYBER_7 0xF2220080 ++#define F367_OFDM_SPYRCOBS_XORREAD 0xF2220040 ++#define F367_OFDM_FSPYRCBER_OBSMODE 0xF2220020 ++#define F367_OFDM_FSPYRCBER_SYNCBYT 0xF2220010 ++#define F367_OFDM_FSPYRCBER_UNSYNC 0xF2220008 ++#define F367_OFDM_FSPYRCBER_CTIME 0xF2220007 ++ ++/* RCFSPYDISTM */ ++#define R367_OFDM_RCFSPYDISTM 0xF223 ++#define F367_OFDM_RCPKTTIME_DISTANCE_HI 0xF22300FF ++ ++/* RCFSPYDISTL */ ++#define R367_OFDM_RCFSPYDISTL 0xF224 ++#define F367_OFDM_RCPKTTIME_DISTANCE_LO 0xF22400FF ++ ++/* RCFSPYOBS7 */ ++#define R367_OFDM_RCFSPYOBS7 0xF228 ++#define F367_OFDM_RCSPYOBS_SPYFAIL 0xF2280080 ++#define F367_OFDM_RCSPYOBS_SPYFAIL1 0xF2280040 ++#define F367_OFDM_RCSPYOBS_ERROR 0xF2280020 ++#define F367_OFDM_RCSPYOBS_STROUT 0xF2280010 ++#define F367_OFDM_RCSPYOBS_RESULTSTATE1 0xF228000F ++ ++/* RCFSPYOBS6 */ ++#define R367_OFDM_RCFSPYOBS6 0xF229 ++#define F367_OFDM_RCSPYOBS_RESULTSTATE0 0xF22900F0 ++#define F367_OFDM_RCSPYOBS_RESULTSTATEM1 0xF229000F ++ ++/* RCFSPYOBS5 */ ++#define R367_OFDM_RCFSPYOBS5 0xF22A ++#define F367_OFDM_RCSPYOBS_BYTEOFPACKET1 0xF22A00FF ++ ++/* RCFSPYOBS4 */ ++#define R367_OFDM_RCFSPYOBS4 0xF22B ++#define F367_OFDM_RCSPYOBS_BYTEVALUE1 0xF22B00FF ++ ++/* RCFSPYOBS3 */ ++#define R367_OFDM_RCFSPYOBS3 0xF22C ++#define F367_OFDM_RCSPYOBS_DATA1 0xF22C00FF ++ ++/* RCFSPYOBS2 */ ++#define R367_OFDM_RCFSPYOBS2 0xF22D ++#define F367_OFDM_RCSPYOBS_DATA0 0xF22D00FF ++ ++/* RCFSPYOBS1 */ ++#define R367_OFDM_RCFSPYOBS1 0xF22E ++#define F367_OFDM_RCSPYOBS_DATAM1 0xF22E00FF ++ ++/* RCFSPYOBS0 */ ++#define R367_OFDM_RCFSPYOBS0 0xF22F ++#define F367_OFDM_RCSPYOBS_DATAM2 0xF22F00FF ++ ++/* TSGENERAL */ ++#define R367_TSGENERAL 0xF230 ++#define F367_TSGENERAL_7 0xF2300080 ++#define F367_TSGENERAL_6 0xF2300040 ++#define F367_TSFIFO_BCLK1ALL 0xF2300020 ++#define F367_TSGENERAL_4 0xF2300010 ++#define F367_MUXSTREAM_OUTMODE 0xF2300008 ++#define F367_TSFIFO_PERMPARAL 0xF2300006 ++#define F367_RST_REEDSOLO 0xF2300001 ++ ++/* RC1SPEED */ ++#define R367_RC1SPEED 0xF231 ++#define F367_TSRCFIFO1_OUTSPEED 0xF23100FF ++ ++/* TSGSTATUS */ ++#define R367_TSGSTATUS 0xF232 ++#define F367_TSGSTATUS_7 0xF2320080 ++#define F367_TSGSTATUS_6 0xF2320040 ++#define F367_RSMEM_FULL 0xF2320020 ++#define F367_RS_MULTCALC 0xF2320010 ++#define F367_RSIN_OVERTIME 0xF2320008 ++#define F367_TSFIFO3_DEMODSEL 0xF2320004 ++#define F367_TSFIFO2_DEMODSEL 0xF2320002 ++#define F367_TSFIFO1_DEMODSEL 0xF2320001 ++ ++ ++/* FECM */ ++#define R367_OFDM_FECM 0xF233 ++#define F367_OFDM_DSS_DVB 0xF2330080 ++#define F367_OFDM_DEMOD_BYPASS 0xF2330040 ++#define F367_OFDM_CMP_SLOWMODE 0xF2330020 ++#define F367_OFDM_DSS_SRCH 0xF2330010 ++#define F367_OFDM_FECM_3 0xF2330008 ++#define F367_OFDM_DIFF_MODEVIT 0xF2330004 ++#define F367_OFDM_SYNCVIT 0xF2330002 ++#define F367_OFDM_I2CSYM 0xF2330001 ++ ++/* VTH12 */ ++#define R367_OFDM_VTH12 0xF234 ++#define F367_OFDM_VTH_12 0xF23400FF ++ ++/* VTH23 */ ++#define R367_OFDM_VTH23 0xF235 ++#define F367_OFDM_VTH_23 0xF23500FF ++ ++/* VTH34 */ ++#define R367_OFDM_VTH34 0xF236 ++#define F367_OFDM_VTH_34 0xF23600FF ++ ++/* VTH56 */ ++#define R367_OFDM_VTH56 0xF237 ++#define F367_OFDM_VTH_56 0xF23700FF ++ ++/* VTH67 */ ++#define R367_OFDM_VTH67 0xF238 ++#define F367_OFDM_VTH_67 0xF23800FF ++ ++/* VTH78 */ ++#define R367_OFDM_VTH78 0xF239 ++#define F367_OFDM_VTH_78 0xF23900FF ++ ++/* VITCURPUN */ ++#define R367_OFDM_VITCURPUN 0xF23A ++#define F367_OFDM_VIT_MAPPING 0xF23A00E0 ++#define F367_OFDM_VIT_CURPUN 0xF23A001F ++ ++/* VERROR */ ++#define R367_OFDM_VERROR 0xF23B ++#define F367_OFDM_REGERR_VIT 0xF23B00FF ++ ++/* PRVIT */ ++#define R367_OFDM_PRVIT 0xF23C ++#define F367_OFDM_PRVIT_7 0xF23C0080 ++#define F367_OFDM_DIS_VTHLOCK 0xF23C0040 ++#define F367_OFDM_E7_8VIT 0xF23C0020 ++#define F367_OFDM_E6_7VIT 0xF23C0010 ++#define F367_OFDM_E5_6VIT 0xF23C0008 ++#define F367_OFDM_E3_4VIT 0xF23C0004 ++#define F367_OFDM_E2_3VIT 0xF23C0002 ++#define F367_OFDM_E1_2VIT 0xF23C0001 ++ ++/* VAVSRVIT */ ++#define R367_OFDM_VAVSRVIT 0xF23D ++#define F367_OFDM_AMVIT 0xF23D0080 ++#define F367_OFDM_FROZENVIT 0xF23D0040 ++#define F367_OFDM_SNVIT 0xF23D0030 ++#define F367_OFDM_TOVVIT 0xF23D000C ++#define F367_OFDM_HYPVIT 0xF23D0003 ++ ++/* VSTATUSVIT */ ++#define R367_OFDM_VSTATUSVIT 0xF23E ++#define F367_OFDM_VITERBI_ON 0xF23E0080 ++#define F367_OFDM_END_LOOPVIT 0xF23E0040 ++#define F367_OFDM_VITERBI_DEPRF 0xF23E0020 ++#define F367_OFDM_PRFVIT 0xF23E0010 ++#define F367_OFDM_LOCKEDVIT 0xF23E0008 ++#define F367_OFDM_VITERBI_DELOCK 0xF23E0004 ++#define F367_OFDM_VIT_DEMODSEL 0xF23E0002 ++#define F367_OFDM_VITERBI_COMPOUT 0xF23E0001 ++ ++/* VTHINUSE */ ++#define R367_OFDM_VTHINUSE 0xF23F ++#define F367_OFDM_VIT_INUSE 0xF23F00FF ++ ++/* KDIV12 */ ++#define R367_OFDM_KDIV12 0xF240 ++#define F367_OFDM_KDIV12_MANUAL 0xF2400080 ++#define F367_OFDM_K_DIVIDER_12 0xF240007F ++ ++/* KDIV23 */ ++#define R367_OFDM_KDIV23 0xF241 ++#define F367_OFDM_KDIV23_MANUAL 0xF2410080 ++#define F367_OFDM_K_DIVIDER_23 0xF241007F ++ ++/* KDIV34 */ ++#define R367_OFDM_KDIV34 0xF242 ++#define F367_OFDM_KDIV34_MANUAL 0xF2420080 ++#define F367_OFDM_K_DIVIDER_34 0xF242007F ++ ++/* KDIV56 */ ++#define R367_OFDM_KDIV56 0xF243 ++#define F367_OFDM_KDIV56_MANUAL 0xF2430080 ++#define F367_OFDM_K_DIVIDER_56 0xF243007F ++ ++/* KDIV67 */ ++#define R367_OFDM_KDIV67 0xF244 ++#define F367_OFDM_KDIV67_MANUAL 0xF2440080 ++#define F367_OFDM_K_DIVIDER_67 0xF244007F ++ ++/* KDIV78 */ ++#define R367_OFDM_KDIV78 0xF245 ++#define F367_OFDM_KDIV78_MANUAL 0xF2450080 ++#define F367_OFDM_K_DIVIDER_78 0xF245007F ++ ++/* SIGPOWER */ ++#define R367_OFDM_SIGPOWER 0xF246 ++#define F367_OFDM_SIGPOWER_MANUAL 0xF2460080 ++#define F367_OFDM_SIG_POWER 0xF246007F ++ ++/* DEMAPVIT */ ++#define R367_OFDM_DEMAPVIT 0xF247 ++#define F367_OFDM_DEMAPVIT_7 0xF2470080 ++#define F367_OFDM_K_DIVIDER_VIT 0xF247007F ++ ++/* VITSCALE */ ++#define R367_OFDM_VITSCALE 0xF248 ++#define F367_OFDM_NVTH_NOSRANGE 0xF2480080 ++#define F367_OFDM_VERROR_MAXMODE 0xF2480040 ++#define F367_OFDM_KDIV_MODE 0xF2480030 ++#define F367_OFDM_NSLOWSN_LOCKED 0xF2480008 ++#define F367_OFDM_DELOCK_PRFLOSS 0xF2480004 ++#define F367_OFDM_DIS_RSFLOCK 0xF2480002 ++#define F367_OFDM_VITSCALE_0 0xF2480001 ++ ++/* FFEC1PRG */ ++#define R367_OFDM_FFEC1PRG 0xF249 ++#define F367_OFDM_FDSS_DVB 0xF2490080 ++#define F367_OFDM_FDSS_SRCH 0xF2490040 ++#define F367_OFDM_FFECPROG_5 0xF2490020 ++#define F367_OFDM_FFECPROG_4 0xF2490010 ++#define F367_OFDM_FFECPROG_3 0xF2490008 ++#define F367_OFDM_FFECPROG_2 0xF2490004 ++#define F367_OFDM_FTS1_DISABLE 0xF2490002 ++#define F367_OFDM_FTS2_DISABLE 0xF2490001 ++ ++/* FVITCURPUN */ ++#define R367_OFDM_FVITCURPUN 0xF24A ++#define F367_OFDM_FVIT_MAPPING 0xF24A00E0 ++#define F367_OFDM_FVIT_CURPUN 0xF24A001F ++ ++/* FVERROR */ ++#define R367_OFDM_FVERROR 0xF24B ++#define F367_OFDM_FREGERR_VIT 0xF24B00FF ++ ++/* FVSTATUSVIT */ ++#define R367_OFDM_FVSTATUSVIT 0xF24C ++#define F367_OFDM_FVITERBI_ON 0xF24C0080 ++#define F367_OFDM_F1END_LOOPVIT 0xF24C0040 ++#define F367_OFDM_FVITERBI_DEPRF 0xF24C0020 ++#define F367_OFDM_FPRFVIT 0xF24C0010 ++#define F367_OFDM_FLOCKEDVIT 0xF24C0008 ++#define F367_OFDM_FVITERBI_DELOCK 0xF24C0004 ++#define F367_OFDM_FVIT_DEMODSEL 0xF24C0002 ++#define F367_OFDM_FVITERBI_COMPOUT 0xF24C0001 ++ ++/* DEBUG_LT1 */ ++#define R367_OFDM_DEBUG_LT1 0xF24D ++#define F367_OFDM_DBG_LT1 0xF24D00FF ++ ++/* DEBUG_LT2 */ ++#define R367_OFDM_DEBUG_LT2 0xF24E ++#define F367_OFDM_DBG_LT2 0xF24E00FF ++ ++/* DEBUG_LT3 */ ++#define R367_OFDM_DEBUG_LT3 0xF24F ++#define F367_OFDM_DBG_LT3 0xF24F00FF ++ ++ /* TSTSFMET */ ++#define R367_OFDM_TSTSFMET 0xF250 ++#define F367_OFDM_TSTSFEC_METRIQUES 0xF25000FF ++ ++ /* SELOUT */ ++#define R367_OFDM_SELOUT 0xF252 ++#define F367_OFDM_EN_SYNC 0xF2520080 ++#define F367_OFDM_EN_TBUSDEMAP 0xF2520040 ++#define F367_OFDM_SELOUT_5 0xF2520020 ++#define F367_OFDM_SELOUT_4 0xF2520010 ++#define F367_OFDM_TSTSYNCHRO_MODE 0xF2520002 ++ ++ /* TSYNC */ ++#define R367_OFDM_TSYNC 0xF253 ++#define F367_OFDM_CURPUN_INCMODE 0xF2530080 ++#define F367_OFDM_CERR_TSTMODE 0xF2530040 ++#define F367_OFDM_SHIFTSOF_MODE 0xF2530030 ++#define F367_OFDM_SLOWPHA_MODE 0xF2530008 ++#define F367_OFDM_PXX_BYPALL 0xF2530004 ++#define F367_OFDM_FROTA45_FIRST 0xF2530002 ++#define F367_OFDM_TST_BCHERROR 0xF2530001 ++ ++ /* TSTERR */ ++#define R367_OFDM_TSTERR 0xF254 ++#define F367_OFDM_TST_LONGPKT 0xF2540080 ++#define F367_OFDM_TST_ISSYION 0xF2540040 ++#define F367_OFDM_TST_NPDON 0xF2540020 ++#define F367_OFDM_TSTERR_4 0xF2540010 ++#define F367_OFDM_TRACEBACK_MODE 0xF2540008 ++#define F367_OFDM_TST_RSPARITY 0xF2540004 ++#define F367_OFDM_METRIQUE_MODE 0xF2540003 ++ ++ /* TSFSYNC */ ++#define R367_OFDM_TSFSYNC 0xF255 ++#define F367_OFDM_EN_SFECSYNC 0xF2550080 ++#define F367_OFDM_EN_SFECDEMAP 0xF2550040 ++#define F367_OFDM_SFCERR_TSTMODE 0xF2550020 ++#define F367_OFDM_SFECPXX_BYPALL 0xF2550010 ++#define F367_OFDM_SFECTSTSYNCHRO_MODE 0xF255000F ++ ++ /* TSTSFERR */ ++#define R367_OFDM_TSTSFERR 0xF256 ++#define F367_OFDM_TSTSTERR_7 0xF2560080 ++#define F367_OFDM_TSTSTERR_6 0xF2560040 ++#define F367_OFDM_TSTSTERR_5 0xF2560020 ++#define F367_OFDM_TSTSTERR_4 0xF2560010 ++#define F367_OFDM_SFECTRACEBACK_MODE 0xF2560008 ++#define F367_OFDM_SFEC_NCONVPROG 0xF2560004 ++#define F367_OFDM_SFECMETRIQUE_MODE 0xF2560003 ++ ++ /* TSTTSSF1 */ ++#define R367_OFDM_TSTTSSF1 0xF258 ++#define F367_OFDM_TSTERSSF 0xF2580080 ++#define F367_OFDM_TSTTSSFEN 0xF2580040 ++#define F367_OFDM_SFEC_OUTMODE 0xF2580030 ++#define F367_OFDM_XLSF_NOFTHRESHOLD 0xF2580008 ++#define F367_OFDM_TSTTSSF_STACKSEL 0xF2580007 ++ ++ /* TSTTSSF2 */ ++#define R367_OFDM_TSTTSSF2 0xF259 ++#define F367_OFDM_DILSF_DBBHEADER 0xF2590080 ++#define F367_OFDM_TSTTSSF_DISBUG 0xF2590040 ++#define F367_OFDM_TSTTSSF_NOBADSTART 0xF2590020 ++#define F367_OFDM_TSTTSSF_SELECT 0xF259001F ++ ++ /* TSTTSSF3 */ ++#define R367_OFDM_TSTTSSF3 0xF25A ++#define F367_OFDM_TSTTSSF3_7 0xF25A0080 ++#define F367_OFDM_TSTTSSF3_6 0xF25A0040 ++#define F367_OFDM_TSTTSSF3_5 0xF25A0020 ++#define F367_OFDM_TSTTSSF3_4 0xF25A0010 ++#define F367_OFDM_TSTTSSF3_3 0xF25A0008 ++#define F367_OFDM_TSTTSSF3_2 0xF25A0004 ++#define F367_OFDM_TSTTSSF3_1 0xF25A0002 ++#define F367_OFDM_DISSF_CLKENABLE 0xF25A0001 ++ ++ /* TSTTS1 */ ++#define R367_OFDM_TSTTS1 0xF25C ++#define F367_OFDM_TSTERS 0xF25C0080 ++#define F367_OFDM_TSFIFO_DSSSYNCB 0xF25C0040 ++#define F367_OFDM_TSTTS_FSPYBEFRS 0xF25C0020 ++#define F367_OFDM_NFORCE_SYNCBYTE 0xF25C0010 ++#define F367_OFDM_XL_NOFTHRESHOLD 0xF25C0008 ++#define F367_OFDM_TSTTS_FRFORCEPKT 0xF25C0004 ++#define F367_OFDM_DESCR_NOTAUTO 0xF25C0002 ++#define F367_OFDM_TSTTSEN 0xF25C0001 ++ ++ /* TSTTS2 */ ++#define R367_OFDM_TSTTS2 0xF25D ++#define F367_OFDM_DIL_DBBHEADER 0xF25D0080 ++#define F367_OFDM_TSTTS_NOBADXXX 0xF25D0040 ++#define F367_OFDM_TSFIFO_DELSPEEDUP 0xF25D0020 ++#define F367_OFDM_TSTTS_SELECT 0xF25D001F ++ ++ /* TSTTS3 */ ++#define R367_OFDM_TSTTS3 0xF25E ++#define F367_OFDM_TSTTS_NOPKTGAIN 0xF25E0080 ++#define F367_OFDM_TSTTS_NOPKTENE 0xF25E0040 ++#define F367_OFDM_TSTTS_ISOLATION 0xF25E0020 ++#define F367_OFDM_TSTTS_DISBUG 0xF25E0010 ++#define F367_OFDM_TSTTS_NOBADSTART 0xF25E0008 ++#define F367_OFDM_TSTTS_STACKSEL 0xF25E0007 ++ ++ /* TSTTS4 */ ++#define R367_OFDM_TSTTS4 0xF25F ++#define F367_OFDM_TSTTS4_7 0xF25F0080 ++#define F367_OFDM_TSTTS4_6 0xF25F0040 ++#define F367_OFDM_TSTTS4_5 0xF25F0020 ++#define F367_OFDM_TSTTS_DISDSTATE 0xF25F0010 ++#define F367_OFDM_TSTTS_FASTNOSYNC 0xF25F0008 ++#define F367_OFDM_EXT_FECSPYIN 0xF25F0004 ++#define F367_OFDM_TSTTS_NODPZERO 0xF25F0002 ++#define F367_OFDM_TSTTS_NODIV3 0xF25F0001 ++ ++ /* TSTTSRC */ ++#define R367_OFDM_TSTTSRC 0xF26C ++#define F367_OFDM_TSTTSRC_7 0xF26C0080 ++#define F367_OFDM_TSRCFIFO_DSSSYNCB 0xF26C0040 ++#define F367_OFDM_TSRCFIFO_DPUNACTIVE 0xF26C0020 ++#define F367_OFDM_TSRCFIFO_DELSPEEDUP 0xF26C0010 ++#define F367_OFDM_TSTTSRC_NODIV3 0xF26C0008 ++#define F367_OFDM_TSTTSRC_FRFORCEPKT 0xF26C0004 ++#define F367_OFDM_SAT25_SDDORIGINE 0xF26C0002 ++#define F367_OFDM_TSTTSRC_INACTIVE 0xF26C0001 ++ ++ /* TSTTSRS */ ++#define R367_OFDM_TSTTSRS 0xF26D ++#define F367_OFDM_TSTTSRS_7 0xF26D0080 ++#define F367_OFDM_TSTTSRS_6 0xF26D0040 ++#define F367_OFDM_TSTTSRS_5 0xF26D0020 ++#define F367_OFDM_TSTTSRS_4 0xF26D0010 ++#define F367_OFDM_TSTTSRS_3 0xF26D0008 ++#define F367_OFDM_TSTTSRS_2 0xF26D0004 ++#define F367_OFDM_TSTRS_DISRS2 0xF26D0002 ++#define F367_OFDM_TSTRS_DISRS1 0xF26D0001 ++ ++/* TSSTATEM */ ++#define R367_OFDM_TSSTATEM 0xF270 ++#define F367_OFDM_TSDIL_ON 0xF2700080 ++#define F367_OFDM_TSSKIPRS_ON 0xF2700040 ++#define F367_OFDM_TSRS_ON 0xF2700020 ++#define F367_OFDM_TSDESCRAMB_ON 0xF2700010 ++#define F367_OFDM_TSFRAME_MODE 0xF2700008 ++#define F367_OFDM_TS_DISABLE 0xF2700004 ++#define F367_OFDM_TSACM_MODE 0xF2700002 ++#define F367_OFDM_TSOUT_NOSYNC 0xF2700001 ++ ++/* TSSTATEL */ ++#define R367_OFDM_TSSTATEL 0xF271 ++#define F367_OFDM_TSNOSYNCBYTE 0xF2710080 ++#define F367_OFDM_TSPARITY_ON 0xF2710040 ++#define F367_OFDM_TSSYNCOUTRS_ON 0xF2710020 ++#define F367_OFDM_TSDVBS2_MODE 0xF2710010 ++#define F367_OFDM_TSISSYI_ON 0xF2710008 ++#define F367_OFDM_TSNPD_ON 0xF2710004 ++#define F367_OFDM_TSCRC8_ON 0xF2710002 ++#define F367_OFDM_TSDSS_PACKET 0xF2710001 ++ ++/* TSCFGH */ ++#define R367_OFDM_TSCFGH 0xF272 ++#define F367_OFDM_TSFIFO_DVBCI 0xF2720080 ++#define F367_OFDM_TSFIFO_SERIAL 0xF2720040 ++#define F367_OFDM_TSFIFO_TEIUPDATE 0xF2720020 ++#define F367_OFDM_TSFIFO_DUTY50 0xF2720010 ++#define F367_OFDM_TSFIFO_HSGNLOUT 0xF2720008 ++#define F367_OFDM_TSFIFO_ERRMODE 0xF2720006 ++#define F367_OFDM_RST_HWARE 0xF2720001 ++ ++/* TSCFGM */ ++#define R367_OFDM_TSCFGM 0xF273 ++#define F367_OFDM_TSFIFO_MANSPEED 0xF27300C0 ++#define F367_OFDM_TSFIFO_PERMDATA 0xF2730020 ++#define F367_OFDM_TSFIFO_NONEWSGNL 0xF2730010 ++#define F367_OFDM_TSFIFO_BITSPEED 0xF2730008 ++#define F367_OFDM_NPD_SPECDVBS2 0xF2730004 ++#define F367_OFDM_TSFIFO_STOPCKDIS 0xF2730002 ++#define F367_OFDM_TSFIFO_INVDATA 0xF2730001 ++ ++/* TSCFGL */ ++#define R367_OFDM_TSCFGL 0xF274 ++#define F367_OFDM_TSFIFO_BCLKDEL1CK 0xF27400C0 ++#define F367_OFDM_BCHERROR_MODE 0xF2740030 ++#define F367_OFDM_TSFIFO_NSGNL2DATA 0xF2740008 ++#define F367_OFDM_TSFIFO_EMBINDVB 0xF2740004 ++#define F367_OFDM_TSFIFO_DPUNACT 0xF2740002 ++#define F367_OFDM_TSFIFO_NPDOFF 0xF2740001 ++ ++/* TSSYNC */ ++#define R367_OFDM_TSSYNC 0xF275 ++#define F367_OFDM_TSFIFO_PERMUTE 0xF2750080 ++#define F367_OFDM_TSFIFO_FISCR3B 0xF2750060 ++#define F367_OFDM_TSFIFO_SYNCMODE 0xF2750018 ++#define F367_OFDM_TSFIFO_SYNCSEL 0xF2750007 ++ ++/* TSINSDELH */ ++#define R367_OFDM_TSINSDELH 0xF276 ++#define F367_OFDM_TSDEL_SYNCBYTE 0xF2760080 ++#define F367_OFDM_TSDEL_XXHEADER 0xF2760040 ++#define F367_OFDM_TSDEL_BBHEADER 0xF2760020 ++#define F367_OFDM_TSDEL_DATAFIELD 0xF2760010 ++#define F367_OFDM_TSINSDEL_ISCR 0xF2760008 ++#define F367_OFDM_TSINSDEL_NPD 0xF2760004 ++#define F367_OFDM_TSINSDEL_RSPARITY 0xF2760002 ++#define F367_OFDM_TSINSDEL_CRC8 0xF2760001 ++ ++/* TSINSDELM */ ++#define R367_OFDM_TSINSDELM 0xF277 ++#define F367_OFDM_TSINS_BBPADDING 0xF2770080 ++#define F367_OFDM_TSINS_BCHFEC 0xF2770040 ++#define F367_OFDM_TSINS_LDPCFEC 0xF2770020 ++#define F367_OFDM_TSINS_EMODCOD 0xF2770010 ++#define F367_OFDM_TSINS_TOKEN 0xF2770008 ++#define F367_OFDM_TSINS_XXXERR 0xF2770004 ++#define F367_OFDM_TSINS_MATYPE 0xF2770002 ++#define F367_OFDM_TSINS_UPL 0xF2770001 ++ ++/* TSINSDELL */ ++#define R367_OFDM_TSINSDELL 0xF278 ++#define F367_OFDM_TSINS_DFL 0xF2780080 ++#define F367_OFDM_TSINS_SYNCD 0xF2780040 ++#define F367_OFDM_TSINS_BLOCLEN 0xF2780020 ++#define F367_OFDM_TSINS_SIGPCOUNT 0xF2780010 ++#define F367_OFDM_TSINS_FIFO 0xF2780008 ++#define F367_OFDM_TSINS_REALPACK 0xF2780004 ++#define F367_OFDM_TSINS_TSCONFIG 0xF2780002 ++#define F367_OFDM_TSINS_LATENCY 0xF2780001 ++ ++/* TSDIVN */ ++#define R367_OFDM_TSDIVN 0xF279 ++#define F367_OFDM_TSFIFO_LOWSPEED 0xF2790080 ++#define F367_OFDM_BYTE_OVERSAMPLING 0xF2790070 ++#define F367_OFDM_TSMANUAL_PACKETNBR 0xF279000F ++ ++/* TSDIVPM */ ++#define R367_OFDM_TSDIVPM 0xF27A ++#define F367_OFDM_TSMANUAL_P_HI 0xF27A00FF ++ ++/* TSDIVPL */ ++#define R367_OFDM_TSDIVPL 0xF27B ++#define F367_OFDM_TSMANUAL_P_LO 0xF27B00FF ++ ++/* TSDIVQM */ ++#define R367_OFDM_TSDIVQM 0xF27C ++#define F367_OFDM_TSMANUAL_Q_HI 0xF27C00FF ++ ++/* TSDIVQL */ ++#define R367_OFDM_TSDIVQL 0xF27D ++#define F367_OFDM_TSMANUAL_Q_LO 0xF27D00FF ++ ++/* TSDILSTKM */ ++#define R367_OFDM_TSDILSTKM 0xF27E ++#define F367_OFDM_TSFIFO_DILSTK_HI 0xF27E00FF ++ ++/* TSDILSTKL */ ++#define R367_OFDM_TSDILSTKL 0xF27F ++#define F367_OFDM_TSFIFO_DILSTK_LO 0xF27F00FF ++ ++/* TSSPEED */ ++#define R367_OFDM_TSSPEED 0xF280 ++#define F367_OFDM_TSFIFO_OUTSPEED 0xF28000FF ++ ++/* TSSTATUS */ ++#define R367_OFDM_TSSTATUS 0xF281 ++#define F367_OFDM_TSFIFO_LINEOK 0xF2810080 ++#define F367_OFDM_TSFIFO_ERROR 0xF2810040 ++#define F367_OFDM_TSFIFO_DATA7 0xF2810020 ++#define F367_OFDM_TSFIFO_NOSYNC 0xF2810010 ++#define F367_OFDM_ISCR_INITIALIZED 0xF2810008 ++#define F367_OFDM_ISCR_UPDATED 0xF2810004 ++#define F367_OFDM_SOFFIFO_UNREGUL 0xF2810002 ++#define F367_OFDM_DIL_READY 0xF2810001 ++ ++/* TSSTATUS2 */ ++#define R367_OFDM_TSSTATUS2 0xF282 ++#define F367_OFDM_TSFIFO_DEMODSEL 0xF2820080 ++#define F367_OFDM_TSFIFOSPEED_STORE 0xF2820040 ++#define F367_OFDM_DILXX_RESET 0xF2820020 ++#define F367_OFDM_TSSERIAL_IMPOSSIBLE 0xF2820010 ++#define F367_OFDM_TSFIFO_UNDERSPEED 0xF2820008 ++#define F367_OFDM_BITSPEED_EVENT 0xF2820004 ++#define F367_OFDM_UL_SCRAMBDETECT 0xF2820002 ++#define F367_OFDM_ULDTV67_FALSELOCK 0xF2820001 ++ ++/* TSBITRATEM */ ++#define R367_OFDM_TSBITRATEM 0xF283 ++#define F367_OFDM_TSFIFO_BITRATE_HI 0xF28300FF ++ ++/* TSBITRATEL */ ++#define R367_OFDM_TSBITRATEL 0xF284 ++#define F367_OFDM_TSFIFO_BITRATE_LO 0xF28400FF ++ ++/* TSPACKLENM */ ++#define R367_OFDM_TSPACKLENM 0xF285 ++#define F367_OFDM_TSFIFO_PACKCPT 0xF28500E0 ++#define F367_OFDM_DIL_RPLEN_HI 0xF285001F ++ ++/* TSPACKLENL */ ++#define R367_OFDM_TSPACKLENL 0xF286 ++#define F367_OFDM_DIL_RPLEN_LO 0xF28600FF ++ ++/* TSBLOCLENM */ ++#define R367_OFDM_TSBLOCLENM 0xF287 ++#define F367_OFDM_TSFIFO_PFLEN_HI 0xF28700FF ++ ++/* TSBLOCLENL */ ++#define R367_OFDM_TSBLOCLENL 0xF288 ++#define F367_OFDM_TSFIFO_PFLEN_LO 0xF28800FF ++ ++/* TSDLYH */ ++#define R367_OFDM_TSDLYH 0xF289 ++#define F367_OFDM_SOFFIFO_TSTIMEVALID 0xF2890080 ++#define F367_OFDM_SOFFIFO_SPEEDUP 0xF2890040 ++#define F367_OFDM_SOFFIFO_STOP 0xF2890020 ++#define F367_OFDM_SOFFIFO_REGULATED 0xF2890010 ++#define F367_OFDM_SOFFIFO_REALSBOFF_HI 0xF289000F ++ ++/* TSDLYM */ ++#define R367_OFDM_TSDLYM 0xF28A ++#define F367_OFDM_SOFFIFO_REALSBOFF_MED 0xF28A00FF ++ ++/* TSDLYL */ ++#define R367_OFDM_TSDLYL 0xF28B ++#define F367_OFDM_SOFFIFO_REALSBOFF_LO 0xF28B00FF ++ ++/* TSNPDAV */ ++#define R367_OFDM_TSNPDAV 0xF28C ++#define F367_OFDM_TSNPD_AVERAGE 0xF28C00FF ++ ++/* TSBUFSTATH */ ++#define R367_OFDM_TSBUFSTATH 0xF28D ++#define F367_OFDM_TSISCR_3BYTES 0xF28D0080 ++#define F367_OFDM_TSISCR_NEWDATA 0xF28D0040 ++#define F367_OFDM_TSISCR_BUFSTAT_HI 0xF28D003F ++ ++/* TSBUFSTATM */ ++#define R367_OFDM_TSBUFSTATM 0xF28E ++#define F367_OFDM_TSISCR_BUFSTAT_MED 0xF28E00FF ++ ++/* TSBUFSTATL */ ++#define R367_OFDM_TSBUFSTATL 0xF28F ++#define F367_OFDM_TSISCR_BUFSTAT_LO 0xF28F00FF ++ ++/* TSDEBUGM */ ++#define R367_OFDM_TSDEBUGM 0xF290 ++#define F367_OFDM_TSFIFO_ILLPACKET 0xF2900080 ++#define F367_OFDM_DIL_NOSYNC 0xF2900040 ++#define F367_OFDM_DIL_ISCR 0xF2900020 ++#define F367_OFDM_DILOUT_BSYNCB 0xF2900010 ++#define F367_OFDM_TSFIFO_EMPTYPKT 0xF2900008 ++#define F367_OFDM_TSFIFO_EMPTYRD 0xF2900004 ++#define F367_OFDM_SOFFIFO_STOPM 0xF2900002 ++#define F367_OFDM_SOFFIFO_SPEEDUPM 0xF2900001 ++ ++/* TSDEBUGL */ ++#define R367_OFDM_TSDEBUGL 0xF291 ++#define F367_OFDM_TSFIFO_PACKLENFAIL 0xF2910080 ++#define F367_OFDM_TSFIFO_SYNCBFAIL 0xF2910040 ++#define F367_OFDM_TSFIFO_VITLIBRE 0xF2910020 ++#define F367_OFDM_TSFIFO_BOOSTSPEEDM 0xF2910010 ++#define F367_OFDM_TSFIFO_UNDERSPEEDM 0xF2910008 ++#define F367_OFDM_TSFIFO_ERROR_EVNT 0xF2910004 ++#define F367_OFDM_TSFIFO_FULL 0xF2910002 ++#define F367_OFDM_TSFIFO_OVERFLOWM 0xF2910001 ++ ++/* TSDLYSETH */ ++#define R367_OFDM_TSDLYSETH 0xF292 ++#define F367_OFDM_SOFFIFO_OFFSET 0xF29200E0 ++#define F367_OFDM_SOFFIFO_SYMBOFFSET_HI 0xF292001F ++ ++/* TSDLYSETM */ ++#define R367_OFDM_TSDLYSETM 0xF293 ++#define F367_OFDM_SOFFIFO_SYMBOFFSET_MED 0xF29300FF ++ ++/* TSDLYSETL */ ++#define R367_OFDM_TSDLYSETL 0xF294 ++#define F367_OFDM_SOFFIFO_SYMBOFFSET_LO 0xF29400FF ++ ++/* TSOBSCFG */ ++#define R367_OFDM_TSOBSCFG 0xF295 ++#define F367_OFDM_TSFIFO_OBSCFG 0xF29500FF ++ ++/* TSOBSM */ ++#define R367_OFDM_TSOBSM 0xF296 ++#define F367_OFDM_TSFIFO_OBSDATA_HI 0xF29600FF ++ ++/* TSOBSL */ ++#define R367_OFDM_TSOBSL 0xF297 ++#define F367_OFDM_TSFIFO_OBSDATA_LO 0xF29700FF ++ ++/* ERRCTRL1 */ ++#define R367_OFDM_ERRCTRL1 0xF298 ++#define F367_OFDM_ERR_SRC1 0xF29800F0 ++#define F367_OFDM_ERRCTRL1_3 0xF2980008 ++#define F367_OFDM_NUM_EVT1 0xF2980007 ++ ++/* ERRCNT1H */ ++#define R367_OFDM_ERRCNT1H 0xF299 ++#define F367_OFDM_ERRCNT1_OLDVALUE 0xF2990080 ++#define F367_OFDM_ERR_CNT1 0xF299007F ++ ++/* ERRCNT1M */ ++#define R367_OFDM_ERRCNT1M 0xF29A ++#define F367_OFDM_ERR_CNT1_HI 0xF29A00FF ++ ++/* ERRCNT1L */ ++#define R367_OFDM_ERRCNT1L 0xF29B ++#define F367_OFDM_ERR_CNT1_LO 0xF29B00FF ++ ++/* ERRCTRL2 */ ++#define R367_OFDM_ERRCTRL2 0xF29C ++#define F367_OFDM_ERR_SRC2 0xF29C00F0 ++#define F367_OFDM_ERRCTRL2_3 0xF29C0008 ++#define F367_OFDM_NUM_EVT2 0xF29C0007 ++ ++/* ERRCNT2H */ ++#define R367_OFDM_ERRCNT2H 0xF29D ++#define F367_OFDM_ERRCNT2_OLDVALUE 0xF29D0080 ++#define F367_OFDM_ERR_CNT2_HI 0xF29D007F ++ ++/* ERRCNT2M */ ++#define R367_OFDM_ERRCNT2M 0xF29E ++#define F367_OFDM_ERR_CNT2_MED 0xF29E00FF ++ ++/* ERRCNT2L */ ++#define R367_OFDM_ERRCNT2L 0xF29F ++#define F367_OFDM_ERR_CNT2_LO 0xF29F00FF ++ ++/* FECSPY */ ++#define R367_OFDM_FECSPY 0xF2A0 ++#define F367_OFDM_SPY_ENABLE 0xF2A00080 ++#define F367_OFDM_NO_SYNCBYTE 0xF2A00040 ++#define F367_OFDM_SERIAL_MODE 0xF2A00020 ++#define F367_OFDM_UNUSUAL_PACKET 0xF2A00010 ++#define F367_OFDM_BERMETER_DATAMODE 0xF2A0000C ++#define F367_OFDM_BERMETER_LMODE 0xF2A00002 ++#define F367_OFDM_BERMETER_RESET 0xF2A00001 ++ ++/* FSPYCFG */ ++#define R367_OFDM_FSPYCFG 0xF2A1 ++#define F367_OFDM_FECSPY_INPUT 0xF2A100C0 ++#define F367_OFDM_RST_ON_ERROR 0xF2A10020 ++#define F367_OFDM_ONE_SHOT 0xF2A10010 ++#define F367_OFDM_I2C_MOD 0xF2A1000C ++#define F367_OFDM_SPY_HYSTERESIS 0xF2A10003 ++ ++/* FSPYDATA */ ++#define R367_OFDM_FSPYDATA 0xF2A2 ++#define F367_OFDM_SPY_STUFFING 0xF2A20080 ++#define F367_OFDM_NOERROR_PKTJITTER 0xF2A20040 ++#define F367_OFDM_SPY_CNULLPKT 0xF2A20020 ++#define F367_OFDM_SPY_OUTDATA_MODE 0xF2A2001F ++ ++/* FSPYOUT */ ++#define R367_OFDM_FSPYOUT 0xF2A3 ++#define F367_OFDM_FSPY_DIRECT 0xF2A30080 ++#define F367_OFDM_FSPYOUT_6 0xF2A30040 ++#define F367_OFDM_SPY_OUTDATA_BUS 0xF2A30038 ++#define F367_OFDM_STUFF_MODE 0xF2A30007 ++ ++/* FSTATUS */ ++#define R367_OFDM_FSTATUS 0xF2A4 ++#define F367_OFDM_SPY_ENDSIM 0xF2A40080 ++#define F367_OFDM_VALID_SIM 0xF2A40040 ++#define F367_OFDM_FOUND_SIGNAL 0xF2A40020 ++#define F367_OFDM_DSS_SYNCBYTE 0xF2A40010 ++#define F367_OFDM_RESULT_STATE 0xF2A4000F ++ ++/* FGOODPACK */ ++#define R367_OFDM_FGOODPACK 0xF2A5 ++#define F367_OFDM_FGOOD_PACKET 0xF2A500FF ++ ++/* FPACKCNT */ ++#define R367_OFDM_FPACKCNT 0xF2A6 ++#define F367_OFDM_FPACKET_COUNTER 0xF2A600FF ++ ++/* FSPYMISC */ ++#define R367_OFDM_FSPYMISC 0xF2A7 ++#define F367_OFDM_FLABEL_COUNTER 0xF2A700FF ++ ++/* FBERCPT4 */ ++#define R367_OFDM_FBERCPT4 0xF2A8 ++#define F367_OFDM_FBERMETER_CPT5 0xF2A800FF ++ ++/* FBERCPT3 */ ++#define R367_OFDM_FBERCPT3 0xF2A9 ++#define F367_OFDM_FBERMETER_CPT4 0xF2A900FF ++ ++/* FBERCPT2 */ ++#define R367_OFDM_FBERCPT2 0xF2AA ++#define F367_OFDM_FBERMETER_CPT3 0xF2AA00FF ++ ++/* FBERCPT1 */ ++#define R367_OFDM_FBERCPT1 0xF2AB ++#define F367_OFDM_FBERMETER_CPT2 0xF2AB00FF ++ ++/* FBERCPT0 */ ++#define R367_OFDM_FBERCPT0 0xF2AC ++#define F367_OFDM_FBERMETER_CPT1 0xF2AC00FF ++ ++/* FBERERR2 */ ++#define R367_OFDM_FBERERR2 0xF2AD ++#define F367_OFDM_FBERMETER_ERR_HI 0xF2AD00FF ++ ++/* FBERERR1 */ ++#define R367_OFDM_FBERERR1 0xF2AE ++#define F367_OFDM_FBERMETER_ERR_MED 0xF2AE00FF ++ ++/* FBERERR0 */ ++#define R367_OFDM_FBERERR0 0xF2AF ++#define F367_OFDM_FBERMETER_ERR_LO 0xF2AF00FF ++ ++/* FSTATESM */ ++#define R367_OFDM_FSTATESM 0xF2B0 ++#define F367_OFDM_RSTATE_F 0xF2B00080 ++#define F367_OFDM_RSTATE_E 0xF2B00040 ++#define F367_OFDM_RSTATE_D 0xF2B00020 ++#define F367_OFDM_RSTATE_C 0xF2B00010 ++#define F367_OFDM_RSTATE_B 0xF2B00008 ++#define F367_OFDM_RSTATE_A 0xF2B00004 ++#define F367_OFDM_RSTATE_9 0xF2B00002 ++#define F367_OFDM_RSTATE_8 0xF2B00001 ++ ++/* FSTATESL */ ++#define R367_OFDM_FSTATESL 0xF2B1 ++#define F367_OFDM_RSTATE_7 0xF2B10080 ++#define F367_OFDM_RSTATE_6 0xF2B10040 ++#define F367_OFDM_RSTATE_5 0xF2B10020 ++#define F367_OFDM_RSTATE_4 0xF2B10010 ++#define F367_OFDM_RSTATE_3 0xF2B10008 ++#define F367_OFDM_RSTATE_2 0xF2B10004 ++#define F367_OFDM_RSTATE_1 0xF2B10002 ++#define F367_OFDM_RSTATE_0 0xF2B10001 ++ ++/* FSPYBER */ ++#define R367_OFDM_FSPYBER 0xF2B2 ++#define F367_OFDM_FSPYBER_7 0xF2B20080 ++#define F367_OFDM_FSPYOBS_XORREAD 0xF2B20040 ++#define F367_OFDM_FSPYBER_OBSMODE 0xF2B20020 ++#define F367_OFDM_FSPYBER_SYNCBYTE 0xF2B20010 ++#define F367_OFDM_FSPYBER_UNSYNC 0xF2B20008 ++#define F367_OFDM_FSPYBER_CTIME 0xF2B20007 ++ ++/* FSPYDISTM */ ++#define R367_OFDM_FSPYDISTM 0xF2B3 ++#define F367_OFDM_PKTTIME_DISTANCE_HI 0xF2B300FF ++ ++/* FSPYDISTL */ ++#define R367_OFDM_FSPYDISTL 0xF2B4 ++#define F367_OFDM_PKTTIME_DISTANCE_LO 0xF2B400FF ++ ++/* FSPYOBS7 */ ++#define R367_OFDM_FSPYOBS7 0xF2B8 ++#define F367_OFDM_FSPYOBS_SPYFAIL 0xF2B80080 ++#define F367_OFDM_FSPYOBS_SPYFAIL1 0xF2B80040 ++#define F367_OFDM_FSPYOBS_ERROR 0xF2B80020 ++#define F367_OFDM_FSPYOBS_STROUT 0xF2B80010 ++#define F367_OFDM_FSPYOBS_RESULTSTATE1 0xF2B8000F ++ ++/* FSPYOBS6 */ ++#define R367_OFDM_FSPYOBS6 0xF2B9 ++#define F367_OFDM_FSPYOBS_RESULTSTATE0 0xF2B900F0 ++#define F367_OFDM_FSPYOBS_RESULTSTATEM1 0xF2B9000F ++ ++/* FSPYOBS5 */ ++#define R367_OFDM_FSPYOBS5 0xF2BA ++#define F367_OFDM_FSPYOBS_BYTEOFPACKET1 0xF2BA00FF ++ ++/* FSPYOBS4 */ ++#define R367_OFDM_FSPYOBS4 0xF2BB ++#define F367_OFDM_FSPYOBS_BYTEVALUE1 0xF2BB00FF ++ ++/* FSPYOBS3 */ ++#define R367_OFDM_FSPYOBS3 0xF2BC ++#define F367_OFDM_FSPYOBS_DATA1 0xF2BC00FF ++ ++/* FSPYOBS2 */ ++#define R367_OFDM_FSPYOBS2 0xF2BD ++#define F367_OFDM_FSPYOBS_DATA0 0xF2BD00FF ++ ++/* FSPYOBS1 */ ++#define R367_OFDM_FSPYOBS1 0xF2BE ++#define F367_OFDM_FSPYOBS_DATAM1 0xF2BE00FF ++ ++/* FSPYOBS0 */ ++#define R367_OFDM_FSPYOBS0 0xF2BF ++#define F367_OFDM_FSPYOBS_DATAM2 0xF2BF00FF ++ ++/* SFDEMAP */ ++#define R367_OFDM_SFDEMAP 0xF2C0 ++#define F367_OFDM_SFDEMAP_7 0xF2C00080 ++#define F367_OFDM_SFEC_K_DIVIDER_VIT 0xF2C0007F ++ ++/* SFERROR */ ++#define R367_OFDM_SFERROR 0xF2C1 ++#define F367_OFDM_SFEC_REGERR_VIT 0xF2C100FF ++ ++/* SFAVSR */ ++#define R367_OFDM_SFAVSR 0xF2C2 ++#define F367_OFDM_SFEC_SUMERRORS 0xF2C20080 ++#define F367_OFDM_SERROR_MAXMODE 0xF2C20040 ++#define F367_OFDM_SN_SFEC 0xF2C20030 ++#define F367_OFDM_KDIV_MODE_SFEC 0xF2C2000C ++#define F367_OFDM_SFAVSR_1 0xF2C20002 ++#define F367_OFDM_SFAVSR_0 0xF2C20001 ++ ++/* SFECSTATUS */ ++#define R367_OFDM_SFECSTATUS 0xF2C3 ++#define F367_OFDM_SFEC_ON 0xF2C30080 ++#define F367_OFDM_SFSTATUS_6 0xF2C30040 ++#define F367_OFDM_SFSTATUS_5 0xF2C30020 ++#define F367_OFDM_SFSTATUS_4 0xF2C30010 ++#define F367_OFDM_LOCKEDSFEC 0xF2C30008 ++#define F367_OFDM_SFEC_DELOCK 0xF2C30004 ++#define F367_OFDM_SFEC_DEMODSEL1 0xF2C30002 ++#define F367_OFDM_SFEC_OVFON 0xF2C30001 ++ ++/* SFKDIV12 */ ++#define R367_OFDM_SFKDIV12 0xF2C4 ++#define F367_OFDM_SFECKDIV12_MAN 0xF2C40080 ++#define F367_OFDM_SFEC_K_DIVIDER_12 0xF2C4007F ++ ++/* SFKDIV23 */ ++#define R367_OFDM_SFKDIV23 0xF2C5 ++#define F367_OFDM_SFECKDIV23_MAN 0xF2C50080 ++#define F367_OFDM_SFEC_K_DIVIDER_23 0xF2C5007F ++ ++/* SFKDIV34 */ ++#define R367_OFDM_SFKDIV34 0xF2C6 ++#define F367_OFDM_SFECKDIV34_MAN 0xF2C60080 ++#define F367_OFDM_SFEC_K_DIVIDER_34 0xF2C6007F ++ ++/* SFKDIV56 */ ++#define R367_OFDM_SFKDIV56 0xF2C7 ++#define F367_OFDM_SFECKDIV56_MAN 0xF2C70080 ++#define F367_OFDM_SFEC_K_DIVIDER_56 0xF2C7007F ++ ++/* SFKDIV67 */ ++#define R367_OFDM_SFKDIV67 0xF2C8 ++#define F367_OFDM_SFECKDIV67_MAN 0xF2C80080 ++#define F367_OFDM_SFEC_K_DIVIDER_67 0xF2C8007F ++ ++/* SFKDIV78 */ ++#define R367_OFDM_SFKDIV78 0xF2C9 ++#define F367_OFDM_SFECKDIV78_MAN 0xF2C90080 ++#define F367_OFDM_SFEC_K_DIVIDER_78 0xF2C9007F ++ ++/* SFDILSTKM */ ++#define R367_OFDM_SFDILSTKM 0xF2CA ++#define F367_OFDM_SFEC_PACKCPT 0xF2CA00E0 ++#define F367_OFDM_SFEC_DILSTK_HI 0xF2CA001F ++ ++/* SFDILSTKL */ ++#define R367_OFDM_SFDILSTKL 0xF2CB ++#define F367_OFDM_SFEC_DILSTK_LO 0xF2CB00FF ++ ++/* SFSTATUS */ ++#define R367_OFDM_SFSTATUS 0xF2CC ++#define F367_OFDM_SFEC_LINEOK 0xF2CC0080 ++#define F367_OFDM_SFEC_ERROR 0xF2CC0040 ++#define F367_OFDM_SFEC_DATA7 0xF2CC0020 ++#define F367_OFDM_SFEC_OVERFLOW 0xF2CC0010 ++#define F367_OFDM_SFEC_DEMODSEL2 0xF2CC0008 ++#define F367_OFDM_SFEC_NOSYNC 0xF2CC0004 ++#define F367_OFDM_SFEC_UNREGULA 0xF2CC0002 ++#define F367_OFDM_SFEC_READY 0xF2CC0001 ++ ++/* SFDLYH */ ++#define R367_OFDM_SFDLYH 0xF2CD ++#define F367_OFDM_SFEC_TSTIMEVALID 0xF2CD0080 ++#define F367_OFDM_SFEC_SPEEDUP 0xF2CD0040 ++#define F367_OFDM_SFEC_STOP 0xF2CD0020 ++#define F367_OFDM_SFEC_REGULATED 0xF2CD0010 ++#define F367_OFDM_SFEC_REALSYMBOFFSET 0xF2CD000F ++ ++/* SFDLYM */ ++#define R367_OFDM_SFDLYM 0xF2CE ++#define F367_OFDM_SFEC_REALSYMBOFFSET_HI 0xF2CE00FF ++ ++/* SFDLYL */ ++#define R367_OFDM_SFDLYL 0xF2CF ++#define F367_OFDM_SFEC_REALSYMBOFFSET_LO 0xF2CF00FF ++ ++/* SFDLYSETH */ ++#define R367_OFDM_SFDLYSETH 0xF2D0 ++#define F367_OFDM_SFEC_OFFSET 0xF2D000E0 ++#define F367_OFDM_SFECDLYSETH_4 0xF2D00010 ++#define F367_OFDM_RST_SFEC 0xF2D00008 ++#define F367_OFDM_SFECDLYSETH_2 0xF2D00004 ++#define F367_OFDM_SFEC_DISABLE 0xF2D00002 ++#define F367_OFDM_SFEC_UNREGUL 0xF2D00001 ++ ++/* SFDLYSETM */ ++#define R367_OFDM_SFDLYSETM 0xF2D1 ++#define F367_OFDM_SFECDLYSETM_7 0xF2D10080 ++#define F367_OFDM_SFEC_SYMBOFFSET_HI 0xF2D1007F ++ ++/* SFDLYSETL */ ++#define R367_OFDM_SFDLYSETL 0xF2D2 ++#define F367_OFDM_SFEC_SYMBOFFSET_LO 0xF2D200FF ++ ++/* SFOBSCFG */ ++#define R367_OFDM_SFOBSCFG 0xF2D3 ++#define F367_OFDM_SFEC_OBSCFG 0xF2D300FF ++ ++/* SFOBSM */ ++#define R367_OFDM_SFOBSM 0xF2D4 ++#define F367_OFDM_SFEC_OBSDATA_HI 0xF2D400FF ++ ++/* SFOBSL */ ++#define R367_OFDM_SFOBSL 0xF2D5 ++#define F367_OFDM_SFEC_OBSDATA_LO 0xF2D500FF ++ ++/* SFECINFO */ ++#define R367_OFDM_SFECINFO 0xF2D6 ++#define F367_OFDM_SFECINFO_7 0xF2D60080 ++#define F367_OFDM_SFEC_SYNCDLSB 0xF2D60070 ++#define F367_OFDM_SFCE_S1CPHASE 0xF2D6000F ++ ++/* SFERRCTRL */ ++#define R367_OFDM_SFERRCTRL 0xF2D8 ++#define F367_OFDM_SFEC_ERR_SOURCE 0xF2D800F0 ++#define F367_OFDM_SFERRCTRL_3 0xF2D80008 ++#define F367_OFDM_SFEC_NUM_EVENT 0xF2D80007 ++ ++/* SFERRCNTH */ ++#define R367_OFDM_SFERRCNTH 0xF2D9 ++#define F367_OFDM_SFERRC_OLDVALUE 0xF2D90080 ++#define F367_OFDM_SFEC_ERR_CNT 0xF2D9007F ++ ++/* SFERRCNTM */ ++#define R367_OFDM_SFERRCNTM 0xF2DA ++#define F367_OFDM_SFEC_ERR_CNT_HI 0xF2DA00FF ++ ++/* SFERRCNTL */ ++#define R367_OFDM_SFERRCNTL 0xF2DB ++#define F367_OFDM_SFEC_ERR_CNT_LO 0xF2DB00FF ++ ++/* SYMBRATEM */ ++#define R367_OFDM_SYMBRATEM 0xF2E0 ++#define F367_OFDM_DEFGEN_SYMBRATE_HI 0xF2E000FF ++ ++/* SYMBRATEL */ ++#define R367_OFDM_SYMBRATEL 0xF2E1 ++#define F367_OFDM_DEFGEN_SYMBRATE_LO 0xF2E100FF ++ ++/* SYMBSTATUS */ ++#define R367_OFDM_SYMBSTATUS 0xF2E2 ++#define F367_OFDM_SYMBDLINE2_OFF 0xF2E20080 ++#define F367_OFDM_SDDL_REINIT1 0xF2E20040 ++#define F367_OFDM_SDD_REINIT1 0xF2E20020 ++#define F367_OFDM_TOKENID_ERROR 0xF2E20010 ++#define F367_OFDM_SYMBRATE_OVERFLOW 0xF2E20008 ++#define F367_OFDM_SYMBRATE_UNDERFLOW 0xF2E20004 ++#define F367_OFDM_TOKENID_RSTEVENT 0xF2E20002 ++#define F367_OFDM_TOKENID_RESET1 0xF2E20001 ++ ++/* SYMBCFG */ ++#define R367_OFDM_SYMBCFG 0xF2E3 ++#define F367_OFDM_SYMBCFG_7 0xF2E30080 ++#define F367_OFDM_SYMBCFG_6 0xF2E30040 ++#define F367_OFDM_SYMBCFG_5 0xF2E30020 ++#define F367_OFDM_SYMBCFG_4 0xF2E30010 ++#define F367_OFDM_SYMRATE_FSPEED 0xF2E3000C ++#define F367_OFDM_SYMRATE_SSPEED 0xF2E30003 ++ ++/* SYMBFIFOM */ ++#define R367_OFDM_SYMBFIFOM 0xF2E4 ++#define F367_OFDM_SYMBFIFOM_7 0xF2E40080 ++#define F367_OFDM_SYMBFIFOM_6 0xF2E40040 ++#define F367_OFDM_DEFGEN_SYMFIFO_HI 0xF2E4003F ++ ++/* SYMBFIFOL */ ++#define R367_OFDM_SYMBFIFOL 0xF2E5 ++#define F367_OFDM_DEFGEN_SYMFIFO_LO 0xF2E500FF ++ ++/* SYMBOFFSM */ ++#define R367_OFDM_SYMBOFFSM 0xF2E6 ++#define F367_OFDM_TOKENID_RESET2 0xF2E60080 ++#define F367_OFDM_SDDL_REINIT2 0xF2E60040 ++#define F367_OFDM_SDD_REINIT2 0xF2E60020 ++#define F367_OFDM_SYMBOFFSM_4 0xF2E60010 ++#define F367_OFDM_SYMBOFFSM_3 0xF2E60008 ++#define F367_OFDM_DEFGEN_SYMBOFFSET_HI 0xF2E60007 ++ ++/* SYMBOFFSL */ ++#define R367_OFDM_SYMBOFFSL 0xF2E7 ++#define F367_OFDM_DEFGEN_SYMBOFFSET_LO 0xF2E700FF ++ ++/* DEBUG_LT4 */ ++#define R367_DEBUG_LT4 0xF400 ++#define F367_F_DEBUG_LT4 0xF40000FF ++ ++/* DEBUG_LT5 */ ++#define R367_DEBUG_LT5 0xF401 ++#define F367_F_DEBUG_LT5 0xF40100FF ++ ++/* DEBUG_LT6 */ ++#define R367_DEBUG_LT6 0xF402 ++#define F367_F_DEBUG_LT6 0xF40200FF ++ ++/* DEBUG_LT7 */ ++#define R367_DEBUG_LT7 0xF403 ++#define F367_F_DEBUG_LT7 0xF40300FF ++ ++/* DEBUG_LT8 */ ++#define R367_DEBUG_LT8 0xF404 ++#define F367_F_DEBUG_LT8 0xF40400FF ++ ++/* DEBUG_LT9 */ ++#define R367_DEBUG_LT9 0xF405 ++#define F367_F_DEBUG_LT9 0xF40500FF ++ ++/* CTRL_1 */ ++#define R367_QAM_CTRL_1 0xF402 ++#define F367_QAM_SOFT_RST 0xF4020080 ++#define F367_QAM_EQU_RST 0xF4020008 ++#define F367_QAM_CRL_RST 0xF4020004 ++#define F367_QAM_TRL_RST 0xF4020002 ++#define F367_QAM_AGC_RST 0xF4020001 ++ ++/* CTRL_2 */ ++#define R367_QAM_CTRL_2 0xF403 ++#define F367_QAM_DEINT_RST 0xF4030008 ++#define F367_QAM_RS_RST 0xF4030004 ++ ++/* IT_STATUS1 */ ++#define R367_QAM_IT_STATUS1 0xF408 ++#define F367_QAM_SWEEP_OUT 0xF4080080 ++#define F367_QAM_FSM_CRL 0xF4080040 ++#define F367_QAM_CRL_LOCK 0xF4080020 ++#define F367_QAM_MFSM 0xF4080010 ++#define F367_QAM_TRL_LOCK 0xF4080008 ++#define F367_QAM_TRL_AGC_LIMIT 0xF4080004 ++#define F367_QAM_ADJ_AGC_LOCK 0xF4080002 ++#define F367_QAM_AGC_QAM_LOCK 0xF4080001 ++ ++/* IT_STATUS2 */ ++#define R367_QAM_IT_STATUS2 0xF409 ++#define F367_QAM_TSMF_CNT 0xF4090080 ++#define F367_QAM_TSMF_EOF 0xF4090040 ++#define F367_QAM_TSMF_RDY 0xF4090020 ++#define F367_QAM_FEC_NOCORR 0xF4090010 ++#define F367_QAM_SYNCSTATE 0xF4090008 ++#define F367_QAM_DEINT_LOCK 0xF4090004 ++#define F367_QAM_FADDING_FRZ 0xF4090002 ++#define F367_QAM_TAPMON_ALARM 0xF4090001 ++ ++/* IT_EN1 */ ++#define R367_QAM_IT_EN1 0xF40A ++#define F367_QAM_SWEEP_OUTE 0xF40A0080 ++#define F367_QAM_FSM_CRLE 0xF40A0040 ++#define F367_QAM_CRL_LOCKE 0xF40A0020 ++#define F367_QAM_MFSME 0xF40A0010 ++#define F367_QAM_TRL_LOCKE 0xF40A0008 ++#define F367_QAM_TRL_AGC_LIMITE 0xF40A0004 ++#define F367_QAM_ADJ_AGC_LOCKE 0xF40A0002 ++#define F367_QAM_AGC_LOCKE 0xF40A0001 ++ ++/* IT_EN2 */ ++#define R367_QAM_IT_EN2 0xF40B ++#define F367_QAM_TSMF_CNTE 0xF40B0080 ++#define F367_QAM_TSMF_EOFE 0xF40B0040 ++#define F367_QAM_TSMF_RDYE 0xF40B0020 ++#define F367_QAM_FEC_NOCORRE 0xF40B0010 ++#define F367_QAM_SYNCSTATEE 0xF40B0008 ++#define F367_QAM_DEINT_LOCKE 0xF40B0004 ++#define F367_QAM_FADDING_FRZE 0xF40B0002 ++#define F367_QAM_TAPMON_ALARME 0xF40B0001 ++ ++/* CTRL_STATUS */ ++#define R367_QAM_CTRL_STATUS 0xF40C ++#define F367_QAM_QAMFEC_LOCK 0xF40C0004 ++#define F367_QAM_TSMF_LOCK 0xF40C0002 ++#define F367_QAM_TSMF_ERROR 0xF40C0001 ++ ++/* TEST_CTL */ ++#define R367_QAM_TEST_CTL 0xF40F ++#define F367_QAM_TST_BLK_SEL 0xF40F0060 ++#define F367_QAM_TST_BUS_SEL 0xF40F001F ++ ++/* AGC_CTL */ ++#define R367_QAM_AGC_CTL 0xF410 ++#define F367_QAM_AGC_LCK_TH 0xF41000F0 ++#define F367_QAM_AGC_ACCUMRSTSEL 0xF4100007 ++ ++/* AGC_IF_CFG */ ++#define R367_QAM_AGC_IF_CFG 0xF411 ++#define F367_QAM_AGC_IF_BWSEL 0xF41100F0 ++#define F367_QAM_AGC_IF_FREEZE 0xF4110002 ++ ++/* AGC_RF_CFG */ ++#define R367_QAM_AGC_RF_CFG 0xF412 ++#define F367_QAM_AGC_RF_BWSEL 0xF4120070 ++#define F367_QAM_AGC_RF_FREEZE 0xF4120002 ++ ++/* AGC_PWM_CFG */ ++#define R367_QAM_AGC_PWM_CFG 0xF413 ++#define F367_QAM_AGC_RF_PWM_TST 0xF4130080 ++#define F367_QAM_AGC_RF_PWM_INV 0xF4130040 ++#define F367_QAM_AGC_IF_PWM_TST 0xF4130008 ++#define F367_QAM_AGC_IF_PWM_INV 0xF4130004 ++#define F367_QAM_AGC_PWM_CLKDIV 0xF4130003 ++ ++/* AGC_PWR_REF_L */ ++#define R367_QAM_AGC_PWR_REF_L 0xF414 ++#define F367_QAM_AGC_PWRREF_LO 0xF41400FF ++ ++/* AGC_PWR_REF_H */ ++#define R367_QAM_AGC_PWR_REF_H 0xF415 ++#define F367_QAM_AGC_PWRREF_HI 0xF4150003 ++ ++/* AGC_RF_TH_L */ ++#define R367_QAM_AGC_RF_TH_L 0xF416 ++#define F367_QAM_AGC_RF_TH_LO 0xF41600FF ++ ++/* AGC_RF_TH_H */ ++#define R367_QAM_AGC_RF_TH_H 0xF417 ++#define F367_QAM_AGC_RF_TH_HI 0xF417000F ++ ++/* AGC_IF_LTH_L */ ++#define R367_QAM_AGC_IF_LTH_L 0xF418 ++#define F367_QAM_AGC_IF_THLO_LO 0xF41800FF ++ ++/* AGC_IF_LTH_H */ ++#define R367_QAM_AGC_IF_LTH_H 0xF419 ++#define F367_QAM_AGC_IF_THLO_HI 0xF419000F ++ ++/* AGC_IF_HTH_L */ ++#define R367_QAM_AGC_IF_HTH_L 0xF41A ++#define F367_QAM_AGC_IF_THHI_LO 0xF41A00FF ++ ++/* AGC_IF_HTH_H */ ++#define R367_QAM_AGC_IF_HTH_H 0xF41B ++#define F367_QAM_AGC_IF_THHI_HI 0xF41B000F ++ ++/* AGC_PWR_RD_L */ ++#define R367_QAM_AGC_PWR_RD_L 0xF41C ++#define F367_QAM_AGC_PWR_WORD_LO 0xF41C00FF ++ ++/* AGC_PWR_RD_M */ ++#define R367_QAM_AGC_PWR_RD_M 0xF41D ++#define F367_QAM_AGC_PWR_WORD_ME 0xF41D00FF ++ ++/* AGC_PWR_RD_H */ ++#define R367_QAM_AGC_PWR_RD_H 0xF41E ++#define F367_QAM_AGC_PWR_WORD_HI 0xF41E0003 ++ ++/* AGC_PWM_IFCMD_L */ ++#define R367_QAM_AGC_PWM_IFCMD_L 0xF420 ++#define F367_QAM_AGC_IF_PWMCMD_LO 0xF42000FF ++ ++/* AGC_PWM_IFCMD_H */ ++#define R367_QAM_AGC_PWM_IFCMD_H 0xF421 ++#define F367_QAM_AGC_IF_PWMCMD_HI 0xF421000F ++ ++/* AGC_PWM_RFCMD_L */ ++#define R367_QAM_AGC_PWM_RFCMD_L 0xF422 ++#define F367_QAM_AGC_RF_PWMCMD_LO 0xF42200FF ++ ++/* AGC_PWM_RFCMD_H */ ++#define R367_QAM_AGC_PWM_RFCMD_H 0xF423 ++#define F367_QAM_AGC_RF_PWMCMD_HI 0xF423000F ++ ++/* IQDEM_CFG */ ++#define R367_QAM_IQDEM_CFG 0xF424 ++#define F367_QAM_IQDEM_CLK_SEL 0xF4240004 ++#define F367_QAM_IQDEM_INVIQ 0xF4240002 ++#define F367_QAM_IQDEM_A2DTYPE 0xF4240001 ++ ++/* MIX_NCO_LL */ ++#define R367_QAM_MIX_NCO_LL 0xF425 ++#define F367_QAM_MIX_NCO_INC_LL 0xF42500FF ++ ++/* MIX_NCO_HL */ ++#define R367_QAM_MIX_NCO_HL 0xF426 ++#define F367_QAM_MIX_NCO_INC_HL 0xF42600FF ++ ++/* MIX_NCO_HH */ ++#define R367_QAM_MIX_NCO_HH 0xF427 ++#define F367_QAM_MIX_NCO_INVCNST 0xF4270080 ++#define F367_QAM_MIX_NCO_INC_HH 0xF427007F ++ ++/* SRC_NCO_LL */ ++#define R367_QAM_SRC_NCO_LL 0xF428 ++#define F367_QAM_SRC_NCO_INC_LL 0xF42800FF ++ ++/* SRC_NCO_LH */ ++#define R367_QAM_SRC_NCO_LH 0xF429 ++#define F367_QAM_SRC_NCO_INC_LH 0xF42900FF ++ ++/* SRC_NCO_HL */ ++#define R367_QAM_SRC_NCO_HL 0xF42A ++#define F367_QAM_SRC_NCO_INC_HL 0xF42A00FF ++ ++/* SRC_NCO_HH */ ++#define R367_QAM_SRC_NCO_HH 0xF42B ++#define F367_QAM_SRC_NCO_INC_HH 0xF42B007F ++ ++/* IQDEM_GAIN_SRC_L */ ++#define R367_QAM_IQDEM_GAIN_SRC_L 0xF42C ++#define F367_QAM_GAIN_SRC_LO 0xF42C00FF ++ ++/* IQDEM_GAIN_SRC_H */ ++#define R367_QAM_IQDEM_GAIN_SRC_H 0xF42D ++#define F367_QAM_GAIN_SRC_HI 0xF42D0003 ++ ++/* IQDEM_DCRM_CFG_LL */ ++#define R367_QAM_IQDEM_DCRM_CFG_LL 0xF430 ++#define F367_QAM_DCRM0_DCIN_L 0xF43000FF ++ ++/* IQDEM_DCRM_CFG_LH */ ++#define R367_QAM_IQDEM_DCRM_CFG_LH 0xF431 ++#define F367_QAM_DCRM1_I_DCIN_L 0xF43100FC ++#define F367_QAM_DCRM0_DCIN_H 0xF4310003 ++ ++/* IQDEM_DCRM_CFG_HL */ ++#define R367_QAM_IQDEM_DCRM_CFG_HL 0xF432 ++#define F367_QAM_DCRM1_Q_DCIN_L 0xF43200F0 ++#define F367_QAM_DCRM1_I_DCIN_H 0xF432000F ++ ++/* IQDEM_DCRM_CFG_HH */ ++#define R367_QAM_IQDEM_DCRM_CFG_HH 0xF433 ++#define F367_QAM_DCRM1_FRZ 0xF4330080 ++#define F367_QAM_DCRM0_FRZ 0xF4330040 ++#define F367_QAM_DCRM1_Q_DCIN_H 0xF433003F ++ ++/* IQDEM_ADJ_COEFF0 */ ++#define R367_QAM_IQDEM_ADJ_COEFF0 0xF434 ++#define F367_QAM_ADJIIR_COEFF10_L 0xF43400FF ++ ++/* IQDEM_ADJ_COEFF1 */ ++#define R367_QAM_IQDEM_ADJ_COEFF1 0xF435 ++#define F367_QAM_ADJIIR_COEFF11_L 0xF43500FC ++#define F367_QAM_ADJIIR_COEFF10_H 0xF4350003 ++ ++/* IQDEM_ADJ_COEFF2 */ ++#define R367_QAM_IQDEM_ADJ_COEFF2 0xF436 ++#define F367_QAM_ADJIIR_COEFF12_L 0xF43600F0 ++#define F367_QAM_ADJIIR_COEFF11_H 0xF436000F ++ ++/* IQDEM_ADJ_COEFF3 */ ++#define R367_QAM_IQDEM_ADJ_COEFF3 0xF437 ++#define F367_QAM_ADJIIR_COEFF20_L 0xF43700C0 ++#define F367_QAM_ADJIIR_COEFF12_H 0xF437003F ++ ++/* IQDEM_ADJ_COEFF4 */ ++#define R367_QAM_IQDEM_ADJ_COEFF4 0xF438 ++#define F367_QAM_ADJIIR_COEFF20_H 0xF43800FF ++ ++/* IQDEM_ADJ_COEFF5 */ ++#define R367_QAM_IQDEM_ADJ_COEFF5 0xF439 ++#define F367_QAM_ADJIIR_COEFF21_L 0xF43900FF ++ ++/* IQDEM_ADJ_COEFF6 */ ++#define R367_QAM_IQDEM_ADJ_COEFF6 0xF43A ++#define F367_QAM_ADJIIR_COEFF22_L 0xF43A00FC ++#define F367_QAM_ADJIIR_COEFF21_H 0xF43A0003 ++ ++/* IQDEM_ADJ_COEFF7 */ ++#define R367_QAM_IQDEM_ADJ_COEFF7 0xF43B ++#define F367_QAM_ADJIIR_COEFF22_H 0xF43B000F ++ ++/* IQDEM_ADJ_EN */ ++#define R367_QAM_IQDEM_ADJ_EN 0xF43C ++#define F367_QAM_ALLPASSFILT_EN 0xF43C0008 ++#define F367_QAM_ADJ_AGC_EN 0xF43C0004 ++#define F367_QAM_ADJ_COEFF_FRZ 0xF43C0002 ++#define F367_QAM_ADJ_EN 0xF43C0001 ++ ++/* IQDEM_ADJ_AGC_REF */ ++#define R367_QAM_IQDEM_ADJ_AGC_REF 0xF43D ++#define F367_QAM_ADJ_AGC_REF 0xF43D00FF ++ ++/* ALLPASSFILT1 */ ++#define R367_QAM_ALLPASSFILT1 0xF440 ++#define F367_QAM_ALLPASSFILT_COEFF1_LO 0xF44000FF ++ ++/* ALLPASSFILT2 */ ++#define R367_QAM_ALLPASSFILT2 0xF441 ++#define F367_QAM_ALLPASSFILT_COEFF1_ME 0xF44100FF ++ ++/* ALLPASSFILT3 */ ++#define R367_QAM_ALLPASSFILT3 0xF442 ++#define F367_QAM_ALLPASSFILT_COEFF2_LO 0xF44200C0 ++#define F367_QAM_ALLPASSFILT_COEFF1_HI 0xF442003F ++ ++/* ALLPASSFILT4 */ ++#define R367_QAM_ALLPASSFILT4 0xF443 ++#define F367_QAM_ALLPASSFILT_COEFF2_MEL 0xF44300FF ++ ++/* ALLPASSFILT5 */ ++#define R367_QAM_ALLPASSFILT5 0xF444 ++#define F367_QAM_ALLPASSFILT_COEFF2_MEH 0xF44400FF ++ ++/* ALLPASSFILT6 */ ++#define R367_QAM_ALLPASSFILT6 0xF445 ++#define F367_QAM_ALLPASSFILT_COEFF3_LO 0xF44500F0 ++#define F367_QAM_ALLPASSFILT_COEFF2_HI 0xF445000F ++ ++/* ALLPASSFILT7 */ ++#define R367_QAM_ALLPASSFILT7 0xF446 ++#define F367_QAM_ALLPASSFILT_COEFF3_MEL 0xF44600FF ++ ++/* ALLPASSFILT8 */ ++#define R367_QAM_ALLPASSFILT8 0xF447 ++#define F367_QAM_ALLPASSFILT_COEFF3_MEH 0xF44700FF ++ ++/* ALLPASSFILT9 */ ++#define R367_QAM_ALLPASSFILT9 0xF448 ++#define F367_QAM_ALLPASSFILT_COEFF4_LO 0xF44800FC ++#define F367_QAM_ALLPASSFILT_COEFF3_HI 0xF4480003 ++ ++/* ALLPASSFILT10 */ ++#define R367_QAM_ALLPASSFILT10 0xF449 ++#define F367_QAM_ALLPASSFILT_COEFF4_ME 0xF44900FF ++ ++/* ALLPASSFILT11 */ ++#define R367_QAM_ALLPASSFILT11 0xF44A ++#define F367_QAM_ALLPASSFILT_COEFF4_HI 0xF44A00FF ++ ++/* TRL_AGC_CFG */ ++#define R367_QAM_TRL_AGC_CFG 0xF450 ++#define F367_QAM_TRL_AGC_FREEZE 0xF4500080 ++#define F367_QAM_TRL_AGC_REF 0xF450007F ++ ++/* TRL_LPF_CFG */ ++#define R367_QAM_TRL_LPF_CFG 0xF454 ++#define F367_QAM_NYQPOINT_INV 0xF4540040 ++#define F367_QAM_TRL_SHIFT 0xF4540030 ++#define F367_QAM_NYQ_COEFF_SEL 0xF454000C ++#define F367_QAM_TRL_LPF_FREEZE 0xF4540002 ++#define F367_QAM_TRL_LPF_CRT 0xF4540001 ++ ++/* TRL_LPF_ACQ_GAIN */ ++#define R367_QAM_TRL_LPF_ACQ_GAIN 0xF455 ++#define F367_QAM_TRL_GDIR_ACQ 0xF4550070 ++#define F367_QAM_TRL_GINT_ACQ 0xF4550007 ++ ++/* TRL_LPF_TRK_GAIN */ ++#define R367_QAM_TRL_LPF_TRK_GAIN 0xF456 ++#define F367_QAM_TRL_GDIR_TRK 0xF4560070 ++#define F367_QAM_TRL_GINT_TRK 0xF4560007 ++ ++/* TRL_LPF_OUT_GAIN */ ++#define R367_QAM_TRL_LPF_OUT_GAIN 0xF457 ++#define F367_QAM_TRL_GAIN_OUT 0xF4570007 ++ ++/* TRL_LOCKDET_LTH */ ++#define R367_QAM_TRL_LOCKDET_LTH 0xF458 ++#define F367_QAM_TRL_LCK_THLO 0xF4580007 ++ ++/* TRL_LOCKDET_HTH */ ++#define R367_QAM_TRL_LOCKDET_HTH 0xF459 ++#define F367_QAM_TRL_LCK_THHI 0xF45900FF ++ ++/* TRL_LOCKDET_TRGVAL */ ++#define R367_QAM_TRL_LOCKDET_TRGVAL 0xF45A ++#define F367_QAM_TRL_LCK_TRG 0xF45A00FF ++ ++/* IQ_QAM */ ++#define R367_QAM_IQ_QAM 0xF45C ++#define F367_QAM_IQ_INPUT 0xF45C0008 ++#define F367_QAM_DETECT_MODE 0xF45C0007 ++ ++/* FSM_STATE */ ++#define R367_QAM_FSM_STATE 0xF460 ++#define F367_QAM_CRL_DFE 0xF4600080 ++#define F367_QAM_DFE_START 0xF4600040 ++#define F367_QAM_CTRLG_START 0xF4600030 ++#define F367_QAM_FSM_FORCESTATE 0xF460000F ++ ++/* FSM_CTL */ ++#define R367_QAM_FSM_CTL 0xF461 ++#define F367_QAM_FEC2_EN 0xF4610040 ++#define F367_QAM_SIT_EN 0xF4610020 ++#define F367_QAM_TRL_AHEAD 0xF4610010 ++#define F367_QAM_TRL2_EN 0xF4610008 ++#define F367_QAM_FSM_EQA1_EN 0xF4610004 ++#define F367_QAM_FSM_BKP_DIS 0xF4610002 ++#define F367_QAM_FSM_FORCE_EN 0xF4610001 ++ ++/* FSM_STS */ ++#define R367_QAM_FSM_STS 0xF462 ++#define F367_QAM_FSM_STATUS 0xF462000F ++ ++/* FSM_SNR0_HTH */ ++#define R367_QAM_FSM_SNR0_HTH 0xF463 ++#define F367_QAM_SNR0_HTH 0xF46300FF ++ ++/* FSM_SNR1_HTH */ ++#define R367_QAM_FSM_SNR1_HTH 0xF464 ++#define F367_QAM_SNR1_HTH 0xF46400FF ++ ++/* FSM_SNR2_HTH */ ++#define R367_QAM_FSM_SNR2_HTH 0xF465 ++#define F367_QAM_SNR2_HTH 0xF46500FF ++ ++/* FSM_SNR0_LTH */ ++#define R367_QAM_FSM_SNR0_LTH 0xF466 ++#define F367_QAM_SNR0_LTH 0xF46600FF ++ ++/* FSM_SNR1_LTH */ ++#define R367_QAM_FSM_SNR1_LTH 0xF467 ++#define F367_QAM_SNR1_LTH 0xF46700FF ++ ++/* FSM_EQA1_HTH */ ++#define R367_QAM_FSM_EQA1_HTH 0xF468 ++#define F367_QAM_SNR3_HTH_LO 0xF46800F0 ++#define F367_QAM_EQA1_HTH 0xF468000F ++ ++/* FSM_TEMPO */ ++#define R367_QAM_FSM_TEMPO 0xF469 ++#define F367_QAM_SIT 0xF46900C0 ++#define F367_QAM_WST 0xF4690038 ++#define F367_QAM_ELT 0xF4690006 ++#define F367_QAM_SNR3_HTH_HI 0xF4690001 ++ ++/* FSM_CONFIG */ ++#define R367_QAM_FSM_CONFIG 0xF46A ++#define F367_QAM_FEC2_DFEOFF 0xF46A0004 ++#define F367_QAM_PRIT_STATE 0xF46A0002 ++#define F367_QAM_MODMAP_STATE 0xF46A0001 ++ ++/* EQU_I_TESTTAP_L */ ++#define R367_QAM_EQU_I_TESTTAP_L 0xF474 ++#define F367_QAM_I_TEST_TAP_L 0xF47400FF ++ ++/* EQU_I_TESTTAP_M */ ++#define R367_QAM_EQU_I_TESTTAP_M 0xF475 ++#define F367_QAM_I_TEST_TAP_M 0xF47500FF ++ ++/* EQU_I_TESTTAP_H */ ++#define R367_QAM_EQU_I_TESTTAP_H 0xF476 ++#define F367_QAM_I_TEST_TAP_H 0xF476001F ++ ++/* EQU_TESTAP_CFG */ ++#define R367_QAM_EQU_TESTAP_CFG 0xF477 ++#define F367_QAM_TEST_FFE_DFE_SEL 0xF4770040 ++#define F367_QAM_TEST_TAP_SELECT 0xF477003F ++ ++/* EQU_Q_TESTTAP_L */ ++#define R367_QAM_EQU_Q_TESTTAP_L 0xF478 ++#define F367_QAM_Q_TEST_TAP_L 0xF47800FF ++ ++/* EQU_Q_TESTTAP_M */ ++#define R367_QAM_EQU_Q_TESTTAP_M 0xF479 ++#define F367_QAM_Q_TEST_TAP_M 0xF47900FF ++ ++/* EQU_Q_TESTTAP_H */ ++#define R367_QAM_EQU_Q_TESTTAP_H 0xF47A ++#define F367_QAM_Q_TEST_TAP_H 0xF47A001F ++ ++/* EQU_TAP_CTRL */ ++#define R367_QAM_EQU_TAP_CTRL 0xF47B ++#define F367_QAM_MTAP_FRZ 0xF47B0010 ++#define F367_QAM_PRE_FREEZE 0xF47B0008 ++#define F367_QAM_DFE_TAPMON_EN 0xF47B0004 ++#define F367_QAM_FFE_TAPMON_EN 0xF47B0002 ++#define F367_QAM_MTAP_ONLY 0xF47B0001 ++ ++/* EQU_CTR_CRL_CONTROL_L */ ++#define R367_QAM_EQU_CTR_CRL_CONTROL_L 0xF47C ++#define F367_QAM_EQU_CTR_CRL_CONTROL_LO 0xF47C00FF ++ ++/* EQU_CTR_CRL_CONTROL_H */ ++#define R367_QAM_EQU_CTR_CRL_CONTROL_H 0xF47D ++#define F367_QAM_EQU_CTR_CRL_CONTROL_HI 0xF47D00FF ++ ++/* EQU_CTR_HIPOW_L */ ++#define R367_QAM_EQU_CTR_HIPOW_L 0xF47E ++#define F367_QAM_CTR_HIPOW_L 0xF47E00FF ++ ++/* EQU_CTR_HIPOW_H */ ++#define R367_QAM_EQU_CTR_HIPOW_H 0xF47F ++#define F367_QAM_CTR_HIPOW_H 0xF47F00FF ++ ++/* EQU_I_EQU_LO */ ++#define R367_QAM_EQU_I_EQU_LO 0xF480 ++#define F367_QAM_EQU_I_EQU_L 0xF48000FF ++ ++/* EQU_I_EQU_HI */ ++#define R367_QAM_EQU_I_EQU_HI 0xF481 ++#define F367_QAM_EQU_I_EQU_H 0xF4810003 ++ ++/* EQU_Q_EQU_LO */ ++#define R367_QAM_EQU_Q_EQU_LO 0xF482 ++#define F367_QAM_EQU_Q_EQU_L 0xF48200FF ++ ++/* EQU_Q_EQU_HI */ ++#define R367_QAM_EQU_Q_EQU_HI 0xF483 ++#define F367_QAM_EQU_Q_EQU_H 0xF4830003 ++ ++/* EQU_MAPPER */ ++#define R367_QAM_EQU_MAPPER 0xF484 ++#define F367_QAM_QUAD_AUTO 0xF4840080 ++#define F367_QAM_QUAD_INV 0xF4840040 ++#define F367_QAM_QAM_MODE 0xF4840007 ++ ++/* EQU_SWEEP_RATE */ ++#define R367_QAM_EQU_SWEEP_RATE 0xF485 ++#define F367_QAM_SNR_PER 0xF48500C0 ++#define F367_QAM_SWEEP_RATE 0xF485003F ++ ++/* EQU_SNR_LO */ ++#define R367_QAM_EQU_SNR_LO 0xF486 ++#define F367_QAM_SNR_LO 0xF48600FF ++ ++/* EQU_SNR_HI */ ++#define R367_QAM_EQU_SNR_HI 0xF487 ++#define F367_QAM_SNR_HI 0xF48700FF ++ ++/* EQU_GAMMA_LO */ ++#define R367_QAM_EQU_GAMMA_LO 0xF488 ++#define F367_QAM_GAMMA_LO 0xF48800FF ++ ++/* EQU_GAMMA_HI */ ++#define R367_QAM_EQU_GAMMA_HI 0xF489 ++#define F367_QAM_GAMMA_ME 0xF48900FF ++ ++/* EQU_ERR_GAIN */ ++#define R367_QAM_EQU_ERR_GAIN 0xF48A ++#define F367_QAM_EQA1MU 0xF48A0070 ++#define F367_QAM_CRL2MU 0xF48A000E ++#define F367_QAM_GAMMA_HI 0xF48A0001 ++ ++/* EQU_RADIUS */ ++#define R367_QAM_EQU_RADIUS 0xF48B ++#define F367_QAM_RADIUS 0xF48B00FF ++ ++/* EQU_FFE_MAINTAP */ ++#define R367_QAM_EQU_FFE_MAINTAP 0xF48C ++#define F367_QAM_FFE_MAINTAP_INIT 0xF48C00FF ++ ++/* EQU_FFE_LEAKAGE */ ++#define R367_QAM_EQU_FFE_LEAKAGE 0xF48E ++#define F367_QAM_LEAK_PER 0xF48E00F0 ++#define F367_QAM_EQU_OUTSEL 0xF48E0002 ++#define F367_QAM_PNT2DFE 0xF48E0001 ++ ++/* EQU_FFE_MAINTAP_POS */ ++#define R367_QAM_EQU_FFE_MAINTAP_POS 0xF48F ++#define F367_QAM_FFE_LEAK_EN 0xF48F0080 ++#define F367_QAM_DFE_LEAK_EN 0xF48F0040 ++#define F367_QAM_FFE_MAINTAP_POS 0xF48F003F ++ ++/* EQU_GAIN_WIDE */ ++#define R367_QAM_EQU_GAIN_WIDE 0xF490 ++#define F367_QAM_DFE_GAIN_WIDE 0xF49000F0 ++#define F367_QAM_FFE_GAIN_WIDE 0xF490000F ++ ++/* EQU_GAIN_NARROW */ ++#define R367_QAM_EQU_GAIN_NARROW 0xF491 ++#define F367_QAM_DFE_GAIN_NARROW 0xF49100F0 ++#define F367_QAM_FFE_GAIN_NARROW 0xF491000F ++ ++/* EQU_CTR_LPF_GAIN */ ++#define R367_QAM_EQU_CTR_LPF_GAIN 0xF492 ++#define F367_QAM_CTR_GTO 0xF4920080 ++#define F367_QAM_CTR_GDIR 0xF4920070 ++#define F367_QAM_SWEEP_EN 0xF4920008 ++#define F367_QAM_CTR_GINT 0xF4920007 ++ ++/* EQU_CRL_LPF_GAIN */ ++#define R367_QAM_EQU_CRL_LPF_GAIN 0xF493 ++#define F367_QAM_CRL_GTO 0xF4930080 ++#define F367_QAM_CRL_GDIR 0xF4930070 ++#define F367_QAM_SWEEP_DIR 0xF4930008 ++#define F367_QAM_CRL_GINT 0xF4930007 ++ ++/* EQU_GLOBAL_GAIN */ ++#define R367_QAM_EQU_GLOBAL_GAIN 0xF494 ++#define F367_QAM_CRL_GAIN 0xF49400F8 ++#define F367_QAM_CTR_INC_GAIN 0xF4940004 ++#define F367_QAM_CTR_FRAC 0xF4940003 ++ ++/* EQU_CRL_LD_SEN */ ++#define R367_QAM_EQU_CRL_LD_SEN 0xF495 ++#define F367_QAM_CTR_BADPOINT_EN 0xF4950080 ++#define F367_QAM_CTR_GAIN 0xF4950070 ++#define F367_QAM_LIMANEN 0xF4950008 ++#define F367_QAM_CRL_LD_SEN 0xF4950007 ++ ++/* EQU_CRL_LD_VAL */ ++#define R367_QAM_EQU_CRL_LD_VAL 0xF496 ++#define F367_QAM_CRL_BISTH_LIMIT 0xF4960080 ++#define F367_QAM_CARE_EN 0xF4960040 ++#define F367_QAM_CRL_LD_PER 0xF4960030 ++#define F367_QAM_CRL_LD_WST 0xF496000C ++#define F367_QAM_CRL_LD_TFS 0xF4960003 ++ ++/* EQU_CRL_TFR */ ++#define R367_QAM_EQU_CRL_TFR 0xF497 ++#define F367_QAM_CRL_LD_TFR 0xF49700FF ++ ++/* EQU_CRL_BISTH_LO */ ++#define R367_QAM_EQU_CRL_BISTH_LO 0xF498 ++#define F367_QAM_CRL_BISTH_LO 0xF49800FF ++ ++/* EQU_CRL_BISTH_HI */ ++#define R367_QAM_EQU_CRL_BISTH_HI 0xF499 ++#define F367_QAM_CRL_BISTH_HI 0xF49900FF ++ ++/* EQU_SWEEP_RANGE_LO */ ++#define R367_QAM_EQU_SWEEP_RANGE_LO 0xF49A ++#define F367_QAM_SWEEP_RANGE_LO 0xF49A00FF ++ ++/* EQU_SWEEP_RANGE_HI */ ++#define R367_QAM_EQU_SWEEP_RANGE_HI 0xF49B ++#define F367_QAM_SWEEP_RANGE_HI 0xF49B00FF ++ ++/* EQU_CRL_LIMITER */ ++#define R367_QAM_EQU_CRL_LIMITER 0xF49C ++#define F367_QAM_BISECTOR_EN 0xF49C0080 ++#define F367_QAM_PHEST128_EN 0xF49C0040 ++#define F367_QAM_CRL_LIM 0xF49C003F ++ ++/* EQU_MODULUS_MAP */ ++#define R367_QAM_EQU_MODULUS_MAP 0xF49D ++#define F367_QAM_PNT_DEPTH 0xF49D00E0 ++#define F367_QAM_MODULUS_CMP 0xF49D001F ++ ++/* EQU_PNT_GAIN */ ++#define R367_QAM_EQU_PNT_GAIN 0xF49E ++#define F367_QAM_PNT_EN 0xF49E0080 ++#define F367_QAM_MODULUSMAP_EN 0xF49E0040 ++#define F367_QAM_PNT_GAIN 0xF49E003F ++ ++/* FEC_AC_CTR_0 */ ++#define R367_QAM_FEC_AC_CTR_0 0xF4A8 ++#define F367_QAM_BE_BYPASS 0xF4A80020 ++#define F367_QAM_REFRESH47 0xF4A80010 ++#define F367_QAM_CT_NBST 0xF4A80008 ++#define F367_QAM_TEI_ENA 0xF4A80004 ++#define F367_QAM_DS_ENA 0xF4A80002 ++#define F367_QAM_TSMF_EN 0xF4A80001 ++ ++/* FEC_AC_CTR_1 */ ++#define R367_QAM_FEC_AC_CTR_1 0xF4A9 ++#define F367_QAM_DEINT_DEPTH 0xF4A900FF ++ ++/* FEC_AC_CTR_2 */ ++#define R367_QAM_FEC_AC_CTR_2 0xF4AA ++#define F367_QAM_DEINT_M 0xF4AA00F8 ++#define F367_QAM_DIS_UNLOCK 0xF4AA0004 ++#define F367_QAM_DESCR_MODE 0xF4AA0003 ++ ++/* FEC_AC_CTR_3 */ ++#define R367_QAM_FEC_AC_CTR_3 0xF4AB ++#define F367_QAM_DI_UNLOCK 0xF4AB0080 ++#define F367_QAM_DI_FREEZE 0xF4AB0040 ++#define F367_QAM_MISMATCH 0xF4AB0030 ++#define F367_QAM_ACQ_MODE 0xF4AB000C ++#define F367_QAM_TRK_MODE 0xF4AB0003 ++ ++/* FEC_STATUS */ ++#define R367_QAM_FEC_STATUS 0xF4AC ++#define F367_QAM_DEINT_SMCNTR 0xF4AC00E0 ++#define F367_QAM_DEINT_SYNCSTATE 0xF4AC0018 ++#define F367_QAM_DEINT_SYNLOST 0xF4AC0004 ++#define F367_QAM_DESCR_SYNCSTATE 0xF4AC0002 ++ ++/* RS_COUNTER_0 */ ++#define R367_QAM_RS_COUNTER_0 0xF4AE ++#define F367_QAM_BK_CT_L 0xF4AE00FF ++ ++/* RS_COUNTER_1 */ ++#define R367_QAM_RS_COUNTER_1 0xF4AF ++#define F367_QAM_BK_CT_H 0xF4AF00FF ++ ++/* RS_COUNTER_2 */ ++#define R367_QAM_RS_COUNTER_2 0xF4B0 ++#define F367_QAM_CORR_CT_L 0xF4B000FF ++ ++/* RS_COUNTER_3 */ ++#define R367_QAM_RS_COUNTER_3 0xF4B1 ++#define F367_QAM_CORR_CT_H 0xF4B100FF ++ ++/* RS_COUNTER_4 */ ++#define R367_QAM_RS_COUNTER_4 0xF4B2 ++#define F367_QAM_UNCORR_CT_L 0xF4B200FF ++ ++/* RS_COUNTER_5 */ ++#define R367_QAM_RS_COUNTER_5 0xF4B3 ++#define F367_QAM_UNCORR_CT_H 0xF4B300FF ++ ++/* BERT_0 */ ++#define R367_QAM_BERT_0 0xF4B4 ++#define F367_QAM_RS_NOCORR 0xF4B40004 ++#define F367_QAM_CT_HOLD 0xF4B40002 ++#define F367_QAM_CT_CLEAR 0xF4B40001 ++ ++/* BERT_1 */ ++#define R367_QAM_BERT_1 0xF4B5 ++#define F367_QAM_BERT_ON 0xF4B50020 ++#define F367_QAM_BERT_ERR_SRC 0xF4B50010 ++#define F367_QAM_BERT_ERR_MODE 0xF4B50008 ++#define F367_QAM_BERT_NBYTE 0xF4B50007 ++ ++/* BERT_2 */ ++#define R367_QAM_BERT_2 0xF4B6 ++#define F367_QAM_BERT_ERRCOUNT_L 0xF4B600FF ++ ++/* BERT_3 */ ++#define R367_QAM_BERT_3 0xF4B7 ++#define F367_QAM_BERT_ERRCOUNT_H 0xF4B700FF ++ ++/* OUTFORMAT_0 */ ++#define R367_QAM_OUTFORMAT_0 0xF4B8 ++#define F367_QAM_CLK_POLARITY 0xF4B80080 ++#define F367_QAM_FEC_TYPE 0xF4B80040 ++#define F367_QAM_SYNC_STRIP 0xF4B80008 ++#define F367_QAM_TS_SWAP 0xF4B80004 ++#define F367_QAM_OUTFORMAT 0xF4B80003 ++ ++/* OUTFORMAT_1 */ ++#define R367_QAM_OUTFORMAT_1 0xF4B9 ++#define F367_QAM_CI_DIVRANGE 0xF4B900FF ++ ++/* SMOOTHER_2 */ ++#define R367_QAM_SMOOTHER_2 0xF4BE ++#define F367_QAM_FIFO_BYPASS 0xF4BE0020 ++ ++/* TSMF_CTRL_0 */ ++#define R367_QAM_TSMF_CTRL_0 0xF4C0 ++#define F367_QAM_TS_NUMBER 0xF4C0001E ++#define F367_QAM_SEL_MODE 0xF4C00001 ++ ++/* TSMF_CTRL_1 */ ++#define R367_QAM_TSMF_CTRL_1 0xF4C1 ++#define F367_QAM_CHECK_ERROR_BIT 0xF4C10080 ++#define F367_QAM_CHCK_F_SYNC 0xF4C10040 ++#define F367_QAM_H_MODE 0xF4C10008 ++#define F367_QAM_D_V_MODE 0xF4C10004 ++#define F367_QAM_MODE 0xF4C10003 ++ ++/* TSMF_CTRL_3 */ ++#define R367_QAM_TSMF_CTRL_3 0xF4C3 ++#define F367_QAM_SYNC_IN_COUNT 0xF4C300F0 ++#define F367_QAM_SYNC_OUT_COUNT 0xF4C3000F ++ ++/* TS_ON_ID_0 */ ++#define R367_QAM_TS_ON_ID_0 0xF4C4 ++#define F367_QAM_TS_ID_L 0xF4C400FF ++ ++/* TS_ON_ID_1 */ ++#define R367_QAM_TS_ON_ID_1 0xF4C5 ++#define F367_QAM_TS_ID_H 0xF4C500FF ++ ++/* TS_ON_ID_2 */ ++#define R367_QAM_TS_ON_ID_2 0xF4C6 ++#define F367_QAM_ON_ID_L 0xF4C600FF ++ ++/* TS_ON_ID_3 */ ++#define R367_QAM_TS_ON_ID_3 0xF4C7 ++#define F367_QAM_ON_ID_H 0xF4C700FF ++ ++/* RE_STATUS_0 */ ++#define R367_QAM_RE_STATUS_0 0xF4C8 ++#define F367_QAM_RECEIVE_STATUS_L 0xF4C800FF ++ ++/* RE_STATUS_1 */ ++#define R367_QAM_RE_STATUS_1 0xF4C9 ++#define F367_QAM_RECEIVE_STATUS_LH 0xF4C900FF ++ ++/* RE_STATUS_2 */ ++#define R367_QAM_RE_STATUS_2 0xF4CA ++#define F367_QAM_RECEIVE_STATUS_HL 0xF4CA00FF ++ ++/* RE_STATUS_3 */ ++#define R367_QAM_RE_STATUS_3 0xF4CB ++#define F367_QAM_RECEIVE_STATUS_HH 0xF4CB003F ++ ++/* TS_STATUS_0 */ ++#define R367_QAM_TS_STATUS_0 0xF4CC ++#define F367_QAM_TS_STATUS_L 0xF4CC00FF ++ ++/* TS_STATUS_1 */ ++#define R367_QAM_TS_STATUS_1 0xF4CD ++#define F367_QAM_TS_STATUS_H 0xF4CD007F ++ ++/* TS_STATUS_2 */ ++#define R367_QAM_TS_STATUS_2 0xF4CE ++#define F367_QAM_ERROR 0xF4CE0080 ++#define F367_QAM_EMERGENCY 0xF4CE0040 ++#define F367_QAM_CRE_TS 0xF4CE0030 ++#define F367_QAM_VER 0xF4CE000E ++#define F367_QAM_M_LOCK 0xF4CE0001 ++ ++/* TS_STATUS_3 */ ++#define R367_QAM_TS_STATUS_3 0xF4CF ++#define F367_QAM_UPDATE_READY 0xF4CF0080 ++#define F367_QAM_END_FRAME_HEADER 0xF4CF0040 ++#define F367_QAM_CONTCNT 0xF4CF0020 ++#define F367_QAM_TS_IDENTIFIER_SEL 0xF4CF000F ++ ++/* T_O_ID_0 */ ++#define R367_QAM_T_O_ID_0 0xF4D0 ++#define F367_QAM_ON_ID_I_L 0xF4D000FF ++ ++/* T_O_ID_1 */ ++#define R367_QAM_T_O_ID_1 0xF4D1 ++#define F367_QAM_ON_ID_I_H 0xF4D100FF ++ ++/* T_O_ID_2 */ ++#define R367_QAM_T_O_ID_2 0xF4D2 ++#define F367_QAM_TS_ID_I_L 0xF4D200FF ++ ++/* T_O_ID_3 */ ++#define R367_QAM_T_O_ID_3 0xF4D3 ++#define F367_QAM_TS_ID_I_H 0xF4D300FF ++ +diff --git a/drivers/media/dvb-frontends/tda18212dd.c b/drivers/media/dvb-frontends/tda18212dd.c +new file mode 100644 +index 0000000..de2350b +--- /dev/null ++++ b/drivers/media/dvb-frontends/tda18212dd.c +@@ -0,0 +1,906 @@ ++/* ++ * tda18212: Driver for the TDA18212 tuner ++ * ++ * Copyright (C) 2011 Digital Devices GmbH ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++ ++#ifndef CHK_ERROR ++ #define CHK_ERROR(s) if ((status = s) < 0) break ++#endif ++ ++#define MASTER_PSM_AGC1 0 ++#define MASTER_AGC1_6_15dB 1 ++ ++#define SLAVE_PSM_AGC1 1 ++#define SLAVE_AGC1_6_15dB 0 ++ ++// 0 = 2 Vpp ... 2 = 1 Vpp, 7 = 0.5 Vpp ++#define IF_LEVEL_DVBC 2 ++#define IF_LEVEL_DVBT 2 ++ ++enum { ++ ID_1 = 0x00, ++ ID_2 = 0x01, ++ ID_3 = 0x02, ++ THERMO_1, ++ THERMO_2, ++ POWER_STATE_1, ++ POWER_STATE_2, ++ INPUT_POWER_LEVEL, ++ IRQ_STATUS, ++ IRQ_ENABLE, ++ IRQ_CLEAR, ++ IRQ_SET, ++ AGC1_1, ++ AGC2_1, ++ AGCK_1, ++ RF_AGC_1, ++ IR_MIXER_1 = 0x10, ++ AGC5_1, ++ IF_AGC, ++ IF_1, ++ REFERENCE, ++ IF_FREQUENCY_1, ++ RF_FREQUENCY_1, ++ RF_FREQUENCY_2, ++ RF_FREQUENCY_3, ++ MSM_1, ++ MSM_2, ++ PSM_1, ++ DCC_1, ++ FLO_MAX, ++ IR_CAL_1, ++ IR_CAL_2, ++ IR_CAL_3 = 0x20, ++ IR_CAL_4, ++ VSYNC_MGT, ++ IR_MIXER_2, ++ AGC1_2, ++ AGC5_2, ++ RF_CAL_1, ++ RF_CAL_2, ++ RF_CAL_3, ++ RF_CAL_4, ++ RF_CAL_5, ++ RF_CAL_6, ++ RF_FILTER_1, ++ RF_FILTER_2, ++ RF_FILTER_3, ++ RF_BAND_PASS_FILTER, ++ CP_CURRENT = 0x30, ++ AGC_DET_OUT = 0x31, ++ RF_AGC_GAIN_1 = 0x32, ++ RF_AGC_GAIN_2 = 0x33, ++ IF_AGC_GAIN = 0x34, ++ POWER_1 = 0x35, ++ POWER_2 = 0x36, ++ MISC_1, ++ RFCAL_LOG_1, ++ RFCAL_LOG_2, ++ RFCAL_LOG_3, ++ RFCAL_LOG_4, ++ RFCAL_LOG_5, ++ RFCAL_LOG_6, ++ RFCAL_LOG_7, ++ RFCAL_LOG_8, ++ RFCAL_LOG_9 = 0x40, ++ RFCAL_LOG_10 = 0x41, ++ RFCAL_LOG_11 = 0x42, ++ RFCAL_LOG_12 = 0x43, ++ REG_MAX, ++}; ++ ++enum HF_Standard { ++ HF_None=0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio, ++ HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ, ++ HF_DVBT, HF_ATSC, HF_DVBC_6MHZ, HF_DVBC_7MHZ, ++ HF_DVBC_8MHZ, HF_DVBC ++}; ++ ++struct SStandardParams { ++ s32 m_IFFrequency; ++ u32 m_BandWidth; ++ u8 m_IF_1; // FF IF_HP_fc:2 IF_Notch:1 LP_FC_Offset:2 LP_FC:3 ++ u8 m_IR_MIXER_2; // 03 :6 HI_Pass:1 DC_Notch:1 ++ u8 m_AGC1_1; // 0F :4 AGC1_Top:4 ++ u8 m_AGC2_1; // 0F :4 AGC2_Top:4 ++ u8 m_RF_AGC_1_Low; // EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1 RF_AGC_Top:3 ++ u8 m_RF_AGC_1_High;// EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1 RF_AGC_Top:3 ++ u8 m_IR_MIXER_1; // 0F :4 IR_mixer_Top:4 ++ u8 m_AGC5_1; // 1F :3 AGC5_Ana AGC5_Top:4 ++ u8 m_AGCK_1; // 0F :4 AGCK_Step:2 AGCK_Mode:2 ++ u8 m_PSM_1; // 20 :2 PSM_StoB:1 :5 ++ bool m_AGC1_Freeze; ++ bool m_LTO_STO_immune; ++}; ++ ++struct SStandardParams m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] = ++{ ++ { 3250000, 6000000, 0x20, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, // HF_DVBT_6MHZ ++ { 3500000, 7000000, 0x31, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, // HF_DVBT_7MHZ ++ { 4000000, 8000000, 0x22, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, // HF_DVBT_8MHZ ++ { 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, false, false }, // HF_DVBT (Unused) ++ { 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false }, // HF_ATSC ++ { 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_6MHZ ++// { 5000000, 7000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ) ++// { 5000000, 8000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_8MHZ ++ { 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ) ++ { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_8MHZ ++}; ++ ++struct tda_state { ++ struct i2c_adapter *i2c; ++ u8 adr; ++ ++ enum HF_Standard m_Standard; ++ u32 m_Frequency; ++ u32 IF; ++ ++ bool m_isMaster; ++ bool m_bPowerMeasurement; ++ bool m_bLTEnable; ++ bool m_bEnableFreeze; ++ ++ u16 m_ID; ++ ++ s32 m_SettlingTime; ++ ++ u8 m_IFLevelDVBC; ++ u8 m_IFLevelDVBT; ++ u8 m_Regs[REG_MAX]; ++ u8 m_LastPowerLevel; ++}; ++ ++static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, ++ .buf = data, .len = len}}; ++ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; ++} ++ ++static int i2c_read(struct i2c_adapter *adap, ++ u8 adr, u8 *msg, int len, u8 *answ, int alen) ++{ ++ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, ++ .buf = msg, .len = len}, ++ { .addr = adr, .flags = I2C_M_RD, ++ .buf = answ, .len = alen } }; ++ if (i2c_transfer(adap, msgs, 2) != 2) { ++ printk("tda18212dd: i2c_read error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, ++ .buf = data, .len = len}; ++ ++ if (i2c_transfer(adap, &msg, 1) != 1) { ++ printk("tda18212: i2c_write error\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int write_regs(struct tda_state *state, ++ u8 SubAddr, u8 *Regs, u16 nRegs) ++{ ++ u8 data[nRegs+1]; ++ ++ data[0] = SubAddr; ++ memcpy(data + 1, Regs, nRegs); ++ return i2c_write(state->i2c, state->adr, data, nRegs+1); ++} ++ ++static int write_reg(struct tda_state *state, u8 SubAddr,u8 Reg) ++{ ++ u8 msg[2] = {SubAddr, Reg}; ++ ++ return i2c_write(state->i2c, state->adr, msg, 2); ++} ++ ++static int Read(struct tda_state *state, u8 * Regs) ++{ ++ return i2c_readn(state->i2c, state->adr, Regs, REG_MAX); ++} ++ ++static int update_regs(struct tda_state *state, u8 RegFrom,u8 RegTo) ++{ ++ return write_regs(state, RegFrom, ++ &state->m_Regs[RegFrom], RegTo-RegFrom+1); ++} ++ ++static int update_reg(struct tda_state *state, u8 Reg) ++{ ++ return write_reg(state, Reg,state->m_Regs[Reg]); ++} ++ ++ ++static int read_regs(struct tda_state *state, ++ u8 SubAddr, u8 *Regs, u16 nRegs) ++{ ++ return i2c_read(state->i2c, state->adr, ++ &SubAddr, 1, Regs, nRegs); ++} ++ ++static int read_reg(struct tda_state *state, ++ u8 SubAddr, u8 *Reg) ++{ ++ return i2c_read(state->i2c, state->adr, ++ &SubAddr, 1, Reg, 1); ++} ++ ++static int read_reg1(struct tda_state *state, u8 Reg) ++{ ++ return read_reg(state, Reg, &state->m_Regs[Reg]); ++} ++ ++static void init_state(struct tda_state *state) ++{ ++ u32 ulIFLevelDVBC = IF_LEVEL_DVBC; ++ u32 ulIFLevelDVBT = IF_LEVEL_DVBT; ++ u32 ulPowerMeasurement = 1; ++ u32 ulLTEnable = 1; ++ u32 ulEnableFreeze = 0; ++ ++ state->m_Frequency = 0; ++ state->m_isMaster = true; ++ state->m_ID = 0; ++ state->m_LastPowerLevel = 0xFF; ++ state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07); ++ state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07); ++ state->m_bPowerMeasurement = (ulPowerMeasurement != 0); ++ state->m_bLTEnable = (ulLTEnable != 0); ++ state->m_bEnableFreeze = (ulEnableFreeze != 0); ++} ++ ++static int StartCalibration(struct tda_state *state) ++{ ++ int status = 0; ++ do { ++ state->m_Regs[POWER_2] &= ~0x02; // RSSI CK = 31.25 kHz ++ CHK_ERROR(update_reg(state, POWER_2)); ++ ++ state->m_Regs[AGC1_2] = (state->m_Regs[AGC1_2] & ~0x60) | 0x40; // AGC1 Do Step = 2 ++ CHK_ERROR(update_reg(state, AGC1_2)); // AGC ++ ++ state->m_Regs[RF_FILTER_3] = (state->m_Regs[RF_FILTER_3] & ~0xC0) | 0x40; // AGC2 Do Step = 1 ++ CHK_ERROR(update_reg(state, RF_FILTER_3)); ++ ++ state->m_Regs[AGCK_1] |= 0xC0; // AGCs Assym Up Step = 3 // Datasheet sets all bits to 1! ++ CHK_ERROR(update_reg(state, AGCK_1)); ++ ++ state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x60) | 0x40; // AGCs Assym Do Step = 2 ++ CHK_ERROR(update_reg(state, AGC5_1)); ++ ++ state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ ++ CHK_ERROR(update_reg(state, IRQ_CLEAR)); ++ ++ state->m_Regs[MSM_1] = 0x3B; // Set Calibration ++ state->m_Regs[MSM_2] = 0x01; // Start MSM ++ CHK_ERROR(update_regs(state, MSM_1,MSM_2)); ++ state->m_Regs[MSM_2] = 0x00; ++ ++ } while(0); ++ return status; ++} ++ ++static int FinishCalibration(struct tda_state *state) ++{ ++ int status = 0; ++ u8 RFCal_Log[12]; ++ ++ do { ++ u8 IRQ = 0; ++ int Timeout = 150; // 1.5 s ++ while(true) { ++ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); ++ if ((IRQ & 0x80) != 0 ) ++ break; ++ Timeout -= 1; ++ if (Timeout == 0) { ++ status = -1; ++ break; ++ } ++ msleep(10); ++ } ++ CHK_ERROR(status); ++ ++ state->m_Regs[FLO_MAX] = 0x0A; ++ CHK_ERROR(update_reg(state, FLO_MAX)); ++ ++ state->m_Regs[AGC1_1] &= ~0xC0; ++ if( state->m_bLTEnable ) state->m_Regs[AGC1_1] |= 0x80; // LTEnable ++ ++ state->m_Regs[AGC1_1] |= (state->m_isMaster ? MASTER_AGC1_6_15dB : SLAVE_AGC1_6_15dB ) << 6; ++ CHK_ERROR(update_reg(state, AGC1_1)); ++ ++ state->m_Regs[PSM_1] &= ~0xC0; ++ state->m_Regs[PSM_1] |= (state->m_isMaster ? MASTER_PSM_AGC1 : SLAVE_PSM_AGC1 ) << 6; ++ CHK_ERROR(update_reg(state, PSM_1)); ++ ++ state->m_Regs[REFERENCE] |= 0x03; // XTOUT = 3 ++ CHK_ERROR(update_reg(state, REFERENCE)); ++ ++ CHK_ERROR(read_regs(state, RFCAL_LOG_1,RFCal_Log,sizeof(RFCal_Log))); ++ } while(0); ++ return status; ++} ++ ++static int PowerOn(struct tda_state *state) ++{ ++ state->m_Regs[POWER_STATE_2] &= ~0x0F; ++ update_reg(state, POWER_STATE_2); ++ state->m_Regs[REFERENCE] |= 0x40; // Digital clock source = Sigma Delta ++ update_reg(state, REFERENCE); ++ return 0; ++} ++ ++static int Standby(struct tda_state *state) ++{ ++ int status = 0; ++ ++ do { ++ state->m_Regs[REFERENCE] &= ~0x40; // Digital clock source = Quarz ++ CHK_ERROR(update_reg(state, REFERENCE)); ++ ++ state->m_Regs[POWER_STATE_2] &= ~0x0F; ++ state->m_Regs[POWER_STATE_2] |= state->m_isMaster ? 0x08 : 0x0E; ++ CHK_ERROR(update_reg(state, POWER_STATE_2)); ++ } while(0); ++ return status; ++} ++ ++static int attach_init(struct tda_state *state) ++{ ++ int stat = 0; ++ u8 Id[2]; ++ u8 PowerState = 0x00; ++ ++ state->m_Standard = HF_None; ++ ++ /* first read after cold reset sometimes fails on some cards, ++ try twice */ ++ stat = read_regs(state, ID_1, Id, sizeof(Id)); ++ stat = read_regs(state, ID_1, Id, sizeof(Id)); ++ if (stat < 0) ++ return -1; ++ ++ state->m_ID = ((Id[0] & 0x7F) << 8) | Id[1]; ++ state->m_isMaster = ((Id[0] & 0x80) != 0); ++ if( !state->m_isMaster ) ++ state->m_bLTEnable = false; ++ ++ printk("tda18212dd: ChipID %04x\n", state->m_ID); ++ ++ if( state->m_ID != 18212 ) ++ return -1; ++ ++ stat = read_reg(state, POWER_STATE_1 ,&PowerState); ++ if (stat < 0) ++ return stat; ++ ++ printk("tda18212dd: PowerState %02x\n", PowerState); ++ ++ if (state->m_isMaster) { ++ if( PowerState & 0x02 ) { ++ // msleep for XTAL Calibration (on a PC this should be long done) ++ u8 IRQStatus = 0; ++ int Timeout = 10; ++ ++ while(Timeout > 0) { ++ read_reg(state, IRQ_STATUS, &IRQStatus); ++ if (IRQStatus & 0x20) ++ break; ++ Timeout -= 1; ++ msleep(10); ++ } ++ if( (IRQStatus & 0x20) == 0 ) { ++ stat = -ETIMEDOUT; ++ } ++ } ++ } else { ++ write_reg(state, FLO_MAX, 0x00); ++ write_reg(state, CP_CURRENT,0x68); ++ } ++ Read(state, state->m_Regs); ++ ++ PowerOn(state); ++ StartCalibration(state); ++ FinishCalibration(state); ++ Standby(state); ++ return stat; ++} ++ ++static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel) ++{ ++ int status = 0; ++ ++ do { ++ u8 IRQ = 0; ++ int Timeout = 70; // 700 ms ++ ++ state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ ++ CHK_ERROR(update_reg(state, IRQ_CLEAR)); ++ ++ state->m_Regs[MSM_1] = 0x80; // power measurement ++ state->m_Regs[MSM_2] = 0x01; // Start MSM ++ CHK_ERROR(update_regs(state, MSM_1,MSM_2)); ++ state->m_Regs[MSM_2] = 0x00; ++ ++ while(true) { ++ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); ++ if( (IRQ & 0x80) != 0 ) ++ break; ++ Timeout -= 1; ++ if( Timeout == 0 ) ++ { ++ status = -1; ++ break; ++ } ++ msleep(10); ++ } ++ CHK_ERROR(status); ++ ++ CHK_ERROR(read_reg1(state, INPUT_POWER_LEVEL)); ++ *pPowerLevel = state->m_Regs[INPUT_POWER_LEVEL] & 0x7F; ++ ++ ++ if( *pPowerLevel > 110 ) *pPowerLevel = 110; ++ } while(0); ++ /* printk("PL %d\n", *pPowerLevel); */ ++ return status; ++} ++ ++static int SetFrequency(struct tda_state *state, u32 Frequency, enum HF_Standard Standard) ++{ ++ int status = 0; ++ struct SStandardParams *StandardParams; ++ u32 f = Frequency / 1000; ++ u8 IRQ = 0; ++ int Timeout = 25; // 250 ms ++ u32 fRatio = Frequency / 16000000; ++ u32 fDelta = Frequency - fRatio * 16000000; ++ ++ if( Standard < HF_DVBT_6MHZ || Standard > HF_DVBC_8MHZ ) ++ return -EINVAL; ++ StandardParams = &m_StandardTable[Standard - HF_DVBT_6MHZ]; ++ ++ if( StandardParams->m_IFFrequency == 0 ) ++ return -EINVAL; ++ state->m_Standard = HF_None; ++ state->m_Frequency = 0; ++ ++ do { ++ // IF Level ++ state->m_Regs[IF_AGC] = (Standard >= HF_DVBC_6MHZ) ? state->m_IFLevelDVBC : state->m_IFLevelDVBT; ++ CHK_ERROR(update_reg(state, IF_AGC)); ++ ++ // --------------------------------------------------------------------------------- ++ // Standard setup ++ ++ state->m_Regs[IF_1] = StandardParams->m_IF_1; ++ CHK_ERROR(update_reg(state, IF_1)); ++ ++ state->m_Regs[IR_MIXER_2] = (state->m_Regs[IR_MIXER_2] & ~0x03) | StandardParams->m_IR_MIXER_2; ++ CHK_ERROR(update_reg(state, IR_MIXER_2)); ++ ++ state->m_Regs[AGC1_1] = (state->m_Regs[AGC1_1] & ~0x0F) | StandardParams->m_AGC1_1; ++ CHK_ERROR(update_reg(state, AGC1_1)); ++ ++ state->m_Regs[AGC2_1] = (state->m_Regs[AGC2_1] & ~0x0F) | StandardParams->m_AGC2_1; ++ CHK_ERROR(update_reg(state, AGC2_1)); ++ ++ state->m_Regs[RF_AGC_1] &= ~0xEF; ++ if( Frequency < 291000000 ) ++ state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_Low; ++ else ++ state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_High; ++ CHK_ERROR(update_reg(state, RF_AGC_1)); ++ ++ state->m_Regs[IR_MIXER_1] = (state->m_Regs[IR_MIXER_1] & ~0x0F) | StandardParams->m_IR_MIXER_1; ++ CHK_ERROR(update_reg(state, IR_MIXER_1)); ++ ++ state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x1F) | StandardParams->m_AGC5_1; ++ CHK_ERROR(update_reg(state, AGC5_1)); ++ ++ state->m_Regs[AGCK_1] = (state->m_Regs[AGCK_1] & ~0x0F) | StandardParams->m_AGCK_1; ++ CHK_ERROR(update_reg(state, AGCK_1)); ++ ++ state->m_Regs[PSM_1] = (state->m_Regs[PSM_1] & ~0x20) | StandardParams->m_PSM_1; ++ CHK_ERROR(update_reg(state, PSM_1)); ++ ++ state->m_Regs[IF_FREQUENCY_1] = ( StandardParams->m_IFFrequency / 50000 ); ++ CHK_ERROR(update_reg(state, IF_FREQUENCY_1)); ++ ++ if( state->m_isMaster && StandardParams->m_LTO_STO_immune ) ++ { ++ u8 tmp; ++ u8 RF_Filter_Gain; ++ ++ CHK_ERROR(read_reg(state, RF_AGC_GAIN_1,&tmp)); ++ RF_Filter_Gain = (tmp & 0x30) >> 4; ++ ++ state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2); ++ CHK_ERROR(update_reg(state, RF_FILTER_1)); ++ ++ state->m_Regs[RF_FILTER_1] |= 0x10; // Force ++ CHK_ERROR(update_reg(state, RF_FILTER_1)); ++ ++ while( RF_Filter_Gain != 0 ) ++ { ++ RF_Filter_Gain -= 1; ++ state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2); ++ CHK_ERROR(update_reg(state, RF_FILTER_1)); ++ msleep(10); ++ } ++ CHK_ERROR(status); ++ ++ state->m_Regs[RF_AGC_1] |= 0x08; ++ CHK_ERROR(update_reg(state, RF_AGC_1)); ++ } ++ ++ // --------------------------------------------------------------------------------- ++ ++ state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ ++ CHK_ERROR(update_reg(state, IRQ_CLEAR)); ++ ++ CHK_ERROR(PowerOn(state)); ++ ++ state->m_Regs[RF_FREQUENCY_1] = ((f >> 16) & 0xFF); ++ state->m_Regs[RF_FREQUENCY_2] = ((f >> 8) & 0xFF); ++ state->m_Regs[RF_FREQUENCY_3] = ((f ) & 0xFF); ++ CHK_ERROR(update_regs(state, RF_FREQUENCY_1,RF_FREQUENCY_3)); ++ ++ state->m_Regs[MSM_1] = 0x41; // Tune ++ state->m_Regs[MSM_2] = 0x01; // Start MSM ++ CHK_ERROR(update_regs(state, MSM_1, MSM_2)); ++ state->m_Regs[MSM_2] = 0x00; ++ ++ while(true) ++ { ++ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); ++ if( (IRQ & 0x80) != 0 ) break; ++ Timeout -= 1; ++ if (Timeout == 0) { ++ status = -1; ++ break; ++ } ++ msleep(10); ++ } ++ CHK_ERROR(status); ++ ++ // --------------------------------------------------------------------------------- ++ ++ if( state->m_isMaster && StandardParams->m_LTO_STO_immune ) ++ { ++ state->m_Regs[RF_AGC_1] &= ~0x08; ++ CHK_ERROR(update_reg(state, RF_AGC_1)); ++ ++ msleep(50); ++ ++ state->m_Regs[RF_FILTER_1] &= ~0x10; // remove force ++ CHK_ERROR(update_reg(state, RF_FILTER_1)); ++ } ++ ++ // --------------------------------------------------------------------------------- ++ // Spur reduction ++ ++ if( Frequency < 72000000 ) ++ { ++ state->m_Regs[REFERENCE] |= 0x40; // Set digital clock ++ } ++ else if( Frequency < 104000000 ) ++ { ++ state->m_Regs[REFERENCE] &= ~0x40; // Clear digital clock ++ } ++ else if( Frequency < 120000000 ) ++ { ++ state->m_Regs[REFERENCE] |= 0x40; // Set digital clock ++ } ++ else ++ { ++ if( fDelta <= 8000000 ) ++ { ++ if( fRatio & 1 ) state->m_Regs[REFERENCE] &= ~0x40; // Clear digital clock ++ else state->m_Regs[REFERENCE] |= 0x40; // Set digital clock ++ } ++ else ++ { ++ if( fRatio & 1 ) state->m_Regs[REFERENCE] |= 0x40; // Set digital clock ++ else state->m_Regs[REFERENCE] &= ~0x40; // Clear digital clock ++ } ++ ++ } ++ CHK_ERROR(update_reg(state, REFERENCE)); ++ ++ if( StandardParams->m_AGC1_Freeze && state->m_bEnableFreeze ) ++ { ++ u8 tmp; ++ int AGC1GainMin = 0; ++ int nSteps = 10; ++ int Step = 0; ++ ++ CHK_ERROR(read_reg(state, AGC1_2,&tmp)); ++ ++ if( (tmp & 0x80) == 0 ) ++ { ++ state->m_Regs[AGC1_2] |= 0x80; // Loop off ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ state->m_Regs[AGC1_2] |= 0x10 ; // Force gain ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ } ++ // Adapt ++ if( state->m_Regs[AGC1_1] & 0x40 ) // AGC1_6_15dB set ++ { ++ AGC1GainMin = 6; ++ nSteps = 4; ++ } ++ while( Step < nSteps ) ++ { ++ int Down = 0; ++ int Up = 0, i; ++ u8 AGC1_Gain; ++ ++ Step = Step + 1; ++ ++ for (i = 0; i < 40; i += 1) { ++ CHK_ERROR(read_reg(state, AGC_DET_OUT, &tmp)); ++ Up += (tmp & 0x02) ? 1 : -4; ++ Down += (tmp & 0x01) ? 14 : -1; ++ msleep(1); ++ } ++ CHK_ERROR(status); ++ AGC1_Gain = (state->m_Regs[AGC1_2] & 0x0F); ++ if( Up >= 15 && AGC1_Gain != 9 ) ++ { ++ state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain + 1); ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ } ++ else if ( Down >= 10 && AGC1_Gain != AGC1GainMin ) ++ { ++ state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain - 1); ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ } ++ else ++ { ++ Step = nSteps; ++ } ++ } ++ } ++ else ++ { ++ state->m_Regs[AGC1_2] &= ~0x10 ; // unforce gain ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ state->m_Regs[AGC1_2] &= ~0x80; // Loop on ++ CHK_ERROR(update_reg(state, AGC1_2)); ++ } ++ ++ state->m_Standard = Standard; ++ state->m_Frequency = Frequency; ++ ++ if( state->m_bPowerMeasurement ) ++ PowerMeasurement(state, &state->m_LastPowerLevel); ++ } while(0); ++ ++ return status; ++} ++ ++static int sleep(struct dvb_frontend* fe) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ ++ Standby(state); ++ return 0; ++} ++ ++static int init(struct dvb_frontend* fe) ++{ ++ //struct tda_state *state = fe->tuner_priv; ++ return 0; ++} ++ ++static int release(struct dvb_frontend* fe) ++{ ++ kfree(fe->tuner_priv); ++ fe->tuner_priv = NULL; ++ return 0; ++} ++ ++#ifdef USE_API3 ++static int set_params(struct dvb_frontend *fe, ++ struct dvb_frontend_parameters *params) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ int status = 0; ++ int Standard; ++ ++ state->m_Frequency = params->frequency; ++ ++ if (fe->ops.info.type == FE_OFDM) ++ switch (params->u.ofdm.bandwidth) { ++ case BANDWIDTH_6_MHZ: ++ Standard = HF_DVBT_6MHZ; ++ break; ++ case BANDWIDTH_7_MHZ: ++ Standard = HF_DVBT_7MHZ; ++ break; ++ default: ++ case BANDWIDTH_8_MHZ: ++ Standard = HF_DVBT_8MHZ; ++ break; ++ } ++ else if (fe->ops.info.type == FE_QAM) { ++ Standard = HF_DVBC_8MHZ; ++ } else ++ return -EINVAL; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ SetFrequency(state, state->m_Frequency, Standard); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ return status; ++} ++#else ++static int set_params(struct dvb_frontend *fe) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ int status = 0; ++ int Standard; ++ ++ state->m_Frequency = p->frequency; ++ ++ if (p->delivery_system == SYS_DVBT) ++ switch (p->bandwidth_hz) { ++ case 6000000: ++ Standard = HF_DVBT_6MHZ; ++ break; ++ case 7000000: ++ Standard = HF_DVBT_7MHZ; ++ break; ++ default: ++ case 8000000: ++ Standard = HF_DVBT_8MHZ; ++ break; ++ } ++ else if (p->delivery_system == SYS_DVBC_ANNEX_A) { ++ Standard = HF_DVBC_8MHZ; ++ } else ++ return -EINVAL; ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ SetFrequency(state, state->m_Frequency, Standard); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ ++ return status; ++} ++#endif ++ ++static int get_frequency(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ ++ *frequency = state->IF; ++ return 0; ++} ++ ++static int get_rf_strength(struct dvb_frontend *fe, u16 *st) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ ++ *st = state->m_LastPowerLevel; ++ return 0; ++} ++ ++static int get_if(struct dvb_frontend *fe, u32 *frequency) ++{ ++ struct tda_state *state = fe->tuner_priv; ++ ++ state->IF = 0; ++ if (state->m_Standard < HF_DVBT_6MHZ || ++ state->m_Standard > HF_DVBC_8MHZ) ++ return 0; ++ state->IF = m_StandardTable[state->m_Standard - HF_DVBT_6MHZ].m_IFFrequency; ++ *frequency = state->IF; ++ return 0; ++} ++ ++static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) ++{ ++ //struct tda_state *state = fe->tuner_priv; ++ //*bandwidth = priv->bandwidth; ++ return 0; ++} ++ ++ ++static struct dvb_tuner_ops tuner_ops = { ++ .info = { ++ .name = "NXP TDA18212", ++ .frequency_min = 47125000, ++ .frequency_max = 865000000, ++ .frequency_step = 62500 ++ }, ++ .init = init, ++ .sleep = sleep, ++ .set_params = set_params, ++ .release = release, ++ .get_frequency = get_frequency, ++ .get_if_frequency = get_if, ++ .get_bandwidth = get_bandwidth, ++ .get_rf_strength = get_rf_strength, ++}; ++ ++struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, u8 adr) ++{ ++ struct tda_state *state; ++ int stat; ++ ++ state = kzalloc(sizeof(struct tda_state), GFP_KERNEL); ++ if (!state) ++ return NULL; ++ state->adr = adr; ++ state->i2c = i2c; ++ memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops)); ++ init_state(state); ++ ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 1); ++ stat = attach_init(state); ++ if (fe->ops.i2c_gate_ctrl) ++ fe->ops.i2c_gate_ctrl(fe, 0); ++ if (stat < 0) { ++ kfree(state); ++ return 0; ++ } ++ fe->tuner_priv = state; ++ return fe; ++} ++ ++EXPORT_SYMBOL_GPL(tda18212dd_attach); ++MODULE_DESCRIPTION("TDA18212 driver"); ++MODULE_AUTHOR("DD"); ++MODULE_LICENSE("GPL"); ++ ++/* ++ * Local variables: ++ * c-basic-offset: 8 ++ * End: ++ */ +diff --git a/drivers/media/dvb-frontends/tda18212dd.h b/drivers/media/dvb-frontends/tda18212dd.h +new file mode 100644 +index 0000000..687fab4 +--- /dev/null ++++ b/drivers/media/dvb-frontends/tda18212dd.h +@@ -0,0 +1,5 @@ ++#ifndef _TDA18212DD_H_ ++#define _TDA18212DD_H_ ++struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe, ++ struct i2c_adapter *i2c, u8 adr); ++#endif +diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig +index 44e5dc1..0a4ae75 100644 +--- a/drivers/media/pci/ddbridge/Kconfig ++++ b/drivers/media/pci/ddbridge/Kconfig +@@ -1,11 +1,14 @@ + config DVB_DDBRIDGE + tristate "Digital Devices bridge support" + depends on DVB_CORE && PCI && I2C +- select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT +- select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT +- select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT +- select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT +- select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_CXD2099 ++ select DVB_LNBP21 if !DVB_FE_CUSTOMISE ++ select DVB_STV6110x if !DVB_FE_CUSTOMISE ++ select DVB_STV090x if !DVB_FE_CUSTOMISE ++ select DVB_DRXK if !DVB_FE_CUSTOMISE ++ select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE ++ select DVB_STV0367DD if !DVB_FE_CUSTOMISE ++ select DVB_TDA18212DD if !DVB_FE_CUSTOMISE + ---help--- + Support for cards with the Digital Devices PCI express bridge: + - Octopus PCIe Bridge +@@ -14,5 +17,6 @@ config DVB_DDBRIDGE + - DuoFlex S2 Octopus + - DuoFlex CT Octopus + - cineS2(v6) ++ - cineCT(v6) + + Say Y if you own such a card and want to use it. +diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c +index 36e3452..adff8cd 100644 +--- a/drivers/media/pci/ddbridge/ddbridge-core.c ++++ b/drivers/media/pci/ddbridge/ddbridge-core.c +@@ -31,11 +31,11 @@ + #include + #include + #include ++#include + #include + #include + #include + #include "ddbridge.h" +- + #include "ddbridge-regs.h" + + #include "tda18271c2dd.h" +@@ -43,14 +43,60 @@ + #include "stv090x.h" + #include "lnbh24.h" + #include "drxk.h" ++#if 0 ++#include "stv0367.h" ++#else ++#include "stv0367dd.h" ++#endif ++#if 0 ++#include "tda18212.h" ++#else ++#include "tda18212dd.h" ++#endif ++ ++static int adapter_alloc; ++module_param(adapter_alloc, int, 0444); ++MODULE_PARM_DESC(adapter_alloc, "0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all"); ++ ++static int ts_loop = -1; ++module_param(ts_loop, int, 0444); ++MODULE_PARM_DESC(ts_loop, "TS in/out on port ts_loop"); + + DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); + ++static struct ddb *ddbs[32]; ++ + /* MSI had problems with lost interrupts, fixed but needs testing */ +-#undef CONFIG_PCI_MSI ++/* #undef CONFIG_PCI_MSI */ ++ ++/******************************************************************************/ ++ ++static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr) ++{ ++ writel(val, (char *) (dev->regs+(adr))); ++} ++ ++static inline u32 ddbreadl(struct ddb *dev, u32 adr) ++{ ++ return readl((char *) (dev->regs+(adr))); ++} ++ ++#define ddbcpyto(_dev, _adr, _src, _count) memcpy_toio((char *) \ ++ (_dev->regs + (_adr)), (_src), (_count)) ++ ++#define ddbcpyfrom(_dev, _dst, _adr, _count) memcpy_fromio((_dst), (char *) \ ++ (_dev->regs + (_adr)), (_count)) ++ + + /******************************************************************************/ + ++static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) ++{ ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len}; ++ ++ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; ++} ++ + static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) + { + struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, +@@ -58,10 +104,31 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) + return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; + } + ++static int i2c_read_regs(struct i2c_adapter *adapter, ++ u8 adr, u8 reg, u8 *val, u8 len) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = ®, .len = 1}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ ++static int i2c_read_regs16(struct i2c_adapter *adapter, ++ u8 adr, u16 reg, u8 *val, u8 len) ++{ ++ u8 reg16[2] = { reg >> 8, reg }; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = (u8 *)®16, .len = 2}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = val, .len = len } }; ++ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; ++} ++ + static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) + { + struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, +- .buf = ®, .len = 1 }, ++ .buf = ®, .len = 1}, + {.addr = adr, .flags = I2C_M_RD, + .buf = val, .len = 1 } }; + return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; +@@ -70,14 +137,22 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) + static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, + u16 reg, u8 *val) + { +- u8 msg[2] = {reg>>8, reg&0xff}; ++ u8 msg[2] = {reg >> 8, reg & 0xff}; + struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, + .buf = msg, .len = 2}, + {.addr = adr, .flags = I2C_M_RD, +- .buf = val, .len = 1} }; ++ .buf = val, .len = 1 } }; + return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; + } + ++static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, ++ u16 reg, u8 val) ++{ ++ u8 msg[3] = {reg >> 8, reg & 0xff, val}; ++ ++ return i2c_write(adap, adr, msg, 3); ++} ++ + static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) + { + struct ddb *dev = i2c->dev; +@@ -85,18 +160,18 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) + u32 val; + + i2c->done = 0; +- ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND); ++ ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND); + stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ); + if (stat <= 0) { + printk(KERN_ERR "I2C timeout\n"); + { /* MSI debugging*/ +- u32 istat = ddbreadl(INTERRUPT_STATUS); ++ u32 istat = ddbreadl(dev, INTERRUPT_STATUS); + printk(KERN_ERR "IRS %08x\n", istat); +- ddbwritel(istat, INTERRUPT_ACK); ++ ddbwritel(dev, istat, INTERRUPT_ACK); + } + return -EIO; + } +- val = ddbreadl(i2c->regs+I2C_COMMAND); ++ val = ddbreadl(dev, i2c->regs+I2C_COMMAND); + if (val & 0x70000) + return -EIO; + return 0; +@@ -105,7 +180,7 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) + static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, + struct i2c_msg msg[], int num) + { +- struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter); ++ struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter); + struct ddb *dev = i2c->dev; + u8 addr = 0; + +@@ -116,8 +191,8 @@ static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, + !(msg[0].flags & I2C_M_RD)) { + memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf, + msg[0].buf, msg[0].len); +- ddbwritel(msg[0].len|(msg[1].len << 16), +- i2c->regs+I2C_TASKLENGTH); ++ ddbwritel(dev, msg[0].len|(msg[1].len << 16), ++ i2c->regs + I2C_TASKLENGTH); + if (!ddb_i2c_cmd(i2c, addr, 1)) { + memcpy_fromio(msg[1].buf, + dev->regs + I2C_TASKMEM_BASE + i2c->rbuf, +@@ -125,17 +200,16 @@ static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, + return num; + } + } +- + if (num == 1 && !(msg[0].flags & I2C_M_RD)) { +- ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len); +- ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH); ++ ddbcpyto(dev, I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len); ++ ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH); + if (!ddb_i2c_cmd(i2c, addr, 2)) + return num; + } + if (num == 1 && (msg[0].flags & I2C_M_RD)) { +- ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); ++ ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); + if (!ddb_i2c_cmd(i2c, addr, 3)) { +- ddbcpyfrom(msg[0].buf, ++ ddbcpyfrom(dev, msg[0].buf, + I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len); + return num; + } +@@ -160,7 +234,7 @@ static void ddb_i2c_release(struct ddb *dev) + struct ddb_i2c *i2c; + struct i2c_adapter *adap; + +- for (i = 0; i < dev->info->port_num; i++) { ++ for (i = 0; i < dev->info->i2c_num; i++) { + i2c = &dev->i2c[i]; + adap = &i2c->adap; + i2c_del_adapter(adap); +@@ -173,15 +247,15 @@ static int ddb_i2c_init(struct ddb *dev) + struct ddb_i2c *i2c; + struct i2c_adapter *adap; + +- for (i = 0; i < dev->info->port_num; i++) { ++ for (i = 0; i < dev->info->i2c_num; i++) { + i2c = &dev->i2c[i]; + i2c->dev = dev; + i2c->nr = i; + i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4); + i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8); + i2c->regs = 0x80 + i * 0x20; +- ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING); +- ddbwritel((i2c->rbuf << 16) | i2c->wbuf, ++ ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING); ++ ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf, + i2c->regs + I2C_TASKADDRESS); + init_waitqueue_head(&i2c->wq); + +@@ -216,69 +290,94 @@ static int ddb_i2c_init(struct ddb *dev) + /******************************************************************************/ + /******************************************************************************/ + +-#if 0 +-static void set_table(struct ddb *dev, u32 off, +- dma_addr_t *pbuf, u32 num) ++static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma) + { + u32 i, base; + u64 mem; + +- base = DMA_BASE_ADDRESS_TABLE + off; +- for (i = 0; i < num; i++) { +- mem = pbuf[i]; +- ddbwritel(mem & 0xffffffff, base + i * 8); +- ddbwritel(mem >> 32, base + i * 8 + 4); ++ if (!dma) ++ return; ++ base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100; ++ for (i = 0; i < dma->num; i++) { ++ mem = dma->pbuf[i]; ++ ddbwritel(dev, mem & 0xffffffff, base + i * 8); ++ ddbwritel(dev, mem >> 32, base + i * 8 + 4); + } ++ dma->bufreg = (dma->div << 16) | ++ ((dma->num & 0x1f) << 11) | ++ ((dma->size >> 7) & 0x7ff); + } +-#endif + +-static void ddb_address_table(struct ddb *dev) ++static void ddb_set_dma_tables(struct ddb *dev) + { +- u32 i, j, base; +- u64 mem; +- dma_addr_t *pbuf; ++ u32 i; + +- for (i = 0; i < dev->info->port_num * 2; i++) { +- base = DMA_BASE_ADDRESS_TABLE + i * 0x100; +- pbuf = dev->input[i].pbuf; +- for (j = 0; j < dev->input[i].dma_buf_num; j++) { +- mem = pbuf[j]; +- ddbwritel(mem & 0xffffffff, base + j * 8); +- ddbwritel(mem >> 32, base + j * 8 + 4); +- } +- } +- for (i = 0; i < dev->info->port_num; i++) { +- base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100; +- pbuf = dev->output[i].pbuf; +- for (j = 0; j < dev->output[i].dma_buf_num; j++) { +- mem = pbuf[j]; +- ddbwritel(mem & 0xffffffff, base + j * 8); +- ddbwritel(mem >> 32, base + j * 8 + 4); +- } +- } ++ for (i = 0; i < dev->info->port_num * 2; i++) ++ ddb_set_dma_table(dev, dev->input[i].dma); ++ for (i = 0; i < dev->info->port_num; i++) ++ ddb_set_dma_table(dev, dev->output[i].dma); + } + +-static void io_free(struct pci_dev *pdev, u8 **vbuf, +- dma_addr_t *pbuf, u32 size, int num) ++static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma) + { + int i; + +- for (i = 0; i < num; i++) { +- if (vbuf[i]) { +- pci_free_consistent(pdev, size, vbuf[i], pbuf[i]); +- vbuf[i] = 0; ++ if (!dma) ++ return; ++ for (i = 0; i < dma->num; i++) { ++ if (dma->vbuf[i]) { ++ pci_free_consistent(pdev, dma->size, ++ dma->vbuf[i], dma->pbuf[i]); ++ dma->vbuf[i] = 0; + } + } + } + +-static int io_alloc(struct pci_dev *pdev, u8 **vbuf, +- dma_addr_t *pbuf, u32 size, int num) ++static void ddb_redirect_dma(struct ddb *dev, ++ struct ddb_dma *sdma, ++ struct ddb_dma *ddma) ++{ ++ u32 i, base; ++ u64 mem; ++ ++ sdma->bufreg = ddma->bufreg; ++ base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100; ++ for (i = 0; i < ddma->num; i++) { ++ mem = ddma->pbuf[i]; ++ ddbwritel(dev, mem & 0xffffffff, base + i * 8); ++ ddbwritel(dev, mem >> 32, base + i * 8 + 4); ++ } ++} ++ ++static void ddb_unredirect(struct ddb_port *port) ++{ ++ struct ddb_input *ored, *ired; ++ ++ ored = port->output->redirect; ++ ired = port->input[0]->redirect; ++ ++ if (!ored || !ired) ++ return; ++ if (ired->port->output->redirect == port->input[0]) { ++ ired->port->output->redirect = ored; ++ ddb_set_dma_table(port->dev, port->input[0]->dma); ++ ddb_redirect_dma(ored->port->dev, ored->dma, ired->port->output->dma); ++ } else ++ ddb_set_dma_table(ored->port->dev, ored->dma); ++ ored->redirect = ired; ++ port->input[0]->redirect = 0; ++ port->output->redirect = 0; ++} ++ ++static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma) + { + int i; + +- for (i = 0; i < num; i++) { +- vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]); +- if (!vbuf[i]) ++ if (!dma) ++ return 0; ++ for (i = 0; i < dma->num; i++) { ++ dma->vbuf[i] = pci_alloc_consistent(pdev, dma->size, &dma->pbuf[i]); ++ if (!dma->vbuf[i]) + return -ENOMEM; + } + return 0; +@@ -293,34 +392,23 @@ static int ddb_buffers_alloc(struct ddb *dev) + port = &dev->port[i]; + switch (port->class) { + case DDB_PORT_TUNER: +- if (io_alloc(dev->pdev, port->input[0]->vbuf, +- port->input[0]->pbuf, +- port->input[0]->dma_buf_size, +- port->input[0]->dma_buf_num) < 0) ++ if (dma_alloc(dev->pdev, port->input[0]->dma) < 0) + return -1; +- if (io_alloc(dev->pdev, port->input[1]->vbuf, +- port->input[1]->pbuf, +- port->input[1]->dma_buf_size, +- port->input[1]->dma_buf_num) < 0) ++ if (dma_alloc(dev->pdev, port->input[1]->dma) < 0) + return -1; + break; + case DDB_PORT_CI: +- if (io_alloc(dev->pdev, port->input[0]->vbuf, +- port->input[0]->pbuf, +- port->input[0]->dma_buf_size, +- port->input[0]->dma_buf_num) < 0) ++ case DDB_PORT_LOOP: ++ if (dma_alloc(dev->pdev, port->input[0]->dma) < 0) + return -1; +- if (io_alloc(dev->pdev, port->output->vbuf, +- port->output->pbuf, +- port->output->dma_buf_size, +- port->output->dma_buf_num) < 0) ++ if (dma_alloc(dev->pdev, port->output->dma) < 0) + return -1; + break; + default: + break; + } + } +- ddb_address_table(dev); ++ ddb_set_dma_tables(dev); + return 0; + } + +@@ -331,18 +419,11 @@ static void ddb_buffers_free(struct ddb *dev) + + for (i = 0; i < dev->info->port_num; i++) { + port = &dev->port[i]; +- io_free(dev->pdev, port->input[0]->vbuf, +- port->input[0]->pbuf, +- port->input[0]->dma_buf_size, +- port->input[0]->dma_buf_num); +- io_free(dev->pdev, port->input[1]->vbuf, +- port->input[1]->pbuf, +- port->input[1]->dma_buf_size, +- port->input[1]->dma_buf_num); +- io_free(dev->pdev, port->output->vbuf, +- port->output->pbuf, +- port->output->dma_buf_size, +- port->output->dma_buf_num); ++ ++ ddb_unredirect(port); ++ dma_free(dev->pdev, port->input[0]->dma); ++ dma_free(dev->pdev, port->input[1]->dma); ++ dma_free(dev->pdev, port->output->dma); + } + } + +@@ -350,90 +431,116 @@ static void ddb_input_start(struct ddb_input *input) + { + struct ddb *dev = input->port->dev; + +- spin_lock_irq(&input->lock); +- input->cbuf = 0; +- input->coff = 0; ++ spin_lock_irq(&input->dma->lock); ++ input->dma->cbuf = 0; ++ input->dma->coff = 0; + + /* reset */ +- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); +- ddbwritel(2, TS_INPUT_CONTROL(input->nr)); +- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); ++ ddbwritel(dev, 2, TS_INPUT_CONTROL(input->nr)); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); + +- ddbwritel((1 << 16) | +- (input->dma_buf_num << 11) | +- (input->dma_buf_size >> 7), +- DMA_BUFFER_SIZE(input->nr)); +- ddbwritel(0, DMA_BUFFER_ACK(input->nr)); ++ ddbwritel(dev, input->dma->bufreg, DMA_BUFFER_SIZE(input->dma->nr)); ++ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); + +- ddbwritel(1, DMA_BASE_WRITE); +- ddbwritel(3, DMA_BUFFER_CONTROL(input->nr)); +- ddbwritel(9, TS_INPUT_CONTROL(input->nr)); +- input->running = 1; +- spin_unlock_irq(&input->lock); ++ ddbwritel(dev, 1, DMA_BASE_WRITE); ++ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr)); ++ ddbwritel(dev, 9, TS_INPUT_CONTROL(input->nr)); ++ input->dma->running = 1; ++ spin_unlock_irq(&input->dma->lock); ++ /* printk(KERN_INFO "input_start %d\n", input->nr); */ + } + + static void ddb_input_stop(struct ddb_input *input) + { + struct ddb *dev = input->port->dev; + +- spin_lock_irq(&input->lock); +- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); +- ddbwritel(0, DMA_BUFFER_CONTROL(input->nr)); +- input->running = 0; +- spin_unlock_irq(&input->lock); ++ spin_lock_irq(&input->dma->lock); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); ++ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); ++ input->dma->running = 0; ++ spin_unlock_irq(&input->dma->lock); + } + + static void ddb_output_start(struct ddb_output *output) + { + struct ddb *dev = output->port->dev; + +- spin_lock_irq(&output->lock); +- output->cbuf = 0; +- output->coff = 0; +- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel(2, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel((1 << 16) | +- (output->dma_buf_num << 11) | +- (output->dma_buf_size >> 7), +- DMA_BUFFER_SIZE(output->nr + 8)); +- ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8)); +- +- ddbwritel(1, DMA_BASE_READ); +- ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8)); +- /* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */ +- ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr)); +- output->running = 1; +- spin_unlock_irq(&output->lock); ++ spin_lock_irq(&output->dma->lock); ++ output->dma->cbuf = 0; ++ output->dma->coff = 0; ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, output->dma->bufreg, DMA_BUFFER_SIZE(output->dma->nr)); ++ ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); ++ ++ ddbwritel(dev, 1, DMA_BASE_READ); ++ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr)); ++ if (output->port->input[0]->port->class == DDB_PORT_LOOP) ++ ddbwritel(dev, 0x05, TS_OUTPUT_CONTROL(output->nr)); ++ else ++ ddbwritel(dev, 0x1d, TS_OUTPUT_CONTROL(output->nr)); ++ output->dma->running = 1; ++ spin_unlock_irq(&output->dma->lock); ++ /* printk(KERN_INFO "output_start %d\n", output->nr); */ ++} ++ ++#if 0 ++static void ddb_input_start_all(struct ddb_input *input) ++{ ++ struct ddb_input *next; ++ ++ ddb_input_start(input); ++ while ((next = input->redirect) && ++ next != input) { ++ ddb_input_start(next); ++ ddb_output_start(next->port->output); ++ } + } ++#endif + + static void ddb_output_stop(struct ddb_output *output) + { + struct ddb *dev = output->port->dev; + +- spin_lock_irq(&output->lock); +- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); +- ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8)); +- output->running = 0; +- spin_unlock_irq(&output->lock); ++ spin_lock_irq(&output->dma->lock); ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); ++ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); ++ output->dma->running = 0; ++ spin_unlock_irq(&output->dma->lock); ++} ++ ++#if 0 ++static void ddb_input_stop_all(struct ddb_input *input) ++{ ++ struct ddb_input *next; ++ ++ ddb_input_stop(input); ++ while ((next = input->redirect) && ++ next != input) { ++ ddb_input_stop(next); ++ ddb_output_stop(next->port->output); ++ } + } ++#endif + + static u32 ddb_output_free(struct ddb_output *output) + { +- u32 idx, off, stat = output->stat; ++ u32 idx, off, stat = output->dma->stat; + s32 diff; + + idx = (stat >> 11) & 0x1f; + off = (stat & 0x7ff) << 7; + +- if (output->cbuf != idx) { +- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && +- (output->dma_buf_size - output->coff <= 188)) ++ if (output->dma->cbuf != idx) { ++ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && ++ (output->dma->size - output->dma->coff <= 188)) + return 0; + return 188; + } +- diff = off - output->coff; ++ diff = off - output->dma->coff; + if (diff <= 0 || diff > 188) + return 188; + return 0; +@@ -443,24 +550,24 @@ static ssize_t ddb_output_write(struct ddb_output *output, + const u8 *buf, size_t count) + { + struct ddb *dev = output->port->dev; +- u32 idx, off, stat = output->stat; ++ u32 idx, off, stat = output->dma->stat; + u32 left = count, len; + + idx = (stat >> 11) & 0x1f; + off = (stat & 0x7ff) << 7; + + while (left) { +- len = output->dma_buf_size - output->coff; +- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && ++ len = output->dma->size - output->dma->coff; ++ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && + (off == 0)) { + if (len <= 188) + break; + len -= 188; + } +- if (output->cbuf == idx) { +- if (off > output->coff) { ++ if (output->dma->cbuf == idx) { ++ if (off > output->dma->coff) { + #if 1 +- len = off - output->coff; ++ len = off - output->dma->coff; + len -= (len % 188); + if (len <= 188) + +@@ -471,68 +578,146 @@ static ssize_t ddb_output_write(struct ddb_output *output, + } + if (len > left) + len = left; +- if (copy_from_user(output->vbuf[output->cbuf] + output->coff, ++ if (copy_from_user(output->dma->vbuf[output->dma->cbuf] + ++ output->dma->coff, + buf, len)) + return -EIO; ++ /* printk("cfu %d %d %d\n", len, output->cbuf, output->coff); */ + left -= len; + buf += len; +- output->coff += len; +- if (output->coff == output->dma_buf_size) { +- output->coff = 0; +- output->cbuf = ((output->cbuf + 1) % output->dma_buf_num); ++ output->dma->coff += len; ++ if (output->dma->coff == output->dma->size) { ++ output->dma->coff = 0; ++ output->dma->cbuf = ((output->dma->cbuf + 1) % ++ output->dma->num); + } +- ddbwritel((output->cbuf << 11) | (output->coff >> 7), +- DMA_BUFFER_ACK(output->nr + 8)); ++ ddbwritel(dev, (output->dma->cbuf << 11) | (output->dma->coff >> 7), ++ DMA_BUFFER_ACK(output->dma->nr)); + } + return count - left; + } + ++#if 0 ++static u32 ddb_input_free_bytes(struct ddb_input *input) ++{ ++ struct ddb *dev = input->port->dev; ++ u32 idx, off, stat = input->dma->stat; ++ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); ++ ++ idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; ++ ++ if (ctrl & 4) ++ return 0; ++ if (input->dma->cbuf != idx) ++ return 1; ++ return 0; ++} ++ ++static s32 ddb_output_used_bufs(struct ddb_output *output) ++{ ++ u32 idx, off, stat, ctrl; ++ s32 diff; ++ ++ spin_lock_irq(&output->dma->lock); ++ stat = output->dma->stat; ++ ctrl = output->dma->ctrl; ++ spin_unlock_irq(&output->dma->lock); ++ ++ idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; ++ ++ if (ctrl & 4) ++ return 0; ++ diff = output->dma->cbuf - idx; ++ if (diff == 0 && off < output->dma->coff) ++ return 0; ++ if (diff <= 0) ++ diff += output->dma->num; ++ return diff; ++} ++ ++static s32 ddb_input_free_bufs(struct ddb_input *input) ++{ ++ u32 idx, off, stat, ctrl; ++ s32 free; ++ ++ spin_lock_irq(&input->dma->lock); ++ ctrl = input->dma->ctrl; ++ stat = input->dma->stat; ++ spin_unlock_irq(&input->dma->lock); ++ if (ctrl & 4) ++ return 0; ++ idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; ++ free = input->dma->cbuf - idx; ++ if (free == 0 && off < input->dma->coff) ++ return 0; ++ if (free <= 0) ++ free += input->dma->num; ++ return free - 1; ++} ++ ++static u32 ddb_output_ok(struct ddb_output *output) ++{ ++ struct ddb_input *input = output->port->input[0]; ++ s32 diff; ++ ++ diff = ddb_input_free_bufs(input) - ddb_output_used_bufs(output); ++ if (diff > 0) ++ return 1; ++ return 0; ++} ++#endif ++ + static u32 ddb_input_avail(struct ddb_input *input) + { + struct ddb *dev = input->port->dev; +- u32 idx, off, stat = input->stat; +- u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr)); ++ u32 idx, off, stat = input->dma->stat; ++ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); + + idx = (stat >> 11) & 0x1f; + off = (stat & 0x7ff) << 7; + + if (ctrl & 4) { + printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl); +- ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr)); ++ ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr)); + return 0; + } +- if (input->cbuf != idx) ++ if (input->dma->cbuf != idx || off < input->dma->coff) + return 188; + return 0; + } + +-static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count) ++static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count) + { + struct ddb *dev = input->port->dev; + u32 left = count; +- u32 idx, free, stat = input->stat; ++ u32 idx, off, free, stat = input->dma->stat; + int ret; + + idx = (stat >> 11) & 0x1f; ++ off = (stat & 0x7ff) << 7; + + while (left) { +- if (input->cbuf == idx) ++ if (input->dma->cbuf == idx) + return count - left; +- free = input->dma_buf_size - input->coff; ++ free = input->dma->size - input->dma->coff; + if (free > left) + free = left; +- ret = copy_to_user(buf, input->vbuf[input->cbuf] + +- input->coff, free); ++ ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] + ++ input->dma->coff, free); + if (ret) + return -EFAULT; +- input->coff += free; +- if (input->coff == input->dma_buf_size) { +- input->coff = 0; +- input->cbuf = (input->cbuf+1) % input->dma_buf_num; ++ input->dma->coff += free; ++ if (input->dma->coff == input->dma->size) { ++ input->dma->coff = 0; ++ input->dma->cbuf = (input->dma->cbuf+1) % ++ input->dma->num; + } + left -= free; +- ddbwritel((input->cbuf << 11) | (input->coff >> 7), +- DMA_BUFFER_ACK(input->nr)); ++ ddbwritel(dev, (input->dma->cbuf << 11) | (input->dma->coff >> 7), ++ DMA_BUFFER_ACK(input->dma->nr)); + } + return count; + } +@@ -554,7 +739,7 @@ static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe) + } + #endif + +-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) ++static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) + { + struct ddb_input *input = fe->sec_priv; + struct ddb_port *port = input->port; +@@ -562,9 +747,9 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) + + if (enable) { + mutex_lock(&port->i2c_gate_lock); +- status = input->gate_ctrl(fe, 1); ++ status = input->dvb.gate_ctrl(fe, 1); + } else { +- status = input->gate_ctrl(fe, 0); ++ status = input->dvb.gate_ctrl(fe, 0); + mutex_unlock(&port->i2c_gate_lock); + } + return status; +@@ -577,18 +762,88 @@ static int demod_attach_drxk(struct ddb_input *input) + struct drxk_config config; + + memset(&config, 0, sizeof(config)); +- config.microcode_name = "drxk_a3.mc"; +- config.qam_demod_parameter_count = 4; + config.adr = 0x29 + (input->nr & 1); ++ config.microcode_name = "drxk_a3.mc"; + +- fe = input->fe = dvb_attach(drxk_attach, &config, i2c); +- if (!input->fe) { ++#ifdef USE_API3 ++ fe = input->dvb.fe = dvb_attach(drxk_attach, &config, i2c, &input->dvb.fe2); ++#else ++ fe = input->dvb.fe = dvb_attach(drxk_attach, &config, i2c); ++#endif ++ if (!input->dvb.fe) { + printk(KERN_ERR "No DRXK found!\n"); + return -ENODEV; + } + fe->sec_priv = input; +- input->gate_ctrl = fe->ops.i2c_gate_ctrl; +- fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; ++ input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl; ++ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++ ++#if 0 ++struct stv0367_config stv0367_0 = { ++ .demod_address = 0x1f, ++ .xtal = 27000000, ++ .if_khz = 5000, ++ .if_iq_mode = FE_TER_NORMAL_IF_TUNER, ++ .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, ++ .clk_pol = STV0367_RISINGEDGE_CLOCK, ++}; ++ ++struct stv0367_config stv0367_1 = { ++ .demod_address = 0x1e, ++ .xtal = 27000000, ++ .if_khz = 5000, ++ .if_iq_mode = FE_TER_NORMAL_IF_TUNER, ++ .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, ++ .clk_pol = STV0367_RISINGEDGE_CLOCK, ++}; ++ ++ ++static int demod_attach_stv0367(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct dvb_frontend *fe; ++ ++ fe = input->dvb.fe = dvb_attach(stv0367ter_attach, ++ (input->nr & 1) ? &stv0367_1 : &stv0367_0, ++ i2c); ++ if (!input->dvb.fe) { ++ printk(KERN_ERR "No stv0367 found!\n"); ++ return -ENODEV; ++ } ++ fe->sec_priv = input; ++ input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl; ++ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++#endif ++ ++struct stv0367_cfg stv0367dd_0 = { ++ .adr = 0x1f, ++ .xtal = 27000000, ++}; ++ ++struct stv0367_cfg stv0367dd_1 = { ++ .adr = 0x1e, ++ .xtal = 27000000, ++}; ++ ++static int demod_attach_stv0367dd(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct dvb_frontend *fe; ++ ++ fe = input->dvb.fe = dvb_attach(stv0367_attach, i2c, ++ (input->nr & 1) ? &stv0367dd_1 : &stv0367dd_0, ++ &input->dvb.fe2); ++ if (!input->dvb.fe) { ++ printk(KERN_ERR "No stv0367 found!\n"); ++ return -ENODEV; ++ } ++ fe->sec_priv = input; ++ input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl; ++ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; + return 0; + } + +@@ -597,18 +852,57 @@ static int tuner_attach_tda18271(struct ddb_input *input) + struct i2c_adapter *i2c = &input->port->i2c->adap; + struct dvb_frontend *fe; + +- if (input->fe->ops.i2c_gate_ctrl) +- input->fe->ops.i2c_gate_ctrl(input->fe, 1); +- fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60); ++ if (input->dvb.fe->ops.i2c_gate_ctrl) ++ input->dvb.fe->ops.i2c_gate_ctrl(input->dvb.fe, 1); ++ fe = dvb_attach(tda18271c2dd_attach, input->dvb.fe, i2c, 0x60); ++ if (input->dvb.fe->ops.i2c_gate_ctrl) ++ input->dvb.fe->ops.i2c_gate_ctrl(input->dvb.fe, 0); + if (!fe) { + printk(KERN_ERR "No TDA18271 found!\n"); + return -ENODEV; + } +- if (input->fe->ops.i2c_gate_ctrl) +- input->fe->ops.i2c_gate_ctrl(input->fe, 0); + return 0; + } + ++static int tuner_attach_tda18212dd(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct dvb_frontend *fe; ++ ++ fe = dvb_attach(tda18212dd_attach, input->dvb.fe, i2c, ++ (input->nr & 1) ? 0x63 : 0x60); ++ if (!fe) { ++ printk(KERN_ERR "No TDA18212 found!\n"); ++ return -ENODEV; ++ } ++ return 0; ++} ++ ++#if 0 ++struct tda18212_config tda18212_0 = { ++ .i2c_address = 0x60, ++}; ++ ++struct tda18212_config tda18212_1 = { ++ .i2c_address = 0x63, ++}; ++ ++static int tuner_attach_tda18212(struct ddb_input *input) ++{ ++ struct i2c_adapter *i2c = &input->port->i2c->adap; ++ struct dvb_frontend *fe; ++ struct tda18212_config *cfg; ++ ++ cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0; ++ fe = dvb_attach(tda18212_attach, input->dvb.fe, i2c, cfg); ++ if (!fe) { ++ printk(KERN_ERR "No TDA18212 found!\n"); ++ return -ENODEV; ++ } ++ return 0; ++} ++#endif ++ + /******************************************************************************/ + /******************************************************************************/ + /******************************************************************************/ +@@ -668,14 +962,14 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) + struct i2c_adapter *i2c = &input->port->i2c->adap; + struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; + +- input->fe = dvb_attach(stv090x_attach, feconf, i2c, ++ input->dvb.fe = dvb_attach(stv090x_attach, feconf, i2c, + (input->nr & 1) ? STV090x_DEMODULATOR_1 + : STV090x_DEMODULATOR_0); +- if (!input->fe) { ++ if (!input->dvb.fe) { + printk(KERN_ERR "No STV0900 found!\n"); + return -ENODEV; + } +- if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0, ++ if (!dvb_attach(lnbh24_attach, input->dvb.fe, i2c, 0, + 0, (input->nr & 1) ? + (0x09 - type) : (0x0b - type))) { + printk(KERN_ERR "No LNBH24 found!\n"); +@@ -692,7 +986,7 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) + &stv6110b : &stv6110a; + struct stv6110x_devctl *ctl; + +- ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); ++ ctl = dvb_attach(stv6110x_attach, input->dvb.fe, tunerconf, i2c); + if (!ctl) { + printk(KERN_ERR "No STV6110X found!\n"); + return -ENODEV; +@@ -760,10 +1054,10 @@ static int start_feed(struct dvb_demux_feed *dvbdmxfeed) + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ddb_input *input = dvbdmx->priv; + +- if (!input->users) ++ if (!input->dvb.users) + ddb_input_start(input); + +- return ++input->users; ++ return ++input->dvb.users; + } + + static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) +@@ -771,8 +1065,8 @@ static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ddb_input *input = dvbdmx->priv; + +- if (--input->users) +- return input->users; ++ if (--input->dvb.users) ++ return input->dvb.users; + + ddb_input_stop(input); + return 0; +@@ -781,116 +1075,200 @@ static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) + + static void dvb_input_detach(struct ddb_input *input) + { +- struct dvb_adapter *adap = &input->adap; +- struct dvb_demux *dvbdemux = &input->demux; ++ struct dvb_demux *dvbdemux = &input->dvb.demux; + +- switch (input->attached) { ++ switch (input->dvb.attached) { ++ case 6: ++ if (input->dvb.fe2) ++ dvb_unregister_frontend(input->dvb.fe2); ++ if (input->dvb.fe) ++ dvb_unregister_frontend(input->dvb.fe); + case 5: +- if (input->fe2) +- dvb_unregister_frontend(input->fe2); +- if (input->fe) { +- dvb_unregister_frontend(input->fe); +- dvb_frontend_detach(input->fe); +- input->fe = NULL; +- } ++ dvb_frontend_detach(input->dvb.fe); ++ input->dvb.fe = NULL; + case 4: +- dvb_net_release(&input->dvbnet); +- ++ dvb_net_release(&input->dvb.dvbnet); + case 3: + dvbdemux->dmx.close(&dvbdemux->dmx); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, +- &input->hw_frontend); ++ &input->dvb.hw_frontend); + dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, +- &input->mem_frontend); +- dvb_dmxdev_release(&input->dmxdev); +- ++ &input->dvb.mem_frontend); ++ dvb_dmxdev_release(&input->dvb.dmxdev); + case 2: +- dvb_dmx_release(&input->demux); +- ++ dvb_dmx_release(&input->dvb.demux); + case 1: +- dvb_unregister_adapter(adap); ++ break; + } +- input->attached = 0; ++ input->dvb.attached = 0; + } + ++static int dvb_register_adapters(struct ddb *dev) ++{ ++ int i, ret = 0; ++ struct ddb_port *port; ++ struct dvb_adapter *adap; ++ ++ if (adapter_alloc == 3) { ++ port = &dev->port[0]; ++ adap = port->input[0]->dvb.adap; ++ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, ++ &port->dev->pdev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->input[0]->dvb.adap_registered = 1; ++ for (i = 0; i < dev->info->port_num; i++) { ++ port = &dev->port[i]; ++ port->input[0]->dvb.adap = adap; ++ port->input[1]->dvb.adap = adap; ++ } ++ return 0; ++ } ++ ++ for (i = 0; i < dev->info->port_num; i++) { ++ port = &dev->port[i]; ++ switch (port->class) { ++ case DDB_PORT_TUNER: ++ adap = port->input[0]->dvb.adap; ++ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, ++ &port->dev->pdev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->input[0]->dvb.adap_registered = 1; ++ ++ if (adapter_alloc > 0) { ++ port->input[1]->dvb.adap = port->input[0]->dvb.adap; ++ break; ++ } ++ adap = port->input[1]->dvb.adap; ++ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, ++ &port->dev->pdev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->input[1]->dvb.adap_registered = 1; ++ break; ++ ++ case DDB_PORT_CI: ++ case DDB_PORT_LOOP: ++ adap = port->input[0]->dvb.adap; ++ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, ++ &port->dev->pdev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->input[0]->dvb.adap_registered = 1; ++ break; ++ default: ++ if (adapter_alloc < 2) ++ break; ++ adap = port->input[0]->dvb.adap; ++ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, ++ &port->dev->pdev->dev, ++ adapter_nr); ++ if (ret < 0) ++ return ret; ++ port->input[0]->dvb.adap_registered = 1; ++ break; ++ } ++ } ++ return ret; ++} ++ ++static void dvb_unregister_adapters(struct ddb *dev) ++{ ++ int i; ++ struct ddb_port *port; ++ struct ddb_input *input; ++ ++ for (i = 0; i < dev->info->port_num; i++) { ++ port = &dev->port[i]; ++ ++ input = port->input[0]; ++ if (input->dvb.adap_registered) ++ dvb_unregister_adapter(input->dvb.adap); ++ input->dvb.adap_registered = 0; ++ ++ input = port->input[1]; ++ if (input->dvb.adap_registered) ++ dvb_unregister_adapter(input->dvb.adap); ++ input->dvb.adap_registered = 0; ++ } ++} ++ ++ + static int dvb_input_attach(struct ddb_input *input) + { +- int ret; ++ int ret = 0; + struct ddb_port *port = input->port; +- struct dvb_adapter *adap = &input->adap; +- struct dvb_demux *dvbdemux = &input->demux; +- +- ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, +- &input->port->dev->pdev->dev, +- adapter_nr); +- if (ret < 0) { +- printk(KERN_ERR "ddbridge: Could not register adapter." +- "Check if you enabled enough adapters in dvb-core!\n"); +- return ret; +- } +- input->attached = 1; ++ struct dvb_adapter *adap = input->dvb.adap; ++ struct dvb_demux *dvbdemux = &input->dvb.demux; ++ ++ input->dvb.attached = 1; + + ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", + start_feed, + stop_feed, input); + if (ret < 0) + return ret; +- input->attached = 2; ++ input->dvb.attached = 2; + +- ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux, +- &input->hw_frontend, +- &input->mem_frontend, adap); ++ ret = my_dvb_dmxdev_ts_card_init(&input->dvb.dmxdev, ++ &input->dvb.demux, ++ &input->dvb.hw_frontend, ++ &input->dvb.mem_frontend, adap); + if (ret < 0) + return ret; +- input->attached = 3; ++ input->dvb.attached = 3; + +- ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux); ++ ret = dvb_net_init(adap, &input->dvb.dvbnet, input->dvb.dmxdev.demux); + if (ret < 0) + return ret; +- input->attached = 4; ++ input->dvb.attached = 4; + +- input->fe = 0; ++ input->dvb.fe = 0; + switch (port->type) { + case DDB_TUNER_DVBS_ST: + if (demod_attach_stv0900(input, 0) < 0) + return -ENODEV; + if (tuner_attach_stv6110(input, 0) < 0) + return -ENODEV; +- if (input->fe) { +- if (dvb_register_frontend(adap, input->fe) < 0) +- return -ENODEV; +- } + break; + case DDB_TUNER_DVBS_ST_AA: + if (demod_attach_stv0900(input, 1) < 0) + return -ENODEV; + if (tuner_attach_stv6110(input, 1) < 0) + return -ENODEV; +- if (input->fe) { +- if (dvb_register_frontend(adap, input->fe) < 0) +- return -ENODEV; +- } + break; + case DDB_TUNER_DVBCT_TR: + if (demod_attach_drxk(input) < 0) + return -ENODEV; + if (tuner_attach_tda18271(input) < 0) + return -ENODEV; +- if (input->fe) { +- if (dvb_register_frontend(adap, input->fe) < 0) +- return -ENODEV; +- } +- if (input->fe2) { +- if (dvb_register_frontend(adap, input->fe2) < 0) +- return -ENODEV; +- input->fe2->tuner_priv = input->fe->tuner_priv; +- memcpy(&input->fe2->ops.tuner_ops, +- &input->fe->ops.tuner_ops, +- sizeof(struct dvb_tuner_ops)); +- } + break; ++ case DDB_TUNER_DVBCT_ST: ++ if (demod_attach_stv0367dd(input) < 0) ++ return -ENODEV; ++ if (tuner_attach_tda18212dd(input) < 0) ++ return -ENODEV; ++ break; ++ } ++ input->dvb.attached = 5; ++ if (input->dvb.fe) { ++ if (dvb_register_frontend(adap, input->dvb.fe) < 0) ++ return -ENODEV; + } +- input->attached = 5; ++ if (input->dvb.fe2) { ++ if (dvb_register_frontend(adap, input->dvb.fe2) < 0) ++ return -ENODEV; ++ input->dvb.fe2->tuner_priv = input->dvb.fe->tuner_priv; ++ memcpy(&input->dvb.fe2->ops.tuner_ops, ++ &input->dvb.fe->ops.tuner_ops, ++ sizeof(struct dvb_tuner_ops)); ++ } ++ input->dvb.attached = 6; + return 0; + } + +@@ -910,7 +1288,8 @@ static ssize_t ts_write(struct file *file, const char *buf, + if (file->f_flags & O_NONBLOCK) + break; + if (wait_event_interruptible( +- output->wq, ddb_output_free(output) >= 188) < 0) ++ output->dma->wq, ++ ddb_output_free(output) >= 188) < 0) + break; + } + stat = ddb_output_write(output, buf, left); +@@ -937,7 +1316,7 @@ static ssize_t ts_read(struct file *file, char *buf, + if (file->f_flags & O_NONBLOCK) + break; + if (wait_event_interruptible( +- input->wq, ddb_input_avail(input) >= 188) < 0) ++ input->dma->wq, ddb_input_avail(input) >= 188) < 0) + break; + } + read = ddb_input_read(input, buf, left); +@@ -970,21 +1349,53 @@ static unsigned int ts_poll(struct file *file, poll_table *wait) + return mask; + } + +-static const struct file_operations ci_fops = { +- .owner = THIS_MODULE, +- .read = ts_read, +- .write = ts_write, +- .open = dvb_generic_open, +- .release = dvb_generic_release, +- .poll = ts_poll, +- .mmap = 0, +-}; +- ++#if 0 ++static int ts_release(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ struct ddb_input *input = output->port->input[0]; ++ ++ ++ return dvb_generic_release(inode, file); ++} ++ ++static unsigned int ts_open(struct inode *inode, struct file *file) ++{ ++ int err; ++ struct dvb_device *dvbdev = file->private_data; ++ struct ddb_output *output = dvbdev->priv; ++ struct ddb_input *input = output->port->input[0]; ++ ++ err = dvb_generic_open(inode, file); ++ if (err < 0) ++ return err; ++ ++#if 0 ++ if ((file->f_flags & O_ACCMODE) == O_RDONLY) ++ ddb_input_start(input); ++ else ++ ddb_output_start(output); ++#endif ++ return err; ++} ++#endif ++ ++static const struct file_operations ci_fops = { ++ .owner = THIS_MODULE, ++ .read = ts_read, ++ .write = ts_write, ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++ .poll = ts_poll, ++ .mmap = 0, ++}; ++ + static struct dvb_device dvbdev_ci = { + .priv = 0, +- .readers = -1, +- .writers = -1, +- .users = -1, ++ .readers = 1, ++ .writers = 1, ++ .users = 2, + .fops = &ci_fops, + }; + +@@ -992,53 +1403,297 @@ static struct dvb_device dvbdev_ci = { + /****************************************************************************/ + /****************************************************************************/ + ++static int set_redirect(u32 i, u32 p) ++{ ++ struct ddb *idev = ddbs[(i >> 4) & 0x1f]; ++ struct ddb_input *input; ++ struct ddb *pdev = ddbs[(p >> 4) & 0x1f]; ++ struct ddb_port *port; ++ ++ if (!idev || !pdev) ++ return -EINVAL; ++ ++ port = &pdev->port[p & 3]; ++ if (port->class != DDB_PORT_CI && port->class != DDB_PORT_LOOP) ++ return -EINVAL; ++ ++ ddb_unredirect(port); ++ if (i == 8) ++ return 0; ++ input = &idev->input[i & 7]; ++ if (input->port->class != DDB_PORT_TUNER) ++ port->input[0]->redirect = input->redirect; ++ else ++ port->input[0]->redirect = input; ++ input->redirect = port->input[0]; ++ port->output->redirect = input; ++ ++ ddb_redirect_dma(input->port->dev, input->dma, port->output->dma); ++ return 0; ++} ++ ++static void input_write_output(struct ddb_input *input, ++ struct ddb_output *output) ++{ ++ ddbwritel(output->port->dev, ++ input->dma->stat, DMA_BUFFER_ACK(output->dma->nr)); ++} ++ ++static void output_ack_input(struct ddb_output *output, ++ struct ddb_input *input) ++{ ++ ddbwritel(input->port->dev, ++ output->dma->stat, DMA_BUFFER_ACK(input->dma->nr)); ++} ++ ++static void input_write_dvb(struct ddb_input *input, struct ddb_dvb *dvb) ++{ ++ struct ddb_dma *dma = input->dma; ++ struct ddb *dev = input->port->dev; ++ ++ if (4 & ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr))) ++ printk(KERN_ERR "Overflow dma %d\n", dma->nr); ++ while (dma->cbuf != ((dma->stat >> 11) & 0x1f) ++ || (4 & ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)))) { ++ dvb_dmx_swfilter_packets(&dvb->demux, ++ dma->vbuf[dma->cbuf], ++ dma->size / 188); ++ dma->cbuf = (dma->cbuf + 1) % dma->num; ++ ddbwritel(dev, (dma->cbuf << 11), DMA_BUFFER_ACK(dma->nr)); ++ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); ++ } ++} ++ + static void input_tasklet(unsigned long data) + { + struct ddb_input *input = (struct ddb_input *) data; ++ struct ddb_dma *dma = input->dma; + struct ddb *dev = input->port->dev; + +- spin_lock(&input->lock); +- if (!input->running) { +- spin_unlock(&input->lock); ++ spin_lock(&dma->lock); ++ if (!dma->running) { ++ spin_unlock(&dma->lock); + return; + } +- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); ++ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); + + if (input->port->class == DDB_PORT_TUNER) { +- if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr))) +- printk(KERN_ERR "Overflow input %d\n", input->nr); +- while (input->cbuf != ((input->stat >> 11) & 0x1f) +- || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) { +- dvb_dmx_swfilter_packets(&input->demux, +- input->vbuf[input->cbuf], +- input->dma_buf_size / 188); +- +- input->cbuf = (input->cbuf + 1) % input->dma_buf_num; +- ddbwritel((input->cbuf << 11), +- DMA_BUFFER_ACK(input->nr)); +- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); +- } ++ if (input->redirect) ++ input_write_output(input, ++ input->redirect->port->output); ++ else ++ input_write_dvb(input, &input->dvb); ++ } ++ if (input->port->class == DDB_PORT_CI || ++ input->port->class == DDB_PORT_LOOP) { ++ if (input->redirect) { ++ if (input->redirect->port->class == DDB_PORT_TUNER) ++ input_write_dvb(input, &input->redirect->dvb); ++ else ++ input_write_output(input, ++ input->redirect->port->output); ++ } else ++ wake_up(&dma->wq); + } +- if (input->port->class == DDB_PORT_CI) +- wake_up(&input->wq); +- spin_unlock(&input->lock); ++ spin_unlock(&dma->lock); + } + + static void output_tasklet(unsigned long data) + { + struct ddb_output *output = (struct ddb_output *) data; ++ struct ddb_dma *dma = output->dma; + struct ddb *dev = output->port->dev; + +- spin_lock(&output->lock); +- if (!output->running) { +- spin_unlock(&output->lock); ++ spin_lock(&dma->lock); ++ if (!dma->running) { ++ spin_unlock(&dma->lock); + return; + } +- output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8)); +- wake_up(&output->wq); +- spin_unlock(&output->lock); ++ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); ++ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); ++ if (output->redirect) ++ output_ack_input(output, output->redirect); ++ wake_up(&dma->wq); ++ spin_unlock(&dma->lock); ++} ++ ++#if 0 ++static void io_tasklet(unsigned long data) ++{ ++ struct ddb_dma *dma = (struct ddb_dma *) data; ++ ++ spin_lock(&dma->lock); ++ if (!dma->running) { ++ spin_unlock(&dma->lock); ++ return; ++ } ++ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); ++ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); ++ if (dma->nr & 8) ++ handle_output((struct ddb_output *) dma->io); ++ else ++ handle_input((struct ddb_input *) dma->io); ++ wake_up(&dma->wq); ++ spin_unlock(&dma->lock); ++} ++#endif ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ ++static int wait_ci_ready(struct ddb_ci *ci) ++{ ++ u32 count = 100; ++ ++ do { ++ if (ddbreadl(ci->port->dev, ++ CI_CONTROL(ci->nr)) & CI_READY) ++ break; ++ msleep(1); ++ if ((--count) == 0) ++ return -1; ++ } while (1); ++ return 0; ++} ++ ++static int read_attribute_mem(struct dvb_ca_en50221 *ca, ++ int slot, int address) ++{ ++ struct ddb_ci *ci = ca->data; ++ u32 val, off = (address >> 1) & (CI_BUFFER_SIZE-1); ++ ++ if (address > CI_BUFFER_SIZE) ++ return -1; ++ ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, ++ CI_DO_READ_ATTRIBUTES(ci->nr)); ++ wait_ci_ready(ci); ++ val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); ++ /* printk("%04x: %02x\n", address, val); */ ++ return val; ++} ++ ++static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, ++ int address, u8 value) ++{ ++ struct ddb_ci *ci = ca->data; ++ ++ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, ++ CI_DO_ATTRIBUTE_RW(ci->nr)); ++ wait_ci_ready(ci); ++ return 0; ++} ++ ++static int read_cam_control(struct dvb_ca_en50221 *ca, ++ int slot, u8 address) ++{ ++ u32 count = 100; ++ struct ddb_ci *ci = ca->data; ++ u32 res; ++ ++ ddbwritel(ci->port->dev, CI_READ_CMD | address, ++ CI_DO_IO_RW(ci->nr)); ++ do { ++ res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); ++ if (res & CI_READY) ++ break; ++ msleep(1); ++ if ((--count) == 0) ++ return -1; ++ } while (1); ++ return 0xff & res; ++} ++ ++static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, ++ u8 address, u8 value) ++{ ++ struct ddb_ci *ci = ca->data; ++ ++ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, ++ CI_DO_IO_RW(ci->nr)); ++ wait_ci_ready(ci); ++ return 0; ++} ++ ++static int slot_reset(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct ddb_ci *ci = ca->data; ++ ++ printk(KERN_INFO "slot reset %d\n", ci->nr); ++ ddbwritel(ci->port->dev, CI_POWER_ON, ++ CI_CONTROL(ci->nr)); ++ msleep(300); ++ ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, ++ CI_CONTROL(ci->nr)); ++ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, ++ CI_CONTROL(ci->nr)); ++ udelay(20); ++ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, ++ CI_CONTROL(ci->nr)); ++ return 0; ++} ++ ++static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct ddb_ci *ci = ca->data; ++ ++ printk(KERN_INFO "slot shutdown\n"); ++ ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); ++ return 0; ++} ++ ++static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) ++{ ++ struct ddb_ci *ci = ca->data; ++ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); ++ ++ ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, ++ CI_CONTROL(ci->nr)); ++ return 0; ++} ++ ++static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) ++{ ++ struct ddb_ci *ci = ca->data; ++ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); ++ int stat = 0; ++ ++ if (val & CI_CAM_DETECT) ++ stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; ++ if (val & CI_CAM_READY) ++ stat |= DVB_CA_EN50221_POLL_CAM_READY; ++ return stat; + } + ++static struct dvb_ca_en50221 en_templ = { ++ .read_attribute_mem = read_attribute_mem, ++ .write_attribute_mem = write_attribute_mem, ++ .read_cam_control = read_cam_control, ++ .write_cam_control = write_cam_control, ++ .slot_reset = slot_reset, ++ .slot_shutdown = slot_shutdown, ++ .slot_ts_enable = slot_ts_enable, ++ .poll_slot_status = poll_slot_status, ++}; ++ ++static void ci_attach(struct ddb_port *port) ++{ ++ struct ddb_ci *ci = 0; ++ ++ ci = kzalloc(sizeof(*ci), GFP_KERNEL); ++ if (!ci) ++ return; ++ memcpy(&ci->en, &en_templ, sizeof(en_templ)); ++ ci->en.data = ci; ++ port->en = &ci->en; ++ ci->port = port; ++ ci->nr = port->nr - 2; ++} ++ ++/****************************************************************************/ ++/****************************************************************************/ ++/****************************************************************************/ ++ + + struct cxd2099_cfg cxd_cfg = { + .bitrate = 62000, +@@ -1049,28 +1704,22 @@ struct cxd2099_cfg cxd_cfg = { + + static int ddb_ci_attach(struct ddb_port *port) + { +- int ret; +- +- ret = dvb_register_adapter(&port->output->adap, +- "DDBridge", +- THIS_MODULE, +- &port->dev->pdev->dev, +- adapter_nr); +- if (ret < 0) +- return ret; +- port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); +- if (!port->en) { +- dvb_unregister_adapter(&port->output->adap); +- return -ENODEV; ++ if (port->type == DDB_CI_EXTERNAL_SONY) { ++ port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); ++ if (!port->en) ++ return -ENODEV; ++ dvb_ca_en50221_init(port->input[0]->dvb.adap, ++ port->en, 0, 1); + } +- ddb_input_start(port->input[0]); +- ddb_output_start(port->output); +- dvb_ca_en50221_init(&port->output->adap, +- port->en, 0, 1); +- ret = dvb_register_device(&port->output->adap, &port->output->dev, +- &dvbdev_ci, (void *) port->output, +- DVB_DEVICE_SEC); +- return ret; ++#if 1 ++ if (port->type == DDB_CI_INTERNAL) { ++ ci_attach(port); ++ if (!port->en) ++ return -ENODEV; ++ dvb_ca_en50221_init(port->input[0]->dvb.adap, port->en, 0, 1); ++ } ++#endif ++ return 0; + } + + static int ddb_port_attach(struct ddb_port *port) +@@ -1086,6 +1735,15 @@ static int ddb_port_attach(struct ddb_port *port) + break; + case DDB_PORT_CI: + ret = ddb_ci_attach(port); ++ if (ret < 0) ++ break; ++ case DDB_PORT_LOOP: ++ ddb_input_start(port->input[0]); ++ ddb_output_start(port->output); ++ ret = dvb_register_device(port->input[0]->dvb.adap, ++ &port->input[0]->dvb.dev, ++ &dvbdev_ci, (void *) port->output, ++ DVB_DEVICE_SEC); + break; + default: + break; +@@ -1100,6 +1758,10 @@ static int ddb_ports_attach(struct ddb *dev) + int i, ret = 0; + struct ddb_port *port; + ++ ret = dvb_register_adapters(dev); ++ if (ret < 0) ++ return ret; ++ + for (i = 0; i < dev->info->port_num; i++) { + port = &dev->port[i]; + ret = ddb_port_attach(port); +@@ -1122,25 +1784,26 @@ static void ddb_ports_detach(struct ddb *dev) + dvb_input_detach(port->input[1]); + break; + case DDB_PORT_CI: +- if (port->output->dev) +- dvb_unregister_device(port->output->dev); ++ case DDB_PORT_LOOP: ++ if (port->input[0]->dvb.dev) ++ dvb_unregister_device(port->input[0]->dvb.dev); ++ ddb_input_stop(port->input[0]); ++ ddb_output_stop(port->output); + if (port->en) { +- ddb_input_stop(port->input[0]); +- ddb_output_stop(port->output); + dvb_ca_en50221_release(port->en); + kfree(port->en); + port->en = 0; +- dvb_unregister_adapter(&port->output->adap); + } + break; + } + } ++ dvb_unregister_adapters(dev); + } + + /****************************************************************************/ + /****************************************************************************/ + +-static int port_has_ci(struct ddb_port *port) ++static int port_has_cxd(struct ddb_port *port) + { + u8 val; + return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1; +@@ -1172,6 +1835,21 @@ static int port_has_drxks(struct ddb_port *port) + return 1; + } + ++static int port_has_stv0367(struct ddb_port *port) ++{ ++ u8 val; ++ ++ if (i2c_read_reg16(&port->i2c->adap, 0x1e, 0xf000, &val) < 0) ++ return 0; ++ if (val != 0x60) ++ return 0; ++ if (i2c_read_reg16(&port->i2c->adap, 0x1f, 0xf000, &val) < 0) ++ return 0; ++ if (val != 0x60) ++ return 0; ++ return 1; ++} ++ + static void ddb_port_probe(struct ddb_port *port) + { + struct ddb *dev = port->dev; +@@ -1179,62 +1857,92 @@ static void ddb_port_probe(struct ddb_port *port) + + port->class = DDB_PORT_NONE; + +- if (port_has_ci(port)) { ++ if (port->nr > 1 && dev->info->type == DDB_OCTOPUS_CI) { ++ modname = "CI internal"; ++ port->class = DDB_PORT_CI; ++ port->type = DDB_CI_INTERNAL; ++ } else if (port_has_cxd(port)) { + modname = "CI"; + port->class = DDB_PORT_CI; +- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); ++ port->type = DDB_CI_EXTERNAL_SONY; ++ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); + } else if (port_has_stv0900(port)) { + modname = "DUAL DVB-S2"; + port->class = DDB_PORT_TUNER; + port->type = DDB_TUNER_DVBS_ST; +- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); ++ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); + } else if (port_has_stv0900_aa(port)) { + modname = "DUAL DVB-S2"; + port->class = DDB_PORT_TUNER; + port->type = DDB_TUNER_DVBS_ST_AA; +- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); ++ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); + } else if (port_has_drxks(port)) { + modname = "DUAL DVB-C/T"; + port->class = DDB_PORT_TUNER; + port->type = DDB_TUNER_DVBCT_TR; +- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); ++ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); ++ } else if (port_has_stv0367(port)) { ++ modname = "DUAL DVB-C/T"; ++ port->class = DDB_PORT_TUNER; ++ port->type = DDB_TUNER_DVBCT_ST; ++ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); ++ } else if (port->nr == ts_loop) { ++ modname = "TS LOOP"; ++ port->class = DDB_PORT_LOOP; + } +- printk(KERN_INFO "Port %d (TAB %d): %s\n", +- port->nr, port->nr+1, modname); ++ printk(KERN_INFO "Port %d (TAB %d): %s\n", port->nr, port->nr+1, modname); + } + +-static void ddb_input_init(struct ddb_port *port, int nr) ++static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io) ++{ ++ unsigned long priv = (unsigned long) io; ++ ++ dma->io = io; ++ dma->nr = nr; ++ spin_lock_init(&dma->lock); ++ init_waitqueue_head(&dma->wq); ++ if (nr & 8) { ++ tasklet_init(&dma->tasklet, output_tasklet, priv); ++ dma->num = OUTPUT_DMA_BUFS; ++ dma->size = OUTPUT_DMA_SIZE; ++ dma->div = OUTPUT_DMA_IRQ_DIV; ++ } else { ++ tasklet_init(&dma->tasklet, input_tasklet, priv); ++ dma->num = INPUT_DMA_BUFS; ++ dma->size = INPUT_DMA_SIZE; ++ dma->div = INPUT_DMA_IRQ_DIV; ++ } ++} ++ ++static void ddb_input_init(struct ddb_port *port, int nr, int pnr) + { + struct ddb *dev = port->dev; + struct ddb_input *input = &dev->input[nr]; + ++ port->input[pnr] = input; + input->nr = nr; + input->port = port; +- input->dma_buf_num = INPUT_DMA_BUFS; +- input->dma_buf_size = INPUT_DMA_SIZE; +- ddbwritel(0, TS_INPUT_CONTROL(nr)); +- ddbwritel(2, TS_INPUT_CONTROL(nr)); +- ddbwritel(0, TS_INPUT_CONTROL(nr)); +- ddbwritel(0, DMA_BUFFER_ACK(nr)); +- tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input); +- spin_lock_init(&input->lock); +- init_waitqueue_head(&input->wq); ++ input->dma = &dev->dma[nr]; ++ ddb_dma_init(input->dma, nr, (void *) input); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); ++ ddbwritel(dev, 2, TS_INPUT_CONTROL(nr)); ++ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); ++ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); ++ input->dvb.adap = &dev->adap[input->nr]; + } + + static void ddb_output_init(struct ddb_port *port, int nr) + { + struct ddb *dev = port->dev; + struct ddb_output *output = &dev->output[nr]; ++ port->output = output; + output->nr = nr; + output->port = port; +- output->dma_buf_num = OUTPUT_DMA_BUFS; +- output->dma_buf_size = OUTPUT_DMA_SIZE; +- +- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); +- ddbwritel(2, TS_OUTPUT_CONTROL(nr)); +- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); +- tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output); +- init_waitqueue_head(&output->wq); ++ output->dma = &dev->dma[nr + 8]; ++ ddb_dma_init(output->dma, nr + 8, (void *) output); ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); ++ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr)); ++ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); + } + + static void ddb_ports_init(struct ddb *dev) +@@ -1247,14 +1955,16 @@ static void ddb_ports_init(struct ddb *dev) + port->dev = dev; + port->nr = i; + port->i2c = &dev->i2c[i]; +- port->input[0] = &dev->input[2 * i]; +- port->input[1] = &dev->input[2 * i + 1]; +- port->output = &dev->output[i]; + + mutex_init(&port->i2c_gate_lock); + ddb_port_probe(port); +- ddb_input_init(port, 2 * i); +- ddb_input_init(port, 2 * i + 1); ++ if (i >= 2 && dev->info->type == DDB_OCTOPUS_CI) { ++ ddb_input_init(port, 2 + i, 0); ++ ddb_input_init(port, 4 + i, 1); ++ } else { ++ ddb_input_init(port, 2 * i, 0); ++ ddb_input_init(port, 2 * i + 1, 1); ++ } + ddb_output_init(port, i); + } + } +@@ -1267,9 +1977,12 @@ static void ddb_ports_release(struct ddb *dev) + for (i = 0; i < dev->info->port_num; i++) { + port = &dev->port[i]; + port->dev = dev; +- tasklet_kill(&port->input[0]->tasklet); +- tasklet_kill(&port->input[1]->tasklet); +- tasklet_kill(&port->output->tasklet); ++ if (port->input[0]) ++ tasklet_kill(&port->input[0]->dma->tasklet); ++ if (port->input[1]) ++ tasklet_kill(&port->input[1]->dma->tasklet); ++ if (port->output) ++ tasklet_kill(&port->output->dma->tasklet); + } + } + +@@ -1288,13 +2001,18 @@ static void irq_handle_i2c(struct ddb *dev, int n) + static irqreturn_t irq_handler(int irq, void *dev_id) + { + struct ddb *dev = (struct ddb *) dev_id; +- u32 s = ddbreadl(INTERRUPT_STATUS); ++ u32 s = ddbreadl(dev, INTERRUPT_STATUS); + + if (!s) + return IRQ_NONE; + + do { +- ddbwritel(s, INTERRUPT_ACK); ++ ddbwritel(dev, s, INTERRUPT_ACK); ++ ++ if (s & 0x0000000f) ++ dev->i2c_irq++; ++ if (s & 0x000fff00) ++ dev->ts_irq++; + + if (s & 0x00000001) + irq_handle_i2c(dev, 0); +@@ -1306,33 +2024,32 @@ static irqreturn_t irq_handler(int irq, void *dev_id) + irq_handle_i2c(dev, 3); + + if (s & 0x00000100) +- tasklet_schedule(&dev->input[0].tasklet); ++ tasklet_schedule(&dev->dma[0].tasklet); + if (s & 0x00000200) +- tasklet_schedule(&dev->input[1].tasklet); ++ tasklet_schedule(&dev->dma[1].tasklet); + if (s & 0x00000400) +- tasklet_schedule(&dev->input[2].tasklet); ++ tasklet_schedule(&dev->dma[2].tasklet); + if (s & 0x00000800) +- tasklet_schedule(&dev->input[3].tasklet); ++ tasklet_schedule(&dev->dma[3].tasklet); + if (s & 0x00001000) +- tasklet_schedule(&dev->input[4].tasklet); ++ tasklet_schedule(&dev->dma[4].tasklet); + if (s & 0x00002000) +- tasklet_schedule(&dev->input[5].tasklet); ++ tasklet_schedule(&dev->dma[5].tasklet); + if (s & 0x00004000) +- tasklet_schedule(&dev->input[6].tasklet); ++ tasklet_schedule(&dev->dma[6].tasklet); + if (s & 0x00008000) +- tasklet_schedule(&dev->input[7].tasklet); +- ++ tasklet_schedule(&dev->dma[7].tasklet); + if (s & 0x00010000) +- tasklet_schedule(&dev->output[0].tasklet); ++ tasklet_schedule(&dev->dma[8].tasklet); + if (s & 0x00020000) +- tasklet_schedule(&dev->output[1].tasklet); ++ tasklet_schedule(&dev->dma[9].tasklet); + if (s & 0x00040000) +- tasklet_schedule(&dev->output[2].tasklet); ++ tasklet_schedule(&dev->dma[10].tasklet); + if (s & 0x00080000) +- tasklet_schedule(&dev->output[3].tasklet); ++ tasklet_schedule(&dev->dma[11].tasklet); + +- /* if (s & 0x000f0000) printk(KERN_DEBUG "%08x\n", istat); */ +- } while ((s = ddbreadl(INTERRUPT_STATUS))); ++ /* if (s & 0x000f0000) printk("%08x\n", istat); */ ++ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); + + return IRQ_HANDLED; + } +@@ -1346,21 +2063,21 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) + u32 data, shift; + + if (wlen > 4) +- ddbwritel(1, SPI_CONTROL); ++ ddbwritel(dev, 1, SPI_CONTROL); + while (wlen > 4) { + /* FIXME: check for big-endian */ + data = swab32(*(u32 *)wbuf); + wbuf += 4; + wlen -= 4; +- ddbwritel(data, SPI_DATA); +- while (ddbreadl(SPI_CONTROL) & 0x0004) ++ ddbwritel(dev, data, SPI_DATA); ++ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) + ; + } + + if (rlen) +- ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); ++ ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); + else +- ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); ++ ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); + + data = 0; + shift = ((4 - wlen) * 8); +@@ -1372,33 +2089,33 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) + } + if (shift) + data <<= shift; +- ddbwritel(data, SPI_DATA); +- while (ddbreadl(SPI_CONTROL) & 0x0004) ++ ddbwritel(dev, data, SPI_DATA); ++ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) + ; + + if (!rlen) { +- ddbwritel(0, SPI_CONTROL); ++ ddbwritel(dev, 0, SPI_CONTROL); + return 0; + } + if (rlen > 4) +- ddbwritel(1, SPI_CONTROL); ++ ddbwritel(dev, 1, SPI_CONTROL); + + while (rlen > 4) { +- ddbwritel(0xffffffff, SPI_DATA); +- while (ddbreadl(SPI_CONTROL) & 0x0004) ++ ddbwritel(dev, 0xffffffff, SPI_DATA); ++ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) + ; +- data = ddbreadl(SPI_DATA); ++ data = ddbreadl(dev, SPI_DATA); + *(u32 *) rbuf = swab32(data); + rbuf += 4; + rlen -= 4; + } +- ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); +- ddbwritel(0xffffffff, SPI_DATA); +- while (ddbreadl(SPI_CONTROL) & 0x0004) ++ ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); ++ ddbwritel(dev, 0xffffffff, SPI_DATA); ++ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) + ; + +- data = ddbreadl(SPI_DATA); +- ddbwritel(0, SPI_CONTROL); ++ data = ddbreadl(dev, SPI_DATA); ++ ddbwritel(dev, 0, SPI_CONTROL); + + if (rlen < 4) + data <<= ((4 - rlen) * 8); +@@ -1421,14 +2138,21 @@ struct ddb_flashio { + __u32 read_len; + }; + ++struct ddb_gpio { ++ __u32 mask; ++ __u32 data; ++}; ++ ++ + #define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) ++#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) ++#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) + + #define DDB_NAME "ddbridge" + + static u32 ddb_num; +-static struct ddb *ddbs[32]; +-static struct class *ddb_class; + static int ddb_major; ++static DEFINE_MUTEX(ddb_mutex); + + static int ddb_open(struct inode *inode, struct file *file) + { +@@ -1470,6 +2194,16 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + return -EFAULT; + break; + } ++ case IOCTL_DDB_GPIO_OUT: ++ { ++ struct ddb_gpio gpio; ++ if (copy_from_user(&gpio, parg, sizeof(gpio))) ++ break; ++ ddbwritel(dev, gpio.mask, GPIO_DIRECTION); ++ ddbwritel(dev, gpio.data, GPIO_OUTPUT); ++ res = 0; ++ break; ++ } + default: + return -ENOTTY; + } +@@ -1481,52 +2215,336 @@ static const struct file_operations ddb_fops = { + .open = ddb_open, + }; + +-static char *ddb_devnode(struct device *device, umode_t *mode) ++static char *ddb_devnode(struct device *device, mode_t *mode) + { + struct ddb *dev = dev_get_drvdata(device); + + return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr); + } + ++static ssize_t ports_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ ++ return sprintf(buf, "%d\n", dev->info->port_num); ++} ++ ++static ssize_t ts_irq_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ ++ return sprintf(buf, "%d\n", dev->ts_irq); ++} ++ ++static ssize_t i2c_irq_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ ++ return sprintf(buf, "%d\n", dev->i2c_irq); ++} ++ ++static char *class_name[] = { ++ "NONE", "CI", "TUNER", "LOOP" ++}; ++ ++static char *type_name[] = { ++ "NONE", "DVBS_ST", "DVBS_ST_AA", "DVBCT_TR", "DVBCT_ST", "INTERNAL", "CXD2099", ++}; ++ ++static ssize_t fan_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ u32 val; ++ ++ val = ddbreadl(dev, GPIO_OUTPUT) & 1; ++ return sprintf(buf, "%d\n", val); ++} ++ ++static ssize_t fan_store(struct device *device, struct device_attribute *d, ++ const char *buf, size_t count) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ unsigned val; ++ ++ if (sscanf(buf, "%u\n", &val) != 1) ++ return -EINVAL; ++ ddbwritel(dev, 1, GPIO_DIRECTION); ++ ddbwritel(dev, val & 1, GPIO_OUTPUT); ++ return count; ++} ++ ++static ssize_t temp_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int temp; ++ u8 tmp[2]; ++ ++ if (!dev->info->temp_num) ++ return sprintf(buf, "no sensor\n"); ++ if (i2c_read_regs(&dev->i2c[0].adap, 0x48, 0, tmp, 2) < 0) ++ return sprintf(buf, "read_error\n"); ++ temp = (tmp[0] << 3) | (tmp[1] >> 5); ++ temp *= 125; ++ return sprintf(buf, "%d\n", temp); ++} ++ ++static ssize_t mod_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; ++ ++ return sprintf(buf, "%s:%s\n", ++ class_name[dev->port[num].class], ++ type_name[dev->port[num].type]); ++} ++ ++static ssize_t led_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; ++ ++ return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0); ++} ++ ++ ++static void ddb_set_led(struct ddb *dev, int num, int val) ++{ ++ if (!dev->info->led_num) ++ return; ++ switch (dev->port[num].class) { ++ case DDB_PORT_TUNER: ++ switch (dev->port[num].type) { ++ case DDB_TUNER_DVBS_ST: ++ printk(KERN_INFO "LED %d %d\n", num, val); ++ i2c_write_reg16(&dev->i2c[num].adap, ++ 0x69, 0xf14c, val ? 2 : 0); ++ break; ++ case DDB_TUNER_DVBCT_ST: ++ printk(KERN_INFO "LED %d %d\n", num, val); ++ i2c_write_reg16(&dev->i2c[num].adap, ++ 0x1f, 0xf00e, 0); ++ i2c_write_reg16(&dev->i2c[num].adap, ++ 0x1f, 0xf00f, val ? 1 : 0); ++ break; ++ } ++ break; ++ default: ++ break; ++ } ++} ++ ++static ssize_t led_store(struct device *device, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; ++ unsigned val; ++ ++ if (sscanf(buf, "%u\n", &val) != 1) ++ return -EINVAL; ++ if (val) ++ dev->leds |= (1 << num); ++ else ++ dev->leds &= ~(1 << num); ++ ddb_set_led(dev, num, val); ++ return count; ++} ++ ++static ssize_t snr_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ char snr[32]; ++ int num = attr->attr.name[3] - 0x30; ++ ++ /* serial number at 0x100-0x11f */ ++ if (i2c_read_regs16(&dev->i2c[num].adap, 0x57, 0x100, snr, 32) < 0) ++ return sprintf(buf, "NO SNR\n"); ++ snr[31] = 0; /* in case it is not terminated on EEPROM */ ++ return sprintf(buf, "%s\n", snr); ++} ++ ++ ++static ssize_t snr_store(struct device *device, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct ddb *dev = dev_get_drvdata(device); ++ int num = attr->attr.name[3] - 0x30; ++ u8 snr[34] = { 0x01, 0x00 }; ++ ++ if (count > 31) ++ return -EINVAL; ++ memcpy(snr + 2, buf, count); ++ i2c_write(&dev->i2c[num].adap, 0x57, snr, 34); ++ return count; ++} ++ ++static ssize_t redirect_show(struct device *device, struct device_attribute *attr, char *buf) ++{ ++ return 0; ++} ++ ++static ssize_t redirect_store(struct device *device, struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned int i, p; ++ int res; ++ ++ if (sscanf(buf, "%x %x\n", &i, &p) != 2) ++ return -EINVAL; ++ printk(KERN_INFO "redirect: %02x, %02x\n", i, p); ++ res = set_redirect(i, p); ++ if (res < 0) ++ return res; ++ return count; ++} ++ ++#define __ATTR_MRO(_name, _show) { \ ++ .attr = { .name = __stringify(_name), .mode = 0444 }, \ ++ .show = _show, \ ++} ++ ++struct device_attribute ddb_attrs[] = { ++ __ATTR_RO(ports), ++ __ATTR_RO(ts_irq), ++ __ATTR_RO(i2c_irq), ++ __ATTR(redirect, 0666, redirect_show, redirect_store), ++ __ATTR_NULL ++}; ++ ++static struct device_attribute ddb_mod[] = { ++ __ATTR_MRO(mod0, mod_show), ++ __ATTR_MRO(mod1, mod_show), ++ __ATTR_MRO(mod2, mod_show), ++ __ATTR_MRO(mod3, mod_show), ++}; ++ ++static struct device_attribute ddb_temp = ++ __ATTR_RO(temp); ++ ++static struct device_attribute ddb_fan = ++ __ATTR(fan, 0666, fan_show, fan_store); ++ ++static struct device_attribute ddb_led[] = { ++ __ATTR(led0, 0666, led_show, led_store), ++ __ATTR(led1, 0666, led_show, led_store), ++ __ATTR(led2, 0666, led_show, led_store), ++ __ATTR(led3, 0666, led_show, led_store), ++}; ++ ++static struct device_attribute ddb_snr[] = { ++ __ATTR(snr0, 0666, snr_show, snr_store), ++ __ATTR(snr1, 0666, snr_show, snr_store), ++ __ATTR(snr2, 0666, snr_show, snr_store), ++ __ATTR(snr3, 0666, snr_show, snr_store), ++}; ++ ++static struct class ddb_class = { ++ .name = "ddbridge", ++ .owner = THIS_MODULE, ++ .dev_attrs = ddb_attrs, ++ .devnode = ddb_devnode, ++}; ++ + static int ddb_class_create(void) + { + ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops); + if (ddb_major < 0) + return ddb_major; +- +- ddb_class = class_create(THIS_MODULE, DDB_NAME); +- if (IS_ERR(ddb_class)) { +- unregister_chrdev(ddb_major, DDB_NAME); +- return PTR_ERR(ddb_class); +- } +- ddb_class->devnode = ddb_devnode; ++ if (class_register(&ddb_class) < 0) ++ return -1; + return 0; + } + + static void ddb_class_destroy(void) + { +- class_destroy(ddb_class); ++ class_unregister(&ddb_class); + unregister_chrdev(ddb_major, DDB_NAME); + } + ++static int ddb_device_files_create(struct ddb *dev) ++{ ++ int i, error = 0; ++ ++ if (dev->info->temp_num > 0) ++ error = device_create_file(dev->ddb_dev, &ddb_temp); ++ ++ if (!error && dev->info->fan_num > 0) ++ error = device_create_file(dev->ddb_dev, &ddb_fan); ++ ++ for (i = 0; !error && (i < dev->info->led_num); i++) ++ error = device_create_file(dev->ddb_dev, &ddb_led[i]); ++ ++ for (i = 0; !error && (i < dev->info->port_num); i++) ++ error = device_create_file(dev->ddb_dev, &ddb_mod[i]); ++ ++ for (i = 0; !error && (i < dev->info->i2c_num); i++) ++ error = device_create_file(dev->ddb_dev, &ddb_snr[i]); ++ ++ return error; ++} ++ ++static void ddb_device_files_delete(struct ddb *dev) ++{ ++ int i; ++ ++ if (dev->info->temp_num > 0) ++ device_remove_file(dev->ddb_dev, &ddb_temp); ++ ++ if (dev->info->fan_num > 0) ++ device_remove_file(dev->ddb_dev, &ddb_fan); ++ ++ for (i = 0; i < dev->info->led_num; i++) ++ device_remove_file(dev->ddb_dev, &ddb_led[i]); ++ ++ for (i = 0; i < dev->info->port_num; i++) ++ device_remove_file(dev->ddb_dev, &ddb_mod[i]); ++ ++ for (i = 0; i < dev->info->i2c_num; i++) ++ device_remove_file(dev->ddb_dev, &ddb_snr[i]); ++} ++ + static int ddb_device_create(struct ddb *dev) + { ++ int error = -1; ++ ++ mutex_lock(&ddb_mutex); + dev->nr = ddb_num++; +- dev->ddb_dev = device_create(ddb_class, NULL, ++ ddbs[dev->nr] = dev; ++ mutex_unlock(&ddb_mutex); ++ dev->ddb_dev = device_create(&ddb_class, &dev->pdev->dev, + MKDEV(ddb_major, dev->nr), + dev, "ddbridge%d", dev->nr); +- ddbs[dev->nr] = dev; +- if (IS_ERR(dev->ddb_dev)) +- return -1; ++ if (IS_ERR(dev->ddb_dev)) { ++ printk(KERN_ERR ": Could not create ddbridge device\n"); ++ goto fail1; ++ } ++ error = ddb_device_files_create(dev); ++ if (error) { ++ printk(KERN_ERR ": Could not create ddbridge sysfs files\n"); ++ goto fail2; ++ } ++ + return 0; ++ ++fail2: ++ ddb_device_files_delete(dev); ++ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); ++ ++fail1: ++ mutex_lock(&ddb_mutex); ++ ddb_num--; ++ ddbs[dev->nr] = NULL; ++ mutex_unlock(&ddb_mutex); ++ ++ return error; + } + + static void ddb_device_destroy(struct ddb *dev) + { +- ddb_num--; + if (IS_ERR(dev->ddb_dev)) + return; +- device_destroy(ddb_class, MKDEV(ddb_major, 0)); ++ ddb_device_files_delete(dev); ++ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); + } + + +@@ -1549,7 +2567,7 @@ static void ddb_remove(struct pci_dev *pdev) + ddb_ports_detach(dev); + ddb_i2c_release(dev); + +- ddbwritel(0, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0, INTERRUPT_ENABLE); + free_irq(dev->pdev->irq, dev); + #ifdef CONFIG_PCI_MSI + if (dev->msi) +@@ -1564,7 +2582,6 @@ static void ddb_remove(struct pci_dev *pdev) + pci_disable_device(pdev); + } + +- + static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + { + struct ddb *dev; +@@ -1574,10 +2591,9 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + if (pci_enable_device(pdev) < 0) + return -ENODEV; + +- dev = vmalloc(sizeof(struct ddb)); ++ dev = vzalloc(sizeof(struct ddb)); + if (dev == NULL) + return -ENOMEM; +- memset(dev, 0, sizeof(struct ddb)); + + dev->pdev = pdev; + pci_set_drvdata(pdev, dev); +@@ -1590,7 +2606,8 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + stat = -ENOMEM; + goto fail; + } +- printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4)); ++ printk(KERN_INFO "HW %08x REG %08x\n", ++ ddbreadl(dev, 0), ddbreadl(dev, 4)); + + #ifdef CONFIG_PCI_MSI + if (pci_msi_enabled()) +@@ -1606,11 +2623,11 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + irq_flag, "DDBridge", (void *) dev); + if (stat < 0) + goto fail1; +- ddbwritel(0, DMA_BASE_WRITE); +- ddbwritel(0, DMA_BASE_READ); +- ddbwritel(0xffffffff, INTERRUPT_ACK); +- ddbwritel(0xfff0f, INTERRUPT_ENABLE); +- ddbwritel(0, MSI1_ENABLE); ++ ddbwritel(dev, 0, DMA_BASE_WRITE); ++ ddbwritel(dev, 0, DMA_BASE_READ); ++ ddbwritel(dev, 0xffffffff, INTERRUPT_ACK); ++ ddbwritel(dev, 0x000fff0f, INTERRUPT_ENABLE); ++ ddbwritel(dev, 0, MSI1_ENABLE); + + if (ddb_i2c_init(dev) < 0) + goto fail1; +@@ -1621,7 +2638,14 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) + } + if (ddb_ports_attach(dev) < 0) + goto fail3; +- ddb_device_create(dev); ++ ++ if (ddb_device_create(dev) < 0) ++ goto fail3; ++ ++ if (dev->info->fan_num) { ++ ddbwritel(dev, 1, GPIO_DIRECTION); ++ ddbwritel(dev, 1, GPIO_OUTPUT); ++ } + return 0; + + fail3: +@@ -1631,11 +2655,14 @@ fail3: + fail2: + printk(KERN_ERR "fail2\n"); + ddb_buffers_free(dev); ++ ddb_i2c_release(dev); + fail1: + printk(KERN_ERR "fail1\n"); ++ free_irq(dev->pdev->irq, dev); ++#ifdef CONFIG_PCI_MSI + if (dev->msi) + pci_disable_msi(dev->pdev); +- free_irq(dev->pdev->irq, dev); ++#endif + fail: + printk(KERN_ERR "fail\n"); + ddb_unmap(dev); +@@ -1657,23 +2684,78 @@ static struct ddb_info ddb_octopus = { + .type = DDB_OCTOPUS, + .name = "Digital Devices Octopus DVB adapter", + .port_num = 4, ++ .i2c_num = 4, + }; + + static struct ddb_info ddb_octopus_le = { + .type = DDB_OCTOPUS, + .name = "Digital Devices Octopus LE DVB adapter", + .port_num = 2, ++ .i2c_num = 2, ++}; ++ ++static struct ddb_info ddb_octopus_oem = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Octopus OEM", ++ .port_num = 4, ++ .i2c_num = 4, ++ .led_num = 1, ++ .fan_num = 1, ++ .temp_num = 1, ++}; ++ ++static struct ddb_info ddb_octopus_mini = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Octopus Mini", ++ .port_num = 4, ++ .i2c_num = 4, + }; + + static struct ddb_info ddb_v6 = { + .type = DDB_OCTOPUS, + .name = "Digital Devices Cine S2 V6 DVB adapter", + .port_num = 3, ++ .i2c_num = 3, ++}; ++ ++static struct ddb_info ddb_v6_5 = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices Cine S2 V6.5 DVB adapter", ++ .port_num = 4, ++ .i2c_num = 4, ++}; ++ ++static struct ddb_info ddb_dvbct = { ++ .type = DDB_OCTOPUS, ++ .name = "Digital Devices DVBCT V6.1 DVB adapter", ++ .port_num = 3, ++ .i2c_num = 3, ++}; ++ ++static struct ddb_info ddb_satixS2v3 = { ++ .type = DDB_OCTOPUS, ++ .name = "Mystique SaTiX-S2 V3 DVB adapter", ++ .port_num = 3, ++ .i2c_num = 3, ++}; ++ ++static struct ddb_info ddb_ci = { ++ .type = DDB_OCTOPUS_CI, ++ .name = "Digital Devices Octopus CI", ++ .port_num = 4, ++ .i2c_num = 2, ++}; ++ ++static struct ddb_info ddb_cis = { ++ .type = DDB_OCTOPUS_CI, ++ .name = "Digital Devices Octopus CI single", ++ .port_num = 3, ++ .i2c_num = 2, + }; + + #define DDVID 0xdd01 /* Digital Devices Vendor ID */ + +-#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ ++#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ + .vendor = _vend, .device = _dev, \ + .subvendor = _subvend, .subdevice = _subdev, \ + .driver_data = (unsigned long)&_driverdata } +@@ -1682,8 +2764,15 @@ static const struct pci_device_id ddb_id_tbl[] = { + DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus), + DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus), + DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le), +- DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini), + DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5), ++ DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct), ++ DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3), ++ DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopus), ++ DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci), ++ DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis), + /* in case sub-ids got deleted in flash */ + DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none), + {0} +@@ -1700,18 +2789,16 @@ static struct pci_driver ddb_pci_driver = { + + static __init int module_init_ddbridge(void) + { +- int ret; ++ int stat; + + printk(KERN_INFO "Digital Devices PCIE bridge driver, " + "Copyright (C) 2010-11 Digital Devices GmbH\n"); +- +- ret = ddb_class_create(); +- if (ret < 0) +- return ret; +- ret = pci_register_driver(&ddb_pci_driver); +- if (ret < 0) ++ if (ddb_class_create()) ++ return -1; ++ stat = pci_register_driver(&ddb_pci_driver); ++ if (stat < 0) + ddb_class_destroy(); +- return ret; ++ return stat; + } + + static __exit void module_exit_ddbridge(void) +@@ -1726,4 +2813,4 @@ module_exit(module_exit_ddbridge); + MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); + MODULE_AUTHOR("Ralph Metzler"); + MODULE_LICENSE("GPL"); +-MODULE_VERSION("0.5"); ++MODULE_VERSION("0.8"); +diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h +index a3ccb31..46e8a21 100644 +--- a/drivers/media/pci/ddbridge/ddbridge-regs.h ++++ b/drivers/media/pci/ddbridge/ddbridge-regs.h +@@ -21,11 +21,12 @@ + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + */ + +-/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */ ++/* DD-DVBBridgeV1.h 388 2011-07-13 20:47:08Z manfred */ + + /* Register Definitions */ + +-#define CUR_REGISTERMAP_VERSION 0x10000 ++#define CUR_REGISTERMAP_VERSION 0x10003 ++#define CUR_REGISTERMAP_VERSION_CI 0x10000 + + #define HARDWARE_VERSION 0x00 + #define REGISTERMAP_VERSION 0x04 +@@ -36,8 +37,14 @@ + #define SPI_CONTROL 0x10 + #define SPI_DATA 0x14 + +-/* ------------------------------------------------------------------------- */ ++/* -------------------------------------------------------------------------- */ ++/* GPIO */ ++ ++#define GPIO_OUTPUT 0x20 ++#define GPIO_INPUT 0x24 ++#define GPIO_DIRECTION 0x28 + ++/* -------------------------------------------------------------------------- */ + /* Interrupt controller */ + /* How many MSI's are available depends on HW (Min 2 max 8) */ + /* How many are usable also depends on Host platform */ +@@ -149,3 +156,46 @@ + #define DMA_BASE_ADDRESS_TABLE (0x2000) + #define DMA_BASE_ADDRESS_TABLE_ENTRIES (512) + ++/* -------------------------------------------------------------------------- */ ++/* CI Interface (only CI-Bridge) */ ++ ++#define CI_BASE (0x400) ++#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00) ++ ++#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04) ++#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08) ++#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c) ++#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10) ++ ++#define CI_RESET_CAM (0x00000001) ++#define CI_POWER_ON (0x00000002) ++#define CI_ENABLE (0x00000004) ++#define CI_BLOCKIO_ENABLE (0x00000008) ++#define CI_BYPASS_DISABLE (0x00000010) ++#define CI_DISABLE_AUTO_OFF (0x00000020) ++ ++#define CI_CAM_READY (0x00010000) ++#define CI_CAM_DETECT (0x00020000) ++#define CI_READY (0x80000000) ++#define CI_BLOCKIO_ACTIVE (0x40000000) ++#define CI_BLOCKIO_RCVDATA (0x20000000) ++#define CI_BLOCKIO_SEND_PENDING (0x10000000) ++#define CI_BLOCKIO_SEND_COMPLETE (0x08000000) ++ ++#define CI_READ_CMD (0x40000000) ++#define CI_WRITE_CMD (0x80000000) ++ ++#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14) ++#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18) ++ ++#define CI_BLOCKIO_SEND_COMMAND (0x80000000) ++#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000) ++#define CI_BLOCKIO_RCVDATA_ACK (0x40000000) ++ ++#define CI_BUFFER_BASE (0x3000) ++#define CI_BUFFER_SIZE (0x0800) ++#define CI_BLOCKIO_BUFFER_SIZE (CI_BUFFER_SIZE/2) ++ ++#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) ++#define CI_BLOCKIO_RECEIVE_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) ++#define CI_BLOCKIO_SEND_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE) +diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h +index 8b1b41d..ce2df00 100644 +--- a/drivers/media/pci/ddbridge/ddbridge.h ++++ b/drivers/media/pci/ddbridge/ddbridge.h +@@ -32,7 +32,10 @@ + #include + #include + #include ++#include ++#include + #include ++#include + + #include "dmxdev.h" + #include "dvbdev.h" +@@ -52,43 +55,53 @@ struct ddb_info { + int type; + #define DDB_NONE 0 + #define DDB_OCTOPUS 1 ++#define DDB_OCTOPUS_CI 2 + char *name; + int port_num; +- u32 port_type[DDB_MAX_PORT]; ++ int i2c_num; ++ int led_num; ++ int fan_num; ++ int temp_num; + }; + + /* DMA_SIZE MUST be divisible by 188 and 128 !!! */ + +-#define INPUT_DMA_MAX_BUFS 32 /* hardware table limit */ ++#define DMA_MAX_BUFS 32 /* hardware table limit */ ++ + #define INPUT_DMA_BUFS 8 + #define INPUT_DMA_SIZE (128*47*21) ++#define INPUT_DMA_IRQ_DIV 1 + +-#define OUTPUT_DMA_MAX_BUFS 32 + #define OUTPUT_DMA_BUFS 8 + #define OUTPUT_DMA_SIZE (128*47*21) ++#define OUTPUT_DMA_IRQ_DIV 1 + + struct ddb; + struct ddb_port; + +-struct ddb_input { +- struct ddb_port *port; ++struct ddb_dma { ++ void *io; + u32 nr; +- int attached; +- +- dma_addr_t pbuf[INPUT_DMA_MAX_BUFS]; +- u8 *vbuf[INPUT_DMA_MAX_BUFS]; +- u32 dma_buf_num; +- u32 dma_buf_size; ++ dma_addr_t pbuf[DMA_MAX_BUFS]; ++ u8 *vbuf[DMA_MAX_BUFS]; ++ u32 num; ++ u32 size; ++ u32 div; ++ u32 bufreg; + + struct tasklet_struct tasklet; + spinlock_t lock; + wait_queue_head_t wq; + int running; + u32 stat; ++ u32 ctrl; + u32 cbuf; + u32 coff; ++}; + +- struct dvb_adapter adap; ++struct ddb_dvb { ++ struct dvb_adapter *adap; ++ int adap_registered; + struct dvb_device *dev; + struct dvb_frontend *fe; + struct dvb_frontend *fe2; +@@ -99,32 +112,36 @@ struct ddb_input { + struct dmx_frontend mem_frontend; + int users; + int (*gate_ctrl)(struct dvb_frontend *, int); ++ int attached; + }; + +-struct ddb_output { ++struct ddb_ci { ++ struct dvb_ca_en50221 en; + struct ddb_port *port; + u32 nr; +- dma_addr_t pbuf[OUTPUT_DMA_MAX_BUFS]; +- u8 *vbuf[OUTPUT_DMA_MAX_BUFS]; +- u32 dma_buf_num; +- u32 dma_buf_size; +- struct tasklet_struct tasklet; +- spinlock_t lock; +- wait_queue_head_t wq; +- int running; +- u32 stat; +- u32 cbuf; +- u32 coff; ++}; + +- struct dvb_adapter adap; +- struct dvb_device *dev; ++ ++struct ddb_input { ++ struct ddb_port *port; ++ u32 nr; ++ struct ddb_dma *dma; ++ struct ddb_input *redirect; ++ ++ struct ddb_dvb dvb; ++}; ++ ++struct ddb_output { ++ struct ddb_port *port; ++ u32 nr; ++ struct ddb_dma *dma; ++ struct ddb_input *redirect; + }; + + struct ddb_i2c { + struct ddb *dev; + u32 nr; + struct i2c_adapter adap; +- struct i2c_adapter adap2; + u32 regs; + u32 rbuf; + u32 wbuf; +@@ -141,12 +158,15 @@ struct ddb_port { + #define DDB_PORT_NONE 0 + #define DDB_PORT_CI 1 + #define DDB_PORT_TUNER 2 ++#define DDB_PORT_LOOP 3 + u32 type; + #define DDB_TUNER_NONE 0 + #define DDB_TUNER_DVBS_ST 1 + #define DDB_TUNER_DVBS_ST_AA 2 +-#define DDB_TUNER_DVBCT_TR 16 +-#define DDB_TUNER_DVBCT_ST 17 ++#define DDB_TUNER_DVBCT_TR 3 ++#define DDB_TUNER_DVBCT_ST 4 ++#define DDB_CI_INTERNAL 5 ++#define DDB_CI_EXTERNAL_SONY 6 + u32 adr; + + struct ddb_input *input[2]; +@@ -161,25 +181,20 @@ struct ddb { + struct ddb_i2c i2c[DDB_MAX_I2C]; + struct ddb_input input[DDB_MAX_INPUT]; + struct ddb_output output[DDB_MAX_OUTPUT]; ++ struct dvb_adapter adap[DDB_MAX_INPUT]; ++ struct ddb_dma dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT]; + + struct device *ddb_dev; +- int nr; ++ u32 nr; + u8 iobuf[1028]; + + struct ddb_info *info; + int msi; +-}; +- +-/****************************************************************************/ + +-#define ddbwritel(_val, _adr) writel((_val), \ +- (char *) (dev->regs+(_adr))) +-#define ddbreadl(_adr) readl((char *) (dev->regs+(_adr))) +-#define ddbcpyto(_adr, _src, _count) memcpy_toio((char *) \ +- (dev->regs+(_adr)), (_src), (_count)) +-#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), (char *) \ +- (dev->regs+(_adr)), (_count)) ++ u8 leds; + +-/****************************************************************************/ ++ u32 ts_irq; ++ u32 i2c_irq; ++}; + + #endif +diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig +index 637d506..14975c7 100644 +--- a/drivers/media/pci/ngene/Kconfig ++++ b/drivers/media/pci/ngene/Kconfig +@@ -1,13 +1,16 @@ + config DVB_NGENE + tristate "Micronas nGene support" + depends on DVB_CORE && PCI && I2C +- select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT +- select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT +- select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT +- select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT +- select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT +- select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT +- select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_CXD2099 ++ select DVB_LNBP21 if !DVB_FE_CUSTOMISE ++ select DVB_STV6110x if !DVB_FE_CUSTOMISE ++ select DVB_STV090x if !DVB_FE_CUSTOMISE ++ select DVB_LGDT330X if !DVB_FE_CUSTOMISE ++ select DVB_DRXK if !DVB_FE_CUSTOMISE ++ select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE ++ select DVB_STV0367DD if !DVB_FE_CUSTOMISE ++ select DVB_TDA18212DD if !DVB_FE_CUSTOMISE ++ select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE + ---help--- + Support for Micronas PCI express cards with nGene bridge. + +diff --git a/drivers/media/pci/ngene/Makefile b/drivers/media/pci/ngene/Makefile +index 5c0b5d6..42c036a 100644 +--- a/drivers/media/pci/ngene/Makefile ++++ b/drivers/media/pci/ngene/Makefile +@@ -2,7 +2,8 @@ + # Makefile for the nGene device driver + # + +-ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o ++ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-av.o \ ++ ngene-eeprom.o ngene-dvb.o + + obj-$(CONFIG_DVB_NGENE) += ngene.o + +diff --git a/drivers/media/pci/ngene/ngene-av.c b/drivers/media/pci/ngene/ngene-av.c +new file mode 100644 +index 0000000..a86459e +--- /dev/null ++++ b/drivers/media/pci/ngene/ngene-av.c +@@ -0,0 +1,348 @@ ++/* ++ * ngene-av.c: nGene PCIe bridge driver - DVB video/audio support ++ * ++ * Copyright (C) 2005-2007 Micronas ++ * ++ * Copyright (C) 2008-2009 Ralph Metzler ++ * Modifications for new nGene firmware, ++ * support for EEPROM-copying, ++ * support for new dual DVB-S2 card prototype ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++/* This file provides the support functions for DVB audio/video devices ++ (/dev/dvb/adapter0/[video|audio]), not to be confused with V4L2 support */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ngene.h" ++ ++#if 0 ++ ++static void *ain_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) ++{ ++ struct ngene_channel *chan = priv; ++ struct ngene *dev = chan->dev; ++ ++ if (dvb_ringbuffer_free(&dev->ain_rbuf) >= len) { ++ dvb_ringbuffer_write(&dev->ain_rbuf, buf, len); ++ wake_up_interruptible(&dev->ain_rbuf.queue); ++ } else ++ printk(KERN_INFO DEVICE_NAME ": Dropped ain packet.\n"); ++ ++ return 0; ++} ++ ++static void *vcap_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) ++{ ++ ++ struct ngene_channel *chan = priv; ++ struct ngene *dev = chan->dev; ++ ++ if (len >= 1920 * 1080) ++ len = 1920 * 1080; ++ if (dvb_ringbuffer_free(&dev->vin_rbuf) >= len) { ++ dvb_ringbuffer_write(&dev->vin_rbuf, buf, len); ++ wake_up_interruptible(&dev->vin_rbuf.queue); ++ } else { ++ ;/*printk(KERN_INFO DEVICE_NAME ": Dropped vcap packet.\n"); */ ++ } ++ return 0; ++} ++ ++static ssize_t audio_write(struct file *file, ++ const char *buf, size_t count, loff_t *ppos) ++{ ++ return -EINVAL; ++} ++ ++ssize_t audio_read(struct file *file, char *buf, size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int left; ++ int avail; ++ ++ left = count; ++ while (left) { ++ if (wait_event_interruptible( ++ dev->ain_rbuf.queue, ++ dvb_ringbuffer_avail(&dev->ain_rbuf) > 0) < 0) ++ return -EAGAIN; ++ avail = dvb_ringbuffer_avail(&dev->ain_rbuf); ++ if (avail > left) ++ avail = left; ++ dvb_ringbuffer_read_user(&dev->ain_rbuf, buf, avail); ++ left -= avail; ++ buf += avail; ++ } ++ return count; ++} ++ ++static int audio_open(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ struct ngene_channel *chan2 = &chan->dev->channel[2]; ++ int ret; ++ ++ ret = dvb_generic_open(inode, file); ++ if (ret < 0) ++ return ret; ++ dvb_ringbuffer_flush(&dev->ain_rbuf); ++ ++ chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE; ++ chan2->pBufferExchange = ain_exchange; ++ ngene_command_stream_control(chan2->dev, chan2->number, 0x80, ++ SMODE_AUDIO_CAPTURE, 0); ++ return ret; ++} ++ ++static int audio_release(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ struct ngene_channel *chan2 = &chan->dev->channel[2]; ++ ++ ngene_command_stream_control(dev, 2, 0, 0, 0); ++ chan2->pBufferExchange = 0; ++ ++ return dvb_generic_release(inode, file); ++} ++ ++static const struct file_operations audio_fops = { ++ .owner = THIS_MODULE, ++ .read = audio_read, ++ .write = audio_write, ++ .open = audio_open, ++ .release = audio_release, ++}; ++ ++static struct dvb_device dvbdev_audio = { ++ .priv = 0, ++ .readers = -1, ++ .writers = 1, ++ .users = 1, ++ .fops = &audio_fops, ++}; ++ ++static int video_open(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ struct ngene_channel *chan0 = &chan->dev->channel[0]; ++ int ret; ++ ++ ret = dvb_generic_open(inode, file); ++ if (ret < 0) ++ return ret; ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) ++ return ret; ++ dvb_ringbuffer_flush(&dev->vin_rbuf); ++ ++ chan0->nBytesPerLine = 1920 * 2; ++ chan0->nLines = 540; ++ chan0->Capture1Length = 1920 * 2 * 540; ++ chan0->pBufferExchange = vcap_exchange; ++ chan0->itumode = 2; ++ ngene_command_stream_control(chan0->dev, chan0->number, ++ 0x80, SMODE_VIDEO_CAPTURE, 0); ++ return ret; ++} ++ ++static int video_release(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ struct ngene_channel *chan0 = &chan->dev->channel[0]; ++ ++ ngene_command_stream_control(dev, 0, 0, 0, 0); ++ chan0->pBufferExchange = 0; ++ ++ return dvb_generic_release(inode, file); ++} ++ ++static ssize_t video_write(struct file *file, ++ const char *buf, size_t count, loff_t *ppos) ++{ ++ return -EINVAL; ++} ++ ++ssize_t video_read(struct file *file, char *buf, size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int left, avail; ++ ++ left = count; ++ while (left) { ++ if (wait_event_interruptible( ++ dev->vin_rbuf.queue, ++ dvb_ringbuffer_avail(&dev->vin_rbuf) > 0) < 0) ++ return -EAGAIN; ++ avail = dvb_ringbuffer_avail(&dev->vin_rbuf); ++ if (avail > left) ++ avail = left; ++ dvb_ringbuffer_read_user(&dev->vin_rbuf, buf, avail); ++ left -= avail; ++ buf += avail; ++ } ++ return count; ++} ++ ++/* Why is this not exported from dvb_core ?!?! */ ++ ++static int dvb_usercopy2(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg, ++ int (*func)(struct inode *inode, struct file *file, ++ unsigned int cmd, void *arg)) ++{ ++ char sbuf[128]; ++ void *mbuf = NULL; ++ void *parg = NULL; ++ int err = -EINVAL; ++ ++ /* Copy arguments into temp kernel buffer */ ++ switch (_IOC_DIR(cmd)) { ++ case _IOC_NONE: ++ /* ++ * For this command, the pointer is actually an integer ++ * argument. ++ */ ++ parg = (void *)arg; ++ break; ++ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ ++ case _IOC_WRITE: ++ case (_IOC_WRITE | _IOC_READ): ++ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { ++ parg = sbuf; ++ } else { ++ /* too big to allocate from stack */ ++ mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); ++ if (NULL == mbuf) ++ return -ENOMEM; ++ parg = mbuf; ++ } ++ ++ err = -EFAULT; ++ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) ++ goto out; ++ break; ++ } ++ ++ /* call driver */ ++ err = func(inode, file, cmd, parg); ++ if (err == -ENOIOCTLCMD) ++ err = -EINVAL; ++ ++ if (err < 0) ++ goto out; ++ ++ /* Copy results into user buffer */ ++ switch (_IOC_DIR(cmd)) { ++ case _IOC_READ: ++ case (_IOC_WRITE | _IOC_READ): ++ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ break; ++ } ++ ++out: ++ kfree(mbuf); ++ return err; ++} ++ ++static int video_do_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, void *parg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int ret = 0; ++ unsigned long arg = (unsigned long)parg; ++ ++ switch (cmd) { ++ case VIDEO_SET_STREAMTYPE: ++ switch (arg) { ++ case VIDEO_CAP_MPEG2: ++ /* printk(KERN_INFO DEVICE_NAME ": setting MPEG2\n"); */ ++ send_cli(dev, "vdec mpeg2\n"); ++ break; ++ case VIDEO_CAP_AVC: ++ /* printk(KERN_INFO DEVICE_NAME ": setting H264\n"); */ ++ send_cli(dev, "vdec h264\n"); ++ break; ++ case VIDEO_CAP_VC1: ++ /* printk(KERN_INFO DEVICE_NAME ": setting VC1\n"); */ ++ send_cli(dev, "vdec vc1\n"); ++ break; ++ default: ++ ret = -EINVAL; ++ break; ++ } ++ break; ++ default: ++ ret = -ENOIOCTLCMD; ++ return -EINVAL; ++ } ++ return ret; ++} ++ ++static int video_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ return dvb_usercopy2(inode, file, cmd, arg, video_do_ioctl); ++} ++ ++static const struct file_operations video_fops = { ++ .owner = THIS_MODULE, ++ .read = video_read, ++ .write = video_write, ++ .open = video_open, ++ .release = video_release, ++ .ioctl = video_ioctl, ++}; ++ ++static struct dvb_device dvbdev_video = { ++ .priv = 0, ++ .readers = -1, ++ .writers = 1, ++ .users = -1, ++ .fops = &video_fops, ++}; ++#endif +diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c +index 9e82d21..c9b1bd4 100644 +--- a/drivers/media/pci/ngene/ngene-cards.c ++++ b/drivers/media/pci/ngene/ngene-cards.c +@@ -42,8 +42,8 @@ + #include "mt2131.h" + #include "tda18271c2dd.h" + #include "drxk.h" +-#include "drxd.h" +-#include "dvb-pll.h" ++#include "tda18212dd.h" ++#include "stv0367dd.h" + + + /****************************************************************************/ +@@ -86,8 +86,98 @@ static int tuner_attach_stv6110(struct ngene_channel *chan) + return 0; + } + ++#if 0 ++static int tuner_attach_mt2060(struct ngene_channel *chan) ++{ ++ struct ngene *dev = chan->dev; ++ void *tconf = dev->card_info->tuner_config[chan->number]; ++ u8 drxa = dev->card_info->demoda[chan->number]; ++ struct dvb_frontend *fe = chan->fe, *fe2; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ fe->misc_priv = chan; ++#else ++ fe->sec_priv = chan; ++#endif ++ fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; ++ ++ dev->card_info->gate_ctrl(fe, 1); ++ fe2 = mt2060_attach(fe, &chan->i2c_adapter, tconf, 1220); ++ dev->card_info->gate_ctrl(fe, 0); ++ ++ i2c_write_register(&chan->i2c_adapter, drxa, 3, 4); ++ write_demod(&chan->i2c_adapter, drxa, 0x1012, 15); ++ write_demod(&chan->i2c_adapter, drxa, 0x1007, 0xc27); ++ write_demod(&chan->i2c_adapter, drxa, 0x0020, 0x003); ++ ++ return fe2 ? 0 : -ENODEV; ++} ++ ++static int tuner_attach_xc3028(struct ngene_channel *chan) ++{ ++ struct ngene *dev = chan->dev; ++ void *tconf = dev->card_info->tuner_config[chan->number]; ++ struct dvb_frontend *fe = chan->fe, *fe2; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ fe->misc_priv = chan; ++#else ++ fe->sec_priv = chan; ++#endif ++ fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; ++ ++ dev->card_info->gate_ctrl(fe, 1); ++ fe2 = xc3028_attach(fe, &chan->i2c_adapter, tconf); ++ dev->card_info->gate_ctrl(fe, 0); ++ ++ /*chan->fe->ops.tuner_ops.set_frequency(chan->fe,231250000);*/ ++ ++ return fe2 ? 0 : -ENODEV; ++} ++ ++static int demod_attach_drxd(struct ngene_channel *chan) ++{ ++ void *feconf = chan->dev->card_info->fe_config[chan->number]; ++ ++ chan->fe = drxd_attach(feconf, ++ chan, &chan->i2c_adapter, ++ &chan->dev->pci_dev->dev); ++ return (chan->fe) ? 0 : -ENODEV; ++} ++ ++static int demod_attach_drxh(struct ngene_channel *chan) ++{ ++ void *feconf = chan->dev->card_info->fe_config[chan->number]; ++ ++ chan->fe = drxh_attach(feconf, chan, ++ &chan->i2c_adapter, &chan->dev->pci_dev->dev); ++ return (chan->fe) ? 0 : -ENODEV; ++} ++ ++static int demod_attach_stb0899(struct ngene_channel *chan) ++{ ++ void *feconf = chan->dev->card_info->fe_config[chan->number]; ++ ++ chan->fe = stb0899_attach(feconf, ++ chan, &chan->i2c_adapter, ++ &chan->dev->pci_dev->dev); ++ if (chan->fe) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) ++ chan->set_tone = chan->fe->ops->set_tone; ++ chan->fe->ops->set_tone = lnbh21_set_tone; ++ chan->fe->ops->set_voltage = lnbh21_set_voltage; ++#else ++ chan->set_tone = chan->fe->ops.set_tone; ++ chan->fe->ops.set_tone = lnbh21_set_tone; ++ chan->fe->ops.set_voltage = lnbh21_set_voltage; ++#endif ++ } ++ ++ return (chan->fe) ? 0 : -ENODEV; ++} ++#endif + +-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) ++static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) + { + struct ngene_channel *chan = fe->sec_priv; + int status; +@@ -121,12 +211,29 @@ static int tuner_attach_tda18271(struct ngene_channel *chan) + return 0; + } + ++static int tuner_attach_tda18212dd(struct ngene_channel *chan) ++{ ++ struct i2c_adapter *i2c; ++ struct dvb_frontend *fe; ++ ++ i2c = &chan->dev->channel[0].i2c_adapter; ++ fe = dvb_attach(tda18212dd_attach, chan->fe, i2c, ++ (chan->number & 1) ? 0x63 : 0x60); ++ if (!fe) { ++ printk(KERN_ERR "No TDA18212 found!\n"); ++ return -ENODEV; ++ } ++ return 0; ++} ++ + static int tuner_attach_probe(struct ngene_channel *chan) + { + if (chan->demod_type == 0) + return tuner_attach_stv6110(chan); + if (chan->demod_type == 1) + return tuner_attach_tda18271(chan); ++ if (chan->demod_type == 2) ++ return tuner_attach_tda18212dd(chan); + return -EINVAL; + } + +@@ -218,18 +325,51 @@ static int demod_attach_drxk(struct ngene_channel *chan, + struct drxk_config config; + + memset(&config, 0, sizeof(config)); +- config.microcode_name = "drxk_a3.mc"; +- config.qam_demod_parameter_count = 4; + config.adr = 0x29 + (chan->number ^ 2); ++ config.microcode_name = "drxk_a3.mc"; + ++#ifdef USE_API3 ++ chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2); ++#else + chan->fe = dvb_attach(drxk_attach, &config, i2c); ++#endif + if (!chan->fe) { + printk(KERN_ERR "No DRXK found!\n"); + return -ENODEV; + } + chan->fe->sec_priv = chan; + chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; +- chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; ++ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; ++ return 0; ++} ++ ++static int port_has_stv0367(struct i2c_adapter *i2c, int port) ++{ ++ u8 val; ++ ++ if (i2c_read_reg16(i2c, 0x1c + (port ^ 1), 0xf000, &val) < 0) ++ return 0; ++ if (val != 0x60) ++ return 0; ++ return 1; ++} ++ ++static int demod_attach_stv0367dd(struct ngene_channel *chan, ++ struct i2c_adapter *i2c) ++{ ++ struct stv0367_cfg cfg; ++ ++ memset(&cfg, 0, sizeof cfg); ++ cfg.adr = 0x1c + (chan->number ^ 1); ++ ++ chan->fe = dvb_attach(stv0367_attach, i2c, &cfg, &chan->fe2); ++ if (!chan->fe) { ++ printk(KERN_ERR "No stv0367 found!\n"); ++ return -ENODEV; ++ } ++ chan->fe->sec_priv = chan; ++ chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; ++ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; + return 0; + } + +@@ -279,6 +419,9 @@ static int cineS2_probe(struct ngene_channel *chan) + } else if (port_has_drxk(i2c, chan->number^2)) { + chan->demod_type = 1; + demod_attach_drxk(chan, i2c); ++ } else if (port_has_stv0367(i2c, chan->number)) { ++ chan->demod_type = 2; ++ demod_attach_stv0367dd(chan, i2c); + } else { + printk(KERN_ERR "No demod found on chan %d\n", chan->number); + return -ENODEV; +@@ -315,249 +458,140 @@ static int demod_attach_lg330x(struct ngene_channel *chan) + return (chan->fe) ? 0 : -ENODEV; + } + +-static int demod_attach_drxd(struct ngene_channel *chan) +-{ +- struct drxd_config *feconf; +- +- feconf = chan->dev->card_info->fe_config[chan->number]; +- +- chan->fe = dvb_attach(drxd_attach, feconf, chan, +- &chan->i2c_adapter, &chan->dev->pci_dev->dev); +- if (!chan->fe) { +- pr_err("No DRXD found!\n"); +- return -ENODEV; +- } +- return 0; +-} ++/****************************************************************************/ ++/* Switch control (I2C gates, etc.) *****************************************/ ++/****************************************************************************/ + +-static int tuner_attach_dtt7520x(struct ngene_channel *chan) ++#if 0 ++static int avf_output(struct ngene_channel *chan, int state) + { +- struct drxd_config *feconf; +- +- feconf = chan->dev->card_info->fe_config[chan->number]; +- +- if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address, +- &chan->i2c_adapter, +- feconf->pll_type)) { +- pr_err("No pll(%d) found!\n", feconf->pll_type); +- return -ENODEV; +- } ++ if (chan->dev->card_info->avf[chan->number]) ++ i2c_write_register(&chan->i2c_adapter, ++ chan->dev->card_info->avf[chan->number], ++ 0xf2, state ? 0x89 : 0x80); + return 0; + } + +-/****************************************************************************/ +-/* EEPROM TAGS **************************************************************/ +-/****************************************************************************/ +- +-#define MICNG_EE_START 0x0100 +-#define MICNG_EE_END 0x0FF0 ++/* Viper expander: sw11,sw12,sw21,sw22,i2csw1,i2csw2,tsen1,tsen2 */ + +-#define MICNG_EETAG_END0 0x0000 +-#define MICNG_EETAG_END1 0xFFFF +- +-/* 0x0001 - 0x000F reserved for housekeeping */ +-/* 0xFFFF - 0xFFFE reserved for housekeeping */ +- +-/* Micronas assigned tags +- EEProm tags for hardware support */ +- +-#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ +-#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ +- +-#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ +-#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ +- +-/* Tag range for OEMs */ ++static int exp_set(struct ngene *dev) ++{ ++ return i2c_write(&dev->channel[0].i2c_adapter, ++ dev->card_info->exp, dev->exp_val); ++} + +-#define MICNG_EETAG_OEM_FIRST 0xC000 +-#define MICNG_EETAG_OEM_LAST 0xFFEF ++static int exp_init(struct ngene *dev) ++{ ++ if (!dev->card_info->exp) ++ return 0; ++ dev->exp_val = dev->card_info->exp_init; ++ return exp_set(dev); ++} + +-static int i2c_write_eeprom(struct i2c_adapter *adapter, +- u8 adr, u16 reg, u8 data) ++static int exp_set_bit(struct ngene *dev, int bit, int val) + { +- u8 m[3] = {(reg >> 8), (reg & 0xff), data}; +- struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, +- .len = sizeof(m)}; ++ if (val) ++ set_bit(bit, &dev->exp_val); ++ else ++ clear_bit(bit, &dev->exp_val); ++ return exp_set(dev); ++} + +- if (i2c_transfer(adapter, &msg, 1) != 1) { +- pr_err(DEVICE_NAME ": Error writing EEPROM!\n"); +- return -EIO; ++static int viper_switch_ctrl(struct ngene_channel *chan, int type, int val) ++{ ++ switch (type) { ++ case 0: /* I2C tuner gate on/off */ ++ return exp_set_bit(chan->dev, 4 + chan->number, val); ++ case 1: /* Stream: 0=TS 1=ITU */ ++ avf_output(chan, val); ++ return exp_set_bit(chan->dev, 6 + chan->number, val); ++ case 2: /* Input: 0=digital 1=analog antenna input */ ++ exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); ++ exp_set_bit(chan->dev, 1 + chan->number * 2, val ? 1 : 0); ++ break; + } + return 0; + } + +-static int i2c_read_eeprom(struct i2c_adapter *adapter, +- u8 adr, u16 reg, u8 *data, int len) ++static int viper_switch_ctrl2(struct ngene_channel *chan, int type, int val) + { +- u8 msg[2] = {(reg >> 8), (reg & 0xff)}; +- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, +- .buf = msg, .len = 2 }, +- {.addr = adr, .flags = I2C_M_RD, +- .buf = data, .len = len} }; +- +- if (i2c_transfer(adapter, msgs, 2) != 2) { +- pr_err(DEVICE_NAME ": Error reading EEPROM\n"); +- return -EIO; ++ switch (type) { ++ case 0: /* I2C tuner gate on/off */ ++ return exp_set_bit(chan->dev, 4 + chan->number, val); ++ case 1: /* Stream: 0=TS 1=ITU */ ++ avf_output(chan, val); ++ return exp_set_bit(chan->dev, 6 + chan->number, val); ++ case 2: /* Input: 0=digital 1=analog antenna input */ ++ exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); ++ exp_set_bit(chan->dev, 1 + chan->number * 2, 0); ++ break; + } + return 0; + } + +-static int ReadEEProm(struct i2c_adapter *adapter, +- u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) ++static int viper_gate_ctrl(struct dvb_frontend *fe, int enable) + { +- int status = 0; +- u16 Addr = MICNG_EE_START, Length, tag = 0; +- u8 EETag[3]; +- +- while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { +- if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) +- return -1; +- tag = (EETag[0] << 8) | EETag[1]; +- if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) +- return -1; +- if (tag == Tag) +- break; +- Addr += sizeof(u16) + 1 + EETag[2]; +- } +- if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { +- pr_err(DEVICE_NAME +- ": Reached EOEE @ Tag = %04x Length = %3d\n", +- tag, EETag[2]); +- return -1; +- } +- Length = EETag[2]; +- if (Length > MaxLen) +- Length = (u16) MaxLen; +- if (Length > 0) { +- Addr += sizeof(u16) + 1; +- status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); +- if (!status) { +- *pLength = EETag[2]; +-#if 0 +- if (Length < EETag[2]) +- status = STATUS_BUFFER_OVERFLOW; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ struct ngene_channel *chan = fe->misc_priv; ++#else /* Why is there no misc_priv available anymore !?!?! */ ++ /* Well, just abuse sec :-) */ ++ struct ngene_channel *chan = fe->sec_priv; + #endif +- } +- } +- return status; ++ struct ngene *dev = chan->dev; ++ ++ return dev->card_info->switch_ctrl(chan, 0, enable); + } + +-static int WriteEEProm(struct i2c_adapter *adapter, +- u16 Tag, u32 Length, u8 *data) ++static int python_switch_ctrl(struct ngene_channel *chan, int type, int val) + { +- int status = 0; +- u16 Addr = MICNG_EE_START; +- u8 EETag[3]; +- u16 tag = 0; +- int retry, i; +- +- while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { +- if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) +- return -1; +- tag = (EETag[0] << 8) | EETag[1]; +- if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) +- return -1; +- if (tag == Tag) +- break; +- Addr += sizeof(u16) + 1 + EETag[2]; +- } +- if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { +- pr_err(DEVICE_NAME +- ": Reached EOEE @ Tag = %04x Length = %3d\n", +- tag, EETag[2]); +- return -1; +- } +- +- if (Length > EETag[2]) +- return -EINVAL; +- /* Note: We write the data one byte at a time to avoid +- issues with page sizes. (which are different for +- each manufacture and eeprom size) +- */ +- Addr += sizeof(u16) + 1; +- for (i = 0; i < Length; i++, Addr++) { +- status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); +- +- if (status) +- break; +- +- /* Poll for finishing write cycle */ +- retry = 10; +- while (retry) { +- u8 Tmp; +- +- msleep(50); +- status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); +- if (status) +- break; +- if (Tmp != data[i]) +- pr_err(DEVICE_NAME +- "eeprom write error\n"); +- retry -= 1; +- } +- if (status) { +- pr_err(DEVICE_NAME +- ": Timeout polling eeprom\n"); +- break; +- } ++ switch (type) { ++ case 0: /* I2C tuner gate on/off */ ++ if (chan->number > 1) ++ return -EINVAL; ++ return ngene_command_gpio_set(chan->dev, 3 + chan->number, val); ++ case 1: /* Stream: 0=TS 1=ITU */ ++ avf_output(chan, val); ++ return 0; + } +- return status; ++ return 0; + } + +-static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) ++static int viper_reset_xc(struct dvb_frontend *fe) + { +- int stat; +- u8 buf[2]; +- u32 len = 0; +- +- stat = ReadEEProm(adapter, tag, 2, buf, &len); +- if (stat) +- return stat; +- if (len != 2) +- return -EINVAL; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ struct ngene_channel *chan = fe->misc_priv; ++#else ++ struct ngene_channel *chan = fe->sec_priv; ++#endif ++ struct ngene *dev = chan->dev; + +- *data = (buf[0] << 8) | buf[1]; +- return 0; +-} ++ printk(KERN_INFO DEVICE_NAME ": Reset XC3028\n"); + +-static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) +-{ +- int stat; +- u8 buf[2]; ++ if (chan->number > 1) ++ return -EINVAL; + +- buf[0] = data >> 8; +- buf[1] = data & 0xff; +- stat = WriteEEProm(adapter, tag, 2, buf); +- if (stat) +- return stat; ++ ngene_command_gpio_set(dev, 3 + chan->number, 0); ++ msleep(150); ++ ngene_command_gpio_set(dev, 3 + chan->number, 1); + return 0; + } + +-static s16 osc_deviation(void *priv, s16 deviation, int flag) ++static int python_gate_ctrl(struct dvb_frontend *fe, int enable) + { +- struct ngene_channel *chan = priv; +- struct i2c_adapter *adap = &chan->i2c_adapter; +- u16 data = 0; +- +- if (flag) { +- data = (u16) deviation; +- pr_info(DEVICE_NAME ": write deviation %d\n", +- deviation); +- eeprom_write_ushort(adap, 0x1000 + chan->number, data); +- } else { +- if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) +- data = 0; +- pr_info(DEVICE_NAME ": read deviation %d\n", +- (s16) data); +- } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) ++ struct ngene_channel *chan = fe->misc_priv; ++#else /* Why is there no misc_priv available anymore !?!?! */ ++ struct ngene_channel *chan = fe->sec_priv; ++#endif ++ struct ngene *dev = chan->dev; + +- return (s16) data; ++ if (chan->number == 0) ++ return ngene_command_gpio_set(dev, 3, enable); ++ if (chan->number == 1) ++ return ngene_command_gpio_set(dev, 4, enable); ++ return -EINVAL; + } +- +-/****************************************************************************/ +-/* Switch control (I2C gates, etc.) *****************************************/ +-/****************************************************************************/ +- ++#endif + + static struct stv090x_config fe_cineS2 = { + .device = STV0900, +@@ -705,14 +739,18 @@ static struct ngene_info ngene_info_m780 = { + .fw_version = 15, + }; + ++/****************************************************************************/ ++ ++#if 0 + static struct drxd_config fe_terratec_dvbt_0 = { + .index = 0, + .demod_address = 0x70, + .demod_revision = 0xa2, + .demoda_address = 0x00, + .pll_address = 0x60, +- .pll_type = DVB_PLL_THOMSON_DTT7520X, ++ .pll_type = DRXD_PLL_DTT7520X, + .clock = 20000, ++ .pll_set = ngene_pll_set_th_dtt7520x, + .osc_deviation = osc_deviation, + }; + +@@ -722,8 +760,9 @@ static struct drxd_config fe_terratec_dvbt_1 = { + .demod_revision = 0xa2, + .demoda_address = 0x00, + .pll_address = 0x60, +- .pll_type = DVB_PLL_THOMSON_DTT7520X, ++ .pll_type = DRXD_PLL_DTT7520X, + .clock = 20000, ++ .pll_set = ngene_pll_set_th_dtt7520x, + .osc_deviation = osc_deviation, + }; + +@@ -732,13 +771,293 @@ static struct ngene_info ngene_info_terratec = { + .name = "Terratec Integra/Cinergy2400i Dual DVB-T", + .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, + .demod_attach = {demod_attach_drxd, demod_attach_drxd}, +- .tuner_attach = {tuner_attach_dtt7520x, tuner_attach_dtt7520x}, + .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, + .i2c_access = 1, + }; + + /****************************************************************************/ + ++static struct mt2060_config tuner_python_0 = { ++ .i2c_address = 0x60, ++ .clock_out = 3, ++ .input = 0 ++}; ++ ++static struct mt2060_config tuner_python_1 = { ++ .i2c_address = 0x61, ++ .clock_out = 3, ++ .input = 1 ++}; ++ ++static struct drxd_config fe_python_0 = { ++ .index = 0, ++ .demod_address = 0x71, ++ .demod_revision = 0xb1, ++ .demoda_address = 0x41, ++ .clock = 16000, ++ .osc_deviation = osc_deviation, ++}; ++ ++static struct drxd_config fe_python_1 = { ++ .index = 1, ++ .demod_address = 0x70, ++ .demod_revision = 0xb1, ++ .demoda_address = 0x45, ++ .clock = 16000, ++ .osc_deviation = osc_deviation, ++}; ++ ++static struct ngene_info ngene_info_python = { ++ .type = NGENE_PYTHON, ++ .name = "Micronas MicPython/Hedgehog Dual DVB-T", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, ++ .tuner_attach = {tuner_attach_mt2060, tuner_attach_mt2060}, ++ .fe_config = {&fe_python_0, &fe_python_1}, ++ .tuner_config = {&tuner_python_0, &tuner_python_1}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .demoda = {0x41, 0x45}, ++ .gate_ctrl = python_gate_ctrl, ++ .switch_ctrl = python_switch_ctrl, ++}; ++ ++/****************************************************************************/ ++ ++static struct drxd_config fe_appb_dvbt_0 = { ++ .index = 0, ++ .demod_address = 0x71, ++ .demod_revision = 0xa2, ++ .demoda_address = 0x41, ++ .pll_address = 0x63, ++ .pll_type = DRXD_PLL_MT3X0823, ++ .clock = 20000, ++ .pll_set = ngene_pll_set_mt_3x0823, ++ .osc_deviation = osc_deviation, ++}; ++ ++static struct drxd_config fe_appb_dvbt_1 = { ++ .index = 1, ++ .demod_address = 0x70, ++ .demod_revision = 0xa2, ++ .demoda_address = 0x45, ++ .pll_address = 0x60, ++ .pll_type = DRXD_PLL_MT3X0823, ++ .clock = 20000, ++ .pll_set = ngene_pll_set_mt_3x0823, ++ .osc_deviation = osc_deviation, ++}; ++ ++static struct ngene_info ngene_info_appboard = { ++ .type = NGENE_APP, ++ .name = "Micronas Application Board Dual DVB-T", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, ++ .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, ++ .avf = {0x43, 0x47}, ++}; ++ ++static struct ngene_info ngene_info_appboard_ntsc = { ++ .type = NGENE_APP, ++ .name = "Micronas Application Board Dual DVB-T", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, ++ .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, ++ .avf = {0x43, 0x47}, ++ .ntsc = 1, ++}; ++ ++/****************************************************************************/ ++ ++static struct stb0899_config fe_sidewinder_0 = { ++ .demod_address = 0x68, ++ .pll_address = 0x63, ++}; ++ ++static struct stb0899_config fe_sidewinder_1 = { ++ .demod_address = 0x6b, ++ .pll_address = 0x60, ++}; ++ ++static struct ngene_info ngene_info_sidewinder = { ++ .type = NGENE_SIDEWINDER, ++ .name = "Micronas MicSquirrel/Sidewinder Dual DVB-S2", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_stb0899, demod_attach_stb0899}, ++ .fe_config = {&fe_sidewinder_0, &fe_sidewinder_1}, ++ .lnb = {0x0b, 0x08}, ++}; ++ ++/****************************************************************************/ ++/* Yet unnamed S2 card with dual DVB-S2 demod */ ++/****************************************************************************/ ++ ++static struct stv0900_config fe_s2_0 = { ++ .addr = 0x68, ++ .pll = 0x63, ++ .pll_type = 0, ++ .nr = 0, ++}; ++ ++static struct stv0900_config fe_s2_1 = { ++ .addr = 0x68, ++ .pll = 0x60, ++ .pll_type = 0, ++ .nr = 1, ++}; ++ ++static struct ngene_info ngene_info_s2 = { ++ .type = NGENE_SIDEWINDER, ++ .name = "S2", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, ++ NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, ++ .fe_config = {&fe_s2_0, &fe_s2_1}, ++ .lnb = {0x0b, 0x08}, ++ .tsf = {3, 3}, ++ .fw_version = 15, ++}; ++ ++static struct stv0900_config fe_s2b_0 = { ++ .addr = 0x68, ++ .pll = 0x60, ++ .pll_type = 0x10, ++ .nr = 0, ++}; ++ ++static struct stv0900_config fe_s2b_1 = { ++ .addr = 0x68, ++ .pll = 0x63, ++ .pll_type = 0x10, ++ .nr = 1, ++}; ++ ++static struct ngene_info ngene_info_s2_b = { ++ .type = NGENE_SIDEWINDER, ++ .name = "S2 V2", ++ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, ++ NGENE_IO_TSIN, NGENE_IO_TSIN}, ++ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, ++ .fe_config = {&fe_s2b_0, &fe_s2b_1}, ++ .lnb = {0x0b, 0x08}, ++ .tsf = {3, 3}, ++ .fw_version = 17, ++}; ++ ++/****************************************************************************/ ++ ++static struct xc3028_config tuner_viper_0 = { ++ .adr = 0x61, ++ .reset = viper_reset_xc ++}; ++ ++static struct xc3028_config tuner_viper_1 = { ++ .adr = 0x64, ++ .reset = viper_reset_xc ++}; ++ ++static struct drxh_config fe_viper_h_0 = {.adr = 0x2b}; ++ ++static struct drxh_config fe_viper_h_1 = {.adr = 0x29}; ++ ++static struct drxh_config fe_viper_l_0 = {.adr = 0x2b, .type = 3931}; ++ ++static struct drxh_config fe_viper_l_1 = {.adr = 0x29, .type = 3931}; ++ ++static struct ngene_info ngene_info_viper_v1 = { ++ .type = NGENE_VIPER, ++ .name = "Micronas MicViper Dual ATSC DRXH", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, ++ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, ++ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, ++ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .exp = 0x20, ++ .exp_init = 0xf5, ++ .gate_ctrl = viper_gate_ctrl, ++ .switch_ctrl = viper_switch_ctrl, ++ .tsf = {2, 2}, ++}; ++ ++static struct ngene_info ngene_info_viper_v2 = { ++ .type = NGENE_VIPER, ++ .name = "Micronas MicViper Dual ATSC DRXL", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, ++ .fe_config = {&fe_viper_l_0, &fe_viper_l_1}, ++ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, ++ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .exp = 0x38, ++ .exp_init = 0xf5, ++ .gate_ctrl = viper_gate_ctrl, ++ .switch_ctrl = viper_switch_ctrl, ++ .tsf = {2, 2}, ++}; ++ ++/****************************************************************************/ ++ ++static struct ngene_info ngene_info_vbox_v1 = { ++ .type = NGENE_VBOX_V1, ++ .name = "VBox Cat's Eye 164E", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, ++ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, ++ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, ++ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .exp = 0x20, ++ .exp_init = 0xf5, ++ .gate_ctrl = viper_gate_ctrl, ++ .switch_ctrl = viper_switch_ctrl, ++ .tsf = {2, 2}, ++}; ++ ++/****************************************************************************/ ++ ++static struct ngene_info ngene_info_vbox_v2 = { ++ .type = NGENE_VBOX_V2, ++ .name = "VBox Cat's Eye 164E", ++ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_TSIN | NGENE_IO_TV, ++ NGENE_IO_AIN, NGENE_IO_AIN}, ++ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, ++ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, ++ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, ++ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, ++ .avf = {0x43, 0x47}, ++ .msp = {0x40, 0x42}, ++ .exp = 0x20, ++ .exp_init = 0xf5, ++ .gate_ctrl = viper_gate_ctrl, ++ .switch_ctrl = viper_switch_ctrl2, ++ .tsf = {2, 2}, ++}; ++ ++/****************************************************************************/ ++ ++static struct ngene_info ngene_info_racer = { ++ .type = NGENE_RACER, ++ .name = "Micronas MicRacer HDTV Decoder Card", ++ .io_type = {NGENE_IO_HDTV, NGENE_IO_NONE, ++ NGENE_IO_AIN, NGENE_IO_NONE, ++ NGENE_IO_TSOUT}, ++ .i2s = {0, 0, 1, 0}, ++ .fw_version = 17, ++}; ++#endif + + + /****************************************************************************/ +@@ -753,6 +1072,8 @@ static struct ngene_info ngene_info_terratec = { + /****************************************************************************/ + + static const struct pci_device_id ngene_id_tbl[] = { ++ NGENE_ID(0x18c3, 0xab04, ngene_info_cineS2), ++ NGENE_ID(0x18c3, 0xab05, ngene_info_cineS2v5), + NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), + NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), + NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), +@@ -761,7 +1082,32 @@ static const struct pci_device_id ngene_id_tbl[] = { + NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex), + NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex), + NGENE_ID(0x1461, 0x062e, ngene_info_m780), ++#if 0 /* not (yet?) supported */ ++ NGENE_ID(0x18c3, 0x0000, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x0004, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x8011, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x8015, ngene_info_appboard_ntsc), + NGENE_ID(0x153b, 0x1167, ngene_info_terratec), ++ NGENE_ID(0x18c3, 0x0030, ngene_info_python), ++ NGENE_ID(0x18c3, 0x0052, ngene_info_sidewinder), ++ NGENE_ID(0x18c3, 0x8f00, ngene_info_racer), ++ NGENE_ID(0x18c3, 0x0041, ngene_info_viper_v1), ++ NGENE_ID(0x18c3, 0x0042, ngene_info_viper_v2), ++ NGENE_ID(0x14f3, 0x0041, ngene_info_vbox_v1), ++ NGENE_ID(0x14f3, 0x0043, ngene_info_vbox_v2), ++ NGENE_ID(0x18c3, 0xabcd, ngene_info_s2), ++ NGENE_ID(0x18c3, 0xabc2, ngene_info_s2_b), ++ NGENE_ID(0x18c3, 0xabc3, ngene_info_s2_b), ++ NGENE_ID(0x18c3, 0x0001, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x0005, ngene_info_appboard), ++ NGENE_ID(0x18c3, 0x0009, ngene_info_appboard_atsc), ++ NGENE_ID(0x18c3, 0x000b, ngene_info_appboard_atsc), ++ NGENE_ID(0x18c3, 0x0010, ngene_info_shrek_50_fp), ++ NGENE_ID(0x18c3, 0x0011, ngene_info_shrek_60_fp), ++ NGENE_ID(0x18c3, 0x0012, ngene_info_shrek_50), ++ NGENE_ID(0x18c3, 0x0013, ngene_info_shrek_60), ++ NGENE_ID(0x18c3, 0x0000, ngene_info_hognose), ++#endif + {0} + }; + MODULE_DEVICE_TABLE(pci, ngene_id_tbl); +@@ -798,7 +1144,7 @@ static void ngene_resume(struct pci_dev *dev) + printk(KERN_INFO DEVICE_NAME ": resume\n"); + } + +-static const struct pci_error_handlers ngene_errors = { ++static struct pci_error_handlers ngene_errors = { + .error_detected = ngene_error_detected, + .link_reset = ngene_link_reset, + .slot_reset = ngene_slot_reset, +diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c +index 37ebc42..84510db 100644 +--- a/drivers/media/pci/ngene/ngene-core.c ++++ b/drivers/media/pci/ngene/ngene-core.c +@@ -86,6 +86,14 @@ static void event_tasklet(unsigned long data) + if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify)) + dev->RxEventNotify(dev, Event.TimeStamp, + Event.RXCharacter); ++#if 0 ++ if ((Event.GPIOStatus & 0x80) && (dev->Gpio2EventNotify)) ++ dev->Gpio2EventNotify(dev, Event.TimeStamp, ++ Event.GPIOStatus & 0x1f); ++ if ((Event.GPIOStatus & 0x40) && (dev->Gpio3EventNotify)) ++ dev->Gpio3EventNotify(dev, Event.TimeStamp, ++ Event.GPIOStatus & 0x1f); ++#endif + } + } + +@@ -214,6 +222,13 @@ static irqreturn_t irq_handler(int irq, void *dev_id) + u8 nextWriteIndex = + (dev->EventQueueWriteIndex + 1) & + (EVENT_QUEUE_SIZE - 1); ++#if 0 ++ printk(KERN_ERR DEVICE_NAME ++ ": Event interrupt %02x Uart = %02x Gpio = %02x\n", ++ dev->EventBuffer->EventStatus, ++ dev->EventBuffer->UARTStatus, ++ dev->EventBuffer->GPIOStatus); ++#endif + if (nextWriteIndex != dev->EventQueueReadIndex) { + dev->EventQueue[dev->EventQueueWriteIndex] = + *(dev->EventBuffer); +@@ -258,16 +273,22 @@ static void dump_command_io(struct ngene *dev) + u8 buf[8], *b; + + ngcpyfrom(buf, HOST_TO_NGENE, 8); +- printk(KERN_ERR "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf); ++ printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], ++ buf[4], buf[5], buf[6], buf[7]); + + ngcpyfrom(buf, NGENE_TO_HOST, 8); +- printk(KERN_ERR "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf); ++ printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], ++ buf[4], buf[5], buf[6], buf[7]); + + b = dev->hosttongene; +- printk(KERN_ERR "dev->hosttongene (%p): %*ph\n", b, 8, b); ++ printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + + b = dev->ngenetohost; +- printk(KERN_ERR "dev->ngenetohost (%p): %*ph\n", b, 8, b); ++ printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", ++ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + } + + static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) +@@ -316,12 +337,24 @@ static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) + ngwritel(1, FORCE_INT); + + ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ); ++#if 0 ++ if (ret < 0) ++ return ret; ++ if (!dev->cmd_done) ++ ; ++#endif + if (!ret) { + /*ngwritel(0, FORCE_NMI);*/ + + printk(KERN_ERR DEVICE_NAME + ": Command timeout cmd=%02x prev=%02x\n", + com->cmd.hdr.Opcode, dev->prev_cmd); ++#if 0 ++ printk(KERN_ERR DEVICE_NAME ": Icounts=%08x\n", ++ ngreadl(NGENE_INT_COUNTS)); ++ if (ngreadl(NGENE_INT_COUNTS) == 0xffffffff) ++ ngwritel(0, NGENE_INT_ENABLE); ++#endif + dump_command_io(dev); + return -1; + } +@@ -348,6 +381,19 @@ int ngene_command(struct ngene *dev, struct ngene_command *com) + return result; + } + ++#if 0 ++int ngene_command_nop(struct ngene *dev) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = CMD_NOP; ++ com.cmd.hdr.Length = 0; ++ com.in_len = 0; ++ com.out_len = 0; ++ ++ return ngene_command(dev, &com); ++} ++#endif + + static int ngene_command_load_firmware(struct ngene *dev, + u8 *ngene_fw, u32 size) +@@ -382,6 +428,83 @@ static int ngene_command_load_firmware(struct ngene *dev, + return ngene_command(dev, &com); + } + ++#if 0 ++int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = type ? CMD_SFR_READ : CMD_IRAM_READ; ++ com.cmd.hdr.Length = 1; ++ com.cmd.SfrIramRead.address = adr; ++ com.in_len = 1; ++ com.out_len = 2; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ *data = com.cmd.raw8[1]; ++ return 0; ++} ++ ++int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = type ? CMD_SFR_WRITE : CMD_IRAM_WRITE; ++ com.cmd.hdr.Length = 2; ++ com.cmd.SfrIramWrite.address = adr; ++ com.cmd.SfrIramWrite.data = data; ++ com.in_len = 2; ++ com.out_len = 1; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ return 0; ++} ++ ++static int ngene_command_config_uart(struct ngene *dev, u8 config, ++ tx_cb_t *tx_cb, rx_cb_t *rx_cb) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = CMD_CONFIGURE_UART; ++ com.cmd.hdr.Length = sizeof(struct FW_CONFIGURE_UART) - 2; ++ com.cmd.ConfigureUart.UartControl = config; ++ com.in_len = sizeof(struct FW_CONFIGURE_UART); ++ com.out_len = 0; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ dev->TxEventNotify = tx_cb; ++ dev->RxEventNotify = rx_cb; ++ ++ dprintk(KERN_DEBUG DEVICE_NAME ": Set UART config %02x.\n", config); ++ ++ return 0; ++} ++ ++static void tx_cb(struct ngene *dev, u32 ts) ++{ ++ dev->tx_busy = 0; ++ wake_up_interruptible(&dev->tx_wq); ++} ++ ++static void rx_cb(struct ngene *dev, u32 ts, u8 c) ++{ ++ int rp = dev->uart_rp; ++ int nwp, wp = dev->uart_wp; ++ ++ /* dprintk(KERN_DEBUG DEVICE_NAME ": %c\n", c); */ ++ nwp = (wp + 1) % (UART_RBUF_LEN); ++ if (nwp == rp) ++ return; ++ dev->uart_rbuf[wp] = c; ++ dev->uart_wp = nwp; ++ wake_up_interruptible(&dev->rx_wq); ++} ++#endif + + static int ngene_command_config_buf(struct ngene *dev, u8 config) + { +@@ -427,6 +550,18 @@ int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) + return ngene_command(dev, &com); + } + ++#if 0 ++/* The reset is only wired to GPIO4 on MicRacer Revision 1.10 ! ++ Also better set bootdelay to 1 in nvram or less. */ ++static void ngene_reset_decypher(struct ngene *dev) ++{ ++ printk(KERN_INFO DEVICE_NAME ": Resetting Decypher.\n"); ++ ngene_command_gpio_set(dev, 4, 0); ++ msleep(1); ++ ngene_command_gpio_set(dev, 4, 1); ++ msleep(2000); ++} ++#endif + + /* + 02000640 is sample on rising edge. +@@ -512,6 +647,17 @@ void FillTSBuffer(void *Buffer, int Length, u32 Flags) + } + } + ++#if 0 ++static void clear_tsin(struct ngene_channel *chan) ++{ ++ struct SBufferHeader *Cur = chan->nextBuffer; ++ ++ do { ++ memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); ++ Cur = Cur->Next; ++ } while (Cur != chan->nextBuffer); ++} ++#endif + + static void flush_buffers(struct ngene_channel *chan) + { +@@ -732,6 +878,14 @@ void set_transfer(struct ngene_channel *chan, int state) + if (dev->card_info->switch_ctrl) + dev->card_info->switch_ctrl(chan, 1, state ^ 1); + ++#if 0 ++ /* Disable AVF output if present. */ ++ if (dev->card_info->avf[chan->number]) ++ i2c_write_register(&chan->i2c_adapter, ++ chan->dev->card_info->avf[chan->number], ++ 0xf2, state ? 0x80 : 0x89); ++ ++#endif + if (state) { + spin_lock_irq(&chan->state_lock); + +@@ -752,8 +906,8 @@ void set_transfer(struct ngene_channel *chan, int state) + if (chan->mode & NGENE_IO_TSIN) + chan->pBufferExchange = tsin_exchange; + spin_unlock_irq(&chan->state_lock); +- } +- /* else printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", ++ } else ++ ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", + ngreadl(0x9310)); */ + + ret = ngene_command_stream_control(dev, chan->number, +@@ -771,6 +925,89 @@ void set_transfer(struct ngene_channel *chan, int state) + } + } + ++#if 0 ++/****************************************************************************/ ++/* Decypher firmware loading ************************************************/ ++/****************************************************************************/ ++ ++#define DECYPHER_FW "decypher.fw" ++ ++static int dec_ts_send(struct ngene *dev, u8 *buf, u32 len) ++{ ++#if 0 ++ if (wait_event_interruptible(dev->tsout_rbuf.queue, ++ dvb_ringbuffer_free ++ (&dev->tsout_rbuf) >= len) < 0) ++ return 0; ++#else ++ while (dvb_ringbuffer_free(&dev->tsout_rbuf) < len) ++ msleep(1); ++ ++#endif ++ ++ dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); ++ ++ return len; ++} ++ ++u8 dec_fw_fill_ts[188] = { 0x47, 0x09, 0x0e, 0x10, 0xff, 0xff, 0x00, 0x00 }; ++ ++int dec_fw_send(struct ngene *dev, u8 *fw, u32 size) ++{ ++ struct ngene_channel *chan = &dev->channel[4]; ++ u32 len = 180, cc = 0; ++ u8 buf[8] = { 0x47, 0x09, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00 }; ++ ++ set_transfer(chan, 1); ++ msleep(100); ++ while (size) { ++ len = 180; ++ if (len > size) ++ len = size; ++ buf[3] = 0x10 | (cc & 0x0f); ++ buf[4] = (cc >> 8); ++ buf[5] = cc & 0xff; ++ buf[6] = len; ++ ++ dec_ts_send(dev, buf, 8); ++ dec_ts_send(dev, fw, len); ++ if (len < 180) ++ dec_ts_send(dev, dec_fw_fill_ts + len + 8, 180 - len); ++ cc++; ++ size -= len; ++ fw += len; ++ } ++ for (len = 0; len < 512; len++) ++ dec_ts_send(dev, dec_fw_fill_ts, 188); ++ while (dvb_ringbuffer_avail(&dev->tsout_rbuf)) ++ msleep(10); ++ msleep(100); ++ set_transfer(chan, 0); ++ return 0; ++} ++ ++int dec_fw_boot(struct ngene *dev) ++{ ++ u32 size; ++ const struct firmware *fw = NULL; ++ u8 *dec_fw; ++ ++ if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) { ++ printk(KERN_ERR DEVICE_NAME ++ ": %s not found. Check hotplug directory.\n", ++ DECYPHER_FW); ++ return -1; ++ } ++ printk(KERN_INFO DEVICE_NAME ": Booting decypher firmware file %s\n", ++ DECYPHER_FW); ++ ++ size = fw->size; ++ dec_fw = (u8 *)fw->data; ++ dec_fw_send(dev, dec_fw, size); ++ release_firmware(fw); ++ return 0; ++} ++#endif + + /****************************************************************************/ + /* nGene hardware init and release functions ********************************/ +@@ -1065,6 +1302,85 @@ static u32 Buffer2Sizes[MAX_STREAM] = { + 0 + }; + ++#if 0 ++static int allocate_buffer(struct pci_dev *pci_dev, dma_addr_t of, ++ struct SRingBufferDescriptor *rbuf, ++ u32 entries, u32 size1, u32 size2) ++{ ++ if (create_ring_buffer(pci_dev, rbuf, entries) < 0) ++ return -ENOMEM; ++ ++ if (AllocateRingBuffers(pci_dev, of, rbuf, size1, size2) < 0) ++ return -ENOMEM; ++ ++ return 0; ++} ++ ++static int channel_allocate_buffers(struct ngene_channel *chan) ++{ ++ struct ngene *dev = chan->dev; ++ int type = dev->card_info->io_type[chan->number]; ++ int status; ++ ++ chan->State = KSSTATE_STOP; ++ ++ if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { ++ status = create_ring_buffer(dev->pci_dev, ++ &chan->RingBuffer, ++ RingBufferSizes[chan->number]); ++ if (status < 0) ++ return -ENOMEM; ++ ++ if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { ++ status = AllocateRingBuffers(dev->pci_dev, ++ dev->PAOverflowBuffer, ++ &chan->RingBuffer, ++ Buffer1Sizes[chan->number], ++ Buffer2Sizes[chan-> ++ number]); ++ if (status < 0) ++ return -ENOMEM; ++ } else if (type & NGENE_IO_HDTV) { ++ status = AllocateRingBuffers(dev->pci_dev, ++ dev->PAOverflowBuffer, ++ &chan->RingBuffer, ++ MAX_HDTV_BUFFER_SIZE, 0); ++ if (status < 0) ++ return -ENOMEM; ++ } ++ } ++ ++ if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { ++ ++ status = create_ring_buffer(dev->pci_dev, ++ &chan->TSRingBuffer, RING_SIZE_TS); ++ if (status < 0) ++ return -ENOMEM; ++ ++ status = AllocateRingBuffers(dev->pci_dev, ++ dev->PAOverflowBuffer, ++ &chan->TSRingBuffer, ++ MAX_TS_BUFFER_SIZE, 0); ++ if (status) ++ return -ENOMEM; ++ } ++ ++ if (type & NGENE_IO_TSOUT) { ++ status = create_ring_buffer(dev->pci_dev, ++ &chan->TSIdleBuffer, 1); ++ if (status < 0) ++ return -ENOMEM; ++ status = AllocateRingBuffers(dev->pci_dev, ++ dev->PAOverflowBuffer, ++ &chan->TSIdleBuffer, ++ MAX_TS_BUFFER_SIZE, 0); ++ if (status) ++ return -ENOMEM; ++ FillTSIdleBuffer(&chan->TSIdleBuffer, &chan->TSRingBuffer); ++ } ++ return 0; ++} ++#endif + + static int AllocCommonBuffers(struct ngene *dev) + { +@@ -1318,6 +1634,10 @@ static int ngene_buffer_config(struct ngene *dev) + u8 tsin12_config[6] = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 }; + u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 }; + u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 }; ++#if 0 ++ u8 tsin34_config[6] = { 0x00, 0x00, 0x00, 0x60, 0x60, 0x00 }; ++ u8 tsio35_config[6] = { 0x00, 0x00, 0x00, 0x60, 0x00, 0x60 }; ++#endif + u8 *bconf = tsin12_config; + + if (dev->card_info->io_type[2]&NGENE_IO_TSIN && +@@ -1327,10 +1647,22 @@ static int ngene_buffer_config(struct ngene *dev) + dev->ci.en) + bconf = tsio1235_config; + } ++#if 0 ++ if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { ++ bconf = hdtv_config; ++ ngene_reset_decypher(dev); ++ } ++#endif + stat = ngene_command_config_free_buf(dev, bconf); + } else { + int bconf = BUFFER_CONFIG_4422; + ++#if 0 ++ if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { ++ bconf = BUFFER_CONFIG_8022; ++ ngene_reset_decypher(dev); ++ } ++#endif + if (dev->card_info->io_type[3] == NGENE_IO_TSIN) + bconf = BUFFER_CONFIG_3333; + stat = ngene_command_config_buf(dev, bconf); +@@ -1403,8 +1735,10 @@ static int ngene_start(struct ngene *dev) + if (stat < 0) + goto fail; + +- return 0; ++ if (!stat) ++ return stat; + ++ /* otherwise error: fall through */ + fail: + ngwritel(0, NGENE_INT_ENABLE); + free_irq(dev->pci_dev->irq, dev); +@@ -1688,10 +2022,36 @@ int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) + + + dev->i2c_current_bus = -1; ++#if 0 ++ exp_init(dev); ++ ++ /* Disable analog TV decoder chips if present */ ++ if (dev->card_info->msp[0]) ++ i2c_write_msp_register(&dev->channel[0].i2c_adapter, ++ dev->card_info->msp[0], 0x00, 0x0000); ++ if (dev->card_info->msp[1]) ++ i2c_write_msp_register(&dev->channel[1].i2c_adapter, ++ dev->card_info->msp[1], 0x00, 0x0000); ++ { ++ u16 data; ++ read_msp(&dev->channel[0].i2c_adapter, ++ dev->card_info->msp[0], 0x00, &data); ++ } ++ if (dev->card_info->avf[0]) ++ i2c_write_register(&dev->channel[0].i2c_adapter, ++ dev->card_info->avf[0], 0xf2, 0x80); ++ if (dev->card_info->avf[1]) ++ i2c_write_register(&dev->channel[1].i2c_adapter, ++ dev->card_info->avf[1], 0xf2, 0x80); ++ if (copy_eeprom) { ++ i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52); ++ i2c_dump_eeprom(&dev->channel[0].i2c_adapter, 0x52); ++ } ++ /*i2c_check_eeprom(&dev->i2c_adapter);*/ ++#endif + + /* Register DVB adapters and devices for both channels */ +- stat = init_channels(dev); +- if (stat < 0) ++ if (init_channels(dev) < 0) + goto fail2; + + return 0; +diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c +index fcb16a6..8049e2b 100644 +--- a/drivers/media/pci/ngene/ngene-dvb.c ++++ b/drivers/media/pci/ngene/ngene-dvb.c +@@ -42,10 +42,319 @@ + + #include "ngene.h" + ++#if 0 ++int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, ++ u16 lines, u16 bpl, u16 vblines, u16 vbibpl) ++{ ++ if (!(mode & SMODE_TRANSPORT_STREAM)) ++ return -EINVAL; ++ ++ if (lines * bpl > MAX_VIDEO_BUFFER_SIZE) ++ return -EINVAL; ++ ++ if ((mode & SMODE_TRANSPORT_STREAM) && (((bpl * lines) & 0xff) != 0)) ++ return -EINVAL; ++ ++ if ((mode & SMODE_VIDEO_CAPTURE) && (bpl & 7) != 0) ++ return -EINVAL; ++ ++ return ngene_command_stream_control(dev, stream, control, mode, 0); ++} ++#endif + + /****************************************************************************/ + /* COMMAND API interface ****************************************************/ + /****************************************************************************/ ++#if 0 ++ ++static int command_do_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, void *parg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int err = 0; ++ ++ switch (cmd) { ++ case IOCTL_MIC_NO_OP: ++ err = ngene_command_nop(dev); ++ break; ++ ++ case IOCTL_MIC_DOWNLOAD_FIRMWARE: ++ break; ++ ++ case IOCTL_MIC_I2C_READ: ++ { ++ MIC_I2C_READ *msg = parg; ++ ++ err = ngene_command_i2c_read(dev, msg->I2CAddress >> 1, ++ msg->OutData, msg->OutLength, ++ msg->OutData, msg->InLength, 1); ++ break; ++ } ++ ++ case IOCTL_MIC_I2C_WRITE: ++ { ++ MIC_I2C_WRITE *msg = parg; ++ ++ err = ngene_command_i2c_write(dev, msg->I2CAddress >> 1, ++ msg->Data, msg->Length); ++ break; ++ } ++ ++ case IOCTL_MIC_TEST_GETMEM: ++ { ++ MIC_MEM *m = parg; ++ ++ if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) ++ return -EINVAL; ++ ++ /* WARNING, only use this on x86, ++ other archs may not swallow this */ ++ err = copy_to_user(m->Data, dev->iomem + m->Start, m->Length); ++ break; ++ } ++ ++ case IOCTL_MIC_TEST_SETMEM: ++ { ++ MIC_MEM *m = parg; ++ ++ if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) ++ return -EINVAL; ++ ++ err = copy_from_user(dev->iomem + m->Start, m->Data, m->Length); ++ break; ++ } ++ ++ case IOCTL_MIC_SFR_READ: ++ { ++ MIC_IMEM *m = parg; ++ ++ err = ngene_command_imem_read(dev, m->Address, &m->Data, 1); ++ break; ++ } ++ ++ case IOCTL_MIC_SFR_WRITE: ++ { ++ MIC_IMEM *m = parg; ++ ++ err = ngene_command_imem_write(dev, m->Address, m->Data, 1); ++ break; ++ } ++ ++ case IOCTL_MIC_IRAM_READ: ++ { ++ MIC_IMEM *m = parg; ++ ++ err = ngene_command_imem_read(dev, m->Address, &m->Data, 0); ++ break; ++ } ++ ++ case IOCTL_MIC_IRAM_WRITE: ++ { ++ MIC_IMEM *m = parg; ++ ++ err = ngene_command_imem_write(dev, m->Address, m->Data, 0); ++ break; ++ } ++ ++ case IOCTL_MIC_STREAM_CONTROL: ++ { ++ MIC_STREAM_CONTROL *m = parg; ++ ++ err = ngene_stream_control(dev, m->Stream, m->Control, m->Mode, ++ m->nLines, m->nBytesPerLine, ++ m->nVBILines, m->nBytesPerVBILine); ++ break; ++ } ++ ++ default: ++ err = -EINVAL; ++ break; ++ } ++ return err; ++} ++ ++static int command_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ void *parg = (void *)arg, *pbuf = NULL; ++ char buf[64]; ++ int res = -EFAULT; ++ ++ if (_IOC_DIR(cmd) & _IOC_WRITE) { ++ parg = buf; ++ if (_IOC_SIZE(cmd) > sizeof(buf)) { ++ pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); ++ if (!pbuf) ++ return -ENOMEM; ++ parg = pbuf; ++ } ++ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) ++ goto error; ++ } ++ res = command_do_ioctl(inode, file, cmd, parg); ++ if (res < 0) ++ goto error; ++ if (_IOC_DIR(cmd) & _IOC_READ) ++ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) ++ res = -EFAULT; ++error: ++ kfree(pbuf); ++ return res; ++} ++ ++struct page *ngene_nopage(struct vm_area_struct *vma, ++ unsigned long address, int *type) ++{ ++ return 0; ++} ++ ++static int ngene_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ ++ unsigned long size = vma->vm_end - vma->vm_start; ++ unsigned long off = vma->vm_pgoff << PAGE_SHIFT; ++ unsigned long padr = pci_resource_start(dev->pci_dev, 0) + off; ++ unsigned long psize = pci_resource_len(dev->pci_dev, 0) - off; ++ ++ if (size > psize) ++ return -EINVAL; ++ ++ if (io_remap_pfn_range(vma, vma->vm_start, padr >> PAGE_SHIFT, size, ++ vma->vm_page_prot)) ++ return -EAGAIN; ++ return 0; ++} ++ ++ ++static int write_uart(struct ngene *dev, u8 *data, int len) ++{ ++ struct ngene_command com; ++ ++ com.cmd.hdr.Opcode = CMD_WRITE_UART; ++ com.cmd.hdr.Length = len; ++ memcpy(com.cmd.WriteUart.Data, data, len); ++ com.cmd.WriteUart.Data[len] = 0; ++ com.cmd.WriteUart.Data[len + 1] = 0; ++ com.in_len = len; ++ com.out_len = 0; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ return 0; ++} ++ ++static int send_cli(struct ngene *dev, char *cmd) ++{ ++ /* printk(KERN_INFO DEVICE_NAME ": %s", cmd); */ ++ return write_uart(dev, cmd, strlen(cmd)); ++} ++ ++static int send_cli_val(struct ngene *dev, char *cmd, u32 val) ++{ ++ char s[32]; ++ ++ snprintf(s, 32, "%s %d\n", cmd, val); ++ /* printk(KERN_INFO DEVICE_NAME ": %s", s); */ ++ return write_uart(dev, s, strlen(s)); ++} ++ ++static int ngene_command_write_uart_user(struct ngene *dev, ++ const u8 *data, int len) ++{ ++ struct ngene_command com; ++ ++ dev->tx_busy = 1; ++ com.cmd.hdr.Opcode = CMD_WRITE_UART; ++ com.cmd.hdr.Length = len; ++ ++ if (copy_from_user(com.cmd.WriteUart.Data, data, len)) ++ return -EFAULT; ++ com.in_len = len; ++ com.out_len = 0; ++ ++ if (ngene_command(dev, &com) < 0) ++ return -EIO; ++ ++ return 0; ++} ++ ++static ssize_t uart_write(struct file *file, const char *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int len, ret = 0; ++ size_t left = count; ++ ++ while (left) { ++ len = left; ++ if (len > 250) ++ len = 250; ++ ret = wait_event_interruptible(dev->tx_wq, dev->tx_busy == 0); ++ if (ret < 0) ++ return ret; ++ ngene_command_write_uart_user(dev, buf, len); ++ left -= len; ++ buf += len; ++ } ++ return count; ++} ++ ++static ssize_t uart_read(struct file *file, char *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct ngene_channel *chan = dvbdev->priv; ++ struct ngene *dev = chan->dev; ++ int left; ++ int wp, rp, avail, len; ++ ++ if (!dev->uart_rbuf) ++ return -EINVAL; ++ if (count > 128) ++ count = 128; ++ left = count; ++ while (left) { ++ if (wait_event_interruptible(dev->rx_wq, ++ dev->uart_wp != dev->uart_rp) < 0) ++ return -EAGAIN; ++ wp = dev->uart_wp; ++ rp = dev->uart_rp; ++ avail = (wp - rp); ++ ++ if (avail < 0) ++ avail += UART_RBUF_LEN; ++ if (avail > left) ++ avail = left; ++ if (wp < rp) { ++ len = UART_RBUF_LEN - rp; ++ if (len > avail) ++ len = avail; ++ if (copy_to_user(buf, dev->uart_rbuf + rp, len)) ++ return -EFAULT; ++ if (len < avail) ++ if (copy_to_user(buf + len, dev->uart_rbuf, ++ avail - len)) ++ return -EFAULT; ++ } else { ++ if (copy_to_user(buf, dev->uart_rbuf + rp, avail)) ++ return -EFAULT; ++ } ++ dev->uart_rp = (rp + avail) % UART_RBUF_LEN; ++ left -= avail; ++ buf += avail; ++ } ++ return count; ++} ++ ++#endif + + static ssize_t ts_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +@@ -133,6 +442,11 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) + struct ngene_channel *chan = priv; + struct ngene *dev = chan->dev; + ++#if 0 ++ printk(KERN_INFO DEVICE_NAME ": tsin %08x %02x %02x %02x %02x\n", ++ len, ((u8 *) buf)[512 * 188], ((u8 *) buf)[0], ++ ((u8 *) buf)[1], ((u8 *) buf)[2]); ++#endif + + if (flags & DF_SWAP32) + swap_buffer(buf, len); +@@ -191,12 +505,49 @@ void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) + return buf; + } + ++#if 0 ++static void set_dto(struct ngene_channel *chan, u32 rate) ++{ ++ u64 val = rate * 0x89705f41ULL; /* times val for 2^26 Hz */ ++ ++ val = ((val >> 25) + 1) >> 1; ++ chan->AudioDTOValue = (u32) val; ++ /* chan->AudioDTOUpdated=1; */ ++ /* printk(KERN_INFO DEVICE_NAME ": Setting DTO to %08x\n", val); */ ++} ++#endif + + + int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) + { + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ngene_channel *chan = dvbdmx->priv; ++#if 0 ++ struct ngene *dev = chan->dev; ++ ++ if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { ++ switch (dvbdmxfeed->pes_type) { ++ case DMX_TS_PES_VIDEO: ++ send_cli_val(dev, "vpid", dvbdmxfeed->pid); ++ send_cli(dev, "res 1080i50\n"); ++ /* send_cli(dev, "vdec mpeg2\n"); */ ++ break; ++ ++ case DMX_TS_PES_AUDIO: ++ send_cli_val(dev, "apid", dvbdmxfeed->pid); ++ send_cli(dev, "start\n"); ++ break; ++ ++ case DMX_TS_PES_PCR: ++ send_cli_val(dev, "pcrpid", dvbdmxfeed->pid); ++ break; ++ ++ default: ++ break; ++ } ++ ++ } ++#endif + + if (chan->users == 0) { + if (!chan->dev->cmd_timeout_workaround || !chan->running) +@@ -210,6 +561,27 @@ int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) + { + struct dvb_demux *dvbdmx = dvbdmxfeed->demux; + struct ngene_channel *chan = dvbdmx->priv; ++#if 0 ++ struct ngene *dev = chan->dev; ++ ++ if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { ++ switch (dvbdmxfeed->pes_type) { ++ case DMX_TS_PES_VIDEO: ++ send_cli(dev, "stop\n"); ++ break; ++ ++ case DMX_TS_PES_AUDIO: ++ break; ++ ++ case DMX_TS_PES_PCR: ++ break; ++ ++ default: ++ break; ++ } ++ ++ } ++#endif + + if (--chan->users) + return chan->users; +diff --git a/drivers/media/pci/ngene/ngene-eeprom.c b/drivers/media/pci/ngene/ngene-eeprom.c +new file mode 100644 +index 0000000..281d9f9 +--- /dev/null ++++ b/drivers/media/pci/ngene/ngene-eeprom.c +@@ -0,0 +1,284 @@ ++/* ++ * ngene-eeprom.c: nGene PCIe bridge driver - eeprom support ++ * ++ * Copyright (C) 2005-2007 Micronas ++ * ++ * Copyright (C) 2008-2009 Ralph Metzler ++ * Modifications for new nGene firmware, ++ * support for EEPROM-copying, ++ * support for new dual DVB-S2 card prototype ++ * ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * version 2 only, as published by the Free Software Foundation. ++ * ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA ++ * 02110-1301, USA ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#if 0 ++static int copy_eeprom; ++module_param(copy_eeprom, int, 0444); ++MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); ++ ++#define MICNG_EE_START 0x0100 ++#define MICNG_EE_END 0x0FF0 ++ ++#define MICNG_EETAG_END0 0x0000 ++#define MICNG_EETAG_END1 0xFFFF ++ ++/* 0x0001 - 0x000F reserved for housekeeping */ ++/* 0xFFFF - 0xFFFE reserved for housekeeping */ ++ ++/* Micronas assigned tags ++ EEProm tags for hardware support */ ++ ++#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ ++#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ ++ ++#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ ++#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ ++ ++/* Tag range for OEMs */ ++ ++#define MICNG_EETAG_OEM_FIRST 0xC000 ++#define MICNG_EETAG_OEM_LAST 0xFFEF ++ ++static int i2c_write_eeprom(struct i2c_adapter *adapter, ++ u8 adr, u16 reg, u8 data) ++{ ++ u8 m[3] = {(reg >> 8), (reg & 0xff), data}; ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, ++ .len = sizeof(m)}; ++ ++ if (i2c_transfer(adapter, &msg, 1) != 1) { ++ dprintk(KERN_ERR DEVICE_NAME ": Error writing EEPROM!\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int i2c_read_eeprom(struct i2c_adapter *adapter, ++ u8 adr, u16 reg, u8 *data, int len) ++{ ++ u8 msg[2] = {(reg >> 8), (reg & 0xff)}; ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = msg, .len = 2 }, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = data, .len = len} }; ++ ++ if (i2c_transfer(adapter, msgs, 2) != 2) { ++ dprintk(KERN_ERR DEVICE_NAME ": Error reading EEPROM\n"); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int ReadEEProm(struct i2c_adapter *adapter, ++ u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) ++{ ++ int status = 0; ++ u16 Addr = MICNG_EE_START, Length, tag = 0; ++ u8 EETag[3]; ++ ++ while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { ++ if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) ++ return -1; ++ tag = (EETag[0] << 8) | EETag[1]; ++ if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) ++ return -1; ++ if (tag == Tag) ++ break; ++ Addr += sizeof(u16) + 1 + EETag[2]; ++ } ++ if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Reached EOEE @ Tag = %04x Length = %3d\n", ++ tag, EETag[2]); ++ return -1; ++ } ++ Length = EETag[2]; ++ if (Length > MaxLen) ++ Length = (u16) MaxLen; ++ if (Length > 0) { ++ Addr += sizeof(u16) + 1; ++ status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); ++ if (!status) { ++ *pLength = EETag[2]; ++ if (Length < EETag[2]) ++ ; /*status=STATUS_BUFFER_OVERFLOW; */ ++ } ++ } ++ return status; ++} ++ ++static int WriteEEProm(struct i2c_adapter *adapter, ++ u16 Tag, u32 Length, u8 *data) ++{ ++ int status = 0; ++ u16 Addr = MICNG_EE_START; ++ u8 EETag[3]; ++ u16 tag = 0; ++ int retry, i; ++ ++ while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { ++ if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) ++ return -1; ++ tag = (EETag[0] << 8) | EETag[1]; ++ if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) ++ return -1; ++ if (tag == Tag) ++ break; ++ Addr += sizeof(u16) + 1 + EETag[2]; ++ } ++ if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Reached EOEE @ Tag = %04x Length = %3d\n", ++ tag, EETag[2]); ++ return -1; ++ } ++ ++ if (Length > EETag[2]) ++ return -EINVAL; ++ /* Note: We write the data one byte at a time to avoid ++ issues with page sizes. (which are different for ++ each manufacture and eeprom size) ++ */ ++ Addr += sizeof(u16) + 1; ++ for (i = 0; i < Length; i++, Addr++) { ++ status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); ++ ++ if (status) ++ break; ++ ++ /* Poll for finishing write cycle */ ++ retry = 10; ++ while (retry) { ++ u8 Tmp; ++ ++ msleep(50); ++ status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); ++ if (status) ++ break; ++ if (Tmp != data[i]) ++ printk(KERN_ERR DEVICE_NAME ++ "eeprom write error\n"); ++ retry -= 1; ++ } ++ if (status) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Timeout polling eeprom\n"); ++ break; ++ } ++ } ++ return status; ++} ++ ++static void i2c_init_eeprom(struct i2c_adapter *adapter) ++{ ++ u8 tags[] = {0x10, 0x00, 0x02, 0x00, 0x00, ++ 0x10, 0x01, 0x02, 0x00, 0x00, ++ 0x00, 0x00, 0x00}; ++ ++ int i; ++ ++ for (i = 0; i < sizeof(tags); i++) ++ i2c_write_eeprom(adapter, 0x50, 0x0100 + i, tags[i]); ++} ++ ++int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) ++{ ++ int stat; ++ u8 buf[2]; ++ u32 len = 0; ++ ++ stat = ReadEEProm(adapter, tag, 2, buf, &len); ++ if (stat) ++ return stat; ++ if (len != 2) ++ return -EINVAL; ++ ++ *data = (buf[0] << 8) | buf[1]; ++ return 0; ++} ++ ++static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) ++{ ++ int stat; ++ u8 buf[2]; ++ ++ buf[0] = data >> 8; ++ buf[1] = data & 0xff; ++ stat = WriteEEProm(adapter, tag, 2, buf); ++ if (stat) ++ return stat; ++ return 0; ++} ++ ++int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr) ++{ ++ u8 buf[64]; ++ int i; ++ ++ if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { ++ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); ++ return -1; ++ } ++ for (i = 0; i < sizeof(buf); i++) { ++ if (!(i & 15)) ++ printk(KERN_DEBUG "\n"); ++ printk(KERN_DEBUG "%02x ", buf[i]); ++ } ++ printk("\n"); ++ ++ return 0; ++} ++ ++int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2) ++{ ++ u8 buf[64]; ++ int i; ++ ++ if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { ++ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); ++ return -1; ++ } ++ buf[36] = 0xc3; ++ buf[39] = 0xab; ++ for (i = 0; i < sizeof(buf); i++) { ++ i2c_write_eeprom(adapter, adr2, i, buf[i]); ++ msleep(10); ++ } ++ return 0; ++} ++ ++int i2c_check_eeprom(struct i2c_adapter *adapter) ++{ ++ u8 buf[13]; ++ ++ i2c_dump_eeprom(adapter); ++ ++ if (i2c_read_eeprom(adapter, 0x50, 0x0100, buf, sizeof(buf))) { ++ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); ++ return -1; ++ } ++ if (buf[0] != 0x10 || buf[1] != 0x00) { ++ printk(KERN_INFO DEVICE_NAME ++ ": Initializing EEPROM TAG area\n"); ++ i2c_init_eeprom(adapter); ++ } ++ return 0; ++} ++ ++#endif +diff --git a/drivers/media/pci/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c +index d28554f..601bea4 100644 +--- a/drivers/media/pci/ngene/ngene-i2c.c ++++ b/drivers/media/pci/ngene/ngene-i2c.c +@@ -77,6 +77,11 @@ static int ngene_command_i2c_write(struct ngene *dev, u8 adr, + { + struct ngene_command com; + ++#if 0 ++ /* Probing by writing 0 bytes does not work */ ++ if (!outlen) ++ outlen++; ++#endif + + com.cmd.hdr.Opcode = CMD_I2C_WRITE; + com.cmd.hdr.Length = outlen + 1; +@@ -148,6 +153,39 @@ done: + return num; + } + ++#if 0 ++static int ngene_i2c_algo_control(struct i2c_adapter *adap, ++ unsigned int cmd, unsigned long arg) ++{ ++ struct ngene_channel *chan = ++ (struct ngene_channel *)i2c_get_adapdata(adap); ++ ++ switch (cmd) { ++ case IOCTL_MIC_TUN_RDY: ++ chan->tun_rdy = 1; ++ if (chan->dec_rdy == 1) ++ chan->tun_dec_rdy = 1; ++ break; ++ ++ case IOCTL_MIC_DEC_RDY: ++ chan->dec_rdy = 1; ++ if (chan->tun_rdy == 1) ++ chan->tun_dec_rdy = 1; ++ break; ++ ++ case IOCTL_MIC_TUN_DETECT: ++ { ++ int *palorbtsc = (int *)arg; ++ *palorbtsc = chan->dev->card_info->ntsc; ++ break; ++ } ++ ++ default: ++ break; ++ } ++ return 0; ++} ++#endif + + static u32 ngene_i2c_functionality(struct i2c_adapter *adap) + { +@@ -174,3 +212,78 @@ int ngene_i2c_init(struct ngene *dev, int dev_nr) + return i2c_add_adapter(adap); + } + ++#if 0 ++int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data) ++{ ++ u8 m[1] = {data}; ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 1}; ++ ++ if (i2c_transfer(adapter, &msg, 1) != 1) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Failed to write to I2C adr %02x!\n", adr); ++ return -1; ++ } ++ return 0; ++} ++ ++static int i2c_write_register(struct i2c_adapter *adapter, ++ u8 adr, u8 reg, u8 data) ++{ ++ u8 m[2] = {reg, data}; ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; ++ ++ if (i2c_transfer(adapter, &msg, 1) != 1) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Failed to write to I2C register %02x@%02x!\n", ++ reg, adr); ++ return -1; ++ } ++ return 0; ++} ++ ++static int i2c_write_read(struct i2c_adapter *adapter, ++ u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen) ++{ ++ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, ++ .buf = w, .len = wlen}, ++ {.addr = adr, .flags = I2C_M_RD, ++ .buf = r, .len = rlen} }; ++ ++ if (i2c_transfer(adapter, msgs, 2) != 2) { ++ printk(KERN_ERR DEVICE_NAME ": error in i2c_write_read\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++static int test_dec_i2c(struct i2c_adapter *adapter, int reg) ++{ ++ u8 data[256] = { reg, 0x00, 0x93, 0x78, 0x43, 0x45 }; ++ u8 data2[256]; ++ int i; ++ ++ memset(data2, 0, 256); ++ i2c_write_read(adapter, 0x66, data, 2, data2, 4); ++ for (i = 0; i < 4; i++) ++ printk(KERN_DEBUG "%02x ", data2[i]); ++ printk(KERN_DEBUG "\n"); ++ ++ return 0; ++} ++ ++static int i2c_write_msp_register(struct i2c_adapter *adapter, ++ u8 adr, u8 reg, u16 data) ++{ ++ u8 m[3] = {reg, (data >> 8) & 0xff, data & 0xff}; ++ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 3 }; ++ ++ if (i2c_transfer(adapter, &msg, 1) != 1) { ++ printk(KERN_ERR DEVICE_NAME ++ ": Failed to write to I2C register %02x@%02x!\n", ++ reg, adr); ++ return -1; ++ } ++ return 0; ++} ++ ++#endif +diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h +index 22c39ff..e3ae00c 100644 +--- a/drivers/media/pci/ngene/ngene.h ++++ b/drivers/media/pci/ngene/ngene.h +@@ -653,6 +653,11 @@ struct ngene_channel { + struct dmx_frontend mem_frontend; + int users; + struct video_device *v4l_dev; ++#if 0 ++ struct dvb_device *command_dev; ++ struct dvb_device *audio_dev; ++ struct dvb_device *video_dev; ++#endif + struct dvb_device *ci_dev; + struct tasklet_struct demux_tasklet; + +@@ -691,6 +696,9 @@ struct ngene_channel { + struct mychip *mychip; + struct snd_card *soundcard; + u8 *evenbuffer; ++#if 0 ++ u8 *soundbuffer; ++#endif + u8 dma_on; + int soundstreamon; + int audiomute; +@@ -849,6 +857,10 @@ struct ngene_info { + u8 lnb[4]; + int i2c_access; + u8 ntsc; ++#if 0 ++ u8 exp; ++ u8 exp_init; ++#endif + u8 tsf[4]; + u8 i2s[4]; + +@@ -885,6 +897,25 @@ struct ngene_buffer { + }; + #endif + ++#if 0 ++int ngene_command_stream_control(struct ngene *dev, ++ u8 stream, u8 control, u8 mode, u8 flags); ++int ngene_command_nop(struct ngene *dev); ++int ngene_command_i2c_read(struct ngene *dev, u8 adr, ++ u8 *out, u8 outlen, u8 *in, u8 inlen, int flag); ++int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen); ++int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type); ++int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type); ++int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, ++ u16 lines, u16 bpl, u16 vblines, u16 vbibpl); ++ ++int ngene_v4l2_init(struct ngene_channel *chan); ++void ngene_v4l2_remove(struct ngene_channel *chan); ++int ngene_snd_exit(struct ngene_channel *chan); ++int ngene_snd_init(struct ngene_channel *chan); ++ ++struct i2c_client *avf4910a_attach(struct i2c_adapter *adap, int addr); ++#endif + + /* Provided by ngene-core.c */ + int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); +@@ -914,6 +945,15 @@ int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, + struct dmx_frontend *mem_frontend, + struct dvb_adapter *dvb_adapter); + ++/* Provided by ngene-eeprom.c */ ++#if 0 ++int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2); ++int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr); ++int i2c_check_eeprom(struct i2c_adapter *adapter); ++int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data); ++int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data); ++#endif ++ + #endif + + /* LocalWords: Endif +diff --git a/drivers/staging/media/cxd2099/TODO b/drivers/staging/media/cxd2099/TODO +deleted file mode 100644 +index 375bb6f..0000000 +--- a/drivers/staging/media/cxd2099/TODO ++++ /dev/null +@@ -1,12 +0,0 @@ +-For now, data is passed through '/dev/dvb/adapterX/sec0': +- - Encrypted data must be written to 'sec0'. +- - Decrypted data can be read from 'sec0'. +- - Setup the CAM using device 'ca0'. +- +-But this is wrong. There are some discussions about the proper way for +-doing it, as seen at: +- http://www.mail-archive.com/linux-media@vger.kernel.org/msg22196.html +- +-While there's no proper fix for it, the driver should be kept in staging. +- +-Patches should be submitted to: linux-media@vger.kernel.org. +diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c +index 822c487..6d54b01 100644 +--- a/drivers/staging/media/cxd2099/cxd2099.c ++++ b/drivers/staging/media/cxd2099/cxd2099.c +@@ -66,9 +66,8 @@ static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, + struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; + + if (i2c_transfer(adapter, &msg, 1) != 1) { +- dev_err(&adapter->dev, +- "Failed to write to I2C register %02x@%02x!\n", +- reg, adr); ++ printk(KERN_ERR "Failed to write to I2C register %02x@%02x!\n", ++ reg, adr); + return -1; + } + return 0; +@@ -80,7 +79,7 @@ static int i2c_write(struct i2c_adapter *adapter, u8 adr, + struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len}; + + if (i2c_transfer(adapter, &msg, 1) != 1) { +- dev_err(&adapter->dev, "Failed to write to I2C!\n"); ++ printk(KERN_ERR "Failed to write to I2C!\n"); + return -1; + } + return 0; +@@ -95,7 +94,7 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, + .buf = val, .len = 1} }; + + if (i2c_transfer(adapter, msgs, 2) != 2) { +- dev_err(&adapter->dev, "error in i2c_read_reg\n"); ++ printk(KERN_ERR "error in i2c_read_reg\n"); + return -1; + } + return 0; +@@ -110,7 +109,7 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, + .buf = data, .len = n} }; + + if (i2c_transfer(adapter, msgs, 2) != 2) { +- dev_err(&adapter->dev, "error in i2c_read\n"); ++ printk(KERN_ERR "error in i2c_read\n"); + return -1; + } + return 0; +@@ -118,9 +117,10 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, + + static int read_block(struct cxd *ci, u8 adr, u8 *data, u8 n) + { +- int status; ++ int status = 0; + +- status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); ++ if (ci->lastaddress != adr) ++ status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); + if (!status) { + ci->lastaddress = adr; + status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, n); +@@ -278,7 +278,7 @@ static void cam_mode(struct cxd *ci, int mode) + #ifdef BUFFER_MODE + if (!ci->en.read_data) + return; +- dev_info(&ci->i2c->dev, "enable cam buffer mode\n"); ++ printk(KERN_INFO "enable cam buffer mode\n"); + /* write_reg(ci, 0x0d, 0x00); */ + /* write_reg(ci, 0x0e, 0x01); */ + write_regm(ci, 0x08, 0x40, 0x40); +@@ -525,7 +525,7 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) + msleep(10); + #if 0 + read_reg(ci, 0x06, &val); +- dev_info(&ci->i2c->dev, "%d:%02x\n", i, val); ++ printk(KERN_INFO "%d:%02x\n", i, val); + if (!(val&0x10)) + break; + #else +@@ -543,7 +543,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) + { + struct cxd *ci = ca->data; + +- dev_info(&ci->i2c->dev, "slot_shutdown\n"); ++ printk(KERN_INFO "slot_shutdown\n"); + mutex_lock(&ci->lock); + write_regm(ci, 0x09, 0x08, 0x08); + write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */ +@@ -579,10 +579,10 @@ static int campoll(struct cxd *ci) + + if (istat&0x40) { + ci->dr = 1; +- dev_info(&ci->i2c->dev, "DR\n"); ++ printk(KERN_INFO "DR\n"); + } + if (istat&0x20) +- dev_info(&ci->i2c->dev, "WC\n"); ++ printk(KERN_INFO "WC\n"); + + if (istat&2) { + u8 slotstat; +@@ -598,7 +598,7 @@ static int campoll(struct cxd *ci) + if (ci->slot_stat) { + ci->slot_stat = 0; + write_regm(ci, 0x03, 0x00, 0x08); +- dev_info(&ci->i2c->dev, "NO CAM\n"); ++ printk(KERN_INFO "NO CAM\n"); + ci->ready = 0; + } + } +@@ -635,7 +635,7 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) + campoll(ci); + mutex_unlock(&ci->lock); + +- dev_info(&ci->i2c->dev, "read_data\n"); ++ printk(KERN_INFO "read_data\n"); + if (!ci->dr) + return 0; + +@@ -684,29 +684,30 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, + void *priv, + struct i2c_adapter *i2c) + { +- struct cxd *ci; ++ struct cxd *ci = 0; + u8 val; + + if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) { +- dev_info(&i2c->dev, "No CXD2099 detected at %02x\n", cfg->adr); +- return NULL; ++ printk(KERN_INFO "No CXD2099 detected at %02x\n", cfg->adr); ++ return 0; + } + +- ci = kzalloc(sizeof(struct cxd), GFP_KERNEL); ++ ci = kmalloc(sizeof(struct cxd), GFP_KERNEL); + if (!ci) +- return NULL; ++ return 0; ++ memset(ci, 0, sizeof(*ci)); + + mutex_init(&ci->lock); +- ci->cfg = *cfg; ++ memcpy(&ci->cfg, cfg, sizeof(struct cxd2099_cfg)); + ci->i2c = i2c; + ci->lastaddress = 0xff; + ci->clk_reg_b = 0x4a; + ci->clk_reg_f = 0x1b; + +- ci->en = en_templ; ++ memcpy(&ci->en, &en_templ, sizeof(en_templ)); + ci->en.data = ci; + init(ci); +- dev_info(&i2c->dev, "Attached CXD2099AR at %02x\n", ci->cfg.adr); ++ printk(KERN_INFO "Attached CXD2099AR at %02x\n", ci->cfg.adr); + return &ci->en; + } + EXPORT_SYMBOL(cxd2099_attach); +diff --git a/drivers/staging/media/cxd2099/cxd2099.h b/drivers/staging/media/cxd2099/cxd2099.h +index 0eb607c..19c588a 100644 +--- a/drivers/staging/media/cxd2099/cxd2099.h ++++ b/drivers/staging/media/cxd2099/cxd2099.h +@@ -43,7 +43,7 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, + static inline struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, + void *priv, struct i2c_adapter *i2c) + { +- dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; + } + #endif +-- +1.7.2.5 + diff --git a/packages/linux/patches/3.10/linux-222-stb0899_signal_quality.patch b/packages/linux/patches/3.10/linux-222-stb0899_signal_quality.patch new file mode 100644 index 0000000000..fd6539d2bf --- /dev/null +++ b/packages/linux/patches/3.10/linux-222-stb0899_signal_quality.patch @@ -0,0 +1,62 @@ +diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c +--- linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-16 10:33:10.323380937 +0100 +@@ -971,6 +971,16 @@ + + *strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val); + *strength += 750; ++ ++ const int MIN_STRENGTH_DVBS = 0; ++ const int MAX_STRENGTH_DVBS = 680; ++ if (*strength < MIN_STRENGTH_DVBS) ++ *strength = 0; ++ else if(*strength > MAX_STRENGTH_DVBS) ++ *strength = 0xFFFF; ++ else ++ *strength = (*strength - MIN_STRENGTH_DVBS) * 0xFFFF / (MAX_STRENGTH_DVBS - MIN_STRENGTH_DVBS); ++ + dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm", + val & 0xff, *strength); + } +@@ -983,6 +993,7 @@ + + *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); + *strength += 950; ++ *strength = *strength << 4; + dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", + val & 0x3fff, *strength); + } +@@ -1016,6 +1027,16 @@ + val = MAKEWORD16(buf[0], buf[1]); + + *snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val); ++ ++ const int MIN_SNR_DVBS = 0; ++ const int MAX_SNR_DVBS = 200; ++ if (*snr < MIN_SNR_DVBS) ++ *snr = 0; ++ else if(*snr > MAX_SNR_DVBS) ++ *snr = 0xFFFF; ++ else ++ *snr = (*snr - MIN_SNR_DVBS) * 0xFFFF / (MAX_SNR_DVBS - MIN_SNR_DVBS); ++ + dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n", + buf[0], buf[1], val, *snr); + } +@@ -1040,6 +1061,16 @@ + val = (quantn - estn) / 10; + } + *snr = val; ++ ++ const int MIN_SNR_DVBS2 = 10; ++ const int MAX_SNR_DVBS2 = 70; ++ if (*snr < MIN_SNR_DVBS2) ++ *snr = 0; ++ else if(*snr > MAX_SNR_DVBS2) ++ *snr = 0xFFFF; ++ else ++ *snr = (*snr - MIN_SNR_DVBS2) * 0xFFFF / (MAX_SNR_DVBS2 - MIN_SNR_DVBS2); ++ + dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm", + quant, quantn, est, estn, val); + } diff --git a/packages/linux/patches/3.10/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch b/packages/linux/patches/3.10/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch new file mode 100644 index 0000000000..7aaabc48c0 --- /dev/null +++ b/packages/linux/patches/3.10/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch @@ -0,0 +1,17 @@ +diff -Naur linux-3.7.9/drivers/media/usb/dvb-usb/pctv452e.c linux-3.7.9.patch/drivers/media/usb/dvb-usb/pctv452e.c +--- linux-3.7.9/drivers/media/usb/dvb-usb/pctv452e.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.9.patch/drivers/media/usb/dvb-usb/pctv452e.c 2013-01-16 10:35:01.131342123 +0100 +@@ -995,11 +995,11 @@ + /* parameter for the MPEG2-data transfer */ + .stream = { + .type = USB_ISOC, +- .count = 7, ++ .count = 4, + .endpoint = 0x02, + .u = { + .isoc = { +- .framesperurb = 4, ++ .framesperurb = 64, + .framesize = 940, + .interval = 1 + } diff --git a/packages/linux/patches/3.10/linux-700-jmicron_1_0_8_5.patch b/packages/linux/patches/3.10/linux-700-jmicron_1_0_8_5.patch new file mode 100644 index 0000000000..80a2c8195f --- /dev/null +++ b/packages/linux/patches/3.10/linux-700-jmicron_1_0_8_5.patch @@ -0,0 +1,1603 @@ +diff -Naur linux-3.7.2/drivers/net/ethernet/jme.c linux-3.7.2.patch/drivers/net/ethernet/jme.c +--- linux-3.7.2/drivers/net/ethernet/jme.c 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/net/ethernet/jme.c 2013-01-16 10:16:40.087516337 +0100 +@@ -22,7 +22,10 @@ + * + */ + ++#include ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++#endif + + #include + #include +@@ -48,6 +51,7 @@ + static int force_pseudohp = -1; + static int no_pseudohp = -1; + static int no_extplug = -1; ++static int delay_time = 11; + module_param(force_pseudohp, int, 0); + MODULE_PARM_DESC(force_pseudohp, + "Enable pseudo hot-plug feature manually by driver instead of BIOS."); +@@ -56,6 +60,24 @@ + module_param(no_extplug, int, 0); + MODULE_PARM_DESC(no_extplug, + "Do not use external plug signal for pseudo hot-plug."); ++module_param(delay_time, uint, 0); ++MODULE_PARM_DESC(delay_time, ++ "Seconds to delay before switching lower speed; default = 11 seconds(3 trials)"); ++ ++#ifndef JME_NEW_PM_API ++static void ++jme_pci_wakeup_enable(struct jme_adapter *jme, int enable) ++{ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27) ++ pci_enable_wake(jme->pdev, PCI_D1, enable); ++ pci_enable_wake(jme->pdev, PCI_D2, enable); ++ pci_enable_wake(jme->pdev, PCI_D3hot, enable); ++ pci_enable_wake(jme->pdev, PCI_D3cold, enable); ++#else ++ pci_pme_active(jme->pdev, enable); ++#endif ++} ++#endif + + static int + jme_mdio_read(struct net_device *netdev, int phy, int reg) +@@ -758,6 +780,9 @@ + jme->dev->mtu + RX_EXTRA_LEN); + if (unlikely(!skb)) + return -ENOMEM; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ++ skb->dev = jme->dev; ++#endif + + mapping = pci_map_page(jme->pdev, virt_to_page(skb->data), + offset_in_page(skb->data), skb_tailroom(skb), +@@ -967,11 +992,29 @@ + jme_udpsum(struct sk_buff *skb) + { + u16 csum = 0xFFFFu; ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) ++ struct iphdr *iph; ++ int iphlen; ++ struct udphdr *udph; ++#endif + + if (skb->len < (ETH_HLEN + sizeof(struct iphdr))) + return csum; + if (skb->protocol != htons(ETH_P_IP)) + return csum; ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) ++ iph = (struct iphdr *)skb_pull(skb, ETH_HLEN); ++ iphlen = (iph->ihl << 2); ++ if ((iph->protocol != IPPROTO_UDP) || ++ (skb->len < (iphlen + sizeof(struct udphdr)))) { ++ skb_push(skb, ETH_HLEN); ++ return csum; ++ } ++ udph = (struct udphdr *)skb_pull(skb, iphlen); ++ csum = udph->check; ++ skb_push(skb, iphlen); ++ skb_push(skb, ETH_HLEN); ++#else + skb_set_network_header(skb, ETH_HLEN); + if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || + (skb->len < (ETH_HLEN + +@@ -985,6 +1028,7 @@ + csum = udp_hdr(skb)->check; + skb_reset_transport_header(skb); + skb_reset_network_header(skb); ++#endif + + return csum; + } +@@ -1054,8 +1098,24 @@ + if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) ++ skb->ip_summed = CHECKSUM_NONE; ++#else + skb_checksum_none_assert(skb); +- ++#endif ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ++ if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) { ++ if (jme->vlgrp) { ++ jme->jme_vlan_rx(skb, jme->vlgrp, ++ le16_to_cpu(rxdesc->descwb.vlan)); ++ NET_STAT(jme).rx_bytes += 4; ++ } else { ++ dev_kfree_skb(skb); ++ } ++ } else { ++ jme->jme_rx(skb); ++ } ++#else + if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) { + u16 vid = le16_to_cpu(rxdesc->descwb.vlan); + +@@ -1064,6 +1124,7 @@ + } + jme->jme_rx(skb); + ++#endif + if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) == + cpu_to_le16(RXWBFLAG_DEST_MUL)) + ++(NET_STAT(jme).multicast); +@@ -1292,6 +1353,223 @@ + } + + static void ++jme_set_physpeed_capability(struct jme_adapter *jme, u16 speed) ++{ ++ u32 advert, advert2; ++ ++// spin_lock_bh(&jme->phy_lock); ++ advert = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); ++ advert2 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); ++ switch (speed) { ++ case SPEED_1000: ++ advert = (advert|ADVERTISE_100HALF|ADVERTISE_100FULL); ++ advert2 = (advert2|ADVERTISE_1000HALF|ADVERTISE_1000FULL); ++ break; ++ case SPEED_100: ++ advert = (advert|ADVERTISE_100HALF|ADVERTISE_100FULL); ++ advert2 = advert2 & ~(ADVERTISE_1000HALF|ADVERTISE_1000FULL); ++ break; ++ default: ++ advert = advert & ~(ADVERTISE_100HALF|ADVERTISE_100FULL); ++ advert2 = advert2 & ~(ADVERTISE_1000HALF|ADVERTISE_1000FULL); ++ } ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE, advert); ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, advert2); ++// spin_unlock_bh(&jme->phy_lock); ++ return; ++} ++ ++/* ++ PHY reg: MII_FCSCOUNTER is read and clear, we have to ++ continuing read until RJ45 is attached, then cache ++ this result. ++*/ ++static int ++jme_check_ANcomplete(struct jme_adapter *jme) ++{ ++ u32 val; ++ ++ val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_FCSCOUNTER); ++ return ((val&(PHY_SPEC_STATUS_AN_FAIL|PHY_SPEC_STATUS_AN_COMPLETE)) ++ == PHY_SPEC_STATUS_AN_COMPLETE) ? true : false; ++} ++ ++static int ++jme_media_connected(struct jme_adapter *jme) ++{ ++ if (jme->media_cnct == true) ++ return true; ++ ++ jme->media_cnct = jme_check_ANcomplete(jme); ++ return jme->media_cnct; ++} ++ ++static inline void ++jme_slowspeed_tune(struct jme_adapter *jme, u16 speed) ++{ ++ if (jme_check_ANcomplete(jme)) ++ jme_set_physpeed_capability(jme, speed); ++ else { ++ jme->media_cnct = false; ++ jme->media_cnct_sec = 0; ++ } ++} ++ ++static void ++asd_polling_func(unsigned long data) ++{ ++ struct jme_adapter *jme = (struct jme_adapter *)data; ++ unsigned long flags; ++ /* ++ check condition term by term. ++ 1. link is up() ++ ==> reset all thing, exit the process. ++ 2. there is no RJ45 cable attached ++ ==> do nothing but polling ++ 3. RJ45 cable attached. but link is down ++ ==> downspeed if the timeing is over 3.5 second. ++ */ ++ spin_lock_irqsave(&jme->asd_lock, flags); ++ if (jme->flag_run_asd == true) { ++ if (jme_media_connected(jme)) { ++ jme->media_cnct_sec++; ++ if (jme->media_cnct_sec == (delay_time*3-5)) { ++ /* Unable to link anyway, it can NOT be resolved ++ by slower speed, restore the capability */ ++ jme_set_physpeed_capability(jme, SPEED_1000); ++ jme->media_cnct = false; ++ jme->media_cnct_sec = 0; ++ } else if (jme->media_cnct_sec == (delay_time*2-5)) ++ jme_slowspeed_tune(jme, SPEED_10); ++ else if (jme->media_cnct_sec == delay_time-5) ++ jme_slowspeed_tune(jme, SPEED_100); ++ } ++ mod_timer(&jme->asd_timer, jiffies+HZ); ++ spin_unlock_irqrestore(&jme->asd_lock, flags); ++ return ; ++ } ++ jme->media_cnct = false; ++ jme->media_cnct_sec = 0; ++ spin_unlock_irqrestore(&jme->asd_lock, flags); ++ return; ++} ++ ++static int jme_check_linkup(struct jme_adapter *jme) ++{ ++ u32 phylink; ++ ++ if (jme->fpgaver) ++ phylink = jme_linkstat_from_phy(jme); ++ else ++ phylink = jread32(jme, JME_PHY_LINK); ++ ++ return (phylink & PHY_LINK_UP) ? true : false; ++} ++ ++static void jme_LC_task(struct work_struct *work) ++{ ++ struct jme_adapter *jme; ++ struct net_device *netdev; ++ int rc; ++ unsigned long flags; ++ ++ jme = container_of(work, struct jme_adapter, LC_task); ++ netdev = jme->dev; ++ ++ ++ msleep(500); ++ while (!atomic_dec_and_test(&jme->link_changing)) { ++ atomic_inc(&jme->link_changing); ++ netif_info(jme, intr, jme->dev, "Get link change lock failed\n"); ++ while (atomic_read(&jme->link_changing) != 1) ++ netif_info(jme, intr, jme->dev, "Waiting link change lock\n"); ++ } ++ spin_lock_irqsave(&jme->asd_lock, flags); ++ if (jme_check_linkup(jme)) { ++ if (jme->flag_run_asd) { ++ jme->flag_run_asd = false; ++ del_timer_sync(&jme->asd_timer); ++ } ++ } else { ++ if (!jme->flag_run_asd) { ++ jme_set_physpeed_capability(jme, SPEED_1000); ++ jme_check_ANcomplete(jme); ++ jme->media_cnct = false; ++ jme->flag_run_asd = true; ++ jme->media_cnct_sec = 0; ++ jme->asd_timer.expires = jiffies + 4*HZ; ++ jme->asd_timer.function = &asd_polling_func; ++ jme->asd_timer.data = (unsigned long)jme; ++ add_timer(&jme->asd_timer); ++ } ++ } ++ spin_unlock_irqrestore(&jme->asd_lock, flags); ++ if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu) ++ goto out; ++ ++ jme->old_mtu = netdev->mtu; ++ netif_stop_queue(netdev); ++ if (jme_pseudo_hotplug_enabled(jme)) ++ jme_stop_shutdown_timer(jme); ++ ++ jme_stop_pcc_timer(jme); ++ tasklet_disable(&jme->txclean_task); ++ tasklet_disable(&jme->rxclean_task); ++ tasklet_disable(&jme->rxempty_task); ++ ++ if (netif_carrier_ok(netdev)) { ++ jme_disable_rx_engine(jme); ++ jme_disable_tx_engine(jme); ++ jme_reset_mac_processor(jme); ++ jme_free_rx_resources(jme); ++ jme_free_tx_resources(jme); ++ ++ if (test_bit(JME_FLAG_POLL, &jme->flags)) ++ jme_polling_mode(jme); ++ ++ netif_carrier_off(netdev); ++ } ++ ++ jme_check_link(netdev, 0); ++ if (netif_carrier_ok(netdev)) { ++ rc = jme_setup_rx_resources(jme); ++ if (rc) { ++ pr_err("Allocating resources for RX error, Device STOPPED!\n"); ++ goto out_enable_tasklet; ++ } ++ ++ rc = jme_setup_tx_resources(jme); ++ if (rc) { ++ pr_err("Allocating resources for TX error, Device STOPPED!\n"); ++ goto err_out_free_rx_resources; ++ } ++ ++ jme_enable_rx_engine(jme); ++ jme_enable_tx_engine(jme); ++ ++ netif_start_queue(netdev); ++ ++ if (test_bit(JME_FLAG_POLL, &jme->flags)) ++ jme_interrupt_mode(jme); ++ ++ jme_start_pcc_timer(jme); ++ } else if (jme_pseudo_hotplug_enabled(jme)) { ++ jme_start_shutdown_timer(jme); ++ } ++ ++ goto out_enable_tasklet; ++ ++err_out_free_rx_resources: ++ jme_free_rx_resources(jme); ++out_enable_tasklet: ++ tasklet_enable(&jme->txclean_task); ++ tasklet_hi_enable(&jme->rxclean_task); ++ tasklet_hi_enable(&jme->rxempty_task); ++out: ++ atomic_inc(&jme->link_changing); ++} ++ ++static void + jme_link_change_tasklet(unsigned long arg) + { + struct jme_adapter *jme = (struct jme_adapter *)arg; +@@ -1385,6 +1663,7 @@ + jme_poll(JME_NAPI_HOLDER(holder), JME_NAPI_WEIGHT(budget)) + { + struct jme_adapter *jme = jme_napi_priv(holder); ++ DECLARE_NETDEV + int rest; + + rest = jme_process_receive(jme, JME_NAPI_WEIGHT_VAL(budget)); +@@ -1538,7 +1817,7 @@ + * all other events are ignored + */ + jwrite32(jme, JME_IEVE, intrstat); +- tasklet_schedule(&jme->linkch_task); ++ schedule_work(&jme->LC_task); + goto out_reenable; + } + +@@ -1585,8 +1864,13 @@ + jwrite32f(jme, JME_IENS, INTR_ENABLE); + } + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) ++static irqreturn_t ++jme_intr(int irq, void *dev_id, struct pt_regs *regs) ++#else + static irqreturn_t + jme_intr(int irq, void *dev_id) ++#endif + { + struct net_device *netdev = dev_id; + struct jme_adapter *jme = netdev_priv(netdev); +@@ -1611,8 +1895,13 @@ + return IRQ_HANDLED; + } + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) ++static irqreturn_t ++jme_msi(int irq, void *dev_id, struct pt_regs *regs) ++#else + static irqreturn_t + jme_msi(int irq, void *dev_id) ++#endif + { + struct net_device *netdev = dev_id; + struct jme_adapter *jme = netdev_priv(netdev); +@@ -1648,8 +1937,13 @@ + { + int rc; + struct net_device *netdev = jme->dev; ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) ++ irqreturn_t (*handler)(int, void *, struct pt_regs *) = jme_intr; ++ int irq_flags = SA_SHIRQ; ++#else + irq_handler_t handler = jme_intr; + int irq_flags = IRQF_SHARED; ++#endif + + if (!pci_enable_msi(jme->pdev)) { + set_bit(JME_FLAG_MSI, &jme->flags); +@@ -1746,55 +2040,60 @@ + } + + static int +-jme_phy_specreg_read(struct jme_adapter *jme, u32 specreg) +-{ +- u32 phy_addr; +- +- phy_addr = JM_PHY_SPEC_REG_READ | specreg; +- jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, +- phy_addr); +- return jme_mdio_read(jme->dev, jme->mii_if.phy_id, +- JM_PHY_SPEC_DATA_REG); +-} +- +-static void +-jme_phy_specreg_write(struct jme_adapter *jme, u32 ext_reg, u32 phy_data) +-{ +- u32 phy_addr; +- +- phy_addr = JM_PHY_SPEC_REG_WRITE | ext_reg; +- jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG, +- phy_data); +- jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, +- phy_addr); +-} +- +-static int + jme_phy_calibration(struct jme_adapter *jme) + { +- u32 ctrl1000, phy_data; ++ u32 ctrl1000, bmcr, phy_addr, phy_data; + +- jme_phy_off(jme); +- jme_phy_on(jme); +- /* Enabel PHY test mode 1 */ ++ // Turn PHY off ++ bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); ++ bmcr |= BMCR_PDOWN; ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); ++ // Turn PHY on ++ bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); ++ bmcr &= ~BMCR_PDOWN; ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); ++ // Enabel PHY test mode 1 + ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK; + ctrl1000 |= PHY_GAD_TEST_MODE_1; +- jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); +- +- phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG); ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); ++ ++ ++ phy_addr = JM_PHY_SPEC_REG_READ | JM_PHY_EXT_COMM_2_REG; ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, ++ phy_addr); ++ phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id, ++ JM_PHY_SPEC_DATA_REG); ++ + phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0; + phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH | + JM_PHY_EXT_COMM_2_CALI_ENABLE; +- jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data); ++ ++ phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_2_REG; ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG, ++ phy_data); ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, ++ phy_addr); ++ + msleep(20); +- phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG); ++ ++ phy_addr = JM_PHY_SPEC_REG_READ | JM_PHY_EXT_COMM_2_REG; ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, ++ phy_addr); ++ phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id, ++ JM_PHY_SPEC_DATA_REG); ++ + phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE | + JM_PHY_EXT_COMM_2_CALI_MODE_0 | + JM_PHY_EXT_COMM_2_CALI_LATCH); +- jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data); + +- /* Disable PHY test mode */ ++ phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_2_REG; ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG, ++ phy_data); ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, ++ phy_addr); ++ ++ // Disable PHY test mode + ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); + ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK; + jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); +@@ -1804,11 +2103,11 @@ + static int + jme_phy_setEA(struct jme_adapter *jme) + { +- u32 phy_comm0 = 0, phy_comm1 = 0; ++ u32 phy_addr, phy_comm0 = 0, phy_comm1 = 0; + u8 nic_ctrl; + + pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl); +- if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE) ++ if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE) + return 0; + + switch (jme->pdev->device) { +@@ -1840,14 +2139,23 @@ + if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2)) + phy_comm0 = 0x408A; + break; +- default: ++ default: + return -ENODEV; + } +- if (phy_comm0) +- jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_0_REG, phy_comm0); +- if (phy_comm1) +- jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_1_REG, phy_comm1); +- ++ if (phy_comm0){ ++ phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_0_REG; ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, ++ JM_PHY_SPEC_DATA_REG, phy_comm0); ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, ++ JM_PHY_SPEC_ADDR_REG, phy_addr); ++ } ++ if (phy_comm1){ ++ phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_1_REG; ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, ++ JM_PHY_SPEC_DATA_REG, phy_comm1); ++ jme_mdio_write(jme->dev, jme->mii_if.phy_id, ++ JM_PHY_SPEC_ADDR_REG, phy_addr); ++ } + return 0; + } + +@@ -1995,7 +2303,7 @@ + struct page *page, + u32 page_offset, + u32 len, +- bool hidma) ++ u8 hidma) + { + dma_addr_t dmaaddr; + +@@ -2029,20 +2337,24 @@ + struct jme_ring *txring = &(jme->txring[0]); + struct txdesc *txdesc = txring->desc, *ctxdesc; + struct jme_buffer_info *txbi = txring->bufinf, *ctxbi; +- bool hidma = jme->dev->features & NETIF_F_HIGHDMA; ++ u8 hidma = jme->dev->features & NETIF_F_HIGHDMA; + int i, nr_frags = skb_shinfo(skb)->nr_frags; + int mask = jme->tx_ring_mask; +- const struct skb_frag_struct *frag; ++ struct skb_frag_struct *frag; + u32 len; + + for (i = 0 ; i < nr_frags ; ++i) { + frag = &skb_shinfo(skb)->frags[i]; + ctxdesc = txdesc + ((idx + i + 2) & (mask)); + ctxbi = txbi + ((idx + i + 2) & (mask)); +- ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ++ jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, frag->page, ++ frag->page_offset, frag->size, hidma); ++#else + jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, + skb_frag_page(frag), + frag->page_offset, skb_frag_size(frag), hidma); ++#endif + } + + len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len; +@@ -2056,8 +2368,13 @@ + static int + jme_expand_header(struct jme_adapter *jme, struct sk_buff *skb) + { +- if (unlikely(skb_shinfo(skb)->gso_size && +- skb_header_cloned(skb) && ++ if (unlikely( ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) ++ skb_shinfo(skb)->tso_size ++#else ++ skb_shinfo(skb)->gso_size ++#endif ++ && skb_header_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) { + dev_kfree_skb(skb); + return -1; +@@ -2069,7 +2386,11 @@ + static int + jme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags) + { ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) ++ *mss = cpu_to_le16(skb_shinfo(skb)->tso_size << TXDESC_MSS_SHIFT); ++#else + *mss = cpu_to_le16(skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT); ++#endif + if (*mss) { + *flags |= TXFLAG_LSEN; + +@@ -2099,9 +2420,22 @@ + static void + jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags) + { +- if (skb->ip_summed == CHECKSUM_PARTIAL) { ++#ifdef CHECKSUM_PARTIAL ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++#else ++ if (skb->ip_summed == CHECKSUM_HW) ++#endif ++ { + u8 ip_proto; + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) ++ if (skb->protocol == htons(ETH_P_IP)) ++ ip_proto = ip_hdr(skb)->protocol; ++ else if (skb->protocol == htons(ETH_P_IPV6)) ++ ip_proto = ipv6_hdr(skb)->nexthdr; ++ else ++ ip_proto = 0; ++#else + switch (skb->protocol) { + case htons(ETH_P_IP): + ip_proto = ip_hdr(skb)->protocol; +@@ -2113,6 +2447,7 @@ + ip_proto = 0; + break; + } ++#endif + + switch (ip_proto) { + case IPPROTO_TCP: +@@ -2219,7 +2554,11 @@ + * This function is already protected by netif_tx_lock() + */ + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,31) ++static int ++#else + static netdev_tx_t ++#endif + jme_start_xmit(struct sk_buff *skb, struct net_device *netdev) + { + struct jme_adapter *jme = netdev_priv(netdev); +@@ -2246,6 +2585,9 @@ + TXCS_SELECT_QUEUE0 | + TXCS_QUEUE0S | + TXCS_ENABLE); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29) ++ netdev->trans_start = jiffies; ++#endif + + tx_dbg(jme, "xmit: %d+%d@%lu\n", + idx, skb_shinfo(skb)->nr_frags + 2, jiffies); +@@ -2292,6 +2634,9 @@ + { + struct jme_adapter *jme = netdev_priv(netdev); + u32 mc_hash[2] = {}; ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,33) ++ int i; ++#endif + + spin_lock_bh(&jme->rxmcs_lock); + +@@ -2302,12 +2647,28 @@ + } else if (netdev->flags & IFF_ALLMULTI) { + jme->reg_rxmcs |= RXMCS_ALLMULFRAME; + } else if (netdev->flags & IFF_MULTICAST) { ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34) ++ struct dev_mc_list *mclist; ++#else + struct netdev_hw_addr *ha; ++#endif + int bit_nr; + + jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED; ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,33) ++ for (i = 0, mclist = netdev->mc_list; ++ mclist && i < netdev->mc_count; ++ ++i, mclist = mclist->next) { ++#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34) ++ netdev_for_each_mc_addr(mclist, netdev) { ++#else + netdev_for_each_mc_addr(ha, netdev) { ++#endif ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34) ++ bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3F; ++#else + bit_nr = ether_crc(ETH_ALEN, ha->addr) & 0x3F; ++#endif + mc_hash[bit_nr >> 5] |= 1 << (bit_nr & 0x1F); + } + +@@ -2333,11 +2694,27 @@ + ((new_mtu) < IPV6_MIN_MTU)) + return -EINVAL; + ++ if (new_mtu > 4000) { ++ jme->reg_rxcs &= ~RXCS_FIFOTHNP; ++ jme->reg_rxcs |= RXCS_FIFOTHNP_64QW; ++ jme_restart_rx_engine(jme); ++ } else { ++ jme->reg_rxcs &= ~RXCS_FIFOTHNP; ++ jme->reg_rxcs |= RXCS_FIFOTHNP_128QW; ++ jme_restart_rx_engine(jme); ++ } ++ ++ if (new_mtu > 1900) { ++ netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | ++ NETIF_F_TSO | NETIF_F_TSO6); ++ } else { ++ if (test_bit(JME_FLAG_TXCSUM, &jme->flags)) ++ netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; ++ if (test_bit(JME_FLAG_TSO, &jme->flags)) ++ netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; ++ } + + netdev->mtu = new_mtu; +- netdev_update_features(netdev); +- +- jme_restart_rx_engine(jme); + jme_reset_link(jme); + + return 0; +@@ -2390,15 +2767,45 @@ + atomic_inc(&jme->link_changing); + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ++static void ++jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) ++{ ++ struct jme_adapter *jme = netdev_priv(netdev); ++ ++ jme_pause_rx(jme); ++ jme->vlgrp = grp; ++ jme_resume_rx(jme); ++} ++#endif ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) ++static void ++jme_vlan_rx_kill_vid(struct net_device *netdev, unsigned short vid) ++{ ++ struct jme_adapter *jme = netdev_priv(netdev); ++ ++ if(jme->vlgrp) { ++ jme_pause_rx(jme); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20) ++ jme->vlgrp->vlan_devices[vid] = NULL; ++#else ++ vlan_group_set_device(jme->vlgrp, vid, NULL); ++#endif ++ jme_resume_rx(jme); ++ } ++} ++#endif ++ + static void + jme_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) + { + struct jme_adapter *jme = netdev_priv(netdev); + +- strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); +- strlcpy(info->version, DRV_VERSION, sizeof(info->version)); +- strlcpy(info->bus_info, pci_name(jme->pdev), sizeof(info->bus_info)); ++ strcpy(info->driver, DRV_NAME); ++ strcpy(info->version, DRV_VERSION); ++ strcpy(info->bus_info, pci_name(jme->pdev)); + } + + static int +@@ -2500,6 +2907,9 @@ + test_bit(JME_FLAG_POLL, &jme->flags)) { + clear_bit(JME_FLAG_POLL, &jme->flags); + jme->jme_rx = netif_rx; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ++ jme->jme_vlan_rx = vlan_hwaccel_rx; ++#endif + dpi->cur = PCC_P1; + dpi->attempt = PCC_P1; + dpi->cnt = 0; +@@ -2509,6 +2919,9 @@ + !(test_bit(JME_FLAG_POLL, &jme->flags))) { + set_bit(JME_FLAG_POLL, &jme->flags); + jme->jme_rx = netif_receive_skb; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ++ jme->jme_vlan_rx = vlan_hwaccel_receive_skb; ++#endif + jme_interrupt_mode(jme); + } + +@@ -2622,7 +3035,12 @@ + jme->reg_pmcs |= PMCS_MFEN; + + jwrite32(jme, JME_PMCS, jme->reg_pmcs); ++#ifndef JME_NEW_PM_API ++ jme_pci_wakeup_enable(jme, !!(jme->reg_pmcs)); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs)); ++#endif + + return 0; + } +@@ -2724,21 +3142,21 @@ + jme->msg_enable = value; + } + +-static netdev_features_t +-jme_fix_features(struct net_device *netdev, netdev_features_t features) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ++static u32 ++jme_get_rx_csum(struct net_device *netdev) + { +- if (netdev->mtu > 1900) +- features &= ~(NETIF_F_ALL_TSO | NETIF_F_ALL_CSUM); +- return features; ++ struct jme_adapter *jme = netdev_priv(netdev); ++ return jme->reg_rxmcs & RXMCS_CHECKSUM; + } + + static int +-jme_set_features(struct net_device *netdev, netdev_features_t features) ++jme_set_rx_csum(struct net_device *netdev, u32 on) + { + struct jme_adapter *jme = netdev_priv(netdev); + + spin_lock_bh(&jme->rxmcs_lock); +- if (features & NETIF_F_RXCSUM) ++ if (on) + jme->reg_rxmcs |= RXMCS_CHECKSUM; + else + jme->reg_rxmcs &= ~RXMCS_CHECKSUM; +@@ -2748,14 +3166,40 @@ + return 0; + } + +-#ifdef CONFIG_NET_POLL_CONTROLLER +-static void jme_netpoll(struct net_device *dev) ++static int ++jme_set_tx_csum(struct net_device *netdev, u32 on) + { +- unsigned long flags; ++ struct jme_adapter *jme = netdev_priv(netdev); ++ ++ if (on) { ++ set_bit(JME_FLAG_TXCSUM, &jme->flags); ++ if (netdev->mtu <= 1900) ++ netdev->features |= ++ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; ++ } else { ++ clear_bit(JME_FLAG_TXCSUM, &jme->flags); ++ netdev->features &= ++ ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); ++ } ++ ++ return 0; ++} ++ ++static int ++jme_set_tso(struct net_device *netdev, u32 on) ++{ ++ struct jme_adapter *jme = netdev_priv(netdev); ++ ++ if (on) { ++ set_bit(JME_FLAG_TSO, &jme->flags); ++ if (netdev->mtu <= 1900) ++ netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; ++ } else { ++ clear_bit(JME_FLAG_TSO, &jme->flags); ++ netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); ++ } + +- local_irq_save(flags); +- jme_intr(dev->irq, dev); +- local_irq_restore(flags); ++ return 0; + } + #endif + +@@ -2885,7 +3329,11 @@ + return 0; + } + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) ++static struct ethtool_ops jme_ethtool_ops = { ++#else + static const struct ethtool_ops jme_ethtool_ops = { ++#endif + .get_drvinfo = jme_get_drvinfo, + .get_regs_len = jme_get_regs_len, + .get_regs = jme_get_regs, +@@ -2900,6 +3348,13 @@ + .get_link = jme_get_link, + .get_msglevel = jme_get_msglevel, + .set_msglevel = jme_set_msglevel, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) ++ .get_rx_csum = jme_get_rx_csum, ++ .set_rx_csum = jme_set_rx_csum, ++ .set_tx_csum = jme_set_tx_csum, ++ .set_tso = jme_set_tso, ++ .set_sg = ethtool_op_set_sg, ++#endif + .nway_reset = jme_nway_reset, + .get_eeprom_len = jme_get_eeprom_len, + .get_eeprom = jme_get_eeprom, +@@ -2910,17 +3365,40 @@ + jme_pci_dma64(struct pci_dev *pdev) + { + if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && +- !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) ++ !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) ++#else ++ !pci_set_dma_mask(pdev, DMA_64BIT_MASK) ++#endif ++ ) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) ++#else ++ if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) ++#endif + return 1; + + if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && +- !pci_set_dma_mask(pdev, DMA_BIT_MASK(40))) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) ++ !pci_set_dma_mask(pdev, DMA_BIT_MASK(40)) ++#else ++ !pci_set_dma_mask(pdev, DMA_40BIT_MASK) ++#endif ++ ) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40))) ++#else ++ if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK)) ++#endif + return 1; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) + if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) ++#else ++ if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ++ if (!pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) ++#endif + return 0; + + return -1; +@@ -2948,6 +3426,7 @@ + jme->chip_sub_rev = (jme->chiprev >> 4) & 0xF; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + static const struct net_device_ops jme_netdev_ops = { + .ndo_open = jme_open, + .ndo_stop = jme_close, +@@ -2955,15 +3434,16 @@ + .ndo_do_ioctl = jme_ioctl, + .ndo_start_xmit = jme_start_xmit, + .ndo_set_mac_address = jme_set_macaddr, +- .ndo_set_rx_mode = jme_set_multi, ++ .ndo_set_rx_mode = jme_set_multi, ++ ++ + .ndo_change_mtu = jme_change_mtu, + .ndo_tx_timeout = jme_tx_timeout, +- .ndo_fix_features = jme_fix_features, +- .ndo_set_features = jme_set_features, +-#ifdef CONFIG_NET_POLL_CONTROLLER +- .ndo_poll_controller = jme_netpoll, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ++ .ndo_vlan_rx_register = jme_vlan_rx_register, + #endif + }; ++#endif + + static int __devinit + jme_init_one(struct pci_dev *pdev, +@@ -3013,18 +3493,29 @@ + */ + netdev = alloc_etherdev(sizeof(*jme)); + if (!netdev) { ++ pr_err("Cannot allocate netdev structure\n"); + rc = -ENOMEM; + goto err_out_release_regions; + } ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + netdev->netdev_ops = &jme_netdev_ops; ++#else ++ netdev->open = jme_open; ++ netdev->stop = jme_close; ++ netdev->do_ioctl = jme_ioctl; ++ netdev->hard_start_xmit = jme_start_xmit; ++ netdev->set_mac_address = jme_set_macaddr; ++ netdev->set_multicast_list = jme_set_multi; ++ netdev->change_mtu = jme_change_mtu; ++ netdev->tx_timeout = jme_tx_timeout; ++ netdev->vlan_rx_register = jme_vlan_rx_register; ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) ++ netdev->vlan_rx_kill_vid = jme_vlan_rx_kill_vid; ++#endif ++ NETDEV_GET_STATS(netdev, &jme_get_stats); ++#endif + netdev->ethtool_ops = &jme_ethtool_ops; + netdev->watchdog_timeo = TX_TIMEOUT; +- netdev->hw_features = NETIF_F_IP_CSUM | +- NETIF_F_IPV6_CSUM | +- NETIF_F_SG | +- NETIF_F_TSO | +- NETIF_F_TSO6 | +- NETIF_F_RXCSUM; + netdev->features = NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | + NETIF_F_SG | +@@ -3045,6 +3536,9 @@ + jme->pdev = pdev; + jme->dev = netdev; + jme->jme_rx = netif_rx; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) ++ jme->jme_vlan_rx = vlan_hwaccel_rx; ++#endif + jme->old_mtu = netdev->mtu = 1500; + jme->phylink = 0; + jme->tx_ring_size = 1 << 10; +@@ -3083,6 +3577,9 @@ + tasklet_init(&jme->pcc_task, + jme_pcc_tasklet, + (unsigned long) jme); ++ ++ INIT_WORK(&jme->LC_task, jme_LC_task); ++ + jme->dpi.cur = PCC_P1; + + jme->reg_ghc = 0; +@@ -3091,9 +3588,8 @@ + jme->reg_txpfc = 0; + jme->reg_pmcs = PMCS_MFEN; + jme->reg_gpreg1 = GPREG1_DEFAULT; +- +- if (jme->reg_rxmcs & RXMCS_CHECKSUM) +- netdev->features |= NETIF_F_RXCSUM; ++ set_bit(JME_FLAG_TXCSUM, &jme->flags); ++ set_bit(JME_FLAG_TSO, &jme->flags); + + /* + * Get Max Read Req Size from PCI Config Space +@@ -3149,10 +3645,19 @@ + + jme_clear_pm(jme); + pci_set_power_state(jme->pdev, PCI_D0); ++#ifndef JME_NEW_PM_API ++ jme_pci_wakeup_enable(jme, true); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) + device_set_wakeup_enable(&pdev->dev, true); ++#endif + + jme_set_phyfifo_5level(jme); ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) ++ pci_read_config_byte(pdev, PCI_REVISION_ID, &jme->pcirev); ++#else + jme->pcirev = pdev->revision; ++#endif + if (!jme->fpgaver) + jme_phy_init(jme); + jme_phy_off(jme); +@@ -3179,14 +3684,26 @@ + goto err_out_unmap; + } + +- netif_info(jme, probe, jme->dev, "%s%s chiprev:%x pcirev:%x macaddr:%pM\n", ++ init_timer(&(jme->asd_timer)); ++ jme->media_cnct_sec = 0; ++ jme->flag_run_asd = false; ++ jme->media_cnct = false; ++ ++ netif_info(jme, probe, jme->dev, "%s%s chipver:%x pcirev:%x " ++ "macaddr: %02x:%02x:%02x:%02x:%02x:%02x\n", + (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ? + "JMC250 Gigabit Ethernet" : + (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ? + "JMC260 Fast Ethernet" : "Unknown", + (jme->fpgaver != 0) ? " (FPGA)" : "", + (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev, +- jme->pcirev, netdev->dev_addr); ++ jme->pcirev, ++ netdev->dev_addr[0], ++ netdev->dev_addr[1], ++ netdev->dev_addr[2], ++ netdev->dev_addr[3], ++ netdev->dev_addr[4], ++ netdev->dev_addr[5]); + + return 0; + +@@ -3209,6 +3726,8 @@ + struct net_device *netdev = pci_get_drvdata(pdev); + struct jme_adapter *jme = netdev_priv(netdev); + ++ del_timer_sync(&jme->asd_timer); ++ cancel_work_sync(&jme->LC_task); + unregister_netdev(netdev); + iounmap(jme->regs); + pci_set_drvdata(pdev, NULL); +@@ -3225,26 +3744,48 @@ + struct jme_adapter *jme = netdev_priv(netdev); + + jme_powersave_phy(jme); +- pci_pme_active(pdev, true); ++#ifndef JME_NEW_PM_API ++ jme_pci_wakeup_enable(jme, !!(jme->reg_pmcs)); ++#endif ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs)); ++#endif + } + +-#ifdef CONFIG_PM_SLEEP ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) ++ #ifdef CONFIG_PM ++ #define JME_HAVE_PM ++ #endif ++#else ++ #ifdef CONFIG_PM_SLEEP ++ #define JME_HAVE_PM ++ #endif ++#endif ++ ++#ifdef JME_HAVE_PM + static int ++#ifdef JME_NEW_PM_API + jme_suspend(struct device *dev) ++#else ++jme_suspend(struct pci_dev *pdev, pm_message_t state) ++#endif + { ++#ifdef JME_NEW_PM_API + struct pci_dev *pdev = to_pci_dev(dev); ++#endif + struct net_device *netdev = pci_get_drvdata(pdev); + struct jme_adapter *jme = netdev_priv(netdev); +- +- if (!netif_running(netdev)) +- return 0; +- ++ unsigned long flags; ++ + atomic_dec(&jme->link_changing); + + netif_device_detach(netdev); + netif_stop_queue(netdev); + jme_stop_irq(jme); +- ++ spin_lock_irqsave(&jme->asd_lock, flags); ++ if (jme->flag_run_asd) ++ del_timer_sync(&jme->asd_timer); ++ spin_unlock_irqrestore(&jme->asd_lock, flags); + tasklet_disable(&jme->txclean_task); + tasklet_disable(&jme->rxclean_task); + tasklet_disable(&jme->rxempty_task); +@@ -3268,21 +3809,37 @@ + tasklet_hi_enable(&jme->rxempty_task); + + jme_powersave_phy(jme); ++ jme->media_cnct_sec = 0; ++ jme->media_cnct = false; ++#ifndef JME_NEW_PM_API ++ pci_save_state(pdev); ++ jme_pci_wakeup_enable(jme, !!(jme->reg_pmcs)); ++ pci_set_power_state(pdev, PCI_D3hot); ++#endif + + return 0; + } + + static int ++#ifdef JME_NEW_PM_API + jme_resume(struct device *dev) ++#else ++jme_resume(struct pci_dev *pdev) ++#endif + { ++#ifdef JME_NEW_PM_API + struct pci_dev *pdev = to_pci_dev(dev); ++#endif + struct net_device *netdev = pci_get_drvdata(pdev); + struct jme_adapter *jme = netdev_priv(netdev); +- +- if (!netif_running(netdev)) +- return 0; ++ unsigned long flags; + + jme_clear_pm(jme); ++#ifndef JME_NEW_PM_API ++ pci_set_power_state(pdev, PCI_D0); ++ pci_restore_state(pdev); ++#endif ++ + jme_phy_on(jme); + if (test_bit(JME_FLAG_SSET, &jme->flags)) + jme_set_settings(netdev, &jme->old_ecmd); +@@ -3296,19 +3853,35 @@ + atomic_inc(&jme->link_changing); + + jme_reset_link(jme); +- ++ spin_lock_irqsave(&jme->asd_lock, flags); ++ if (jme->flag_run_asd) { ++ jme_check_ANcomplete(jme); ++ jme->asd_timer.expires = jiffies + 4*HZ; ++ jme->asd_timer.function = &asd_polling_func; ++ jme->asd_timer.data = (unsigned long)jme; ++ add_timer(&jme->asd_timer); ++ } ++ spin_unlock_irqrestore(&jme->asd_lock, flags); + return 0; + } + ++#ifdef JME_NEW_PM_API + static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume); + #define JME_PM_OPS (&jme_pm_ops) ++#endif + + #else + ++#ifdef JME_NEW_PM_API + #define JME_PM_OPS NULL + #endif ++#endif + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24) ++static struct pci_device_id jme_pci_tbl[] = { ++#else + static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { ++#endif + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) }, + { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) }, + { } +@@ -3320,7 +3893,12 @@ + .probe = jme_init_one, + .remove = __devexit_p(jme_remove_one), + .shutdown = jme_shutdown, ++#ifndef JME_NEW_PM_API ++ .suspend = jme_suspend, ++ .resume = jme_resume ++#else + .driver.pm = JME_PM_OPS, ++#endif + }; + + static int __init +@@ -3344,3 +3922,4 @@ + MODULE_LICENSE("GPL"); + MODULE_VERSION(DRV_VERSION); + MODULE_DEVICE_TABLE(pci, jme_pci_tbl); ++ +diff -Naur linux-3.7.2/drivers/net/ethernet/jme.h linux-3.7.2.patch/drivers/net/ethernet/jme.h +--- linux-3.7.2/drivers/net/ethernet/jme.h 2013-01-11 18:19:28.000000000 +0100 ++++ linux-3.7.2.patch/drivers/net/ethernet/jme.h 2013-01-16 10:11:32.534765166 +0100 +@@ -27,7 +27,7 @@ + #include + + #define DRV_NAME "jme" +-#define DRV_VERSION "1.0.8" ++#define DRV_VERSION "1.0.8.5-jmmod" + #define PFX DRV_NAME ": " + + #define PCI_DEVICE_ID_JMICRON_JMC250 0x0250 +@@ -43,6 +43,15 @@ + NETIF_MSG_TX_ERR | \ + NETIF_MSG_HW) + ++#ifndef pr_err ++#define pr_err(fmt, arg...) \ ++ printk(KERN_ERR fmt, ##arg) ++#endif ++#ifndef netdev_err ++#define netdev_err(netdev, fmt, arg...) \ ++ pr_err(fmt, ##arg) ++#endif ++ + #ifdef TX_DEBUG + #define tx_dbg(priv, fmt, args...) \ + printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ##args) +@@ -54,6 +63,55 @@ + } while (0) + #endif + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,33) ++#define jme_msg(msglvl, type, priv, fmt, args...) \ ++ if (netif_msg_##type(priv)) \ ++ printk(msglvl "%s: " fmt, (priv)->dev->name, ## args) ++ ++#define msg_probe(priv, fmt, args...) \ ++ jme_msg(KERN_INFO, probe, priv, fmt, ## args) ++ ++#define msg_link(priv, fmt, args...) \ ++ jme_msg(KERN_INFO, link, priv, fmt, ## args) ++ ++#define msg_intr(priv, fmt, args...) \ ++ jme_msg(KERN_INFO, intr, priv, fmt, ## args) ++ ++#define msg_rx_err(priv, fmt, args...) \ ++ jme_msg(KERN_ERR, rx_err, priv, fmt, ## args) ++ ++#define msg_rx_status(priv, fmt, args...) \ ++ jme_msg(KERN_INFO, rx_status, priv, fmt, ## args) ++ ++#define msg_tx_err(priv, fmt, args...) \ ++ jme_msg(KERN_ERR, tx_err, priv, fmt, ## args) ++ ++#define msg_tx_done(priv, fmt, args...) \ ++ jme_msg(KERN_INFO, tx_done, priv, fmt, ## args) ++ ++#define msg_tx_queued(priv, fmt, args...) \ ++ jme_msg(KERN_INFO, tx_queued, priv, fmt, ## args) ++ ++#define msg_hw(priv, fmt, args...) \ ++ jme_msg(KERN_ERR, hw, priv, fmt, ## args) ++ ++#ifndef netif_info ++#define netif_info(priv, type, dev, fmt, args...) \ ++ msg_ ## type(priv, fmt, ## args) ++#endif ++#ifndef netif_err ++#define netif_err(priv, type, dev, fmt, args...) \ ++ msg_ ## type(priv, fmt, ## args) ++#endif ++#endif ++ ++#ifndef NETIF_F_TSO6 ++#define NETIF_F_TSO6 0 ++#endif ++#ifndef NETIF_F_IPV6_CSUM ++#define NETIF_F_IPV6_CSUM 0 ++#endif ++ + /* + * Extra PCI Configuration space interface + */ +@@ -102,6 +160,7 @@ + }; + + #define HALF_US 500 /* 500 ns */ ++#define JMESPIIOCTL SIOCDEVPRIVATE + + #define PCI_PRIV_PE1 0xE4 + +@@ -388,10 +447,75 @@ + atomic_t nr_free; + }; + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) ++#define false 0 ++#define true 0 ++#define netdev_alloc_skb(dev, len) dev_alloc_skb(len) ++#define PCI_VENDOR_ID_JMICRON 0x197B ++#endif ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,19) ++#define PCI_VDEVICE(vendor, device) \ ++ PCI_VENDOR_ID_##vendor, (device), \ ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0 ++#endif ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) ++#define NET_STAT(priv) priv->stats ++#define NETDEV_GET_STATS(netdev, fun_ptr) \ ++ netdev->get_stats = fun_ptr ++#define DECLARE_NET_DEVICE_STATS struct net_device_stats stats; ++/* ++ * CentOS 5.2 have *_hdr helpers back-ported ++ */ ++#ifdef RHEL_RELEASE_CODE ++#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2) ++#define __DEFINE_IPHDR_HELPERS__ ++#endif ++#else ++#define __DEFINE_IPHDR_HELPERS__ ++#endif ++#else + #define NET_STAT(priv) (priv->dev->stats) + #define NETDEV_GET_STATS(netdev, fun_ptr) + #define DECLARE_NET_DEVICE_STATS ++#endif ++ ++#ifdef __DEFINE_IPHDR_HELPERS__ ++static inline struct iphdr *ip_hdr(const struct sk_buff *skb) ++{ ++ return skb->nh.iph; ++} ++ ++static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb) ++{ ++ return skb->nh.ipv6h; ++} + ++static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb) ++{ ++ return skb->h.th; ++} ++#endif ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) ++#define DECLARE_NAPI_STRUCT ++#define NETIF_NAPI_SET(dev, napis, pollfn, q) \ ++ dev->poll = pollfn; \ ++ dev->weight = q; ++#define JME_NAPI_HOLDER(holder) struct net_device *holder ++#define JME_NAPI_WEIGHT(w) int *w ++#define JME_NAPI_WEIGHT_VAL(w) *w ++#define JME_NAPI_WEIGHT_SET(w, r) *w = r ++#define DECLARE_NETDEV struct net_device *netdev = jme->dev; ++#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(dev) ++#define JME_NAPI_ENABLE(priv) netif_poll_enable(priv->dev); ++#define JME_NAPI_DISABLE(priv) netif_poll_disable(priv->dev); ++#define JME_RX_SCHEDULE_PREP(priv) \ ++ netif_rx_schedule_prep(priv->dev) ++#define JME_RX_SCHEDULE(priv) \ ++ __netif_rx_schedule(priv->dev); ++#else + #define DECLARE_NAPI_STRUCT struct napi_struct napi; + #define NETIF_NAPI_SET(dev, napis, pollfn, q) \ + netif_napi_add(dev, napis, pollfn, q); +@@ -399,6 +523,7 @@ + #define JME_NAPI_WEIGHT(w) int w + #define JME_NAPI_WEIGHT_VAL(w) w + #define JME_NAPI_WEIGHT_SET(w, r) ++#define DECLARE_NETDEV + #define JME_RX_COMPLETE(dev, napis) napi_complete(napis) + #define JME_NAPI_ENABLE(priv) napi_enable(&priv->napi); + #define JME_NAPI_DISABLE(priv) \ +@@ -408,6 +533,18 @@ + napi_schedule_prep(&priv->napi) + #define JME_RX_SCHEDULE(priv) \ + __napi_schedule(&priv->napi); ++#endif ++ ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38) ++#define JME_NEW_PM_API ++#endif ++ ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,26) ++static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep) ++{ ++ return ep->speed; ++} ++#endif + + /* + * Jmac Adapter Private data +@@ -427,6 +564,7 @@ + struct tasklet_struct txclean_task; + struct tasklet_struct linkch_task; + struct tasklet_struct pcc_task; ++ struct work_struct LC_task; + unsigned long flags; + u32 reg_txcs; + u32 reg_txpfc; +@@ -450,6 +588,7 @@ + u32 msg_enable; + struct ethtool_cmd old_ecmd; + unsigned int old_mtu; ++ struct vlan_group *vlgrp; + struct dynpcc_info dpi; + atomic_t intr_sem; + atomic_t link_changing; +@@ -457,13 +596,32 @@ + atomic_t rx_cleaning; + atomic_t rx_empty; + int (*jme_rx)(struct sk_buff *skb); ++ spinlock_t asd_lock; ++ u8 flag_run_asd; ++ u32 media_cnct_sec; ++ u8 media_cnct; ++ struct timer_list asd_timer; ++ int (*jme_vlan_rx)(struct sk_buff *skb, ++ struct vlan_group *grp, ++ unsigned short vlan_tag); + DECLARE_NAPI_STRUCT + DECLARE_NET_DEVICE_STATS + }; + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) ++static struct net_device_stats * ++jme_get_stats(struct net_device *netdev) ++{ ++ struct jme_adapter *jme = netdev_priv(netdev); ++ return &jme->stats; ++} ++#endif ++ + enum jme_flags_bits { + JME_FLAG_MSI = 1, + JME_FLAG_SSET = 2, ++ JME_FLAG_TXCSUM = 3, ++ JME_FLAG_TSO = 4, + JME_FLAG_POLL = 5, + JME_FLAG_SHUTDOWN = 6, + }; +@@ -472,6 +630,15 @@ + #define JME_REG_LEN 0x500 + #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9216 + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) ++static inline struct jme_adapter* ++jme_napi_priv(struct net_device *holder) ++{ ++ struct jme_adapter *jme; ++ jme = netdev_priv(holder); ++ return jme; ++} ++#else + static inline struct jme_adapter* + jme_napi_priv(struct napi_struct *napi) + { +@@ -479,6 +646,7 @@ + jme = container_of(napi, struct jme_adapter, napi); + return jme; + } ++#endif + + /* + * MMaped I/O Resters +@@ -730,7 +898,7 @@ + RXCS_RETRYCNT_60 = 0x00000F00, + + RXCS_DEFAULT = RXCS_FIFOTHTP_128T | +- RXCS_FIFOTHNP_16QW | ++ RXCS_FIFOTHNP_128QW | + RXCS_DMAREQSZ_128B | + RXCS_RETRYGAP_256ns | + RXCS_RETRYCNT_32, +@@ -762,20 +930,20 @@ + + /* Extern PHY common register 2 */ + +-#define PHY_GAD_TEST_MODE_1 0x00002000 +-#define PHY_GAD_TEST_MODE_MSK 0x0000E000 +-#define JM_PHY_SPEC_REG_READ 0x00004000 +-#define JM_PHY_SPEC_REG_WRITE 0x00008000 +-#define PHY_CALIBRATION_DELAY 20 ++#define PHY_GAD_TEST_MODE_1 0x00002000 //BIT_13 GIGA Test mode 1 ++#define PHY_GAD_TEST_MODE_MSK 0x0000E000 //BIT_13_15 GIGA Test mode mask ++#define JM_PHY_SPEC_REG_READ 0x00004000 //BIT_14 ++#define JM_PHY_SPEC_REG_WRITE 0x00008000 //BIT_15 ++#define PHY_CALIBRATION_DELAY 20 // 20 milliseconds + #define JM_PHY_SPEC_ADDR_REG 0x1E + #define JM_PHY_SPEC_DATA_REG 0x1F + + #define JM_PHY_EXT_COMM_0_REG 0x30 +-#define JM_PHY_EXT_COMM_1_REG 0x31 ++#define JM_PHY_EXT_COMM_1_REG 0x31 + #define JM_PHY_EXT_COMM_2_REG 0x32 +-#define JM_PHY_EXT_COMM_2_CALI_ENABLE 0x01 +-#define JM_PHY_EXT_COMM_2_CALI_MODE_0 0x02 +-#define JM_PHY_EXT_COMM_2_CALI_LATCH 0x10 ++#define JM_PHY_EXT_COMM_2_CALI_ENABLE 0x01 //BIT_0 ++#define JM_PHY_EXT_COMM_2_CALI_MODE_0 0x02 //BIT_1 ++#define JM_PHY_EXT_COMM_2_CALI_LATCH 0x10 //BIT_4 + #define PCI_PRIV_SHARE_NICCTRL 0xF5 + #define JME_FLAG_PHYEA_ENABLE 0x2 + +@@ -908,6 +1076,14 @@ + }; + + /* ++ * False carrier Counter ++ */ ++enum jme_phy_an_status { ++ PHY_SPEC_STATUS_AN_COMPLETE = 0x00000800, ++ PHY_SPEC_STATUS_AN_FAIL = 0x00008000, ++}; ++ ++/* + * Giga PHY Status Registers + */ + enum jme_phy_link_bit_mask { +@@ -1277,3 +1453,4 @@ + static void jme_set_multi(struct net_device *netdev); + + #endif ++ diff --git a/packages/linux/patches/3.10/linux-900-hide_tsc_error.patch b/packages/linux/patches/3.10/linux-900-hide_tsc_error.patch new file mode 100644 index 0000000000..61b73b69b0 --- /dev/null +++ b/packages/linux/patches/3.10/linux-900-hide_tsc_error.patch @@ -0,0 +1,12 @@ +diff -uNr linux-3.6.4-orig/arch/x86/kernel/tsc.c linux-3.6.4-new/arch/x86/kernel/tsc.c +--- linux-3.6.4-orig/arch/x86/kernel/tsc.c 2012-11-03 14:19:55.000000000 +0100 ++++ linux-3.6.4-new/arch/x86/kernel/tsc.c 2012-11-03 14:23:05.000000000 +0100 +@@ -374,7 +374,7 @@ + goto success; + } + } +- pr_err("Fast TSC calibration failed\n"); ++ pr_info("Fast TSC calibration failed\n"); + return 0; + + success: diff --git a/packages/linux/patches/3.10/linux-950-saa716x_PCIe_interface_chipset.patch b/packages/linux/patches/3.10/linux-950-saa716x_PCIe_interface_chipset.patch new file mode 100644 index 0000000000..7428c7ce68 --- /dev/null +++ b/packages/linux/patches/3.10/linux-950-saa716x_PCIe_interface_chipset.patch @@ -0,0 +1,13031 @@ +diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig +index b85f88c..238b2ed 100644 +--- a/drivers/media/common/Kconfig ++++ b/drivers/media/common/Kconfig +@@ -22,4 +22,5 @@ config CYPRESS_FIRMWARE + + source "drivers/media/common/b2c2/Kconfig" + source "drivers/media/common/saa7146/Kconfig" ++source "drivers/media/common/saa716x/Kconfig" + source "drivers/media/common/siano/Kconfig" +diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile +index d208de3..b3c373d 100644 +--- a/drivers/media/common/Makefile ++++ b/drivers/media/common/Makefile +@@ -1,4 +1,4 @@ +-obj-y += b2c2/ saa7146/ siano/ ++obj-y += b2c2/ saa7146/ saa716x/ siano/ + obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o + obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o + obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o +diff --git a/drivers/media/common/saa716x/Kconfig b/drivers/media/common/saa716x/Kconfig +new file mode 100644 +index 0000000..e667a58 +--- /dev/null ++++ b/drivers/media/common/saa716x/Kconfig +@@ -0,0 +1,67 @@ ++menuconfig SAA716X_SUPPORT ++ bool "Support for SAA716x family from NXP/Philips" ++ depends on PCI && I2C ++ help ++ support for saa716x ++ ++if SAA716X_SUPPORT ++config SAA716X_CORE ++ tristate "SAA7160/1/2 PCI Express bridge based devices" ++ depends on PCI && I2C ++ ++ help ++ Support for PCI cards based on the SAA7160/1/2 PCI Express bridge. ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_BUDGET ++ tristate "SAA7160/1/2 based Budget PCIe cards (DVB only)" ++ depends on SAA716X_CORE && DVB_CORE ++ select DVB_DS3000 if !DVB_FE_CUSTOMISE ++ select DVB_DS3103 if !DVB_FE_CUSTOMISE ++ select DVB_TS2022 if !DVB_FE_CUSTOMISE ++ ++ help ++ Support for the SAA7160/1/2 based Budget PCIe DVB cards ++ Currently supported devices are: ++ ++ * KNC1 Dual S2 (DVB-S, DVB-S/S2) ++ * Twinhan/Azurewave VP-1028 (DVB-S) ++ * Twinhan/Azurewave VP-3071 (DVB-T x2) ++ * Twinhan/Azurewave VP-6002 (DVB-S) ++ ++ Say Y if you own such a device and want to use it. ++ ++config DVB_SAA716X_HYBRID ++ tristate "SAA7160/1/2 based Hybrid PCIe cards (DVB + Analog)" ++ depends on SAA716X_CORE && DVB_CORE ++ ++ help ++ Support for the SAA7160/1/2 based Hybrid PCIe DVB cards ++ Currently supported devices are: ++ ++ * Avermedia H-788 (DVB-T) ++ * Avermedia HC-82 (DVB-T) ++ * NXP Reference (Atlantis) (DVB-T x2) ++ * NXP Reference (Nemo) (DVB-T) ++ * Twinhan/Azurewave VP-6090 (DVB-S x2, DVB-T x2) ++ ++ Say Y if you own such a device and want to use it. ++ ++#config DVB_SAA716X_FF ++# tristate "SAA7160/1/2 based Full Fledged PCIe cards" ++# depends on SAA716X_CORE && DVB_CORE ++# depends on INPUT # IR ++# default n ++ ++# help ++# Support for the SAA7160/1/2 based Full fledged PCIe DVB cards ++# These cards do feature a hardware MPEG decoder and other ++# peripherals. Also known as Premium cards. ++# Currently supported devices are: ++ ++# * Technotrend S2 6400 Dual S2 HD (DVB-S/S2 x2) ++ ++# Say Y if you own such a device and want to use it. ++ ++endif # SAA716X_SUPPORT +diff --git a/drivers/media/common/saa716x/Makefile b/drivers/media/common/saa716x/Makefile +new file mode 100644 +index 0000000..c86f224 +--- /dev/null ++++ b/drivers/media/common/saa716x/Makefile +@@ -0,0 +1,26 @@ ++saa716x_core-objs := saa716x_pci.o \ ++ saa716x_i2c.o \ ++ saa716x_cgu.o \ ++ saa716x_msi.o \ ++ saa716x_dma.o \ ++ saa716x_vip.o \ ++ saa716x_aip.o \ ++ saa716x_phi.o \ ++ saa716x_boot.o \ ++ saa716x_fgpi.o \ ++ saa716x_adap.o \ ++ saa716x_gpio.o \ ++ saa716x_greg.o \ ++ saa716x_rom.o \ ++ saa716x_spi.o ++ ++#saa716x_ff-objs := saa716x_ff_main.o \ ++# saa716x_ff_cmd.o \ ++# saa716x_ff_ir.o ++ ++obj-$(CONFIG_SAA716X_CORE) += saa716x_core.o ++obj-$(CONFIG_DVB_SAA716X_BUDGET) += saa716x_budget.o ++obj-$(CONFIG_DVB_SAA716X_HYBRID) += saa716x_hybrid.o ++#obj-$(CONFIG_DVB_SAA716X_FF) += saa716x_ff.o ++ ++EXTRA_CFLAGS = -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/ +diff --git a/drivers/media/common/saa716x/saa716x_adap.c b/drivers/media/common/saa716x/saa716x_adap.c +new file mode 100644 +index 0000000..6d7346c +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_adap.c +@@ -0,0 +1,274 @@ ++#include ++ ++#include "dmxdev.h" ++#include "dvbdev.h" ++#include "dvb_demux.h" ++#include "dvb_frontend.h" ++ ++#include "saa716x_mod.h" ++#include "saa716x_spi.h" ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_gpio.h" ++#include "saa716x_priv.h" ++#include "saa716x_budget.h" ++ ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++ ++void saa716x_dma_start(struct saa716x_dev *saa716x, u8 adapter) ++{ ++ struct fgpi_stream_params params; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Start DMA engine for Adapter:%d", adapter); ++ ++ params.bits = 8; ++ params.samples = 188; ++ params.lines = 348; ++ params.pitch = 188; ++ params.offset = 0; ++ params.page_tables = 0; ++ params.stream_type = FGPI_TRANSPORT_STREAM; ++ params.stream_flags = 0; ++ ++ saa716x_fgpi_start(saa716x, saa716x->config->adap_config[adapter].ts_port, ¶ms); ++} ++ ++void saa716x_dma_stop(struct saa716x_dev *saa716x, u8 adapter) ++{ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Stop DMA engine for Adapter:%d", adapter); ++ ++ saa716x_fgpi_stop(saa716x, saa716x->config->adap_config[adapter].ts_port); ++} ++ ++static int saa716x_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; ++ struct saa716x_dev *saa716x = saa716x_adap->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Start feed"); ++ if (!dvbdmx->dmx.frontend) { ++ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); ++ return -EINVAL; ++ } ++ saa716x_adap->feeds++; ++ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed, feeds=%d", ++ saa716x_adap->feeds); ++ ++ if (saa716x_adap->feeds == 1) { ++ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed & dma"); ++ saa716x_dma_start(saa716x, saa716x_adap->count); ++ } ++ ++ return saa716x_adap->feeds; ++} ++ ++static int saa716x_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) ++{ ++ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; ++ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; ++ struct saa716x_dev *saa716x = saa716x_adap->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Stop feed"); ++ if (!dvbdmx->dmx.frontend) { ++ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); ++ return -EINVAL; ++ } ++ saa716x_adap->feeds--; ++ if (saa716x_adap->feeds == 0) { ++ dprintk(SAA716x_DEBUG, 1, "saa716x stop feed and dma"); ++ saa716x_dma_stop(saa716x, saa716x_adap->count); ++ } ++ ++ return 0; ++} ++ ++int saa716x_dvb_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct saa716x_config *config = saa716x->config; ++ int result, i; ++ ++ mutex_init(&saa716x->adap_lock); ++ ++ for (i = 0; i < config->adapters; i++) { ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_register_adapter"); ++ if (dvb_register_adapter(&saa716x_adap->dvb_adapter, ++ "SAA716x dvb adapter", ++ THIS_MODULE, ++ &saa716x->pdev->dev, ++ adapter_nr) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "Error registering adapter"); ++ return -ENODEV; ++ } ++ ++ saa716x_adap->count = i; ++ ++ saa716x_adap->dvb_adapter.priv = saa716x_adap; ++ saa716x_adap->demux.dmx.capabilities = DMX_TS_FILTERING | ++ DMX_SECTION_FILTERING | ++ DMX_MEMORY_BASED_FILTERING; ++ ++ saa716x_adap->demux.priv = saa716x_adap; ++ saa716x_adap->demux.filternum = 256; ++ saa716x_adap->demux.feednum = 256; ++ saa716x_adap->demux.start_feed = saa716x_dvb_start_feed; ++ saa716x_adap->demux.stop_feed = saa716x_dvb_stop_feed; ++ saa716x_adap->demux.write_to_decoder = NULL; ++ switch (saa716x->pdev->subsystem_device) { ++ case TEVII_S472: { ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ u8 mac[6]; ++ u8 b0[] = { 0, 9 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = 0x50, ++ .flags = 0, ++ .buf = b0, ++ .len = 2 ++ }, { ++ .addr = 0x50, ++ .flags = I2C_M_RD, ++ .buf = mac, ++ .len = 6 ++ } ++ }; ++ ++ i2c_transfer(adapter, msg, 2); ++ dprintk(SAA716x_INFO, 1, "TeVii S472 MAC= %pM\n", mac); ++ memcpy(saa716x_adap->dvb_adapter.proposed_mac, mac, 6); ++ } ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_dmx_init"); ++ if ((result = dvb_dmx_init(&saa716x_adap->demux)) < 0) { ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err0; ++ } ++ ++ saa716x_adap->dmxdev.filternum = 256; ++ saa716x_adap->dmxdev.demux = &saa716x_adap->demux.dmx; ++ saa716x_adap->dmxdev.capabilities = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_dmxdev_init"); ++ if ((result = dvb_dmxdev_init(&saa716x_adap->dmxdev, ++ &saa716x_adap->dvb_adapter)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); ++ goto err1; ++ } ++ ++ saa716x_adap->fe_hw.source = DMX_FRONTEND_0; ++ ++ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_hw)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err2; ++ } ++ ++ saa716x_adap->fe_mem.source = DMX_MEMORY_FE; ++ ++ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_mem)) < 0) { ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err3; ++ } ++ ++ if ((result = saa716x_adap->demux.dmx.connect_frontend(&saa716x_adap->demux.dmx, ++ &saa716x_adap->fe_hw)) < 0) { ++ ++ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); ++ goto err4; ++ } ++ ++ dvb_net_init(&saa716x_adap->dvb_adapter, &saa716x_adap->dvb_net, &saa716x_adap->demux.dmx); ++// tasklet_init(&saa716x_adap->tasklet, saa716x_dma_xfer, (unsigned long) saa716x); ++ dprintk(SAA716x_DEBUG, 1, "Frontend Init"); ++ saa716x_adap->saa716x = saa716x; ++ ++ if (config->frontend_attach) { ++ result = config->frontend_attach(saa716x_adap, i); ++ if (result < 0) ++ dprintk(SAA716x_ERROR, 1, "SAA716x frontend attach failed"); ++ ++ if (saa716x_adap->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "A frontend driver was not found for [%04x:%04x] subsystem [%04x:%04x]\n", ++ saa716x->pdev->vendor, ++ saa716x->pdev->device, ++ saa716x->pdev->subsystem_vendor, ++ saa716x->pdev->subsystem_device); ++ } else { ++ result = dvb_register_frontend(&saa716x_adap->dvb_adapter, saa716x_adap->fe); ++ if (result < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x register frontend failed"); ++ goto err6; ++ } ++ } ++ ++ } else { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach = NULL"); ++ } ++ ++ saa716x_fgpi_init(saa716x, config->adap_config[i].ts_port, ++ config->adap_config[i].worker); ++ ++ saa716x_adap++; ++ } ++ ++ ++ return 0; ++ ++ /* Error conditions */ ++err6: ++ dvb_frontend_detach(saa716x_adap->fe); ++err4: ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); ++err3: ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); ++err2: ++ dvb_dmxdev_release(&saa716x_adap->dmxdev); ++err1: ++ dvb_dmx_release(&saa716x_adap->demux); ++err0: ++ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); ++ ++ return result; ++} ++EXPORT_SYMBOL(saa716x_dvb_init); ++ ++void saa716x_dvb_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ int i; ++ ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ ++ saa716x_fgpi_exit(saa716x, saa716x->config->adap_config[i].ts_port); ++ ++ if (saa716x_adap->fe) { ++ dvb_unregister_frontend(saa716x_adap->fe); ++ dvb_frontend_detach(saa716x_adap->fe); ++ } ++ ++// tasklet_kill(&saa716x->tasklet); ++ dvb_net_release(&saa716x_adap->dvb_net); ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); ++ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); ++ dvb_dmxdev_release(&saa716x_adap->dmxdev); ++ dvb_dmx_release(&saa716x_adap->demux); ++ ++ dprintk(SAA716x_DEBUG, 1, "dvb_unregister_adapter"); ++ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); ++ ++ saa716x_adap++; ++ } ++ ++ return; ++} ++EXPORT_SYMBOL(saa716x_dvb_exit); +diff --git a/drivers/media/common/saa716x/saa716x_adap.h b/drivers/media/common/saa716x/saa716x_adap.h +new file mode 100644 +index 0000000..7822e36 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_adap.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_ADAP_H ++#define __SAA716x_ADAP_H ++ ++struct saa716x_dev; ++ ++extern int saa716x_dvb_init(struct saa716x_dev *saa716x); ++extern void saa716x_dvb_exit(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_ADAP_H */ +diff --git a/drivers/media/common/saa716x/saa716x_aip.c b/drivers/media/common/saa716x/saa716x_aip.c +new file mode 100644 +index 0000000..3bdb265 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_aip.c +@@ -0,0 +1,20 @@ ++#include ++ ++#include "saa716x_mod.h" ++#include "saa716x_aip_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_aip.h" ++#include "saa716x_priv.h" ++ ++int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev) ++{ ++ return SAA716x_EPRD(dev, AI_CTL) == 0 ? 0 : -1; ++} ++EXPORT_SYMBOL_GPL(saa716x_aip_status); ++ ++void saa716x_aip_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(AI0, AI_CTL, 0x00); ++ SAA716x_EPWR(AI1, AI_CTL, 0x00); ++} ++EXPORT_SYMBOL_GPL(saa716x_aip_disable); +diff --git a/drivers/media/common/saa716x/saa716x_aip.h b/drivers/media/common/saa716x/saa716x_aip.h +new file mode 100644 +index 0000000..36277b7 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_aip.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_AIP_H ++#define __SAA716x_AIP_H ++ ++struct saa716x_dev; ++ ++extern int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev); ++extern void saa716x_aip_disable(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_AIP_H */ +diff --git a/drivers/media/common/saa716x/saa716x_aip_reg.h b/drivers/media/common/saa716x/saa716x_aip_reg.h +new file mode 100644 +index 0000000..3e0893a +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_aip_reg.h +@@ -0,0 +1,62 @@ ++#ifndef __SAA716x_AIP_REG_H ++#define __SAA716x_AIP_REG_H ++ ++/* -------------- AI Registers ---------------- */ ++ ++#define AI_STATUS 0x000 ++#define AI_BUF1_ACTIVE (0x00000001 << 4) ++#define AI_OVERRUN (0x00000001 << 3) ++#define AI_HBE (0x00000001 << 2) ++#define AI_BUF2_FULL (0x00000001 << 1) ++#define AI_BUF1_FULL (0x00000001 << 0) ++ ++#define AI_CTL 0x004 ++#define AI_RESET (0x00000001 << 31) ++#define AI_CAP_ENABLE (0x00000001 << 30) ++#define AI_CAP_MODE (0x00000003 << 28) ++#define AI_SIGN_CONVERT (0x00000001 << 27) ++#define AI_EARLYMODE (0x00000001 << 26) ++#define AI_DIAGMODE (0x00000001 << 25) ++#define AI_RAWMODE (0x00000001 << 24) ++#define AI_OVR_INTEN (0x00000001 << 7) ++#define AI_HBE_INTEN (0x00000001 << 6) ++#define AI_BUF2_INTEN (0x00000001 << 5) ++#define AI_BUF1_INTEN (0x00000001 << 4) ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_SERIAL 0x008 ++#define AI_SER_MASTER (0x00000001 << 31) ++#define AI_DATAMODE (0x00000001 << 30) ++#define AI_FRAMEMODE (0x00000003 << 28) ++#define AI_CLOCK_EDGE (0x00000001 << 27) ++#define AI_SSPOS4 (0x00000001 << 19) ++#define AI_NR_CHAN (0x00000003 << 17) ++#define AI_WSDIV (0x000001ff << 8) ++#define AI_SCKDIV (0x000000ff << 0) ++ ++#define AI_FRAMING 0x00c ++#define AI_VALIDPOS (0x000001ff << 22) ++#define AI_LEFTPOS (0x000001ff << 13) ++#define AI_RIGHTPOS (0x000001ff << 4) ++#define AI_SSPOS_3_0 (0x0000000f << 0) ++ ++#define AI_BASE1 0x014 ++#define AI_BASE2 0x018 ++#define AI_BASE (0x03ffffff << 6) ++ ++#define AI_SIZE 0x01c ++#define AI_SAMPLE_SIZE (0x03ffffff << 6) ++ ++#define AI_INT_ACK 0x020 ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_PWR_DOWN 0xff4 ++#define AI_PWR_DWN (0x00000001 << 0) ++ ++#endif /* __SAA716x_AIP_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_boot.c b/drivers/media/common/saa716x/saa716x_boot.c +new file mode 100644 +index 0000000..21e59d0 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_boot.c +@@ -0,0 +1,319 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_greg_reg.h" ++#include "saa716x_cgu_reg.h" ++#include "saa716x_vip_reg.h" ++#include "saa716x_aip_reg.h" ++#include "saa716x_msi_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_gpio_reg.h" ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_dcs_reg.h" ++ ++#include "saa716x_boot.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static int saa716x_ext_boot(struct saa716x_dev *saa716x) ++{ ++ /* Write GREG boot_ready to 0 ++ * DW_0 = 0x0001_2018 ++ * DW_1 = 0x0000_0000 ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000000); ++ ++ /* Clear VI0 interrupt ++ * DW_2 = 0x0000_0fe8 ++ * DW_3 = 0x0000_03ff ++ */ ++ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x000003ff); ++ ++ /* Clear VI1 interrupt ++ * DW_4 = 0x0000_1fe8 ++ * DW_5 = 0x0000_03ff ++ */ ++ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x000003ff); ++ ++ /* CLear FGPI0 interrupt ++ * DW_6 = 0x0000_2fe8 ++ * DW_7 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI0, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI1 interrupt ++ * DW_8 = 0x0000_3fe8 ++ * DW_9 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI1, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI2 interrupt ++ * DW_10 = 0x0000_4fe8 ++ * DW_11 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI2, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear FGPI3 interrupt ++ * DW_12 = 0x0000_5fe8 ++ * DW_13 = 0x0000_007f ++ */ ++ SAA716x_EPWR(FGPI3, INT_CLR_STATUS, 0x0000007f); ++ ++ /* Clear AI0 interrupt ++ * DW_14 = 0x0000_6020 ++ * DW_15 = 0x0000_000f ++ */ ++ SAA716x_EPWR(AI0, AI_INT_ACK, 0x0000000f); ++ ++ /* Clear AI1 interrupt ++ * DW_16 = 0x0000_7020 ++ * DW_17 = 0x0000_200f ++ */ ++ SAA716x_EPWR(AI1, AI_INT_ACK, 0x0000000f); ++ ++ /* Set GREG boot_ready bit to 1 ++ * DW_18 = 0x0001_2018 ++ * DW_19 = 0x0000_2000 ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); ++#if 0 ++ /* End of Boot script command ++ * DW_20 = 0x0000_0006 ++ * Where to write this value ?? ++ * This seems very odd an address to trigger the ++ * Boot Control State Machine ! ++ */ ++ SAA716x_EPWR(VI0, 0x00000006, 0xffffffff); ++#endif ++ return 0; ++} ++ ++/* Internal Bootscript configuration */ ++static void saa716x_int_boot(struct saa716x_dev *saa716x) ++{ ++ /* #1 Configure PCI COnfig space ++ * GREG_JETSTR_CONFIG_0 ++ */ ++ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, saa716x->pdev->subsystem_vendor); ++ ++ /* GREG_JETSTR_CONFIG_1 ++ * pmcsr_scale:7 = 0x00 ++ * pmcsr_scale:6 = 0x00 ++ * pmcsr_scale:5 = 0x00 ++ * pmcsr_scale:4 = 0x00 ++ * pmcsr_scale:3 = 0x00 ++ * pmcsr_scale:2 = 0x00 ++ * pmcsr_scale:1 = 0x00 ++ * pmcsr_scale:0 = 0x00 ++ * BAR mask = 20 bit ++ * BAR prefetch = no ++ * MSI capable = 32 messages ++ */ ++ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, 0x00001005); ++ ++ /* GREG_JETSTR_CONFIG_2 ++ * pmcsr_data:3 = 0x0 ++ * pmcsr_data:2 = 0x0 ++ * pmcsr_data:1 = 0x0 ++ * pmcsr_data:0 = 0x0 ++ */ ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, 0x00000000); ++ ++ /* GREG_JETSTR_CONFIG_3 ++ * pmcsr_data:7 = 0x0 ++ * pmcsr_data:6 = 0x0 ++ * pmcsr_data:5 = 0x0 ++ * pmcsr_data:4 = 0x0 ++ */ ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, 0x00000000); ++ ++ /* #2 Release GREG resets ++ * ip_rst_an ++ * dpa1_rst_an ++ * jetsream_reset_an ++ */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000e00); ++ ++ /* #3 GPIO Setup ++ * GPIO 25:24 = Output ++ * GPIO Output "0" after Reset ++ */ ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); ++ ++ /* #4 Custom stuff goes in here */ ++ ++ /* #5 Disable CGU Clocks ++ * except for PHY, Jetstream, DPA1, DCS, Boot, GREG ++ * CGU_PCR_0_3: pss_mmu_clk:0 = 0x0 ++ */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_3, 0x00000006); ++ ++ /* CGU_PCR_0_4: pss_dtl2mtl_mmu_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_4, 0x00000006); ++ ++ /* CGU_PCR_0_5: pss_msi_ck:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_5, 0x00000006); ++ ++ /* CGU_PCR_0_7: pss_gpio_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_7, 0x00000006); ++ ++ /* CGU_PCR_2_1: spi_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_2_1, 0x00000006); ++ ++ /* CGU_PCR_3_2: i2c_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_2, 0x00000006); ++ ++ /* CGU_PCR_4_1: phi_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_4_1, 0x00000006); ++ ++ /* CGU_PCR_5: vip0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_5, 0x00000006); ++ ++ /* CGU_PCR_6: vip1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_6, 0x00000006); ++ ++ /* CGU_PCR_7: fgpi0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_7, 0x00000006); ++ ++ /* CGU_PCR_8: fgpi1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_8, 0x00000006); ++ ++ /* CGU_PCR_9: fgpi2_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_9, 0x00000006); ++ ++ /* CGU_PCR_10: fgpi3_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_10, 0x00000006); ++ ++ /* CGU_PCR_11: ai0_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_11, 0x00000006); ++ ++ /* CGU_PCR_12: ai1_clk:0 = 0x0 */ ++ SAA716x_EPWR(CGU, CGU_PCR_12, 0x00000006); ++ ++ /* #6 Set GREG boot_ready = 0x1 */ ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); ++ ++ /* #7 Disable GREG CGU Clock */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_6, 0x00000006); ++ ++ /* End of Bootscript command ?? */ ++} ++ ++int saa716x_core_boot(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_config *config = saa716x->config; ++ ++ switch (config->boot_mode) { ++ case SAA716x_EXT_BOOT: ++ dprintk(SAA716x_DEBUG, 1, "Using External Boot from config"); ++ saa716x_ext_boot(saa716x); ++ break; ++ case SAA716x_INT_BOOT: ++ dprintk(SAA716x_DEBUG, 1, "Using Internal Boot from config"); ++ saa716x_int_boot(saa716x); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown configuration %d", config->boot_mode); ++ break; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_core_boot); ++ ++static void saa716x_bus_report(struct pci_dev *pdev, int enable) ++{ ++ u32 reg; ++ ++ pci_read_config_dword(pdev, 0x04, ®); ++ if (enable) ++ reg |= 0x00000100; /* enable SERR */ ++ else ++ reg &= 0xfffffeff; /* disable SERR */ ++ pci_write_config_dword(pdev, 0x04, reg); ++ ++ pci_read_config_dword(pdev, 0x58, ®); ++ reg &= 0xfffffffd; ++ pci_write_config_dword(pdev, 0x58, reg); ++} ++ ++int saa716x_jetpack_init(struct saa716x_dev *saa716x) ++{ ++ /* ++ * configure PHY through config space not to report ++ * non-fatal error messages to avoid problems with ++ * quirky BIOS'es ++ */ ++ saa716x_bus_report(saa716x->pdev, 0); ++ ++ /* ++ * create time out for blocks that have no clock ++ * helps with lower bitrates on FGPI ++ */ ++ SAA716x_EPWR(DCS, DCSC_CTRL, ENABLE_TIMEOUT); ++ ++ /* Reset all blocks */ ++ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); ++ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); ++ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); ++ ++ switch (saa716x->pdev->device) { ++ case SAA7162: ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ ++ msleep(10); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x03000000); /* Enable decoders */ ++ break; ++ case SAA7161: ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); ++ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfeffffff); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ ++ msleep(10); ++ SAA716x_EPWR(GPIO, GPIO_WR, 0x01000000); /* Enable decoder */ ++ break; ++ case SAA7160: ++ saa716x->i2c_rate = SAA716x_I2C_RATE_100; ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown device (0x%02x)", saa716x->pdev->device); ++ return -ENODEV; ++ } ++ ++ /* General setup for MMU */ ++ SAA716x_EPWR(MMU, MMU_MODE, 0x14); ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x Jetpack Successfully initialized", saa716x->pdev->device); ++ ++ return 0; ++} ++EXPORT_SYMBOL(saa716x_jetpack_init); ++ ++void saa716x_core_reset(struct saa716x_dev *saa716x) ++{ ++ dprintk(SAA716x_DEBUG, 1, "RESET Modules"); ++ ++ /* VIP */ ++ SAA716x_EPWR(VI0, VI_MODE, SOFT_RESET); ++ SAA716x_EPWR(VI1, VI_MODE, SOFT_RESET); ++ ++ /* FGPI */ ++ SAA716x_EPWR(FGPI0, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI1, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI2, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ SAA716x_EPWR(FGPI3, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ ++ /* AIP */ ++ SAA716x_EPWR(AI0, AI_CTL, AI_RESET); ++ SAA716x_EPWR(AI1, AI_CTL, AI_RESET); ++ ++ /* BAM */ ++ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); ++ ++ /* MMU */ ++ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); ++ ++ /* MSI */ ++ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); ++} ++EXPORT_SYMBOL_GPL(saa716x_core_reset); +diff --git a/drivers/media/common/saa716x/saa716x_boot.h b/drivers/media/common/saa716x/saa716x_boot.h +new file mode 100644 +index 0000000..8102853 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_boot.h +@@ -0,0 +1,18 @@ ++#ifndef __SAA716x_BOOT_H ++#define __SAA716x_BOOT_H ++ ++#define DISABLE_TIMEOUT 0x17 ++#define ENABLE_TIMEOUT 0x16 ++ ++enum saa716x_boot_mode { ++ SAA716x_EXT_BOOT = 1, ++ SAA716x_INT_BOOT, /* GPIO[31:30] = 0x01 */ ++}; ++ ++struct saa716x_dev; ++ ++extern int saa716x_core_boot(struct saa716x_dev *saa716x); ++extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); ++extern void saa716x_core_reset(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_BOOT_H */ +diff --git a/drivers/media/common/saa716x/saa716x_budget.c b/drivers/media/common/saa716x/saa716x_budget.c +new file mode 100644 +index 0000000..6b52fc1 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_budget.c +@@ -0,0 +1,717 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_budget.h" ++#include "saa716x_gpio.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "mb86a16.h" ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "ds3103.h" ++#include "ts2022.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++#define DRIVER_NAME "SAA716x Budget" ++ ++static int saa716x_budget_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ int err = 0; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM read failed"); ++ } ++ ++ /* set default port mapping */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x04080FA9); ++ /* enable FGPI3 and FGPI1 for TS input from Port 2 and 6 */ ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x321); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail4; ++ } ++ ++ return 0; ++ ++fail4: ++ saa716x_dvb_exit(saa716x); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_budget_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static irqreturn_t saa716x_budget_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ u32 stat_h, stat_l, mask_h, mask_l; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ ++ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ stat_l, stat_h, mask_l, mask_h); ++ ++ if (!((stat_l & mask_l) || (stat_h & mask_h))) ++ return IRQ_NONE; ++ ++ if (stat_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); ++ ++ if (stat_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); ++ ++ saa716x_msi_event(saa716x, stat_l, stat_h); ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ ++ if (stat_l) { ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) { ++ tasklet_schedule(&saa716x->fgpi[0].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) { ++ tasklet_schedule(&saa716x->fgpi[1].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) { ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) { ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP3071 "Twinhan/Azurewave VP-3071" ++#define SAA716x_DEV_TWINHAN_VP3071 "2x DVB-T" ++ ++static int saa716x_vp3071_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp3071_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP3071, ++ .dev_type = SAA716x_DEV_TWINHAN_VP3071, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_vp3071_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP1028 "Twinhan/Azurewave VP-1028" ++#define SAA716x_DEV_TWINHAN_VP1028 "DVB-S" ++ ++static int vp1028_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct saa716x_dev *saa716x = fe->dvb->priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); ++ break; ++ case SEC_VOLTAGE_18: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); ++ break; ++ case SEC_VOLTAGE_OFF: ++ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++struct mb86a16_config vp1028_mb86a16_config = { ++ .demod_address = 0x08, ++ .set_voltage = vp1028_dvbs_set_voltage, ++}; ++ ++static int saa716x_vp1028_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[1]; ++ ++ if (count == 0) { ++ ++ mutex_lock(&saa716x->adap_lock); ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Power ON", count); ++ saa716x_gpio_set_output(saa716x, 10); ++ msleep(1); ++ ++ /* VP-1028 has inverted power supply control */ ++ saa716x_gpio_write(saa716x, 10, 1); /* set to standby */ ++ saa716x_gpio_write(saa716x, 10, 0); /* switch it on */ ++ msleep(100); ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Reset", count); ++ saa716x_gpio_set_output(saa716x, 12); ++ msleep(1); ++ ++ /* reset demodulator (Active LOW) */ ++ saa716x_gpio_write(saa716x, 12, 1); ++ msleep(100); ++ saa716x_gpio_write(saa716x, 12, 0); ++ msleep(100); ++ saa716x_gpio_write(saa716x, 12, 1); ++ msleep(100); ++ ++ mutex_unlock(&saa716x->adap_lock); ++ ++ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); ++ adapter->fe = mb86a16_attach(&vp1028_mb86a16_config, &i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", ++ vp1028_mb86a16_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ } ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp1028_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP1028, ++ .dev_type = SAA716x_DEV_TWINHAN_VP1028, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp1028_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_TWINHAN_VP6002 "Twinhan/Azurewave VP-6002" ++#define SAA716x_DEV_TWINHAN_VP6002 "DVB-S" ++ ++static int saa716x_vp6002_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_vp6002_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP6002, ++ .dev_type = SAA716x_DEV_TWINHAN_VP6002, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp6002_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_KNC1_DUALS2 "KNC One Dual S2" ++#define SAA716x_DEV_KNC1_DUALS2 "1xDVB-S + 1xDVB-S/S2" ++ ++static int saa716x_knc1_duals2_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_knc1_duals2_config = { ++ .model_name = SAA716x_MODEL_KNC1_DUALS2, ++ .dev_type = SAA716x_DEV_KNC1_DUALS2, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_knc1_duals2_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++ ++#define SAA716x_MODEL_SKYSTAR2_EXPRESS_HD "SkyStar 2 eXpress HD" ++#define SAA716x_DEV_SKYSTAR2_EXPRESS_HD "DVB-S/S2" ++ ++static struct stv090x_config skystar2_stv090x_config = { ++ .device = STV0903, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 8000000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_DVBCI, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_init = NULL, ++ .tuner_sleep = NULL, ++ .tuner_set_mode = NULL, ++ .tuner_set_frequency = NULL, ++ .tuner_get_frequency = NULL, ++ .tuner_set_bandwidth = NULL, ++ .tuner_get_bandwidth = NULL, ++ .tuner_set_bbgain = NULL, ++ .tuner_get_bbgain = NULL, ++ .tuner_set_refclk = NULL, ++ .tuner_get_status = NULL, ++}; ++ ++static int skystar2_set_voltage(struct dvb_frontend *fe, ++ enum fe_sec_voltage voltage) ++{ ++ int err; ++ u8 en = 0; ++ u8 sel = 0; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_OFF: ++ en = 0; ++ break; ++ ++ case SEC_VOLTAGE_13: ++ en = 1; ++ sel = 0; ++ break; ++ ++ case SEC_VOLTAGE_18: ++ en = 1; ++ sel = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ err = stv090x_set_gpio(fe, 2, 0, en, 0); ++ if (err < 0) ++ goto exit; ++ err = stv090x_set_gpio(fe, 3, 0, sel, 0); ++ if (err < 0) ++ goto exit; ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static int skystar2_voltage_boost(struct dvb_frontend *fe, long arg) ++{ ++ int err; ++ u8 value; ++ ++ if (arg) ++ value = 1; ++ else ++ value = 0; ++ ++ err = stv090x_set_gpio(fe, 4, 0, value, 0); ++ if (err < 0) ++ goto exit; ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static struct stv6110x_config skystar2_stv6110x_config = { ++ .addr = 0x60, ++ .refclk = 16000000, ++ .clk_div = 2, ++}; ++ ++static int skystar2_express_hd_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ struct stv6110x_devctl *ctl; ++ ++ if (count < saa716x->config->adapters) { ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", ++ count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, ++ saa716x->pdev->subsystem_device); ++ ++ saa716x_gpio_set_output(saa716x, 26); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, 26, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 26, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 26, 1); ++ msleep(10); ++ ++ adapter->fe = dvb_attach(stv090x_attach, ++ &skystar2_stv090x_config, ++ &i2c->i2c_adapter, ++ STV090x_DEMODULATOR_0); ++ ++ if (adapter->fe) { ++ dprintk(SAA716x_NOTICE, 1, "found STV0903 @0x%02x", ++ skystar2_stv090x_config.address); ++ } else { ++ goto exit; ++ } ++ ++ adapter->fe->ops.set_voltage = skystar2_set_voltage; ++ adapter->fe->ops.enable_high_lnb_voltage = skystar2_voltage_boost; ++ ++ ctl = dvb_attach(stv6110x_attach, ++ adapter->fe, ++ &skystar2_stv6110x_config, ++ &i2c->i2c_adapter); ++ ++ if (ctl) { ++ dprintk(SAA716x_NOTICE, 1, "found STV6110(A) @0x%02x", ++ skystar2_stv6110x_config.addr); ++ ++ skystar2_stv090x_config.tuner_init = ctl->tuner_init; ++ skystar2_stv090x_config.tuner_sleep = ctl->tuner_sleep; ++ skystar2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; ++ skystar2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; ++ skystar2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; ++ skystar2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; ++ skystar2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; ++ skystar2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; ++ skystar2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; ++ skystar2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; ++ skystar2_stv090x_config.tuner_get_status = ctl->tuner_get_status; ++ ++ /* call the init function once to initialize ++ tuner's clock output divider and demod's ++ master clock */ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ } else { ++ goto exit; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config skystar2_express_hd_config = { ++ .model_name = SAA716x_MODEL_SKYSTAR2_EXPRESS_HD, ++ .dev_type = SAA716x_DEV_SKYSTAR2_EXPRESS_HD, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = skystar2_express_hd_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++static struct ds3103_config s472_ds3103_config = { ++ .demod_address = 0x68, ++ .ci_mode = 1, ++}; ++ ++static int saa716x_s472_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[1]; ++ ++ if (count != 0) ++ return 0; ++ ++ dprintk(SAA716x_ERROR, 1, "Probing for DS3103 (DVB-S/S2)"); ++ adapter->fe = dvb_attach(ds3103_attach, &s472_ds3103_config, ++ &i2c->i2c_adapter); ++ ++ if (adapter->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "found DS3103 DVB-S/S2 frontend @0x%02x", ++ s472_ds3103_config.demod_address); ++ if (NULL == dvb_attach(ts2022_attach, adapter->fe, 0x60, &i2c->i2c_adapter)) ++ dprintk(SAA716x_ERROR, 1, "ts2022 attach failed"); ++ else ++ dprintk(SAA716x_ERROR, 1, "ts2022 attached!"); ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ ++} ++ ++static struct saa716x_config tevii_s472_config = { ++ .model_name = "TeVii S472 DVB-S2", ++ .dev_type = "DVB-S/S2", ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_s472_frontend_attach, ++ .irq_handler = saa716x_budget_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 1, /* using FGPI 1 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++static struct pci_device_id saa716x_budget_pci_table[] = { ++ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_1028, SAA7160, &saa716x_vp1028_config), /* VP-1028 */ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_3071, SAA7160, &saa716x_vp3071_config), /* VP-3071 */ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6002, SAA7160, &saa716x_vp6002_config), /* VP-6002 */ ++ MAKE_ENTRY(KNC_One, KNC_Dual_S2, SAA7160, &saa716x_knc1_duals2_config), ++ MAKE_ENTRY(TECHNISAT, SKYSTAR2_EXPRESS_HD, SAA7160, &skystar2_express_hd_config), ++ MAKE_ENTRY(TEVII, TEVII_S472, SAA7160, &tevii_s472_config), ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_budget_pci_table); ++ ++static struct pci_driver saa716x_budget_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_budget_pci_table, ++ .probe = saa716x_budget_pci_probe, ++ .remove = saa716x_budget_pci_remove, ++}; ++ ++static int saa716x_budget_init(void) ++{ ++ return pci_register_driver(&saa716x_budget_pci_driver); ++} ++ ++static void saa716x_budget_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_budget_pci_driver); ++} ++ ++module_init(saa716x_budget_init); ++module_exit(saa716x_budget_exit); ++ ++MODULE_DESCRIPTION("SAA716x Budget driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/common/saa716x/saa716x_budget.h b/drivers/media/common/saa716x/saa716x_budget.h +new file mode 100644 +index 0000000..d6b8c46 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_budget.h +@@ -0,0 +1,17 @@ ++#ifndef __SAA716x_BUDGET_H ++#define __SAA716x_BUDGET_H ++ ++#define TWINHAN_TECHNOLOGIES 0x1822 ++#define TWINHAN_VP_3071 0x0039 ++#define TWINHAN_VP_1028 0x0044 ++#define TWINHAN_VP_6002 0x0047 ++ ++#define KNC_One 0x1894 ++#define KNC_Dual_S2 0x0110 ++ ++#define TECHNISAT 0x1AE4 ++#define SKYSTAR2_EXPRESS_HD 0x0700 ++#define TEVII 0x9022 ++#define TEVII_S472 0xd472 ++ ++#endif /* __SAA716x_BUDGET_H */ +diff --git a/drivers/media/common/saa716x/saa716x_cgu.c b/drivers/media/common/saa716x/saa716x_cgu.c +new file mode 100644 +index 0000000..a0ffb04 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_cgu.c +@@ -0,0 +1,539 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_cgu_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++u32 cgu_clk[14] = { ++ CGU_FDC_0, ++ CGU_FDC_1, ++ CGU_FDC_2, ++ CGU_FDC_3, ++ CGU_FDC_4, ++ CGU_FDC_5, ++ CGU_FDC_6, ++ CGU_FDC_7, ++ CGU_FDC_8, ++ CGU_FDC_9, ++ CGU_FDC_10, ++ CGU_FDC_11, ++ CGU_FDC_12, ++ CGU_FDC_13 ++}; ++ ++char *clk_desc[14] = { ++ "Clk PSS", ++ "Clk DCS", ++ "Clk SPI", ++ "Clk I2C/Boot", ++ "Clk PHI", ++ "Clk VI0", ++ "Clk VI1", ++ "Clk FGPI0", ++ "Clk FGPI1", ++ "Clk FGPI2", ++ "Clk FGPI3", ++ "Clk AI0", ++ "Clk AI1", ++ "Clk Phy" ++}; ++ ++int saa716x_getbootscript_setup(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 i; ++ s8 N = 0; ++ s16 M = 0; ++ ++ SAA716x_EPWR(CGU, CGU_PCR_0_6, CGU_PCR_RUN); /* GREG */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_3, CGU_PCR_RUN); /* PSS_MMU */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_4, CGU_PCR_RUN); /* PSS_DTL2MTL */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_5, CGU_PCR_RUN); /* MSI */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_2, CGU_PCR_RUN); /* I2C */ ++ SAA716x_EPWR(CGU, CGU_PCR_4_1, CGU_PCR_RUN); /* PHI */ ++ SAA716x_EPWR(CGU, CGU_PCR_0_7, CGU_PCR_RUN); /* GPIO */ ++ SAA716x_EPWR(CGU, CGU_PCR_2_1, CGU_PCR_RUN); /* SPI */ ++ SAA716x_EPWR(CGU, CGU_PCR_1_1, CGU_PCR_RUN); /* DCS */ ++ SAA716x_EPWR(CGU, CGU_PCR_3_1, CGU_PCR_RUN); /* BOOT */ ++ ++ /* get all dividers */ ++ for (i = 0; i < CGU_CLKS; i++) { ++ cgu->clk_boot_div[i] = SAA716x_EPRD(CGU, cgu_clk[i]); ++ cgu->clk_curr_div[i] = cgu->clk_boot_div[i]; ++ ++ N = (cgu->clk_boot_div[i] >> 11) & 0xff; ++ N *= -1; ++ M = ((cgu->clk_boot_div[i] >> 3) & 0xff) + N; ++ ++ if (M) ++ cgu->clk_freq[i] = (u32 ) N * PLL_FREQ / (u32 ) M; ++ else ++ cgu->clk_freq[i] = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Domain %d: %s <0x%02x> Divider: 0x%x --> N=%d, M=%d, freq=%d", ++ i, clk_desc[i], cgu_clk[i], cgu->clk_boot_div[i], N, M, cgu->clk_freq[i]); ++ } ++ /* store clock settings */ ++ cgu->clk_vi_0[0] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_0[1] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_0[2] = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ cgu->clk_vi_1[0] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ cgu->clk_vi_1[1] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ cgu->clk_vi_1[2] = cgu->clk_freq[CLK_DOMAIN_VI1]; ++ ++ return 0; ++} ++ ++int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 delay = 1; ++ ++ switch (port) { ++ case PORT_VI0_VIDEO: ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(5); ++ break; ++ ++ case PORT_VI0_VBI: ++ cgu->clk_int_port[PORT_VI0_VBI] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(5); ++ break; ++ ++ case PORT_VI1_VIDEO: ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(6); ++ break; ++ ++ case PORT_VI1_VBI: ++ cgu->clk_int_port[PORT_VI1_VBI] = 1; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_CGU_CLKRUN(6); ++ break; ++ ++ case PORT_FGPI0: ++ cgu->clk_int_port[PORT_FGPI0] = 1; ++ SAA716x_CGU_CLKRUN(7); ++ break; ++ ++ case PORT_FGPI1: ++ cgu->clk_int_port[PORT_FGPI1] = 1; ++ SAA716x_CGU_CLKRUN(8); ++ break; ++ ++ case PORT_FGPI2: ++ cgu->clk_int_port[PORT_FGPI2] = 1; ++ SAA716x_CGU_CLKRUN(9); ++ break; ++ ++ case PORT_FGPI3: ++ cgu->clk_int_port[PORT_FGPI3] = 1; ++ SAA716x_CGU_CLKRUN(10); ++ break; ++ ++ case PORT_AI0: ++ cgu->clk_int_port[PORT_AI0] = 1; ++ SAA716x_CGU_CLKRUN(11); ++ break; ++ ++ case PORT_AI1: ++ cgu->clk_int_port[PORT_AI1] = 1; ++ SAA716x_CGU_CLKRUN(12); ++ break; ++ ++ case PORT_ALL: ++ SAA716x_CGU_CLKRUN(5); ++ SAA716x_CGU_CLKRUN(6); ++ SAA716x_CGU_CLKRUN(7); ++ SAA716x_CGU_CLKRUN(8); ++ SAA716x_CGU_CLKRUN(9); ++ SAA716x_CGU_CLKRUN(10); ++ SAA716x_CGU_CLKRUN(11); ++ SAA716x_CGU_CLKRUN(12); ++ ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; ++ cgu->clk_int_port[PORT_VI0_VBI] = 1; ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; ++ cgu->clk_int_port[PORT_VI1_VBI] = 1; ++ cgu->clk_int_port[PORT_FGPI0] = 1; ++ cgu->clk_int_port[PORT_FGPI1] = 1; ++ cgu->clk_int_port[PORT_FGPI2] = 1; ++ cgu->clk_int_port[PORT_FGPI3] = 1; ++ cgu->clk_int_port[PORT_AI0] = 1; ++ cgu->clk_int_port[PORT_AI1] = 1; ++ break; ++ ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); ++ delay = 0; ++ break; ++ } ++ ++ /* wait for PLL */ ++ if (delay) ++ msleep(1); ++ ++ return 0; ++} ++ ++int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u8 delay = 1; ++ ++ switch (port) { ++ case PORT_VI0_VIDEO: ++ cgu->clk_int_port[PORT_VI0_VIDEO] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI0_VBI: ++ cgu->clk_int_port[PORT_VI0_VBI] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI1_VIDEO: ++ cgu->clk_int_port[PORT_VI1_VIDEO] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VBI]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_VI1_VBI: ++ cgu->clk_int_port[PORT_VI1_VBI] = 0; ++ ++ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { ++ delay = 0; ++ break; ++ } ++ ++ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI0: ++ cgu->clk_int_port[PORT_FGPI0] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_7, 0x4); /* FGPI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_7, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI1: ++ cgu->clk_int_port[PORT_FGPI1] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_8, 0x5); /* FGPI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_8, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI2: ++ cgu->clk_int_port[PORT_FGPI2] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_9, 0x6); /* FGPI 2 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_9, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_FGPI3: ++ cgu->clk_int_port[PORT_FGPI3] = 0; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_10, 0x7); /* FGPI 3 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_10, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_AI0: ++ cgu->clk_int_port[PORT_AI0] = 1; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_11, 0x8); /* AI 0 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_11, 0x0); /* disable divider */ ++ break; ++ ++ case PORT_AI1: ++ cgu->clk_int_port[PORT_AI1] = 1; ++ ++ SAA716x_EPWR(CGU, CGU_FS1_12, 0x9); /* AI 1 clk */ ++ SAA716x_EPWR(CGU, CGU_ESR_12, 0x0); /* disable divider */ ++ break; ++ ++ default: ++ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); ++ delay = 0; ++ break; ++ ++ } ++ ++ if (delay) ++ msleep(1); ++ ++ return 0; ++} ++ ++int saa716x_get_clk(struct saa716x_dev *saa716x, ++ enum saa716x_clk_domain domain, ++ u32 *frequency) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ switch (domain) { ++ case CLK_DOMAIN_PSS: ++ case CLK_DOMAIN_DCS: ++ case CLK_DOMAIN_SPI: ++ case CLK_DOMAIN_I2C: ++ case CLK_DOMAIN_PHI: ++ case CLK_DOMAIN_VI0: ++ case CLK_DOMAIN_VI1: ++ case CLK_DOMAIN_FGPI0: ++ case CLK_DOMAIN_FGPI1: ++ case CLK_DOMAIN_FGPI2: ++ case CLK_DOMAIN_FGPI3: ++ case CLK_DOMAIN_AI0: ++ case CLK_DOMAIN_AI1: ++ case CLK_DOMAIN_PHY: ++ *frequency = cgu->clk_freq[domain]; ++ break; ++ ++ case CLK_DOMAIN_VI0VBI: ++ *frequency = cgu->clk_freq[CLK_DOMAIN_VI0]; ++ break; ++ ++ case CLK_DOMAIN_VI1VBI: ++ *frequency =cgu->clk_freq[CLK_DOMAIN_VI1]; ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Error Clock domain <%02x>", domain); ++ break; ++ } ++ ++ return 0; ++} ++ ++int saa716x_set_clk(struct saa716x_dev *saa716x, ++ enum saa716x_clk_domain domain, ++ u32 frequency) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ u32 M = 1, N = 1, reset, i; ++ s8 N_tmp, M_tmp, sub, add, lsb; ++ ++ ++ if (cgu->clk_freq_min > frequency) ++ frequency = cgu->clk_freq_min; ++ ++ if (cgu->clk_freq_max < frequency) ++ frequency = cgu->clk_freq_max; ++ ++ switch (domain) { ++ case CLK_DOMAIN_PSS: ++ case CLK_DOMAIN_DCS: ++ case CLK_DOMAIN_SPI: ++ case CLK_DOMAIN_I2C: ++ case CLK_DOMAIN_PHI: ++ case CLK_DOMAIN_FGPI0: ++ case CLK_DOMAIN_FGPI1: ++ case CLK_DOMAIN_FGPI2: ++ case CLK_DOMAIN_FGPI3: ++ case CLK_DOMAIN_AI0: ++ case CLK_DOMAIN_AI1: ++ case CLK_DOMAIN_PHY: ++ ++ if (frequency == cgu->clk_freq[domain]) ++ return 0; /* same frequency */ ++ break; ++ ++ case CLK_DOMAIN_VI0: ++ ++ if (frequency == cgu->clk_vi_0[1]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_0[0]) { ++ cgu->clk_vi_0[1] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_0[2]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_0[1] = frequency; ++ ++ if (frequency != cgu->clk_vi_0[2]) ++ return 0; ++ ++ } ++ break; ++ ++ case CLK_DOMAIN_VI1: ++ if (frequency == cgu->clk_vi_1[1]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_1[0]) { ++ cgu->clk_vi_1[1] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_1[2]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_1[1] = frequency; ++ ++ if (frequency != cgu->clk_vi_1[2]) ++ return 0; ++ ++ } ++ break; ++ ++ case CLK_DOMAIN_VI0VBI: ++ if (frequency == cgu->clk_vi_0[2]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_0[0]) { ++ cgu->clk_vi_0[2] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_0[1]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_0[2] = frequency; /* store */ ++ ++ if (frequency != cgu->clk_vi_0[1]) ++ return 0; ++ ++ } ++ domain = CLK_DOMAIN_VI0; /* change domain */ ++ break; ++ ++ case CLK_DOMAIN_VI1VBI: ++ if (frequency == cgu->clk_vi_1[2]) { ++ return 0; ++ ++ } else if (frequency == cgu->clk_vi_1[0]) { ++ cgu->clk_vi_1[2] = frequency; /* store */ ++ ++ if (frequency == cgu->clk_vi_1[1]) ++ return 0; ++ ++ } else { ++ cgu->clk_vi_1[2] = frequency; /* store */ ++ ++ if (frequency != cgu->clk_vi_1[1]) ++ return 0; ++ ++ } ++ domain = CLK_DOMAIN_VI1; /* change domain */ ++ break; ++ } ++ ++ /* calculate divider */ ++ do { ++ M = (N * PLL_FREQ) / frequency; ++ if (M == 0) ++ N++; ++ ++ } while (M == 0); ++ ++ /* calculate frequency */ ++ cgu->clk_freq[domain] = (N * PLL_FREQ) / M; ++ ++ N_tmp = N & 0xff; ++ M_tmp = M & 0xff; ++ sub = -N_tmp; ++ add = M_tmp - N_tmp; ++ lsb = 4; /* run */ ++ ++ if (((10 * N) / M) < 5) ++ lsb |= 1; /* stretch */ ++ ++ /* store new divider */ ++ cgu->clk_curr_div[domain] = sub & 0xff; ++ cgu->clk_curr_div[domain] <<= 8; ++ cgu->clk_curr_div[domain] = add & 0xff; ++ cgu->clk_curr_div[domain] <<= 3; ++ cgu->clk_curr_div[domain] |= lsb; ++ ++ dprintk(SAA716x_DEBUG, 1, "Domain <0x%02x> Frequency <%d> Set Freq <%d> N=%d M=%d Divider <0x%02x>", ++ domain, ++ frequency, ++ cgu->clk_freq[domain], ++ N, ++ M, ++ cgu->clk_curr_div[domain]); ++ ++ reset = 0; ++ ++ /* Reset */ ++ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain] | 0x2); ++ ++ /* Reset disable */ ++ for (i = 0; i < 1000; i++) { ++ msleep(10); ++ reset = SAA716x_EPRD(CGU, cgu_clk[domain]); ++ ++ if (cgu->clk_curr_div[domain == reset]) ++ break; ++ } ++ ++ if (cgu->clk_curr_div[domain] != reset) ++ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain]); ++ ++ return 0; ++} ++ ++int saa716x_cgu_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_cgu *cgu = &saa716x->cgu; ++ ++ cgu->clk_freq_min = PLL_FREQ / 255; ++ if (PLL_FREQ > (cgu->clk_freq_min * 255)) ++ cgu->clk_freq_min++; ++ ++ cgu->clk_freq_max = PLL_FREQ; ++ ++ saa716x_getbootscript_setup(saa716x); ++ saa716x_set_clk_internal(saa716x, PORT_ALL); ++ ++ return 0; ++} ++EXPORT_SYMBOL(saa716x_cgu_init); +diff --git a/drivers/media/common/saa716x/saa716x_cgu.h b/drivers/media/common/saa716x/saa716x_cgu.h +new file mode 100644 +index 0000000..5353cf2 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_cgu.h +@@ -0,0 +1,61 @@ ++#ifndef __SAA716x_CGU_H ++#define __SAA716x_CGU_H ++ ++#define PLL_FREQ 2500 ++ ++#define SAA716x_CGU_CLKRUN(__reg) do { \ ++ SAA716x_EPWR(CGU, CGU_PCR_##__reg, CGU_PCR_RUN); /* Run */ \ ++ SAA716x_EPWR(CGU, CGU_SCR_##__reg, CGU_SCR_ENF1); /* Switch */ \ ++ SAA716x_EPWR(CGU, CGU_FS1_##__reg, 0x00000000); /* PLL Clk */ \ ++ SAA716x_EPWR(CGU, CGU_ESR_##__reg, CGU_ESR_FD_EN); /* Frac div */ \ ++} while (0) ++ ++enum saa716x_clk_domain { ++ CLK_DOMAIN_PSS = 0, ++ CLK_DOMAIN_DCS = 1, ++ CLK_DOMAIN_SPI = 2, ++ CLK_DOMAIN_I2C = 3, ++ CLK_DOMAIN_PHI = 4, ++ CLK_DOMAIN_VI0 = 5, ++ CLK_DOMAIN_VI1 = 6, ++ CLK_DOMAIN_FGPI0 = 7, ++ CLK_DOMAIN_FGPI1 = 8, ++ CLK_DOMAIN_FGPI2 = 9, ++ CLK_DOMAIN_FGPI3 = 10, ++ CLK_DOMAIN_AI0 = 11, ++ CLK_DOMAIN_AI1 = 12, ++ CLK_DOMAIN_PHY = 13, ++ CLK_DOMAIN_VI0VBI = 14, ++ CLK_DOMAIN_VI1VBI = 15 ++}; ++ ++#define PORT_VI0_VIDEO 0 ++#define PORT_VI0_VBI 2 ++#define PORT_VI1_VIDEO 3 ++#define PORT_VI1_VBI 5 ++#define PORT_FGPI0 6 ++#define PORT_FGPI1 7 ++#define PORT_FGPI2 8 ++#define PORT_FGPI3 9 ++#define PORT_AI0 10 ++#define PORT_AI1 11 ++#define PORT_ALL 12 ++ ++#define CGU_CLKS 14 ++ ++struct saa716x_cgu { ++ u8 clk_int_port[12]; ++ u32 clk_vi_0[3]; ++ u32 clk_vi_1[3]; ++ u32 clk_boot_div[CGU_CLKS]; ++ u32 clk_curr_div[CGU_CLKS]; ++ u32 clk_freq[CGU_CLKS]; ++ u32 clk_freq_min; ++ u32 clk_freq_max; ++}; ++ ++extern int saa716x_cgu_init(struct saa716x_dev *saa716x); ++extern int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port); ++extern int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port); ++ ++#endif /* __SAA716x_CGU_H */ +diff --git a/drivers/media/common/saa716x/saa716x_cgu_reg.h b/drivers/media/common/saa716x/saa716x_cgu_reg.h +new file mode 100644 +index 0000000..f7d82ae +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_cgu_reg.h +@@ -0,0 +1,178 @@ ++#ifndef __SAA716x_CGU_REG_H ++#define __SAA716x_CGU_REG_H ++ ++/* -------------- CGU Registers -------------- */ ++ ++#define CGU_SCR_0 0x000 ++#define CGU_SCR_1 0x004 ++#define CGU_SCR_2 0x008 ++#define CGU_SCR_3 0x00c ++#define CGU_SCR_4 0x010 ++#define CGU_SCR_5 0x014 ++#define CGU_SCR_6 0x018 ++#define CGU_SCR_7 0x01c ++#define CGU_SCR_8 0x020 ++#define CGU_SCR_9 0x024 ++#define CGU_SCR_10 0x028 ++#define CGU_SCR_11 0x02c ++#define CGU_SCR_12 0x030 ++#define CGU_SCR_13 0x034 ++#define CGU_SCR_STOP (0x00000001 << 3) ++#define CGU_SCR_RESET (0x00000001 << 2) ++#define CGU_SCR_ENF2 (0x00000001 << 1) ++#define CGU_SCR_ENF1 (0x00000001 << 0) ++ ++#define CGU_FS1_0 0x038 ++#define CGU_FS1_1 0x03c ++#define CGU_FS1_2 0x040 ++#define CGU_FS1_3 0x044 ++#define CGU_FS1_4 0x048 ++#define CGU_FS1_5 0x04c ++#define CGU_FS1_6 0x050 ++#define CGU_FS1_7 0x054 ++#define CGU_FS1_8 0x058 ++#define CGU_FS1_9 0x05c ++#define CGU_FS1_10 0x060 ++#define CGU_FS1_11 0x064 ++#define CGU_FS1_12 0x068 ++#define CGU_FS1_13 0x06c ++#define CGU_FS1_PLL (0x00000000 << 0) ++ ++ ++#define CGU_FS2_0 0x070 ++#define CGU_FS2_1 0x074 ++#define CGU_FS2_2 0x078 ++#define CGU_FS2_3 0x07c ++#define CGU_FS2_4 0x080 ++#define CGU_FS2_5 0x084 ++#define CGU_FS2_6 0x088 ++#define CGU_FS2_7 0x08c ++#define CGU_FS2_8 0x090 ++#define CGU_FS2_9 0x094 ++#define CGU_FS2_10 0x098 ++#define CGU_FS2_11 0x09c ++#define CGU_FS2_12 0x0a0 ++#define CGU_FS2_13 0x0a4 ++ ++#define CGU_SSR_0 0x0a8 ++#define CGU_SSR_1 0x0ac ++#define CGU_SSR_2 0x0b0 ++#define CGU_SSR_3 0x0b4 ++#define CGU_SSR_4 0x0b8 ++#define CGU_SSR_5 0x0bc ++#define CGU_SSR_6 0x0c0 ++#define CGU_SSR_7 0x0c4 ++#define CGU_SSR_8 0x0c8 ++#define CGU_SSR_9 0x0cc ++#define CGU_SSR_10 0x0d0 ++#define CGU_SSR_11 0x0d4 ++#define CGU_SSR_12 0x0d8 ++#define CGU_SSR_13 0x0dc ++ ++#define CGU_PCR_0_0 0x0e0 ++#define CGU_PCR_0_1 0x0e4 ++#define CGU_PCR_0_2 0x0e8 ++#define CGU_PCR_0_3 0x0ec ++#define CGU_PCR_0_4 0x0f0 ++#define CGU_PCR_0_5 0x0f4 ++#define CGU_PCR_0_6 0x0f8 ++#define CGU_PCR_0_7 0x0fc ++#define CGU_PCR_1_0 0x100 ++#define CGU_PCR_1_1 0x104 ++#define CGU_PCR_2_0 0x108 ++#define CGU_PCR_2_1 0x10c ++#define CGU_PCR_3_0 0x110 ++#define CGU_PCR_3_1 0x114 ++#define CGU_PCR_3_2 0x118 ++#define CGU_PCR_4_0 0x11c ++#define CGU_PCR_4_1 0x120 ++#define CGU_PCR_5 0x124 ++#define CGU_PCR_6 0x128 ++#define CGU_PCR_7 0x12c ++#define CGU_PCR_8 0x130 ++#define CGU_PCR_9 0x134 ++#define CGU_PCR_10 0x138 ++#define CGU_PCR_11 0x13c ++#define CGU_PCR_12 0x140 ++#define CGU_PCR_13 0x144 ++#define CGU_PCR_WAKE_EN (0x00000001 << 2) ++#define CGU_PCR_AUTO (0x00000001 << 1) ++#define CGU_PCR_RUN (0x00000001 << 0) ++ ++ ++#define CGU_PSR_0_0 0x148 ++#define CGU_PSR_0_1 0x14c ++#define CGU_PSR_0_2 0x150 ++#define CGU_PSR_0_3 0x154 ++#define CGU_PSR_0_4 0x158 ++#define CGU_PSR_0_5 0x15c ++#define CGU_PSR_0_6 0x160 ++#define CGU_PSR_0_7 0x164 ++#define CGU_PSR_1_0 0x168 ++#define CGU_PSR_1_1 0x16c ++#define CGU_PSR_2_0 0x170 ++#define CGU_PSR_2_1 0x174 ++#define CGU_PSR_3_0 0x178 ++#define CGU_PSR_3_1 0x17c ++#define CGU_PSR_3_2 0x180 ++#define CGU_PSR_4_0 0x184 ++#define CGU_PSR_4_1 0x188 ++#define CGU_PSR_5 0x18c ++#define CGU_PSR_6 0x190 ++#define CGU_PSR_7 0x194 ++#define CGU_PSR_8 0x198 ++#define CGU_PSR_9 0x19c ++#define CGU_PSR_10 0x1a0 ++#define CGU_PSR_11 0x1a4 ++#define CGU_PSR_12 0x1a8 ++#define CGU_PSR_13 0x1ac ++ ++#define CGU_ESR_0_0 0x1b0 ++#define CGU_ESR_0_1 0x1b4 ++#define CGU_ESR_0_2 0x1b8 ++#define CGU_ESR_0_3 0x1bc ++#define CGU_ESR_0_4 0x1c0 ++#define CGU_ESR_0_5 0x1c4 ++#define CGU_ESR_0_6 0x1c8 ++#define CGU_ESR_0_7 0x1cc ++#define CGU_ESR_1_0 0x1d0 ++#define CGU_ESR_1_1 0x1d4 ++#define CGU_ESR_2_0 0x1d8 ++#define CGU_ESR_2_1 0x1dc ++#define CGU_ESR_3_0 0x1e0 ++#define CGU_ESR_3_1 0x1e4 ++#define CGU_ESR_3_2 0x1e8 ++#define CGU_ESR_4_0 0x1ec ++#define CGU_ESR_4_1 0x1f0 ++#define CGU_ESR_5 0x1f4 ++#define CGU_ESR_6 0x1f8 ++#define CGU_ESR_7 0x1fc ++#define CGU_ESR_8 0x200 ++#define CGU_ESR_9 0x204 ++#define CGU_ESR_10 0x208 ++#define CGU_ESR_11 0x20c ++#define CGU_ESR_12 0x210 ++#define CGU_ESR_13 0x214 ++#define CGU_ESR_FD_EN (0x00000001 << 0) ++ ++#define CGU_FDC_0 0x218 ++#define CGU_FDC_1 0x21c ++#define CGU_FDC_2 0x220 ++#define CGU_FDC_3 0x224 ++#define CGU_FDC_4 0x228 ++#define CGU_FDC_5 0x22c ++#define CGU_FDC_6 0x230 ++#define CGU_FDC_7 0x234 ++#define CGU_FDC_8 0x238 ++#define CGU_FDC_9 0x23c ++#define CGU_FDC_10 0x240 ++#define CGU_FDC_11 0x244 ++#define CGU_FDC_12 0x248 ++#define CGU_FDC_13 0x24c ++#define CGU_FDC_STRETCH (0x00000001 << 0) ++#define CGU_FDC_RESET (0x00000001 << 1) ++#define CGU_FDC_RUN1 (0x00000001 << 2) ++#define CGU_FDC_MADD (0x000000ff << 3) ++#define CGU_FDC_MSUB (0x000000ff << 11) ++ ++#endif /* __SAA716x_CGU_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_dcs_reg.h b/drivers/media/common/saa716x/saa716x_dcs_reg.h +new file mode 100644 +index 0000000..26dba68 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_dcs_reg.h +@@ -0,0 +1,56 @@ ++#ifndef __SAA716x_DCS_REG_H ++#define __SAA716x_DCS_REG_H ++ ++/* -------------- DCS Registers -------------- */ ++ ++#define DCSC_CTRL 0x000 ++#define DCSC_SEL_PLLDI (0x03ffffff << 5) ++#define DCSC_TOUT_SEL (0x0000000f << 1) ++#define DCSC_TOUT_OFF (0x00000001 << 0) ++ ++#define DCSC_ADDR 0x00c ++#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) ++ ++#define DCSC_STAT 0x010 ++#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) ++#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) ++#define DCSC_ERR_TOUT_READ (0x00000001 << 8) ++#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) ++#define DCSC_ERR_ACK (0x00000001 << 1) ++ ++#define DCSC_FEATURES 0x040 ++#define DCSC_UNIQUE_ID (0x00000007 << 16) ++#define DCSC_SECURITY (0x00000001 << 14) ++#define DCSC_NUM_BASE_REGS (0x00000003 << 11) ++#define DCSC_NUM_TARGETS (0x0000001f << 5) ++#define DCSC_NUM_INITIATORS (0x0000001f << 0) ++ ++#define DCSC_BASE_REG0 0x100 ++#define DCSC_BASE_N_REG (0x00000fff << 20) ++ ++#define DCSC_INT_CLR_ENABLE 0xfd8 ++#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_ENABLE 0xfdc ++#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_STATUS 0xfe0 ++#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) ++#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_ENABLE 0xfe4 ++#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_CLR_STATUS 0xfe8 ++#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_STATUS 0xfec ++#define DCSC_INT_SET_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ERROR (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_DCS_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_dma.c b/drivers/media/common/saa716x/saa716x_dma.c +new file mode 100644 +index 0000000..21d1dd8 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_dma.c +@@ -0,0 +1,306 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include "saa716x_dma.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++/* Allocates one page of memory, which is stores the data of one ++ * 716x page table. The result gets stored in the passed DMA buffer ++ * structure. ++ */ ++static int saa716x_allocate_ptable(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "SG Page table allocate"); ++ dmabuf->mem_ptab_virt = (void *) __get_free_page(GFP_KERNEL); ++ ++ if (dmabuf->mem_ptab_virt == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Out of pages !"); ++ return -ENOMEM; ++ } ++ ++ dmabuf->mem_ptab_phys = dma_map_single(&pdev->dev, ++ dmabuf->mem_ptab_virt, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++ if (dmabuf->mem_ptab_phys == 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: map memory failed !"); ++ return -ENOMEM; ++ } ++ ++ BUG_ON(!(((unsigned long) dmabuf->mem_ptab_phys % SAA716x_PAGE_SIZE) == 0)); ++ ++ return 0; ++} ++ ++static void saa716x_free_ptable(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG Page table free"); ++ ++ /* free physical PCI memory */ ++ if (dmabuf->mem_ptab_phys != 0) { ++ dma_unmap_single(&pdev->dev, ++ dmabuf->mem_ptab_phys, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++ dmabuf->mem_ptab_phys = 0; ++ } ++ ++ /* free kernel memory */ ++ if (dmabuf->mem_ptab_virt != NULL) { ++ free_page((unsigned long) dmabuf->mem_ptab_virt); ++ dmabuf->mem_ptab_virt = NULL; ++ } ++} ++ ++static void saa716x_dmabuf_sgfree(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG free"); ++ ++ dmabuf->mem_virt = NULL; ++ if (dmabuf->mem_virt_noalign != NULL) { ++ if (dmabuf->dma_type == SAA716x_DMABUF_INT) ++ vfree(dmabuf->mem_virt_noalign); ++ ++ dmabuf->mem_virt_noalign = NULL; ++ } ++ ++ if (dmabuf->sg_list != NULL) { ++ kfree(dmabuf->sg_list); ++ dmabuf->sg_list = NULL; ++ } ++} ++ ++/* ++ * Create a SG, when an allocated buffer is passed to it, ++ * otherwise the needed memory gets allocated by itself ++ */ ++static int saa716x_dmabuf_sgalloc(struct saa716x_dmabuf *dmabuf, void *buf, int size) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct scatterlist *list; ++ struct page *pg; ++ ++ int i, pages; ++ ++ BUG_ON(!(size > 0)); ++ BUG_ON(dmabuf == NULL); ++ dprintk(SAA716x_DEBUG, 1, "SG allocate"); ++ ++ if ((size % SAA716x_PAGE_SIZE) != 0) /* calculate required pages */ ++ pages = size / SAA716x_PAGE_SIZE + 1; ++ else ++ pages = size / SAA716x_PAGE_SIZE; ++ ++ /* Allocate memory for SG list */ ++ dmabuf->sg_list = kzalloc(sizeof (struct scatterlist) * pages, GFP_KERNEL); ++ if (dmabuf->sg_list == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for scatterlist."); ++ return -ENOMEM; ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SG table"); ++ sg_init_table(dmabuf->sg_list, pages); ++ ++ if (buf == NULL) { ++ ++ /* allocate memory, unaligned */ ++ dmabuf->mem_virt_noalign = vmalloc((pages + 1) * SAA716x_PAGE_SIZE); ++ if (dmabuf->mem_virt_noalign == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for buffer"); ++ return -ENOMEM; ++ } ++ ++ /* align memory to page */ ++ dmabuf->mem_virt = (void *) PAGE_ALIGN (((unsigned long) dmabuf->mem_virt_noalign)); ++ ++ BUG_ON(!((((unsigned long) dmabuf->mem_virt) % SAA716x_PAGE_SIZE) == 0)); ++ } else { ++ dmabuf->mem_virt = buf; ++ } ++ ++ dmabuf->list_len = pages; /* scatterlist length */ ++ list = dmabuf->sg_list; ++ ++ dprintk(SAA716x_DEBUG, 1, "Allocating SG pages"); ++ for (i = 0; i < pages; i++) { ++ if (buf == NULL) ++ pg = vmalloc_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); ++ else ++ pg = virt_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); ++ ++ BUG_ON(pg == NULL); ++ sg_set_page(&list[i], pg, SAA716x_PAGE_SIZE, 0); ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "Done!"); ++ return 0; ++} ++ ++/* Fill the "page table" page with the pointers to the specified SG buffer */ ++static void saa716x_dmabuf_sgpagefill(struct saa716x_dmabuf *dmabuf, struct scatterlist *sg_list, int pages, int offset) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ struct scatterlist *sg_cur; ++ ++ u32 *page; ++ int i, j, k = 0; ++ dma_addr_t addr = 0; ++ ++ BUG_ON(dmabuf == NULL); ++ BUG_ON(sg_list == NULL); ++ BUG_ON(pages == 0); ++ dprintk(SAA716x_DEBUG, 1, "SG page fill"); ++ ++ /* make page writable for the PC */ ++ dma_sync_single_for_cpu(&pdev->dev, dmabuf->mem_ptab_phys, SAA716x_PAGE_SIZE, DMA_TO_DEVICE); ++ page = dmabuf->mem_ptab_virt; ++ ++ /* create page table */ ++ for (i = 0; i < pages; i++) { ++ sg_cur = &sg_list[i]; ++ BUG_ON(!(((sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE) == 0)); ++ ++ if (i == 0) ++ dmabuf->offset = (sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE; ++ else ++ BUG_ON(sg_cur->offset != 0); ++ ++ for (j = 0; (j * SAA716x_PAGE_SIZE) < sg_dma_len(sg_cur); j++) { ++ ++ if ((offset + sg_cur->offset) >= SAA716x_PAGE_SIZE) { ++ offset -= SAA716x_PAGE_SIZE; ++ continue; ++ } ++ ++ addr = ((u64)sg_dma_address(sg_cur)) + (j * SAA716x_PAGE_SIZE) - sg_cur->offset; ++ ++ BUG_ON(addr == 0); ++ page[k * 2] = (u32 )addr; /* Low */ ++ page[k * 2 + 1] = (u32 )(((u64) addr) >> 32); /* High */ ++ BUG_ON(page[k * 2] % SAA716x_PAGE_SIZE); ++ k++; ++ } ++ } ++ ++ for (; k < (SAA716x_PAGE_SIZE / 8); k++) { ++ page[k * 2] = (u32 ) addr; ++ page[k * 2 + 1] = (u32 ) (((u64 ) addr) >> 32); ++ } ++ ++ /* make "page table" page writable for the PC */ ++ dma_sync_single_for_device(&pdev->dev, ++ dmabuf->mem_ptab_phys, ++ SAA716x_PAGE_SIZE, ++ DMA_TO_DEVICE); ++ ++} ++ ++void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "DMABUF sync DEVICE"); ++ BUG_ON(dmabuf->sg_list == NULL); ++ ++ dma_sync_sg_for_device(&pdev->dev, ++ dmabuf->sg_list, ++ dmabuf->list_len, ++ DMA_FROM_DEVICE); ++ ++} ++ ++void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ dprintk(SAA716x_DEBUG, 1, "DMABUF sync CPU"); ++ BUG_ON(dmabuf->sg_list == NULL); ++ ++ dma_sync_sg_for_cpu(&pdev->dev, ++ dmabuf->sg_list, ++ dmabuf->list_len, ++ DMA_FROM_DEVICE); ++} ++ ++/* Allocates a DMA buffer for the specified external linear buffer. */ ++int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf, int size) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ int ret; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(dmabuf == NULL); ++ BUG_ON(! (size > 0)); ++ ++ dmabuf->dma_type = SAA716x_DMABUF_INT; ++ ++ dmabuf->mem_virt_noalign = NULL; ++ dmabuf->mem_virt = NULL; ++ dmabuf->mem_ptab_phys = 0; ++ dmabuf->mem_ptab_virt = NULL; ++ ++ dmabuf->list_len = 0; ++ dmabuf->saa716x = saa716x; ++ ++ /* Allocate page table */ ++ ret = saa716x_allocate_ptable(dmabuf); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "PT alloc failed, Out of memory"); ++ goto err1; ++ } ++ ++ /* Allocate buffer as SG */ ++ ret = saa716x_dmabuf_sgalloc(dmabuf, NULL, size); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SG alloc failed"); ++ goto err2; ++ } ++ ++ ret = dma_map_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SG map failed"); ++ goto err3; ++ } ++ ++ saa716x_dmabuf_sgpagefill(dmabuf, dmabuf->sg_list, ret, 0); ++ ++ return 0; ++err3: ++ saa716x_dmabuf_sgfree(dmabuf); ++err2: ++ saa716x_free_ptable(dmabuf); ++err1: ++ return ret; ++} ++ ++void saa716x_dmabuf_free(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(dmabuf == NULL); ++ ++ dma_unmap_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); ++ saa716x_dmabuf_sgfree(dmabuf); ++ saa716x_free_ptable(dmabuf); ++} +diff --git a/drivers/media/common/saa716x/saa716x_dma.h b/drivers/media/common/saa716x/saa716x_dma.h +new file mode 100644 +index 0000000..f92d667 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_dma.h +@@ -0,0 +1,38 @@ ++#ifndef __SAA716x_DMA_H ++#define __SAA716x_DMA_H ++ ++#define SAA716x_PAGE_SIZE 4096 ++ ++enum saa716x_dma_type { ++ SAA716x_DMABUF_EXT_LIN, /* Linear external */ ++ SAA716x_DMABUF_EXT_SG, /* SG external */ ++ SAA716x_DMABUF_INT /* Linear internal */ ++}; ++ ++struct saa716x_dev; ++ ++struct saa716x_dmabuf { ++ enum saa716x_dma_type dma_type; ++ ++ void *mem_virt_noalign; ++ void *mem_virt; /* page aligned */ ++ dma_addr_t mem_ptab_phys; ++ void *mem_ptab_virt; ++ void *sg_list; /* SG list */ ++ ++ struct saa716x_dev *saa716x; ++ ++ int list_len; /* buffer len */ ++ int offset; /* page offset */ ++}; ++ ++extern int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, ++ struct saa716x_dmabuf *dmabuf, ++ int size); ++extern void saa716x_dmabuf_free(struct saa716x_dev *saa716x, ++ struct saa716x_dmabuf *dmabuf); ++ ++extern void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf); ++extern void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf); ++ ++#endif /* __SAA716x_DMA_H */ +diff --git a/drivers/media/common/saa716x/saa716x_dma_reg.h b/drivers/media/common/saa716x/saa716x_dma_reg.h +new file mode 100644 +index 0000000..6037ca9 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_dma_reg.h +@@ -0,0 +1,200 @@ ++#ifndef __SAA716x_DMA_REG_H ++#define __SAA716x_DMA_REG_H ++ ++/* -------------- BAM Registers -------------- */ ++ ++#define BAM_VI0_0_DMA_BUF_MODE 0x000 ++ ++#define BAM_VI0_0_ADDR_OFFST_0 0x004 ++#define BAM_VI0_0_ADDR_OFFST_1 0x008 ++#define BAM_VI0_0_ADDR_OFFST_2 0x00c ++#define BAM_VI0_0_ADDR_OFFST_3 0x010 ++#define BAM_VI0_0_ADDR_OFFST_4 0x014 ++#define BAM_VI0_0_ADDR_OFFST_5 0x018 ++#define BAM_VI0_0_ADDR_OFFST_6 0x01c ++#define BAM_VI0_0_ADDR_OFFST_7 0x020 ++ ++#define BAM_VI0_1_DMA_BUF_MODE 0x024 ++#define BAM_VI0_1_ADDR_OFFST_0 0x028 ++#define BAM_VI0_1_ADDR_OFFST_1 0x02c ++#define BAM_VI0_1_ADDR_OFFST_2 0x030 ++#define BAM_VI0_1_ADDR_OFFST_3 0x034 ++#define BAM_VI0_1_ADDR_OFFST_4 0x038 ++#define BAM_VI0_1_ADDR_OFFST_5 0x03c ++#define BAM_VI0_1_ADDR_OFFST_6 0x040 ++#define BAM_VI0_1_ADDR_OFFST_7 0x044 ++ ++#define BAM_VI0_2_DMA_BUF_MODE 0x048 ++#define BAM_VI0_2_ADDR_OFFST_0 0x04c ++#define BAM_VI0_2_ADDR_OFFST_1 0x050 ++#define BAM_VI0_2_ADDR_OFFST_2 0x054 ++#define BAM_VI0_2_ADDR_OFFST_3 0x058 ++#define BAM_VI0_2_ADDR_OFFST_4 0x05c ++#define BAM_VI0_2_ADDR_OFFST_5 0x060 ++#define BAM_VI0_2_ADDR_OFFST_6 0x064 ++#define BAM_VI0_2_ADDR_OFFST_7 0x068 ++ ++ ++#define BAM_VI1_0_DMA_BUF_MODE 0x06c ++#define BAM_VI1_0_ADDR_OFFST_0 0x070 ++#define BAM_VI1_0_ADDR_OFFST_1 0x074 ++#define BAM_VI1_0_ADDR_OFFST_2 0x078 ++#define BAM_VI1_0_ADDR_OFFST_3 0x07c ++#define BAM_VI1_0_ADDR_OFFST_4 0x080 ++#define BAM_VI1_0_ADDR_OFFST_5 0x084 ++#define BAM_VI1_0_ADDR_OFFST_6 0x088 ++#define BAM_VI1_0_ADDR_OFFST_7 0x08c ++ ++#define BAM_VI1_1_DMA_BUF_MODE 0x090 ++#define BAM_VI1_1_ADDR_OFFST_0 0x094 ++#define BAM_VI1_1_ADDR_OFFST_1 0x098 ++#define BAM_VI1_1_ADDR_OFFST_2 0x09c ++#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 ++#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 ++#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 ++#define BAM_VI1_1_ADDR_OFFST_6 0x0ac ++#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 ++ ++#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 ++#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 ++#define BAM_VI1_2_ADDR_OFFST_1 0x0bc ++#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 ++#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 ++#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 ++#define BAM_VI1_2_ADDR_OFFST_5 0x0cc ++#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 ++#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 ++ ++ ++#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 ++#define BAM_FGPI0_ADDR_OFFST_0 0x0dc ++#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 ++#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 ++#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 ++#define BAM_FGPI0_ADDR_OFFST_4 0x0ec ++#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 ++#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 ++#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 ++ ++#define BAM_FGPI1_DMA_BUF_MODE 0x0fc ++#define BAM_FGPI1_ADDR_OFFST_0 0x100 ++#define BAM_FGPI1_ADDR_OFFST_1 0x104 ++#define BAM_FGPI1_ADDR_OFFST_2 0x108 ++#define BAM_FGPI1_ADDR_OFFST_3 0x10c ++#define BAM_FGPI1_ADDR_OFFST_4 0x110 ++#define BAM_FGPI1_ADDR_OFFST_5 0x114 ++#define BAM_FGPI1_ADDR_OFFST_6 0x118 ++#define BAM_FGPI1_ADDR_OFFST_7 0x11c ++ ++#define BAM_FGPI2_DMA_BUF_MODE 0x120 ++#define BAM_FGPI2_ADDR_OFFST_0 0x124 ++#define BAM_FGPI2_ADDR_OFFST_1 0x128 ++#define BAM_FGPI2_ADDR_OFFST_2 0x12c ++#define BAM_FGPI2_ADDR_OFFST_3 0x130 ++#define BAM_FGPI2_ADDR_OFFST_4 0x134 ++#define BAM_FGPI2_ADDR_OFFST_5 0x138 ++#define BAM_FGPI2_ADDR_OFFST_6 0x13c ++#define BAM_FGPI2_ADDR_OFFST_7 0x140 ++ ++#define BAM_FGPI3_DMA_BUF_MODE 0x144 ++#define BAM_FGPI3_ADDR_OFFST_0 0x148 ++#define BAM_FGPI3_ADDR_OFFST_1 0x14c ++#define BAM_FGPI3_ADDR_OFFST_2 0x150 ++#define BAM_FGPI3_ADDR_OFFST_3 0x154 ++#define BAM_FGPI3_ADDR_OFFST_4 0x158 ++#define BAM_FGPI3_ADDR_OFFST_5 0x15c ++#define BAM_FGPI3_ADDR_OFFST_6 0x160 ++#define BAM_FGPI3_ADDR_OFFST_7 0x164 ++ ++ ++#define BAM_AI0_DMA_BUF_MODE 0x168 ++#define BAM_AI0_ADDR_OFFST_0 0x16c ++#define BAM_AI0_ADDR_OFFST_1 0x170 ++#define BAM_AI0_ADDR_OFFST_2 0x174 ++#define BAM_AI0_ADDR_OFFST_3 0x178 ++#define BAM_AI0_ADDR_OFFST_4 0x17c ++#define BAM_AIO_ADDR_OFFST_5 0x180 ++#define BAM_AI0_ADDR_OFFST_6 0x184 ++#define BAM_AIO_ADDR_OFFST_7 0x188 ++ ++#define BAM_AI1_DMA_BUF_MODE 0x18c ++#define BAM_AI1_ADDR_OFFST_0 0x190 ++#define BAM_AI1_ADDR_OFFST_1 0x194 ++#define BAM_AI1_ADDR_OFFST_2 0x198 ++#define BAM_AI1_ADDR_OFFST_3 0x19c ++#define BAM_AI1_ADDR_OFFST_4 0x1a0 ++#define BAM_AI1_ADDR_OFFST_5 0x1a4 ++#define BAM_AI1_ADDR_OFFST_6 0x1a8 ++#define BAM_AI1_ADDR_OFFST_7 0x1ac ++ ++#define BAM_SW_RST 0xff0 ++#define BAM_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++ ++/* -------------- MMU Registers -------------- */ ++ ++#define MMU_MODE 0x000 ++ ++#define MMU_DMA_CONFIG0 0x004 ++#define MMU_DMA_CONFIG1 0x008 ++#define MMU_DMA_CONFIG2 0x00c ++#define MMU_DMA_CONFIG3 0x010 ++#define MMU_DMA_CONFIG4 0x014 ++#define MMU_DMA_CONFIG5 0x018 ++#define MMU_DMA_CONFIG6 0x01c ++#define MMU_DMA_CONFIG7 0x020 ++#define MMU_DMA_CONFIG8 0x024 ++#define MMU_DMA_CONFIG9 0x028 ++#define MMU_DMA_CONFIG10 0x02c ++#define MMU_DMA_CONFIG11 0x030 ++#define MMU_DMA_CONFIG12 0x034 ++#define MMU_DMA_CONFIG13 0x038 ++#define MMU_DMA_CONFIG14 0x03c ++#define MMU_DMA_CONFIG15 0x040 ++ ++#define MMU_SW_RST 0xff0 ++#define MMU_SW_RESET (0x0001 << 0) ++ ++#define MMU_PTA_BASE0 0x044 /* DMA 0 */ ++#define MMU_PTA_BASE1 0x084 /* DMA 1 */ ++#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ ++#define MMU_PTA_BASE3 0x104 /* DMA 3 */ ++#define MMU_PTA_BASE4 0x144 /* DMA 4 */ ++#define MMU_PTA_BASE5 0x184 /* DMA 5 */ ++#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ ++#define MMU_PTA_BASE7 0x204 /* DMA 7 */ ++#define MMU_PTA_BASE8 0x244 /* DMA 8 */ ++#define MMU_PTA_BASE9 0x284 /* DMA 9 */ ++#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ ++#define MMU_PTA_BASE11 0x304 /* DMA 11 */ ++#define MMU_PTA_BASE12 0x344 /* DMA 12 */ ++#define MMU_PTA_BASE13 0x384 /* DMA 13 */ ++#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ ++#define MMU_PTA_BASE15 0x404 /* DMA 15 */ ++ ++#define MMU_PTA_BASE 0x044 /* DMA 0 */ ++#define MMU_PTA_OFFSET 0x40 ++ ++#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) ++ ++#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 ++#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 ++#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 ++#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c ++#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 ++#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 ++#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 ++#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c ++#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 ++#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 ++#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 ++#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c ++#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 ++#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 ++#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 ++#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c ++ ++#endif /* __SAA716x_DMA_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_ff.h b/drivers/media/common/saa716x/saa716x_ff.h +new file mode 100644 +index 0000000..cb65929 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff.h +@@ -0,0 +1,158 @@ ++#ifndef __SAA716x_FF_H ++#define __SAA716x_FF_H ++ ++#include "dvb_filter.h" ++#include "dvb_ringbuffer.h" ++ ++#define TECHNOTREND 0x13c2 ++#define S2_6400_DUAL_S2_PREMIUM_DEVEL 0x3009 ++#define S2_6400_DUAL_S2_PREMIUM_PROD 0x300A ++ ++#define TT_PREMIUM_GPIO_POWER_ENABLE 27 ++#define TT_PREMIUM_GPIO_RESET_BACKEND 26 ++#define TT_PREMIUM_GPIO_FPGA_CS1 17 ++#define TT_PREMIUM_GPIO_FPGA_CS0 16 ++#define TT_PREMIUM_GPIO_FPGA_PROGRAMN 15 ++#define TT_PREMIUM_GPIO_FPGA_DONE 14 ++#define TT_PREMIUM_GPIO_FPGA_INITN 13 ++ ++/* fpga interrupt register addresses */ ++#define FPGA_ADDR_PHI_ICTRL 0x8000 /* PHI General control of the PC => STB interrupt controller */ ++#define FPGA_ADDR_PHI_ISR 0x8010 /* PHI Interrupt Status Register */ ++#define FPGA_ADDR_PHI_ISET 0x8020 /* PHI Interrupt Set Register */ ++#define FPGA_ADDR_PHI_ICLR 0x8030 /* PHI Interrupt Clear Register */ ++#define FPGA_ADDR_EMI_ICTRL 0x8100 /* EMI General control of the STB => PC interrupt controller */ ++#define FPGA_ADDR_EMI_ISR 0x8110 /* EMI Interrupt Status Register */ ++#define FPGA_ADDR_EMI_ISET 0x8120 /* EMI Interrupt Set Register */ ++#define FPGA_ADDR_EMI_ICLR 0x8130 /* EMI Interrupt Clear Register */ ++ ++/* fpga TS router register addresses */ ++#define FPGA_ADDR_TSR_CTRL 0x8200 /* TS router control register */ ++#define FPGA_ADDR_TSR_MUX1 0x8210 /* TS multiplexer 1 selection register */ ++#define FPGA_ADDR_TSR_MUX2 0x8220 /* TS multiplexer 2 selection register */ ++#define FPGA_ADDR_TSR_MUX3 0x8230 /* TS multiplexer 3 selection register */ ++#define FPGA_ADDR_TSR_MUXCI1 0x8240 /* TS multiplexer CI 1 selection register */ ++#define FPGA_ADDR_TSR_MUXCI2 0x8250 /* TS multiplexer CI 2 selection register */ ++ ++#define FPGA_ADDR_TSR_BRFE1 0x8280 /* bit rate for TS coming from frontend 1 */ ++#define FPGA_ADDR_TSR_BRFE2 0x8284 /* bit rate for TS coming from frontend 2 */ ++#define FPGA_ADDR_TSR_BRFF1 0x828C /* bit rate for TS coming from FIFO 1 */ ++#define FPGA_ADDR_TSR_BRO1 0x8294 /* bit rate for TS going to output 1 */ ++#define FPGA_ADDR_TSR_BRO2 0x8298 /* bit rate for TS going to output 2 */ ++#define FPGA_ADDR_TSR_BRO3 0x829C /* bit rate for TS going to output 3 */ ++ ++/* fpga TS FIFO register addresses */ ++#define FPGA_ADDR_FIFO_CTRL 0x8300 /* FIFO control register */ ++#define FPGA_ADDR_FIFO_STAT 0x8310 /* FIFO status register */ ++ ++#define FPGA_ADDR_VERSION 0x80F0 /* FPGA bitstream version register */ ++ ++#define FPGA_ADDR_PIO_CTRL 0x8500 /* FPGA GPIO control register */ ++ ++#define ISR_CMD_MASK 0x0001 /* interrupt source for normal cmds (osd, fre, av, ...) */ ++#define ISR_READY_MASK 0x0002 /* interrupt source for command acknowledge */ ++#define ISR_BLOCK_MASK 0x0004 /* interrupt source for single block transfers and acknowledge */ ++#define ISR_DATA_MASK 0x0008 /* interrupt source for data transfer acknowledge */ ++#define ISR_BOOT_FINISH_MASK 0x0010 /* interrupt source for boot finish indication */ ++#define ISR_AUDIO_PTS_MASK 0x0020 /* interrupt source for audio PTS */ ++#define ISR_VIDEO_PTS_MASK 0x0040 /* interrupt source for video PTS */ ++#define ISR_CURRENT_STC_MASK 0x0080 /* interrupt source for current system clock */ ++#define ISR_REMOTE_EVENT_MASK 0x0100 /* interrupt source for remote events */ ++#define ISR_DVO_FORMAT_MASK 0x0200 /* interrupt source for DVO format change */ ++#define ISR_OSD_CMD_MASK 0x0400 /* interrupt source for OSD cmds */ ++#define ISR_OSD_READY_MASK 0x0800 /* interrupt source for OSD command acknowledge */ ++#define ISR_FE_CMD_MASK 0x1000 /* interrupt source for frontend cmds */ ++#define ISR_FE_READY_MASK 0x2000 /* interrupt source for frontend command acknowledge */ ++#define ISR_LOG_MESSAGE_MASK 0x4000 /* interrupt source for log messages */ ++#define ISR_FIFO1_EMPTY_MASK 0x8000 /* interrupt source for FIFO1 empty */ ++ ++#define ADDR_CMD_DATA 0x0000 /* address for cmd data in fpga dpram */ ++#define ADDR_OSD_CMD_DATA 0x01A0 /* address for OSD cmd data */ ++#define ADDR_FE_CMD_DATA 0x05C0 /* address for frontend cmd data */ ++#define ADDR_BLOCK_DATA 0x0600 /* address for block data */ ++#define ADDR_AUDIO_PTS 0x3E00 /* address for audio PTS (64 Bits) */ ++#define ADDR_VIDEO_PTS 0x3E08 /* address for video PTS (64 Bits) */ ++#define ADDR_CURRENT_STC 0x3E10 /* address for system clock (64 Bits) */ ++#define ADDR_DVO_FORMAT 0x3E18 /* address for DVO format 32 Bits) */ ++#define ADDR_REMOTE_EVENT 0x3F00 /* address for remote events (32 Bits) */ ++#define ADDR_LOG_MESSAGE 0x3F80 /* address for log messages */ ++ ++#define SIZE_CMD_DATA 0x01A0 /* maximum size for command data (416 Bytes) */ ++#define SIZE_OSD_CMD_DATA 0x0420 /* maximum size for OSD command data (1056 Bytes) */ ++#define SIZE_FE_CMD_DATA 0x0040 /* maximum size for frontend command data (64 Bytes) */ ++#define SIZE_BLOCK_DATA 0x3800 /* maximum size for block data (14 kB) */ ++#define SIZE_LOG_MESSAGE_DATA 0x0080 /* maximum size for log message data (128 Bytes) */ ++ ++#define SIZE_BLOCK_HEADER 8 /* block header size */ ++ ++#define MAX_RESULT_LEN 256 ++#define MAX_DATA_LEN (1024 * 1024) ++ ++#define TSOUT_LEN (1024 * TS_SIZE) ++#define TSBUF_LEN (8 * 1024) ++ ++/* place to store all the necessary device information */ ++struct sti7109_dev { ++ struct saa716x_dev *dev; ++ struct dvb_device *osd_dev; ++ struct dvb_device *video_dev; ++ struct dvb_device *audio_dev; ++ ++ void *iobuf; /* memory for all buffers */ ++ struct dvb_ringbuffer tsout; /* buffer for TS output */ ++ u8 *tsbuf; /* temp ts buffer */ ++ ++ struct tasklet_struct fifo_tasklet; ++ ++ wait_queue_head_t boot_finish_wq; ++ int boot_finished; ++ ++ wait_queue_head_t cmd_ready_wq; ++ int cmd_ready; ++ u8 cmd_data[SIZE_CMD_DATA]; ++ u32 cmd_len; ++ ++ wait_queue_head_t result_avail_wq; ++ int result_avail; ++ u8 result_data[MAX_RESULT_LEN]; ++ u32 result_len; ++ u32 result_max_len; ++ ++ wait_queue_head_t osd_cmd_ready_wq; ++ int osd_cmd_ready; ++ u8 osd_cmd_data[SIZE_OSD_CMD_DATA]; ++ u32 osd_cmd_len; ++ ++ wait_queue_head_t osd_result_avail_wq; ++ int osd_result_avail; ++ u8 osd_result_data[MAX_RESULT_LEN]; ++ u32 osd_result_len; ++ u32 osd_result_max_len; ++ ++ u16 data_handle; ++ u8 *data_buffer; /* raw data transfer buffer */ ++ wait_queue_head_t data_ready_wq; ++ int data_ready; ++ wait_queue_head_t block_done_wq; ++ int block_done; ++ ++ struct mutex cmd_lock; ++ struct mutex osd_cmd_lock; ++ struct mutex data_lock; ++ ++ u64 audio_pts; ++ u64 video_pts; ++ u64 current_stc; ++ ++ u32 int_count_enable; ++ u32 total_int_count; ++ u32 fgpi_int_count[2]; ++ u32 i2c_int_count[2]; ++ u32 ext_int_total_count; ++ u32 ext_int_source_count[16]; ++ u32 last_int_ticks; ++ ++ u16 fpga_version; ++}; ++ ++#endif /* __SAA716x_FF_H */ +diff --git a/drivers/media/common/saa716x/saa716x_ff_cmd.c b/drivers/media/common/saa716x/saa716x_ff_cmd.c +new file mode 100644 +index 0000000..81c1078 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff_cmd.c +@@ -0,0 +1,412 @@ ++#include ++ ++#include ++#include ++ ++#include "saa716x_phi_reg.h" ++ ++#include "saa716x_phi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++#include "saa716x_ff.h" ++#include "saa716x_ff_cmd.h" ++ ++ ++int sti7109_cmd_init(struct sti7109_dev *sti7109) ++{ ++ mutex_init(&sti7109->cmd_lock); ++ mutex_init(&sti7109->osd_cmd_lock); ++ mutex_init(&sti7109->data_lock); ++ ++ init_waitqueue_head(&sti7109->boot_finish_wq); ++ sti7109->boot_finished = 0; ++ ++ init_waitqueue_head(&sti7109->cmd_ready_wq); ++ sti7109->cmd_ready = 0; ++ ++ init_waitqueue_head(&sti7109->result_avail_wq); ++ sti7109->result_avail = 0; ++ ++ init_waitqueue_head(&sti7109->osd_cmd_ready_wq); ++ sti7109->osd_cmd_ready = 0; ++ init_waitqueue_head(&sti7109->osd_result_avail_wq); ++ sti7109->osd_result_avail = 0; ++ ++ sti7109->data_handle = 0; ++ sti7109->data_buffer = (u8 *) (sti7109->iobuf + TSOUT_LEN + TSBUF_LEN); ++ init_waitqueue_head(&sti7109->data_ready_wq); ++ sti7109->data_ready = 0; ++ init_waitqueue_head(&sti7109->block_done_wq); ++ sti7109->block_done = 0; ++ return 0; ++} ++ ++static int sti7109_do_raw_cmd(struct sti7109_dev * sti7109) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->cmd_ready_wq, ++ sti7109->cmd_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->cmd_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "cmd ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for command ready"); ++ return -EIO; ++ } ++ ++ sti7109->cmd_ready = 0; ++ sti7109->result_avail = 0; ++ saa716x_phi_write(saa716x, ADDR_CMD_DATA, sti7109->cmd_data, ++ sti7109->cmd_len); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_CMD_MASK); ++ ++ if (sti7109->result_max_len > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout( ++ sti7109->result_avail_wq, ++ sti7109->result_avail == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->result_avail == 0) { ++ sti7109->result_len = 0; ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "result ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for command result"); ++ return -EIO; ++ } ++ ++ if (sti7109->result_len > sti7109->result_max_len) { ++ sti7109->result_len = sti7109->result_max_len; ++ dprintk(SAA716x_NOTICE, 1, ++ "not enough space in result buffer"); ++ } ++ } ++ ++ return 0; ++} ++ ++int sti7109_raw_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (cmd->cmd_len > SIZE_CMD_DATA) { ++ dprintk(SAA716x_ERROR, 1, "command too long"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->cmd_data, (void __user *)cmd->cmd_data, ++ cmd->cmd_len)) ++ goto out; ++ ++ sti7109->cmd_len = cmd->cmd_len; ++ sti7109->result_max_len = cmd->result_len; ++ ++ err = sti7109_do_raw_cmd(sti7109); ++ if (err) ++ goto out; ++ ++ cmd->result_len = sti7109->result_len; ++ if (sti7109->result_len > 0) { ++ if (copy_to_user((void __user *)cmd->result_data, ++ sti7109->result_data, ++ sti7109->result_len)) ++ err = -EFAULT; ++ } ++ ++out: ++ mutex_unlock(&sti7109->cmd_lock); ++ return err; ++} ++ ++static int sti7109_do_raw_osd_cmd(struct sti7109_dev * sti7109) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->osd_cmd_ready_wq, ++ sti7109->osd_cmd_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->osd_cmd_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "osd cmd ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for osd command ready"); ++ return -EIO; ++ } ++ ++ sti7109->osd_cmd_ready = 0; ++ sti7109->osd_result_avail = 0; ++ saa716x_phi_write(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_cmd_data, ++ sti7109->osd_cmd_len); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_OSD_CMD_MASK); ++ ++ if (sti7109->osd_result_max_len > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout( ++ sti7109->osd_result_avail_wq, ++ sti7109->osd_result_avail == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->osd_result_avail == 0) { ++ sti7109->osd_result_len = 0; ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, ++ "osd result ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for osd command result"); ++ return -EIO; ++ } ++ ++ if (sti7109->osd_result_len > sti7109->osd_result_max_len) { ++ sti7109->osd_result_len = sti7109->osd_result_max_len; ++ dprintk(SAA716x_NOTICE, 1, ++ "not enough space in result buffer"); ++ } ++ } ++ ++ return 0; ++} ++ ++int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (cmd->cmd_len > SIZE_OSD_CMD_DATA) { ++ dprintk(SAA716x_ERROR, 1, "command too long"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->osd_cmd_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->osd_cmd_data, (void __user *)cmd->cmd_data, ++ cmd->cmd_len)) ++ goto out; ++ ++ sti7109->osd_cmd_len = cmd->cmd_len; ++ sti7109->osd_result_max_len = cmd->result_len; ++ ++ err = sti7109_do_raw_osd_cmd(sti7109); ++ if (err) ++ goto out; ++ ++ cmd->result_len = sti7109->osd_result_len; ++ if (sti7109->osd_result_len > 0) { ++ if (copy_to_user((void __user *)cmd->result_data, ++ sti7109->osd_result_data, ++ sti7109->osd_result_len)) ++ err = -EFAULT; ++ } ++ ++out: ++ mutex_unlock(&sti7109->osd_cmd_lock); ++ return err; ++} ++ ++static int sti7109_do_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ unsigned long timeout; ++ u16 blockSize; ++ u16 lastBlockSize; ++ u16 numBlocks; ++ u16 blockIndex; ++ u8 blockHeader[SIZE_BLOCK_HEADER]; ++ u8 * blockPtr; ++ int activeBlock; ++ ++ timeout = 1 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->data_ready_wq, ++ sti7109->data_ready == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->data_ready == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ dprintk(SAA716x_ERROR, 1, "data ERESTARTSYS"); ++ return -ERESTARTSYS; ++ } ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for data ready"); ++ return -EIO; ++ } ++ ++ sti7109->data_ready = 0; ++ ++ /* ++ * 8 bytes is the size of the block header. Block header structure is: ++ * 16 bit - block index ++ * 16 bit - number of blocks ++ * 16 bit - current block data size ++ * 16 bit - block handle. This is used to reference the data in the ++ * command that uses it. ++ */ ++ blockSize = (SIZE_BLOCK_DATA / 2) - SIZE_BLOCK_HEADER; ++ numBlocks = data->data_length / blockSize; ++ lastBlockSize = data->data_length % blockSize; ++ if (lastBlockSize > 0) ++ numBlocks++; ++ ++ blockHeader[2] = (u8) (numBlocks >> 8); ++ blockHeader[3] = (u8) numBlocks; ++ blockHeader[6] = (u8) (sti7109->data_handle >> 8); ++ blockHeader[7] = (u8) sti7109->data_handle; ++ blockPtr = sti7109->data_buffer; ++ activeBlock = 0; ++ for (blockIndex = 0; blockIndex < numBlocks; blockIndex++) { ++ u32 addr; ++ ++ if (lastBlockSize && (blockIndex == (numBlocks - 1))) ++ blockSize = lastBlockSize; ++ ++ blockHeader[0] = (uint8_t) (blockIndex >> 8); ++ blockHeader[1] = (uint8_t) blockIndex; ++ blockHeader[4] = (uint8_t) (blockSize >> 8); ++ blockHeader[5] = (uint8_t) blockSize; ++ ++ addr = ADDR_BLOCK_DATA + activeBlock * (SIZE_BLOCK_DATA / 2); ++ saa716x_phi_write(saa716x, addr, blockHeader, ++ SIZE_BLOCK_HEADER); ++ saa716x_phi_write(saa716x, addr + SIZE_BLOCK_HEADER, blockPtr, ++ blockSize); ++ activeBlock = (activeBlock + 1) & 1; ++ if (blockIndex > 0) { ++ timeout = 1 * HZ; ++ timeout = wait_event_timeout(sti7109->block_done_wq, ++ sti7109->block_done == 1, ++ timeout); ++ ++ if (sti7109->block_done == 0) { ++ dprintk(SAA716x_ERROR, 1, ++ "timed out waiting for block done"); ++ return -EIO; ++ } ++ } ++ sti7109->block_done = 0; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_BLOCK_MASK); ++ blockPtr += blockSize; ++ } ++ timeout = 1 * HZ; ++ timeout = wait_event_timeout(sti7109->block_done_wq, ++ sti7109->block_done == 1, ++ timeout); ++ ++ if (sti7109->block_done == 0) { ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for block done"); ++ return -EIO; ++ } ++ sti7109->block_done = 0; ++ ++ data->data_handle = sti7109->data_handle; ++ sti7109->data_handle++; ++ return 0; ++} ++ ++int sti7109_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) ++{ ++ struct saa716x_dev * saa716x = sti7109->dev; ++ int err; ++ ++ if (data->data_length > MAX_DATA_LEN) { ++ dprintk(SAA716x_ERROR, 1, "data too big"); ++ return -EFAULT; ++ } ++ ++ mutex_lock(&sti7109->data_lock); ++ ++ err = -EFAULT; ++ if (copy_from_user(sti7109->data_buffer, ++ (void __user *)data->data_buffer, ++ data->data_length)) ++ goto out; ++ ++ err = sti7109_do_raw_data(sti7109, data); ++ if (err) ++ goto out; ++ ++out: ++ mutex_unlock(&sti7109->data_lock); ++ return err; ++} ++ ++int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, u32 *fw_version) ++{ ++ int ret_val = -EINVAL; ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ sti7109->cmd_data[0] = 0x00; ++ sti7109->cmd_data[1] = 0x04; ++ sti7109->cmd_data[2] = 0x00; ++ sti7109->cmd_data[3] = 0x00; ++ sti7109->cmd_data[4] = 0x00; ++ sti7109->cmd_data[5] = 0x00; ++ sti7109->cmd_len = 6; ++ sti7109->result_max_len = MAX_RESULT_LEN; ++ ++ ret_val = sti7109_do_raw_cmd(sti7109); ++ if (ret_val == 0) { ++ *fw_version = (sti7109->result_data[6] << 16) ++ | (sti7109->result_data[7] << 8) ++ | sti7109->result_data[8]; ++ } ++ ++ mutex_unlock(&sti7109->cmd_lock); ++ ++ return ret_val; ++} ++ ++int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, video_size_t *vs) ++{ ++ int ret_val = -EINVAL; ++ ++ mutex_lock(&sti7109->cmd_lock); ++ ++ sti7109->cmd_data[0] = 0x00; ++ sti7109->cmd_data[1] = 0x05; /* command length */ ++ sti7109->cmd_data[2] = 0x00; ++ sti7109->cmd_data[3] = 0x01; /* A/V decoder command group */ ++ sti7109->cmd_data[4] = 0x00; ++ sti7109->cmd_data[5] = 0x10; /* get video format info command */ ++ sti7109->cmd_data[6] = 0x00; /* decoder index 0 */ ++ sti7109->cmd_len = 7; ++ sti7109->result_max_len = MAX_RESULT_LEN; ++ ++ ret_val = sti7109_do_raw_cmd(sti7109); ++ if (ret_val == 0) { ++ vs->w = (sti7109->result_data[7] << 8) ++ | sti7109->result_data[8]; ++ vs->h = (sti7109->result_data[9] << 8) ++ | sti7109->result_data[10]; ++ vs->aspect_ratio = sti7109->result_data[11] >> 4; ++ } ++ ++ mutex_unlock(&sti7109->cmd_lock); ++ ++ return ret_val; ++} ++ +diff --git a/drivers/media/common/saa716x/saa716x_ff_cmd.h b/drivers/media/common/saa716x/saa716x_ff_cmd.h +new file mode 100644 +index 0000000..fc79f08 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff_cmd.h +@@ -0,0 +1,16 @@ ++#ifndef __SAA716x_FF_CMD_H ++#define __SAA716x_FF_CMD_H ++ ++extern int sti7109_cmd_init(struct sti7109_dev *sti7109); ++extern int sti7109_raw_cmd(struct sti7109_dev * sti7109, ++ osd_raw_cmd_t * cmd); ++extern int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, ++ osd_raw_cmd_t * cmd); ++extern int sti7109_raw_data(struct sti7109_dev * sti7109, ++ osd_raw_data_t * data); ++extern int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, ++ u32 *fw_version); ++extern int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, ++ video_size_t *vs); ++ ++#endif /* __SAA716x_FF_CMD_H */ +diff --git a/drivers/media/common/saa716x/saa716x_ff_ir.c b/drivers/media/common/saa716x/saa716x_ff_ir.c +new file mode 100644 +index 0000000..3562478 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff_ir.c +@@ -0,0 +1,265 @@ ++/* ++ * Driver for the remote control of the TT6400 DVB-S2 card ++ * ++ * Copyright (C) 2010 Oliver Endriss ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version 2 ++ * of the License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html ++ * ++ */ ++ ++#include ++#include ++ ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++#include "saa716x_ff.h" ++ ++ ++/* infrared remote control */ ++struct infrared { ++ u16 key_map[128]; ++ struct input_dev *input_dev; ++ char input_phys[32]; ++ struct timer_list keyup_timer; ++ struct tasklet_struct tasklet; ++ u32 command; ++ u32 device_mask; ++ u8 protocol; ++ u16 last_key; ++ u16 last_toggle; ++ bool delay_timer_finished; ++}; ++ ++#define IR_RC5 0 ++#define UP_TIMEOUT (HZ*7/25) ++ ++ ++/* key-up timer */ ++static void ir_emit_keyup(unsigned long parm) ++{ ++ struct infrared *ir = (struct infrared *) parm; ++ ++ if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) ++ return; ++ ++ input_report_key(ir->input_dev, ir->last_key, 0); ++ input_sync(ir->input_dev); ++} ++ ++ ++/* tasklet */ ++static void ir_emit_key(unsigned long parm) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) parm; ++ struct infrared *ir = saa716x->ir_priv; ++ u32 ircom = ir->command; ++ u8 data; ++ u8 addr; ++ u16 toggle; ++ u16 keycode; ++ ++ /* extract device address and data */ ++ if (ircom & 0x80000000) { /* CEC remote command */ ++ addr = 0; ++ data = ircom & 0x7F; ++ toggle = 0; ++ } else { ++ switch (ir->protocol) { ++ case IR_RC5: /* extended RC5: 5 bits device address, 7 bits data */ ++ addr = (ircom >> 6) & 0x1f; ++ /* data bits 1..6 */ ++ data = ircom & 0x3f; ++ /* data bit 7 (inverted) */ ++ if (!(ircom & 0x1000)) ++ data |= 0x40; ++ toggle = ircom & 0x0800; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: invalid protocol %x\n", ++ __func__, ir->protocol); ++ return; ++ } ++ } ++ ++ input_event(ir->input_dev, EV_MSC, MSC_RAW, (addr << 16) | data); ++ input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); ++ ++ keycode = ir->key_map[data]; ++ ++ dprintk(SAA716x_DEBUG, 0, ++ "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n", ++ __func__, ircom, addr, data, keycode); ++ ++ /* check device address */ ++ if (!(ir->device_mask & (1 << addr))) ++ return; ++ ++ if (!keycode) { ++ printk(KERN_WARNING "%s: code %08x -> addr %i data 0x%02x -> unknown key!\n", ++ __func__, ircom, addr, data); ++ return; ++ } ++ ++ if (timer_pending(&ir->keyup_timer)) { ++ del_timer(&ir->keyup_timer); ++ if (ir->last_key != keycode || toggle != ir->last_toggle) { ++ ir->delay_timer_finished = false; ++ input_event(ir->input_dev, EV_KEY, ir->last_key, 0); ++ input_event(ir->input_dev, EV_KEY, keycode, 1); ++ input_sync(ir->input_dev); ++ } else if (ir->delay_timer_finished) { ++ input_event(ir->input_dev, EV_KEY, keycode, 2); ++ input_sync(ir->input_dev); ++ } ++ } else { ++ ir->delay_timer_finished = false; ++ input_event(ir->input_dev, EV_KEY, keycode, 1); ++ input_sync(ir->input_dev); ++ } ++ ++ ir->last_key = keycode; ++ ir->last_toggle = toggle; ++ ++ ir->keyup_timer.expires = jiffies + UP_TIMEOUT; ++ add_timer(&ir->keyup_timer); ++ ++} ++ ++ ++/* register with input layer */ ++static void ir_register_keys(struct infrared *ir) ++{ ++ int i; ++ ++ set_bit(EV_KEY, ir->input_dev->evbit); ++ set_bit(EV_REP, ir->input_dev->evbit); ++ set_bit(EV_MSC, ir->input_dev->evbit); ++ ++ set_bit(MSC_RAW, ir->input_dev->mscbit); ++ set_bit(MSC_SCAN, ir->input_dev->mscbit); ++ ++ memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); ++ ++ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) { ++ if (ir->key_map[i] > KEY_MAX) ++ ir->key_map[i] = 0; ++ else if (ir->key_map[i] > KEY_RESERVED) ++ set_bit(ir->key_map[i], ir->input_dev->keybit); ++ } ++ ++ ir->input_dev->keycode = ir->key_map; ++ ir->input_dev->keycodesize = sizeof(ir->key_map[0]); ++ ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); ++} ++ ++ ++/* called by the input driver after rep[REP_DELAY] ms */ ++static void ir_repeat_key(unsigned long parm) ++{ ++ struct infrared *ir = (struct infrared *) parm; ++ ++ ir->delay_timer_finished = true; ++} ++ ++ ++/* interrupt handler */ ++void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd) ++{ ++ struct infrared *ir = saa716x->ir_priv; ++ ++ if (!ir) ++ return; ++ ++ ir->command = ir_cmd; ++ tasklet_schedule(&ir->tasklet); ++} ++ ++ ++int saa716x_ir_init(struct saa716x_dev *saa716x) ++{ ++ struct input_dev *input_dev; ++ struct infrared *ir; ++ int rc; ++ int i; ++ ++ if (!saa716x) ++ return -ENOMEM; ++ ++ ir = kzalloc(sizeof(struct infrared), GFP_KERNEL); ++ if (!ir) ++ return -ENOMEM; ++ ++ init_timer(&ir->keyup_timer); ++ ir->keyup_timer.function = ir_emit_keyup; ++ ir->keyup_timer.data = (unsigned long) ir; ++ ++ input_dev = input_allocate_device(); ++ if (!input_dev) ++ goto err; ++ ++ ir->input_dev = input_dev; ++ input_dev->name = "TT6400 DVB IR receiver"; ++ snprintf(ir->input_phys, sizeof(ir->input_phys), ++ "pci-%s/ir0", pci_name(saa716x->pdev)); ++ input_dev->phys = ir->input_phys; ++ input_dev->id.bustype = BUS_PCI; ++ input_dev->id.version = 1; ++ input_dev->id.vendor = saa716x->pdev->subsystem_vendor; ++ input_dev->id.product = saa716x->pdev->subsystem_device; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) ++ input_dev->dev.parent = &saa716x->pdev->dev; ++#else ++ input_dev->cdev.dev = &saa716x->pdev->dev; ++#endif ++ rc = input_register_device(input_dev); ++ if (rc) ++ goto err; ++ ++ /* TODO: fix setup/keymap */ ++ ir->protocol = IR_RC5; ++ ir->device_mask = 0xffffffff; ++ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) ++ ir->key_map[i] = i+1; ++ ir_register_keys(ir); ++ ++ /* override repeat timer */ ++ input_dev->timer.function = ir_repeat_key; ++ input_dev->timer.data = (unsigned long) ir; ++ ++ tasklet_init(&ir->tasklet, ir_emit_key, (unsigned long) saa716x); ++ saa716x->ir_priv = ir; ++ ++ return 0; ++ ++err: ++ if (ir->input_dev) ++ input_free_device(ir->input_dev); ++ kfree(ir); ++ return -ENOMEM; ++} ++ ++ ++void saa716x_ir_exit(struct saa716x_dev *saa716x) ++{ ++ struct infrared *ir = saa716x->ir_priv; ++ ++ saa716x->ir_priv = NULL; ++ tasklet_kill(&ir->tasklet); ++ del_timer_sync(&ir->keyup_timer); ++ input_unregister_device(ir->input_dev); ++ kfree(ir); ++} +diff --git a/drivers/media/common/saa716x/saa716x_ff_main.c b/drivers/media/common/saa716x/saa716x_ff_main.c +new file mode 100644 +index 0000000..34093c2 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_ff_main.c +@@ -0,0 +1,1535 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_dma_reg.h" ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_phi_reg.h" ++#include "saa716x_spi_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_vip.h" ++#include "saa716x_aip.h" ++#include "saa716x_msi.h" ++#include "saa716x_adap.h" ++#include "saa716x_gpio.h" ++#include "saa716x_phi.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "saa716x_ff.h" ++#include "saa716x_ff_cmd.h" ++ ++#include "stv6110x.h" ++#include "stv090x.h" ++#include "isl6423.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++unsigned int int_count_enable; ++module_param(int_count_enable, int, 0644); ++MODULE_PARM_DESC(int_count_enable, "enable counting of interrupts"); ++ ++#define DRIVER_NAME "SAA716x FF" ++ ++static int saa716x_ff_fpga_init(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ int fpgaInit; ++ int fpgaDone; ++ int rounds; ++ int ret; ++ const struct firmware *fw; ++ ++ /* request the FPGA firmware, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-fpga-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load FPGA firmware," ++ " file not found: dvb-ttpremium-fpga-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ ++ /* set FPGA PROGRAMN high */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); ++ msleep(10); ++ ++ /* set FPGA PROGRAMN low to set it into configuration mode */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 0); ++ msleep(10); ++ ++ /* set FPGA PROGRAMN high to start configuration process */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); ++ ++ rounds = 0; ++ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ while (fpgaInit == 0 && rounds < 5000) { ++ //msleep(1); ++ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ rounds++; ++ } ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA INITN=%d, rounds=%d", ++ fpgaInit, rounds); ++ ++ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, 0x08); ++ SAA716x_EPWR(SPI, SPI_CONTROL_REG, SPI_MODE_SELECT); ++ ++ msleep(10); ++ ++ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream"); ++ saa716x_spi_write(saa716x, fw->data, fw->size); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream done"); ++ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); ++ ++ msleep(10); ++ ++ release_firmware(fw); ++ ++ if (!fpgaDone) { ++ printk(KERN_ERR "SAA716x FF FPGA is not responding, did you " ++ "connect the power supply?\n"); ++ return -EINVAL; ++ } ++ ++ sti7109->fpga_version = SAA716x_EPRD(PHI_1, FPGA_ADDR_VERSION); ++ printk(KERN_INFO "SAA716x FF FPGA version %X.%02X\n", ++ sti7109->fpga_version >> 8, sti7109->fpga_version & 0xFF); ++ ++ return 0; ++} ++ ++static int saa716x_ff_st7109_init(struct saa716x_dev *saa716x) ++{ ++ int i; ++ int length; ++ u32 requestedBlock; ++ u32 writtenBlock; ++ u32 numBlocks; ++ u32 blockSize; ++ u32 lastBlockSize; ++ u64 startTime; ++ u64 currentTime; ++ u64 waitTime; ++ int ret; ++ const struct firmware *fw; ++ u32 loaderVersion; ++ ++ /* request the st7109 loader, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-loader-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 loader," ++ " file not found: dvb-ttpremium-loader-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ loaderVersion = (fw->data[0x1385] << 8) | fw->data[0x1384]; ++ printk(KERN_INFO "SAA716x FF loader version %X.%02X\n", ++ loaderVersion >> 8, loaderVersion & 0xFF); ++ ++ saa716x_phi_write(saa716x, 0, fw->data, fw->size); ++ msleep(10); ++ ++ release_firmware(fw); ++ ++ /* take ST out of reset */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 1); ++ ++ startTime = jiffies; ++ waitTime = 0; ++ do { ++ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); ++ if (requestedBlock == 1) ++ break; ++ ++ currentTime = jiffies; ++ waitTime = currentTime - startTime; ++ } while (waitTime < (1 * HZ)); ++ ++ if (waitTime >= 1 * HZ) { ++ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); ++ return -1; ++ } ++ dprintk(SAA716x_INFO, 1, "STi7109 ready after %llu ticks", waitTime); ++ ++ /* request the st7109 firmware, this will block until someone uploads it */ ++ ret = request_firmware(&fw, "dvb-ttpremium-st7109-01.fw", &saa716x->pdev->dev); ++ if (ret) { ++ if (ret == -ENOENT) { ++ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 firmware," ++ " file not found: dvb-ttpremium-st7109-01.fw\n"); ++ printk(KERN_ERR "dvb-ttpremium: usually this should be in " ++ "/usr/lib/hotplug/firmware or /lib/firmware\n"); ++ } else ++ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" ++ " (error %i)\n", ret); ++ return -EINVAL; ++ } ++ ++ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware"); ++ writtenBlock = 0; ++ blockSize = 0x3c00; ++ length = fw->size; ++ numBlocks = length / blockSize; ++ lastBlockSize = length % blockSize; ++ for (i = 0; i < length; i += blockSize) { ++ writtenBlock++; ++ /* write one block (last may differ from blockSize) */ ++ if (lastBlockSize && writtenBlock == (numBlocks + 1)) ++ saa716x_phi_write(saa716x, 0, &fw->data[i], lastBlockSize); ++ else ++ saa716x_phi_write(saa716x, 0, &fw->data[i], blockSize); ++ ++ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); ++ startTime = jiffies; ++ waitTime = 0; ++ do { ++ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); ++ if (requestedBlock == (writtenBlock + 1)) ++ break; ++ ++ currentTime = jiffies; ++ waitTime = currentTime - startTime; ++ } while (waitTime < (1 * HZ)); ++ ++ if (waitTime >= 1 * HZ) { ++ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); ++ release_firmware(fw); ++ return -1; ++ } ++ } ++ ++ /* disable frontend support through ST firmware */ ++ SAA716x_EPWR(PHI_1, 0x3ff4, 1); ++ ++ /* indicate end of transfer */ ++ writtenBlock++; ++ writtenBlock |= 0x80000000; ++ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); ++ ++ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware done"); ++ ++ release_firmware(fw); ++ ++ return 0; ++} ++ ++static int saa716x_usercopy(struct dvb_device *dvbdev, ++ unsigned int cmd, unsigned long arg, ++ int (*func)(struct dvb_device *dvbdev, ++ unsigned int cmd, void *arg)) ++{ ++ char sbuf[128]; ++ void *mbuf = NULL; ++ void *parg = NULL; ++ int err = -EINVAL; ++ ++ /* Copy arguments into temp kernel buffer */ ++ switch (_IOC_DIR(cmd)) { ++ case _IOC_NONE: ++ /* ++ * For this command, the pointer is actually an integer ++ * argument. ++ */ ++ parg = (void *) arg; ++ break; ++ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ ++ case _IOC_WRITE: ++ case (_IOC_WRITE | _IOC_READ): ++ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { ++ parg = sbuf; ++ } else { ++ /* too big to allocate from stack */ ++ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); ++ if (NULL == mbuf) ++ return -ENOMEM; ++ parg = mbuf; ++ } ++ ++ err = -EFAULT; ++ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) ++ goto out; ++ break; ++ } ++ ++ /* call driver */ ++ if ((err = func(dvbdev, cmd, parg)) == -ENOIOCTLCMD) ++ err = -EINVAL; ++ ++ if (err < 0) ++ goto out; ++ ++ /* Copy results into user buffer */ ++ switch (_IOC_DIR(cmd)) ++ { ++ case _IOC_READ: ++ case (_IOC_WRITE | _IOC_READ): ++ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ break; ++ } ++ ++out: ++ kfree(mbuf); ++ return err; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_osd_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_osd_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ int err = -EINVAL; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ if (cmd == OSD_RAW_CMD) { ++ osd_raw_cmd_t raw_cmd; ++ u8 hdr[4]; ++ ++ err = -EFAULT; ++ if (copy_from_user(&raw_cmd, (void __user *)arg, ++ _IOC_SIZE(cmd))) ++ goto out; ++ ++ if (copy_from_user(hdr, (void __user *)raw_cmd.cmd_data, 4)) ++ goto out; ++ ++ if (hdr[3] == 4) ++ err = sti7109_raw_osd_cmd(sti7109, &raw_cmd); ++ else ++ err = sti7109_raw_cmd(sti7109, &raw_cmd); ++ ++ if (err) ++ goto out; ++ ++ if (copy_to_user((void __user *)arg, &raw_cmd, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ } ++ else if (cmd == OSD_RAW_DATA) { ++ osd_raw_data_t raw_data; ++ ++ err = -EFAULT; ++ if (copy_from_user(&raw_data, (void __user *)arg, ++ _IOC_SIZE(cmd))) ++ goto out; ++ ++ err = sti7109_raw_data(sti7109, &raw_data); ++ if (err) ++ goto out; ++ ++ if (copy_to_user((void __user *)arg, &raw_data, _IOC_SIZE(cmd))) ++ err = -EFAULT; ++ } ++ ++out: ++ return err; ++} ++ ++static struct file_operations dvb_osd_fops = { ++ .owner = THIS_MODULE, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_osd_ioctl, ++#else ++ .unlocked_ioctl = dvb_osd_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++}; ++ ++static struct dvb_device dvbdev_osd = { ++ .priv = NULL, ++ .users = 2, ++ .writers = 2, ++ .fops = &dvb_osd_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_osd_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_unregister_device(sti7109->osd_dev); ++ return 0; ++} ++ ++static int saa716x_ff_osd_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->osd_dev, ++ &dvbdev_osd, ++ sti7109, ++ DVB_DEVICE_OSD); ++ ++ return 0; ++} ++ ++static int do_dvb_audio_ioctl(struct dvb_device *dvbdev, ++ unsigned int cmd, void *parg) ++{ ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ //struct saa716x_dev *saa716x = sti7109->dev; ++ int ret = 0; ++ ++ switch (cmd) { ++ case AUDIO_GET_PTS: ++ { ++ *(u64 *)parg = sti7109->audio_pts; ++ break; ++ } ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_audio_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_audio_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_audio_ioctl); ++} ++ ++static struct file_operations dvb_audio_fops = { ++ .owner = THIS_MODULE, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_audio_ioctl, ++#else ++ .unlocked_ioctl = dvb_audio_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++}; ++ ++static struct dvb_device dvbdev_audio = { ++ .priv = NULL, ++ .users = 1, ++ .writers = 1, ++ .fops = &dvb_audio_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_audio_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_unregister_device(sti7109->audio_dev); ++ return 0; ++} ++ ++static int saa716x_ff_audio_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->audio_dev, ++ &dvbdev_audio, ++ sti7109, ++ DVB_DEVICE_AUDIO); ++ ++ return 0; ++} ++ ++static void fifo_worker(unsigned long data) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) data; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ u32 fifoCtrl; ++ u32 fifoStat; ++ u16 fifoSize; ++ u16 fifoUsage; ++ u16 fifoFree; ++ int len; ++ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoStat = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_STAT); ++ fifoSize = (u16) (fifoStat >> 16); ++ fifoUsage = (u16) fifoStat; ++ fifoFree = fifoSize - fifoUsage; ++ spin_lock(&sti7109->tsout.lock); ++ len = dvb_ringbuffer_avail(&sti7109->tsout); ++ if (len > fifoFree) ++ len = fifoFree; ++ if (len >= TS_SIZE) ++ { ++ while (len >= TS_SIZE) ++ { ++ dvb_ringbuffer_read(&sti7109->tsout, sti7109->tsbuf, (size_t) TS_SIZE); ++ saa716x_phi_write_fifo(saa716x, sti7109->tsbuf, TS_SIZE); ++ len -= TS_SIZE; ++ } ++ wake_up(&sti7109->tsout.queue); ++ fifoCtrl |= 0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ } ++ spin_unlock(&sti7109->tsout.lock); ++} ++ ++#define FREE_COND_TS (dvb_ringbuffer_free(&sti7109->tsout) >= TS_SIZE) ++ ++static ssize_t dvb_video_write(struct file *file, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct saa716x_dev *saa716x = sti7109->dev; ++ unsigned long todo = count; ++ ++ if ((file->f_flags & O_ACCMODE) == O_RDONLY) ++ return -EPERM; ++/* ++ if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) ++ return -EPERM; ++*/ ++ if ((file->f_flags & O_NONBLOCK) && !FREE_COND_TS) ++ return -EWOULDBLOCK; ++ ++ while (todo >= TS_SIZE) { ++ if (!FREE_COND_TS) { ++ if (file->f_flags & O_NONBLOCK) ++ break; ++ if (wait_event_interruptible(sti7109->tsout.queue, FREE_COND_TS)) ++ break; ++ } ++ dvb_ringbuffer_write(&sti7109->tsout, buf, TS_SIZE); ++ todo -= TS_SIZE; ++ buf += TS_SIZE; ++ } ++ ++ if (count > todo) { ++ u32 fifoCtrl; ++ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl |= 0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ } ++ ++ return count - todo; ++} ++ ++static unsigned int dvb_video_poll(struct file *file, poll_table *wait) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ unsigned int mask = 0; ++ ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) ++ poll_wait(file, &sti7109->tsout.queue, wait); ++ ++ if ((file->f_flags & O_ACCMODE) != O_RDONLY) { ++ if (1/*sti7109->playing*/) { ++ if (FREE_COND_TS) ++ mask |= (POLLOUT | POLLWRNORM); ++ } else /* if not playing: may play if asked for */ ++ mask |= (POLLOUT | POLLWRNORM); ++ } ++ ++ return mask; ++} ++ ++static int do_dvb_video_ioctl(struct dvb_device *dvbdev, ++ unsigned int cmd, void *parg) ++{ ++ struct sti7109_dev *sti7109 = dvbdev->priv; ++ struct saa716x_dev *saa716x = sti7109->dev; ++ int ret = 0; ++ ++ switch (cmd) { ++ case VIDEO_SELECT_SOURCE: ++ { ++ video_stream_source_t stream_source; ++ ++ stream_source = (video_stream_source_t) parg; ++ if (stream_source == VIDEO_SOURCE_DEMUX) { ++ /* stop and reset FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); ++ } ++ else { ++ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); ++ /* reset FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); ++ /* start FIFO 1 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 2); ++ } ++ break; ++ } ++ case VIDEO_CLEAR_BUFFER: ++ { ++ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); ++ break; ++ } ++ case VIDEO_GET_PTS: ++ { ++ *(u64 *)parg = sti7109->video_pts; ++ break; ++ } ++ case VIDEO_GET_SIZE: ++ { ++ ret = sti7109_cmd_get_video_format(sti7109, (video_size_t *) parg); ++ break; ++ } ++ default: ++ ret = -ENOIOCTLCMD; ++ break; ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++static int dvb_video_ioctl(struct inode *inode, struct file *file, ++#else ++static long dvb_video_ioctl(struct file *file, ++#endif ++ unsigned int cmd, unsigned long arg) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ ++ if (!dvbdev) ++ return -ENODEV; ++ ++ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_video_ioctl); ++} ++ ++static struct file_operations dvb_video_fops = { ++ .owner = THIS_MODULE, ++ .write = dvb_video_write, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) ++ .ioctl = dvb_video_ioctl, ++#else ++ .unlocked_ioctl = dvb_video_ioctl, ++#endif ++ .open = dvb_generic_open, ++ .release = dvb_generic_release, ++ .poll = dvb_video_poll, ++}; ++ ++static struct dvb_device dvbdev_video = { ++ .priv = NULL, ++ .users = 1, ++ .writers = 1, ++ .fops = &dvb_video_fops, ++ .kernel_ioctl = NULL, ++}; ++ ++static int saa716x_ff_video_exit(struct saa716x_dev *saa716x) ++{ ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ tasklet_kill(&sti7109->fifo_tasklet); ++ dvb_unregister_device(sti7109->video_dev); ++ return 0; ++} ++ ++static int saa716x_ff_video_init(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ dvb_ringbuffer_init(&sti7109->tsout, sti7109->iobuf, TSOUT_LEN); ++ sti7109->tsbuf = (u8 *) (sti7109->iobuf + TSOUT_LEN); ++ ++ dvb_register_device(&saa716x_adap->dvb_adapter, ++ &sti7109->video_dev, ++ &dvbdev_video, ++ sti7109, ++ DVB_DEVICE_VIDEO); ++ ++ tasklet_init(&sti7109->fifo_tasklet, fifo_worker, ++ (unsigned long)saa716x); ++ ++ return 0; ++} ++ ++static int saa716x_ff_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ struct sti7109_dev *sti7109; ++ int err = 0; ++ u32 value; ++ unsigned long timeout; ++ u32 fw_version; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ err = saa716x_phi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PHI Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ /* prepare the sti7109 device struct */ ++ sti7109 = kzalloc(sizeof(struct sti7109_dev), GFP_KERNEL); ++ if (!sti7109) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x: out of memory"); ++ goto fail3; ++ } ++ ++ sti7109->dev = saa716x; ++ ++ sti7109->iobuf = vmalloc(TSOUT_LEN + TSBUF_LEN + MAX_DATA_LEN); ++ if (!sti7109->iobuf) ++ goto fail4; ++ ++ sti7109_cmd_init(sti7109); ++ ++ sti7109->int_count_enable = int_count_enable; ++ sti7109->total_int_count = 0; ++ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); ++ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); ++ sti7109->ext_int_total_count = 0; ++ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); ++ sti7109->last_int_ticks = jiffies; ++ ++ saa716x->priv = sti7109; ++ ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS0); ++ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS0, 1); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS1); ++ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS1, 1); ++ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN); ++ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); ++ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); ++ ++ /* hold ST in reset */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 0); ++ ++ /* enable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 1); ++ msleep(100); ++ ++ err = saa716x_ff_fpga_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF FPGA Initialization failed"); ++ goto fail5; ++ } ++ ++ /* configure TS muxer */ ++ if (sti7109->fpga_version < 0x110) { ++ /* select FIFO 1 for TS mux 3 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 4); ++ } else { ++ /* select FIFO 1 for TS mux 3 */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 1); ++ } ++ ++ /* enable interrupts from ST7109 -> PC */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICTRL, 0x3); ++ ++ value = SAA716x_EPRD(MSI, MSI_CONFIG33); ++ value &= 0xFCFFFFFF; ++ value |= MSI_INT_POL_EDGE_FALL; ++ SAA716x_EPWR(MSI, MSI_CONFIG33, value); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_EXTINT_0); ++ ++ /* enable tuner reset */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 0); ++ msleep(50); ++ /* disable tuner reset */ ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 1); ++ ++ err = saa716x_ff_st7109_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF STi7109 initialization failed"); ++ goto fail5; ++ } ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ /* enable FGPI2 and FGPI3 for TS inputs */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x0689F04); ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x280); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail6; ++ } ++ ++ /* wait a maximum of 10 seconds for the STi7109 to boot */ ++ timeout = 10 * HZ; ++ timeout = wait_event_interruptible_timeout(sti7109->boot_finish_wq, ++ sti7109->boot_finished == 1, ++ timeout); ++ ++ if (timeout == -ERESTARTSYS || sti7109->boot_finished == 0) { ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ goto fail6; ++ } ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for boot finish"); ++ err = -1; ++ goto fail6; ++ } ++ dprintk(SAA716x_INFO, 1, "STi7109 finished booting"); ++ ++ err = saa716x_ff_video_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF VIDEO initialization failed"); ++ goto fail7; ++ } ++ ++ err = saa716x_ff_audio_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF AUDIO initialization failed"); ++ goto fail8; ++ } ++ ++ err = saa716x_ff_osd_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x FF OSD initialization failed"); ++ goto fail9; ++ } ++ ++ err = sti7109_cmd_get_fw_version(sti7109, &fw_version); ++ if (!err) { ++ printk(KERN_INFO "SAA716x FF firmware version %X.%X.%X\n", ++ (fw_version >> 16) & 0xFF, (fw_version >> 8) & 0xFF, ++ fw_version & 0xFF); ++ } ++ ++ err = saa716x_ir_init(saa716x); ++ if (err) ++ goto fail9; ++ ++ return 0; ++ ++fail9: ++ saa716x_ff_osd_exit(saa716x); ++fail8: ++ saa716x_ff_audio_exit(saa716x); ++fail7: ++ saa716x_ff_video_exit(saa716x); ++fail6: ++ saa716x_dvb_exit(saa716x); ++fail5: ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); ++ ++ /* disable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); ++ ++ vfree(sti7109->iobuf); ++fail4: ++ kfree(sti7109); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_ff_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ struct sti7109_dev *sti7109 = saa716x->priv; ++ ++ saa716x_ir_exit(saa716x); ++ ++ saa716x_ff_osd_exit(saa716x); ++ ++ saa716x_ff_audio_exit(saa716x); ++ ++ saa716x_ff_video_exit(saa716x); ++ ++ saa716x_dvb_exit(saa716x); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); ++ ++ /* disable board power */ ++ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); ++ ++ vfree(sti7109->iobuf); ++ ++ saa716x->priv = NULL; ++ kfree(sti7109); ++ ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++static irqreturn_t saa716x_ff_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ struct sti7109_dev *sti7109; ++ u32 msiStatusL; ++ u32 msiStatusH; ++ u32 phiISR; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ sti7109 = saa716x->priv; ++ if (unlikely(sti7109 == NULL)) { ++ printk("%s: sti7109=NULL", __func__); ++ return IRQ_NONE; ++ } ++ if (sti7109->int_count_enable) ++ sti7109->total_int_count++; ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_L), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ msiStatusL = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, msiStatusL); ++ msiStatusH = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, msiStatusH); ++ ++ if (msiStatusL) { ++ if (msiStatusL & MSI_INT_TAGACK_FGPI_2) { ++ if (sti7109->int_count_enable) ++ sti7109->fgpi_int_count[0]++; ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (msiStatusL & MSI_INT_TAGACK_FGPI_3) { ++ if (sti7109->int_count_enable) ++ sti7109->fgpi_int_count[1]++; ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ if (msiStatusH) { ++ //dprintk(SAA716x_INFO, 1, "msiStatusH: %08X", msiStatusH); ++ } ++ ++ if (msiStatusH & MSI_INT_I2CINT_0) { ++ if (sti7109->int_count_enable) ++ sti7109->i2c_int_count[0]++; ++ saa716x->i2c[0].i2c_op = 0; ++ wake_up(&saa716x->i2c[0].i2c_wq); ++ } ++ if (msiStatusH & MSI_INT_I2CINT_1) { ++ if (sti7109->int_count_enable) ++ sti7109->i2c_int_count[1]++; ++ saa716x->i2c[1].i2c_op = 0; ++ wake_up(&saa716x->i2c[1].i2c_wq); ++ } ++ ++ if (msiStatusH & MSI_INT_EXTINT_0) { ++ ++ phiISR = SAA716x_EPRD(PHI_1, FPGA_ADDR_EMI_ISR); ++ //dprintk(SAA716x_INFO, 1, "interrupt status register: %08X", phiISR); ++ ++ if (sti7109->int_count_enable) { ++ int i; ++ sti7109->ext_int_total_count++; ++ for (i = 0; i < 16; i++) ++ if (phiISR & (1 << i)) ++ sti7109->ext_int_source_count[i]++; ++ } ++ ++ if (phiISR & ISR_CMD_MASK) { ++ ++ u32 value; ++ u32 length; ++ /*dprintk(SAA716x_INFO, 1, "CMD interrupt source");*/ ++ ++ value = SAA716x_EPRD(PHI_1, ADDR_CMD_DATA); ++ value = __cpu_to_be32(value); ++ length = (value >> 16) + 2; ++ ++ /*dprintk(SAA716x_INFO, 1, "CMD length: %d", length);*/ ++ ++ if (length > MAX_RESULT_LEN) { ++ dprintk(SAA716x_ERROR, 1, "CMD length %d > %d", length, MAX_RESULT_LEN); ++ length = MAX_RESULT_LEN; ++ } ++ ++ saa716x_phi_read(saa716x, ADDR_CMD_DATA, sti7109->result_data, length); ++ sti7109->result_len = length; ++ sti7109->result_avail = 1; ++ wake_up(&sti7109->result_avail_wq); ++ ++ phiISR &= ~ISR_CMD_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CMD_MASK); ++ } ++ ++ if (phiISR & ISR_READY_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "READY interrupt source");*/ ++ sti7109->cmd_ready = 1; ++ wake_up(&sti7109->cmd_ready_wq); ++ phiISR &= ~ISR_READY_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_READY_MASK); ++ } ++ ++ if (phiISR & ISR_OSD_CMD_MASK) { ++ ++ u32 value; ++ u32 length; ++ /*dprintk(SAA716x_INFO, 1, "OSD CMD interrupt source");*/ ++ ++ value = SAA716x_EPRD(PHI_1, ADDR_OSD_CMD_DATA); ++ value = __cpu_to_be32(value); ++ length = (value >> 16) + 2; ++ ++ /*dprintk(SAA716x_INFO, 1, "OSD CMD length: %d", length);*/ ++ ++ if (length > MAX_RESULT_LEN) { ++ dprintk(SAA716x_ERROR, 1, "OSD CMD length %d > %d", length, MAX_RESULT_LEN); ++ length = MAX_RESULT_LEN; ++ } ++ ++ saa716x_phi_read(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_result_data, length); ++ sti7109->osd_result_len = length; ++ sti7109->osd_result_avail = 1; ++ wake_up(&sti7109->osd_result_avail_wq); ++ ++ phiISR &= ~ISR_OSD_CMD_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_CMD_MASK); ++ } ++ ++ if (phiISR & ISR_OSD_READY_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "OSD_READY interrupt source");*/ ++ sti7109->osd_cmd_ready = 1; ++ wake_up(&sti7109->osd_cmd_ready_wq); ++ phiISR &= ~ISR_OSD_READY_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_READY_MASK); ++ } ++ ++ if (phiISR & ISR_BLOCK_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "BLOCK interrupt source");*/ ++ sti7109->block_done = 1; ++ wake_up(&sti7109->block_done_wq); ++ phiISR &= ~ISR_BLOCK_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BLOCK_MASK); ++ } ++ ++ if (phiISR & ISR_DATA_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "DATA interrupt source");*/ ++ sti7109->data_ready = 1; ++ wake_up(&sti7109->data_ready_wq); ++ phiISR &= ~ISR_DATA_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DATA_MASK); ++ } ++ ++ if (phiISR & ISR_BOOT_FINISH_MASK) { ++ /*dprintk(SAA716x_INFO, 1, "BOOT FINISH interrupt source");*/ ++ sti7109->boot_finished = 1; ++ wake_up(&sti7109->boot_finish_wq); ++ phiISR &= ~ISR_BOOT_FINISH_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BOOT_FINISH_MASK); ++ } ++ ++ if (phiISR & ISR_AUDIO_PTS_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_AUDIO_PTS, data, 8); ++ sti7109->audio_pts = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_AUDIO_PTS_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_AUDIO_PTS_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "AUDIO PTS: %llX", sti7109->audio_pts);*/ ++ } ++ ++ if (phiISR & ISR_VIDEO_PTS_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_VIDEO_PTS, data, 8); ++ sti7109->video_pts = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_VIDEO_PTS_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_VIDEO_PTS_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "VIDEO PTS: %llX", sti7109->video_pts);*/ ++ } ++ ++ if (phiISR & ISR_CURRENT_STC_MASK) { ++ u8 data[8]; ++ ++ saa716x_phi_read(saa716x, ADDR_CURRENT_STC, data, 8); ++ sti7109->current_stc = (((u64) data[3] & 0x01) << 32) ++ | ((u64) data[4] << 24) ++ | ((u64) data[5] << 16) ++ | ((u64) data[6] << 8) ++ | ((u64) data[7]); ++ ++ phiISR &= ~ISR_CURRENT_STC_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CURRENT_STC_MASK); ++ ++ /*dprintk(SAA716x_INFO, 1, "CURRENT STC: %llu", sti7109->current_stc);*/ ++ } ++ ++ if (phiISR & ISR_REMOTE_EVENT_MASK) { ++ u8 data[4]; ++ u32 remote_event; ++ ++ saa716x_phi_read(saa716x, ADDR_REMOTE_EVENT, data, 4); ++ remote_event = (data[3] << 24) ++ | (data[2] << 16) ++ | (data[1] << 8) ++ | (data[0]); ++ memset(data, 0, sizeof(data)); ++ saa716x_phi_write(saa716x, ADDR_REMOTE_EVENT, data, 4); ++ ++ phiISR &= ~ISR_REMOTE_EVENT_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_REMOTE_EVENT_MASK); ++ ++ if (remote_event == 0) { ++ dprintk(SAA716x_ERROR, 1, "REMOTE EVENT: %X ignored", remote_event); ++ } else { ++ dprintk(SAA716x_INFO, 1, "REMOTE EVENT: %X", remote_event); ++ saa716x_ir_handler(saa716x, remote_event); ++ } ++ } ++ ++ if (phiISR & ISR_DVO_FORMAT_MASK) { ++ u8 data[4]; ++ u32 format; ++ ++ saa716x_phi_read(saa716x, ADDR_DVO_FORMAT, data, 4); ++ format = (data[0] << 24) ++ | (data[1] << 16) ++ | (data[2] << 8) ++ | (data[3]); ++ ++ phiISR &= ~ISR_DVO_FORMAT_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DVO_FORMAT_MASK); ++ ++ dprintk(SAA716x_INFO, 1, "DVO FORMAT CHANGE: %u", format); ++ } ++ ++ if (phiISR & ISR_LOG_MESSAGE_MASK) { ++ char message[SIZE_LOG_MESSAGE_DATA]; ++ ++ saa716x_phi_read(saa716x, ADDR_LOG_MESSAGE, message, ++ SIZE_LOG_MESSAGE_DATA); ++ ++ phiISR &= ~ISR_LOG_MESSAGE_MASK; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_LOG_MESSAGE_MASK); ++ ++ dprintk(SAA716x_INFO, 1, "LOG MESSAGE: %.*s", ++ SIZE_LOG_MESSAGE_DATA, message); ++ } ++ ++ if (phiISR & ISR_FIFO1_EMPTY_MASK) { ++ u32 fifoCtrl; ++ ++ /*dprintk(SAA716x_INFO, 1, "FIFO EMPTY interrupt source");*/ ++ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); ++ fifoCtrl &= ~0x4; ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); ++ tasklet_schedule(&sti7109->fifo_tasklet); ++ phiISR &= ~ISR_FIFO1_EMPTY_MASK; ++ } ++ ++ if (phiISR) { ++ dprintk(SAA716x_INFO, 1, "unknown interrupt source"); ++ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, phiISR); ++ } ++ } ++ ++ if (sti7109->int_count_enable) { ++ if (jiffies - sti7109->last_int_ticks >= HZ) { ++ dprintk(SAA716x_INFO, 1, "int count: t: %d, f:%d %d, i:%d %d," ++ "e: %d (%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)", ++ sti7109->total_int_count, ++ sti7109->fgpi_int_count[0], ++ sti7109->fgpi_int_count[1], ++ sti7109->i2c_int_count[0], ++ sti7109->i2c_int_count[1], ++ sti7109->ext_int_total_count, ++ sti7109->ext_int_source_count[0], ++ sti7109->ext_int_source_count[1], ++ sti7109->ext_int_source_count[2], ++ sti7109->ext_int_source_count[3], ++ sti7109->ext_int_source_count[4], ++ sti7109->ext_int_source_count[5], ++ sti7109->ext_int_source_count[6], ++ sti7109->ext_int_source_count[7], ++ sti7109->ext_int_source_count[8], ++ sti7109->ext_int_source_count[9], ++ sti7109->ext_int_source_count[10], ++ sti7109->ext_int_source_count[11], ++ sti7109->ext_int_source_count[12], ++ sti7109->ext_int_source_count[13], ++ sti7109->ext_int_source_count[14], ++ sti7109->ext_int_source_count[15]); ++ sti7109->total_int_count = 0; ++ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); ++ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); ++ sti7109->ext_int_total_count = 0; ++ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); ++ sti7109->last_int_ticks = jiffies; ++ } ++ } ++ return IRQ_HANDLED; ++} ++ ++#define SAA716x_MODEL_S2_6400_DUAL "Technotrend S2 6400 Dual S2 Premium" ++#define SAA716x_DEV_S2_6400_DUAL "2x DVB-S/S2 + Hardware decode" ++ ++static struct stv090x_config tt6400_stv090x_config = { ++ .device = STV0900, ++ .demod_mode = STV090x_DUAL, ++ .clk_mode = STV090x_CLK_EXT, ++ ++ .xtal = 13500000, ++ .address = 0x68, ++ ++ .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, ++ .ts1_clk = 135000000, ++ .ts2_clk = 135000000, ++ ++ .repeater_level = STV090x_RPTLEVEL_16, ++ ++ .tuner_init = NULL, ++ .tuner_set_mode = NULL, ++ .tuner_set_frequency = NULL, ++ .tuner_get_frequency = NULL, ++ .tuner_set_bandwidth = NULL, ++ .tuner_get_bandwidth = NULL, ++ .tuner_set_bbgain = NULL, ++ .tuner_get_bbgain = NULL, ++ .tuner_set_refclk = NULL, ++ .tuner_get_status = NULL, ++}; ++ ++static struct stv6110x_config tt6400_stv6110x_config = { ++ .addr = 0x60, ++ .refclk = 27000000, ++ .clk_div = 2, ++}; ++ ++static struct isl6423_config tt6400_isl6423_config[2] = { ++ { ++ .current_max = SEC_CURRENT_515m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x09, ++ }, ++ { ++ .current_max = SEC_CURRENT_515m, ++ .curlim = SEC_CURRENT_LIM_ON, ++ .mod_extern = 1, ++ .addr = 0x08, ++ } ++}; ++ ++ ++static int saa716x_s26400_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *i2c_adapter = &i2c[SAA716x_I2C_BUS_A].i2c_adapter; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ if (count == 0 || count == 1) { ++ adapter->fe = dvb_attach(stv090x_attach, ++ &tt6400_stv090x_config, ++ i2c_adapter, ++ STV090x_DEMODULATOR_0 + count); ++ ++ if (adapter->fe) { ++ struct stv6110x_devctl *ctl; ++ ctl = dvb_attach(stv6110x_attach, ++ adapter->fe, ++ &tt6400_stv6110x_config, ++ i2c_adapter); ++ ++ tt6400_stv090x_config.tuner_init = ctl->tuner_init; ++ tt6400_stv090x_config.tuner_sleep = ctl->tuner_sleep; ++ tt6400_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; ++ tt6400_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; ++ tt6400_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; ++ tt6400_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; ++ tt6400_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; ++ tt6400_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; ++ tt6400_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; ++ tt6400_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; ++ tt6400_stv090x_config.tuner_get_status = ctl->tuner_get_status; ++ ++ if (count == 1) { ++ /* call the init function once to initialize ++ tuner's clock output divider and demod's ++ master clock */ ++ /* The second tuner drives the STV0900 so ++ call it only for adapter 1 */ ++ if (adapter->fe->ops.init) ++ adapter->fe->ops.init(adapter->fe); ++ } ++ ++ dvb_attach(isl6423_attach, ++ adapter->fe, ++ i2c_adapter, ++ &tt6400_isl6423_config[count]); ++ ++ } ++ } ++ return 0; ++} ++ ++static struct saa716x_config saa716x_s26400_config = { ++ .model_name = SAA716x_MODEL_S2_6400_DUAL, ++ .dev_type = SAA716x_DEV_S2_6400_DUAL, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_s26400_frontend_attach, ++ .irq_handler = saa716x_ff_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .i2c_mode = SAA716x_I2C_MODE_IRQ_BUFFERED, ++ ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 2, ++ .worker = demux_worker ++ },{ ++ /* Adapter 1 */ ++ .ts_port = 3, ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++static struct pci_device_id saa716x_ff_pci_table[] = { ++ ++ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_DEVEL, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual development version */ ++ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_PROD, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual production version */ ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_ff_pci_table); ++ ++static struct pci_driver saa716x_ff_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_ff_pci_table, ++ .probe = saa716x_ff_pci_probe, ++ .remove = saa716x_ff_pci_remove, ++}; ++ ++static int saa716x_ff_init(void) ++{ ++ return pci_register_driver(&saa716x_ff_pci_driver); ++} ++ ++static void saa716x_ff_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_ff_pci_driver); ++} ++ ++module_init(saa716x_ff_init); ++module_exit(saa716x_ff_exit); ++ ++MODULE_DESCRIPTION("SAA716x FF driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/common/saa716x/saa716x_fgpi.c b/drivers/media/common/saa716x/saa716x_fgpi.c +new file mode 100644 +index 0000000..8bdb13d +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_fgpi.c +@@ -0,0 +1,389 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_fgpi_reg.h" ++#include "saa716x_dma_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_dma.h" ++#include "saa716x_fgpi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static const u32 mmu_pta_base[] = { ++ MMU_PTA_BASE0, ++ MMU_PTA_BASE1, ++ MMU_PTA_BASE2, ++ MMU_PTA_BASE3, ++ MMU_PTA_BASE4, ++ MMU_PTA_BASE5, ++ MMU_PTA_BASE6, ++ MMU_PTA_BASE7, ++ MMU_PTA_BASE8, ++ MMU_PTA_BASE9, ++ MMU_PTA_BASE10, ++ MMU_PTA_BASE11, ++ MMU_PTA_BASE12, ++ MMU_PTA_BASE13, ++ MMU_PTA_BASE14, ++ MMU_PTA_BASE15, ++}; ++ ++static const u32 mmu_dma_cfg[] = { ++ MMU_DMA_CONFIG0, ++ MMU_DMA_CONFIG1, ++ MMU_DMA_CONFIG2, ++ MMU_DMA_CONFIG3, ++ MMU_DMA_CONFIG4, ++ MMU_DMA_CONFIG5, ++ MMU_DMA_CONFIG6, ++ MMU_DMA_CONFIG7, ++ MMU_DMA_CONFIG8, ++ MMU_DMA_CONFIG9, ++ MMU_DMA_CONFIG10, ++ MMU_DMA_CONFIG11, ++ MMU_DMA_CONFIG12, ++ MMU_DMA_CONFIG13, ++ MMU_DMA_CONFIG14, ++ MMU_DMA_CONFIG15, ++}; ++ ++static const u32 fgpi_ch[] = { ++ FGPI0, ++ FGPI1, ++ FGPI2, ++ FGPI3 ++}; ++ ++static const u32 bamdma_bufmode[] = { ++ BAM_FGPI0_DMA_BUF_MODE, ++ BAM_FGPI1_DMA_BUF_MODE, ++ BAM_FGPI2_DMA_BUF_MODE, ++ BAM_FGPI3_DMA_BUF_MODE ++}; ++ ++static const u32 msi_int_tagack[] = { ++ MSI_INT_TAGACK_FGPI_0, ++ MSI_INT_TAGACK_FGPI_1, ++ MSI_INT_TAGACK_FGPI_2, ++ MSI_INT_TAGACK_FGPI_3 ++}; ++ ++static const u32 msi_int_ovrflw[] = { ++ MSI_INT_OVRFLW_FGPI_0, ++ MSI_INT_OVRFLW_FGPI_1, ++ MSI_INT_OVRFLW_FGPI_2, ++ MSI_INT_OVRFLW_FGPI_3 ++}; ++ ++static const u32 msi_int_avint[] = { ++ MSI_INT_AVINT_FGPI_0, ++ MSI_INT_AVINT_FGPI_1, ++ MSI_INT_AVINT_FGPI_2, ++ MSI_INT_AVINT_FGPI_3 ++}; ++ ++void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 fgpi_port; ++ ++ fgpi_port = fgpi_ch[channel]; ++ ++ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0); /* disable FGPI IRQ */ ++ SAA716x_EPWR(fgpi_port, INT_CLR_STATUS, 0x7f); /* clear status */ ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpiint_disable); ++ ++int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, u32 fgpi_index) ++{ ++ u32 fgpi_base; ++ u32 buf_mode_reg; ++ u32 buf_mode; ++ ++ switch (fgpi_index) { ++ case 0: /* FGPI_0 */ ++ fgpi_base = FGPI0; ++ buf_mode_reg = BAM_FGPI0_DMA_BUF_MODE; ++ break; ++ ++ case 1: /* FGPI_1 */ ++ fgpi_base = FGPI1; ++ buf_mode_reg = BAM_FGPI1_DMA_BUF_MODE; ++ break; ++ ++ case 2: /* FGPI_2 */ ++ fgpi_base = FGPI2; ++ buf_mode_reg = BAM_FGPI2_DMA_BUF_MODE; ++ break; ++ ++ case 3: /* FGPI_3 */ ++ fgpi_base = FGPI3; ++ buf_mode_reg = BAM_FGPI3_DMA_BUF_MODE; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s: unexpected fgpi %u\n", ++ __func__, fgpi_index); ++ return -1; ++ } ++ ++ buf_mode = SAA716x_EPRD(BAM, buf_mode_reg); ++ if (saa716x->revision < 2) { ++ /* workaround for revision 1: restore buffer numbers on BAM */ ++ SAA716x_EPWR(fgpi_base, INT_CLR_STATUS, 0x7F); ++ SAA716x_EPWR(BAM, buf_mode_reg, buf_mode | 7); ++ } ++ return (buf_mode >> 3) & 0x7; ++} ++EXPORT_SYMBOL_GPL(saa716x_fgpi_get_write_index); ++ ++static u32 saa716x_init_ptables(struct saa716x_dmabuf *dmabuf, int channel) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 config, i; ++ ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ BUG_ON((dmabuf[i].mem_ptab_phys == 0)); ++ ++ config = mmu_dma_cfg[channel]; /* DMACONFIGx */ ++ ++ SAA716x_EPWR(MMU, config, (FGPI_BUFFERS - 1)); ++ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[4].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[4].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[5].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[5].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[6].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[6].mem_ptab_phys)); /* High */ ++ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[7].mem_ptab_phys)); /* Low */ ++ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[7].mem_ptab_phys)); /* High */ ++ ++ return 0; ++} ++ ++int saa716x_fgpi_setparams(struct saa716x_dmabuf *dmabuf, ++ struct fgpi_stream_params *stream_params, ++ int port) ++{ ++ struct saa716x_dev *saa716x = dmabuf->saa716x; ++ ++ u32 fgpi_port, buf_mode, val, mid; ++ u32 D1_XY_END, offst_1, offst_2; ++ int i = 0; ++ ++ fgpi_port = fgpi_ch[port]; ++ buf_mode = bamdma_bufmode[port]; ++ ++ /* Reset FGPI block */ ++ SAA716x_EPWR(fgpi_port, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); ++ ++ /* Reset DMA channel */ ++ SAA716x_EPWR(BAM, buf_mode, 0x00000040); ++ saa716x_init_ptables(dmabuf, saa716x->fgpi[port].dma_channel); ++ ++ ++ /* monitor BAM reset */ ++ val = SAA716x_EPRD(BAM, buf_mode); ++ while (val && (i < 100)) { ++ msleep(30); ++ val = SAA716x_EPRD(BAM, buf_mode); ++ i++; ++ } ++ ++ if (val) { ++ dprintk(SAA716x_ERROR, 1, "Error: BAM FGPI Reset failed!"); ++ return -EIO; ++ } ++ ++ /* set buffer count */ ++ SAA716x_EPWR(BAM, buf_mode, FGPI_BUFFERS - 1); ++ ++ /* initialize all available address offsets */ ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_0(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_1(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_2(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_3(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_4(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_5(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_6(port), 0x0); ++ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_7(port), 0x0); ++ ++ /* get module ID */ ++ mid = SAA716x_EPRD(fgpi_port, FGPI_MODULE_ID); ++ if (mid != 0x14b0100) ++ dprintk(SAA716x_ERROR, 1, "FGPI Id<%04x> is not supported", mid); ++ ++ /* Initialize FGPI block */ ++ SAA716x_EPWR(fgpi_port, FGPI_REC_SIZE, stream_params->samples * (stream_params->bits / 8)); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch); ++ ++ offst_1 = 0; ++ offst_2 = 0; ++ switch (stream_params->stream_type) { ++ case FGPI_TRANSPORT_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ break; ++ ++ case FGPI_PROGRAM_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ break; ++ ++ case FGPI_VIDEO_STREAM: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); ++ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_START, 0x00000002); ++ ++ if ((stream_params->stream_flags & FGPI_INTERLACED) && ++ (stream_params->stream_flags & FGPI_ODD_FIELD) && ++ (stream_params->stream_flags & FGPI_EVEN_FIELD)) { ++ ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines / 2); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 4); /* interlaced stride of 2 lines */ ++ ++ D1_XY_END = (stream_params->samples << 16); ++ D1_XY_END |= (stream_params->lines / 2) + 2; ++ ++ if (stream_params->stream_flags & FGPI_PAL) ++ offst_1 = 768 * 2; ++ else ++ offst_2 = 768 * 2; ++ ++ } else { ++ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); ++ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 2); /* stride of 1 line */ ++ ++ D1_XY_END = stream_params->samples << 16; ++ D1_XY_END |= stream_params->lines + 2; ++ } ++ ++ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_END, D1_XY_END); ++ break; ++ ++ default: ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); ++ break; ++ } ++ ++ SAA716x_EPWR(fgpi_port, FGPI_BASE_1, ((saa716x->fgpi[port].dma_channel) << 21) + offst_1); ++ SAA716x_EPWR(fgpi_port, FGPI_BASE_2, ((saa716x->fgpi[port].dma_channel) << 21) + offst_2); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, ++ struct fgpi_stream_params *stream_params) ++{ ++ u32 fgpi_port; ++ u32 config; ++ u32 val; ++ u32 i; ++ ++ fgpi_port = fgpi_ch[port]; ++ ++ SAA716x_EPWR(fgpi_port, FGPI_INTERFACE, 0); ++ msleep(10); ++ ++ if (saa716x_fgpi_setparams(saa716x->fgpi[port].dma_buf, stream_params, port) != 0) { ++ return -EIO; ++ } ++ ++ config = mmu_dma_cfg[saa716x->fgpi[port].dma_channel]; /* DMACONFIGx */ ++ ++ val = SAA716x_EPRD(MMU, config); ++ SAA716x_EPWR(MMU, config, val & ~0x40); ++ SAA716x_EPWR(MMU, config, val | 0x40); ++ ++ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0x7F); ++ ++ val = SAA716x_EPRD(MMU, config); ++ i = 0; ++ while (i < 500) { ++ if (val & 0x80) ++ break; ++ msleep(10); ++ val = SAA716x_EPRD(MMU, config); ++ i++; ++ } ++ ++ if (!(val & 0x80)) { ++ dprintk(SAA716x_ERROR, 1, "Error: PTE pre-fetch failed!"); ++ return -EIO; ++ } ++ ++ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); ++ val |= 0x3000; ++ ++ saa716x_set_clk_external(saa716x, saa716x->fgpi[port].dma_channel); ++ ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, msi_int_tagack[port]); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port) ++{ ++ u32 fgpi_port; ++ u32 val; ++ ++ fgpi_port = fgpi_ch[port]; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, msi_int_tagack[port]); ++ ++ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); ++ val &= ~0x3000; ++ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); ++ ++ saa716x_set_clk_internal(saa716x, saa716x->fgpi[port].dma_channel); ++ ++ return 0; ++} ++ ++int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, ++ void (*worker)(unsigned long)) ++{ ++ int i; ++ int ret; ++ ++ saa716x->fgpi[port].dma_channel = port + 6; ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ { ++ /* TODO: what is a good size for TS DMA buffer? */ ++ ret = saa716x_dmabuf_alloc(saa716x, &saa716x->fgpi[port].dma_buf[i], 16 * SAA716x_PAGE_SIZE); ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ saa716x->fgpi[port].saa716x = saa716x; ++ tasklet_init(&saa716x->fgpi[port].tasklet, worker, ++ (unsigned long)&saa716x->fgpi[port]); ++ saa716x->fgpi[port].read_index = 0; ++ ++ return 0; ++} ++ ++int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port) ++{ ++ int i; ++ ++ tasklet_kill(&saa716x->fgpi[port].tasklet); ++ for (i = 0; i < FGPI_BUFFERS; i++) ++ { ++ saa716x_dmabuf_free(saa716x, &saa716x->fgpi[port].dma_buf[i]); ++ } ++ ++ return 0; ++} +diff --git a/drivers/media/common/saa716x/saa716x_fgpi.h b/drivers/media/common/saa716x/saa716x_fgpi.h +new file mode 100644 +index 0000000..225aff0 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_fgpi.h +@@ -0,0 +1,112 @@ ++#ifndef __SAA716x_FGPI_H ++#define __SAA716x_FGPI_H ++ ++#include ++ ++#define FGPI_BUFFERS 8 ++#define PTA_LSB(__mem) ((u32 ) (__mem)) ++#define PTA_MSB(__mem) ((u32 ) ((u64)(__mem) >> 32)) ++ ++#define BAM_DMA_BUF_MODE_BASE 0x0d8 ++#define BAM_DMA_BUF_MODE_OFFSET 0x24 ++ ++#define BAM_DMA_BUF_MODE(__ch) (BAM_DMA_BUF_MODE_BASE + (BAM_DMA_BUF_MODE_OFFSET * __ch)) ++ ++#define BAM_FGPI_ADDR_OFFST_BASE 0x0dc ++#define BAM_FGPI_ADDR_OFFST_OFFSET 0x24 ++ ++#define BAM_FGPI_ADDR_OFFSET(__ch) (BAM_FGPI_ADDR_OFFST_BASE + (BAM_FGPI_ADDR_OFFST_OFFSET * __ch)) ++ ++#define BAM_FGPI_ADDR_OFFST_0(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x00 ++#define BAM_FGPI_ADDR_OFFST_1(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x04 ++#define BAM_FGPI_ADDR_OFFST_2(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x08 ++#define BAM_FGPI_ADDR_OFFST_3(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x0c ++#define BAM_FGPI_ADDR_OFFST_4(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x10 ++#define BAM_FGPI_ADDR_OFFST_5(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x14 ++#define BAM_FGPI_ADDR_OFFST_6(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x18 ++#define BAM_FGPI_ADDR_OFFST_7(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x1c ++ ++struct saa716x_dmabuf; ++ ++/* ++ * Port supported streams ++ * ++ * FGPI_AUDIO_STREAM ++ * FGPI_VIDEO_STREAM ++ * FGPI_VBI_STREAM ++ * FGPI_TRANSPORT_STREAM ++ * FGPI_PROGRAM_STREAM ++ */ ++enum fgpi_stream_type { ++ FGPI_AUDIO_STREAM = 0x01, ++ FGPI_VIDEO_STREAM = 0x02, ++ FGPI_VBI_STREAM = 0x04, ++ FGPI_TRANSPORT_STREAM = 0x08, ++ FGPI_PROGRAM_STREAM = 0x10 ++}; ++ ++/* ++ * Stream port flags ++ * ++ * FGPI_ODD_FIELD ++ * FGPI_EVEN_FIELD ++ * FGPI_HD_0 ++ * FGPI_HD_1 ++ * FGPI_PAL ++ * FGPI_NTSC ++ */ ++enum fgpi_stream_flags { ++ FGPI_ODD_FIELD = 0x0001, ++ FGPI_EVEN_FIELD = 0x0002, ++ FGPI_INTERLACED = 0x0004, ++ FGPI_HD0 = 0x0010, ++ FGPI_HD1 = 0x0020, ++ FGPI_PAL = 0x0040, ++ FGPI_NTSC = 0x0080, ++ FGPI_NO_SCALER = 0x0100, ++}; ++ ++/* ++ * Stream port parameters ++ * bits: Bits per sample ++ * samples: samples perline ++ * lines: number of lines ++ * pitch: stream pitch in bytes ++ * offset: offset to first valid line ++ */ ++struct fgpi_stream_params { ++ u32 bits; ++ u32 samples; ++ u32 lines; ++ ++ s32 pitch; ++ ++ u32 offset; ++ u32 page_tables; ++ ++ enum fgpi_stream_flags stream_flags; ++ enum fgpi_stream_type stream_type; ++}; ++ ++struct saa716x_dmabuf; ++ ++struct saa716x_fgpi_stream_port { ++ u8 dma_channel; ++ struct saa716x_dmabuf dma_buf[FGPI_BUFFERS]; ++ struct saa716x_dev *saa716x; ++ struct tasklet_struct tasklet; ++ u8 read_index; ++}; ++ ++extern void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel); ++extern int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, ++ u32 fgpi_index); ++extern int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, ++ struct fgpi_stream_params *stream_params); ++extern int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port); ++ ++extern int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, ++ void (*worker)(unsigned long)); ++extern int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port); ++ ++#endif /* __SAA716x_FGPI_H */ +diff --git a/drivers/media/common/saa716x/saa716x_fgpi_reg.h b/drivers/media/common/saa716x/saa716x_fgpi_reg.h +new file mode 100644 +index 0000000..1193016 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_fgpi_reg.h +@@ -0,0 +1,74 @@ ++#ifndef __SAA716x_FGPI_REG_H ++#define __SAA716x_FGPI_REG_H ++ ++/* -------------- FGPI Registers -------------- */ ++ ++#define FGPI_CONTROL 0x000 ++#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) ++#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) ++#define FGPI_MODE (0x00000001 << 11) ++#define FGPI_SAMPLE_SIZE (0x00000003 << 8) ++#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) ++#define FGPI_REC_START_MSG_START (0x00000003 << 2) ++#define FGPI_TSTAMP_SELECT (0x00000001 << 1) ++#define FGPI_VAR_LENGTH (0x00000001 << 0) ++ ++#define FGPI_BASE_1 0x004 ++#define FGPI_BASE_2 0x008 ++#define FGPI_SIZE 0x00c ++#define FGPI_REC_SIZE 0x010 ++#define FGPI_STRIDE 0x014 ++#define FGPI_NUM_RECORD_1 0x018 ++#define FGPI_NUM_RECORD_2 0x01c ++#define FGPI_THRESHOLD_1 0x020 ++#define FGPI_THRESHOLD_2 0x024 ++#define FGPI_D1_XY_START 0x028 ++#define FGPI_D1_XY_END 0x02c ++ ++#define INT_STATUS 0xfe0 ++#define FGPI_BUF1_ACTIVE (0x00000001 << 7) ++#define FGPI_OVERFLOW (0x00000001 << 6) ++#define FGPI_MBE (0x00000001 << 5) ++#define FGPI_UNDERRUN (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED (0x00000001 << 2) ++#define FGPI_BUF2_FULL (0x00000001 << 1) ++#define FGPI_BUF1_FULL (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define FGPI_OVERFLOW_ENA (0x00000001 << 6) ++#define FGPI_MBE_ENA (0x00000001 << 5) ++#define FGPI_UNDERRUN_ENA (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) ++#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) ++#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define FGPI_OVERFLOW_ACK (0x00000001 << 6) ++#define FGPI_MBE_ACK (0x00000001 << 5) ++#define FGPI_UNDERRUN_ACK (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) ++#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) ++#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define FGPI_OVERFLOW_SET (0x00000001 << 6) ++#define FGPI_MBE_SET (0x00000001 << 5) ++#define FGPI_UNDERRUN_SET (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) ++#define FGPI_BUF2_DONE_SET (0x00000001 << 1) ++#define FGPI_BUF1_DONE_SET (0x00000001 << 0) ++ ++#define FGPI_SOFT_RESET 0xff0 ++#define FGPI_SOFTWARE_RESET (0x00000001 << 0) ++ ++#define FGPI_INTERFACE 0xff4 ++#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) ++ ++#define FGPI_MOD_ID_EXT 0xff8 ++#define FGPI_MODULE_ID 0xffc ++ ++#endif /* __SAA716x_FGPI_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_gpio.c b/drivers/media/common/saa716x/saa716x_gpio.c +new file mode 100644 +index 0000000..62b6112 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_gpio.c +@@ -0,0 +1,140 @@ ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++ ++#include "saa716x_gpio.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++void saa716x_gpio_init(struct saa716x_dev *saa716x) ++{ ++ spin_lock_init(&saa716x->gpio_lock); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_init); ++ ++int saa716x_get_gpio_mode(struct saa716x_dev *saa716x, u32 *config) ++{ ++ *config = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ ++ return 0; ++} ++ ++int saa716x_set_gpio_mode(struct saa716x_dev *saa716x, u32 mask, u32 config) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ reg = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ reg &= ~mask; ++ reg |= (config & mask); ++ SAA716x_EPWR(GPIO, GPIO_WR_MODE, reg); ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++ ++ return 0; ++} ++ ++u32 saa716x_gpio_rd(struct saa716x_dev *saa716x) ++{ ++ return SAA716x_EPRD(GPIO, GPIO_RD); ++} ++ ++void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data) ++{ ++ SAA716x_EPWR(GPIO, GPIO_WR, data); ++} ++ ++void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ ++ reg = SAA716x_EPRD(GPIO, GPIO_OEN); ++ reg &= mask; ++ reg |= bits; ++ SAA716x_EPWR(GPIO, GPIO_OEN, reg); ++ ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++ ++void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits) ++{ ++ unsigned long flags; ++ u32 reg; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ ++ reg = SAA716x_EPRD(GPIO, GPIO_WR); ++ reg &= ~bits; ++ /* TODO ! add maskable config bits in here */ ++ /* reg |= (config->mask & bits) */ ++ reg |= bits; ++ SAA716x_EPWR(GPIO, GPIO_WR, reg); ++ ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++ ++void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_OEN); ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_OEN, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_output); ++ ++void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_OEN); ++ value |= 1 << gpio; ++ SAA716x_EPWR(GPIO, GPIO_OEN, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_input); ++ ++void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_WR_MODE); ++ if (mode) ++ value |= 1 << gpio; ++ else ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_WR_MODE, value); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_set_mode); ++ ++void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set) ++{ ++ uint32_t value; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++ value = SAA716x_EPRD(GPIO, GPIO_WR); ++ if (set) ++ value |= 1 << gpio; ++ else ++ value &= ~(1 << gpio); ++ SAA716x_EPWR(GPIO, GPIO_WR, value); ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_write); ++ ++int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio) ++{ ++ uint32_t value; ++ ++ value = SAA716x_EPRD(GPIO, GPIO_RD); ++ if (value & (1 << gpio)) ++ return 1; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_gpio_read); +diff --git a/drivers/media/common/saa716x/saa716x_gpio.h b/drivers/media/common/saa716x/saa716x_gpio.h +new file mode 100644 +index 0000000..a82580b +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_gpio.h +@@ -0,0 +1,26 @@ ++#ifndef __SAA716x_GPIO_H ++#define __SAA716x_GPIO_H ++ ++#define BOOT_MODE GPIO_31 | GPIO_30 ++#define AV_UNIT_B GPIO_25 ++#define AV_UNIT_A GPIO_24 ++#define AV_INTR_B GPIO_01 ++#define AV_INTR_A GPIO_00 ++ ++struct saa716x_dev; ++ ++extern void saa716x_gpio_init(struct saa716x_dev *saa716x); ++ ++extern u32 saa716x_gpio_rd(struct saa716x_dev *saa716x); ++extern void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data); ++extern void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits); ++ ++extern void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits); ++ ++extern void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio); ++extern void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio); ++extern void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode); ++extern void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set); ++extern int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio); ++ ++#endif /* __SAA716x_GPIO_H */ +diff --git a/drivers/media/common/saa716x/saa716x_gpio_reg.h b/drivers/media/common/saa716x/saa716x_gpio_reg.h +new file mode 100644 +index 0000000..f36184a +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_gpio_reg.h +@@ -0,0 +1,47 @@ ++#ifndef __SAA716x_GPIO_REG_H ++#define __SAA716x_GPIO_REG_H ++ ++/* -------------- GPIO Registers -------------- */ ++ ++#define GPIO_RD 0x000 ++#define GPIO_WR 0x004 ++#define GPIO_WR_MODE 0x008 ++#define GPIO_OEN 0x00c ++ ++#define GPIO_SW_RST 0xff0 ++#define GPIO_SW_RESET (0x00000001 << 0) ++ ++#define GPIO_31 (1 << 31) ++#define GPIO_30 (1 << 30) ++#define GPIO_29 (1 << 29) ++#define GPIO_28 (1 << 28) ++#define GPIO_27 (1 << 27) ++#define GPIO_26 (1 << 26) ++#define GPIO_25 (1 << 25) ++#define GPIO_24 (1 << 24) ++#define GPIO_23 (1 << 23) ++#define GPIO_22 (1 << 22) ++#define GPIO_21 (1 << 21) ++#define GPIO_20 (1 << 20) ++#define GPIO_19 (1 << 19) ++#define GPIO_18 (1 << 18) ++#define GPIO_17 (1 << 17) ++#define GPIO_16 (1 << 16) ++#define GPIO_15 (1 << 15) ++#define GPIO_14 (1 << 14) ++#define GPIO_13 (1 << 13) ++#define GPIO_12 (1 << 12) ++#define GPIO_11 (1 << 11) ++#define GPIO_10 (1 << 10) ++#define GPIO_09 (1 << 9) ++#define GPIO_08 (1 << 8) ++#define GPIO_07 (1 << 7) ++#define GPIO_06 (1 << 6) ++#define GPIO_05 (1 << 5) ++#define GPIO_04 (1 << 4) ++#define GPIO_03 (1 << 3) ++#define GPIO_02 (1 << 2) ++#define GPIO_01 (1 << 1) ++#define GPIO_00 (1 << 0) ++ ++#endif /* __SAA716x_GPIO_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_greg.c b/drivers/media/common/saa716x/saa716x_greg.c +new file mode 100644 +index 0000000..d93a3b8 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_greg.c +@@ -0,0 +1,42 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_greg_reg.h" ++#include "saa716x_greg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++static u32 g_save[12]; ++ ++void saa716x_greg_save(struct saa716x_dev *saa716x) ++{ ++ g_save[0] = SAA716x_EPRD(GREG, GREG_SUBSYS_CONFIG); ++ g_save[1] = SAA716x_EPRD(GREG, GREG_MSI_BAR_PMCSR); ++ g_save[2] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_1); ++ g_save[3] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_2); ++ g_save[4] = SAA716x_EPRD(GREG, GREG_VI_CTRL); ++ g_save[5] = SAA716x_EPRD(GREG, GREG_FGPI_CTRL); ++ g_save[6] = SAA716x_EPRD(GREG, GREG_RSTU_CTRL); ++ g_save[7] = SAA716x_EPRD(GREG, GREG_I2C_CTRL); ++ g_save[8] = SAA716x_EPRD(GREG, GREG_OVFLW_CTRL); ++ g_save[9] = SAA716x_EPRD(GREG, GREG_TAG_ACK_FLEN); ++ ++ g_save[10] = SAA716x_EPRD(GREG, GREG_VIDEO_IN_CTRL); ++} ++ ++void saa716x_greg_restore(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, g_save[0]); ++ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, g_save[1]); ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, g_save[2]); ++ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, g_save[3]); ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, g_save[4]); ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, g_save[5]); ++ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, g_save[6]); ++ SAA716x_EPWR(GREG, GREG_I2C_CTRL, g_save[7]); ++ SAA716x_EPWR(GREG, GREG_OVFLW_CTRL, g_save[8]); ++ SAA716x_EPWR(GREG, GREG_TAG_ACK_FLEN, g_save[9]); ++ ++ SAA716x_EPWR(GREG, GREG_VIDEO_IN_CTRL, g_save[10]); ++} +diff --git a/drivers/media/common/saa716x/saa716x_greg.h b/drivers/media/common/saa716x/saa716x_greg.h +new file mode 100644 +index 0000000..487595e +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_greg.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_GREG_H ++#define __SAA716x_GREG_H ++ ++struct saa716x_dev; ++ ++extern void saa716x_greg_save(struct saa716x_dev *saa716x); ++extern void saa716x_greg_restore(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_GREG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_greg_reg.h b/drivers/media/common/saa716x/saa716x_greg_reg.h +new file mode 100644 +index 0000000..052e8cd +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_greg_reg.h +@@ -0,0 +1,91 @@ ++#ifndef __SAA716x_GREG_REG_H ++#define __SAA716x_GREG_REG_H ++ ++/* -------------- GREG Registers -------------- */ ++ ++#define GREG_SUBSYS_CONFIG 0x000 ++#define GREG_SUBSYS_ID (0x0000ffff << 16) ++#define GREG_SUBSYS_VID (0x0000ffff << 0) ++ ++#define GREG_MSI_BAR_PMCSR 0x004 ++#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) ++#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) ++#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) ++#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) ++#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) ++#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) ++#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) ++#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) ++ ++#define GREG_BAR_WIDTH_17 (0x0000001e << 8) ++#define GREG_BAR_WIDTH_18 (0x0000001c << 8) ++#define GREG_BAR_WIDTH_19 (0x00000018 << 8) ++#define GREG_BAR_WIDTH_20 (0x00000010 << 8) ++ ++#define GREG_BAR_PREFETCH (0x00000001 << 3) ++#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! ++#define GREG_MSI_MM_CAP2 (0x00000001 << 0) ++#define GREG_MSI_MM_CAP4 (0x00000002 << 0) ++#define GREG_MSI_MM_CAP8 (0x00000003 << 0) ++#define GREG_MSI_MM_CAP16 (0x00000004 << 0) ++#define GREG_MSI_MM_CAP32 (0x00000005 << 0) ++ ++#define GREG_PMCSR_DATA_1 0x008 ++#define GREG_PMCSR_DATA_2 0x00c ++#define GREG_VI_CTRL 0x010 ++#define GREG_FGPI_CTRL 0x014 ++ ++#define GREG_RSTU_CTRL 0x018 ++#define GREG_BOOT_READY (0x00000001 << 13) ++#define GREG_RESET_REQ (0x00000001 << 12) ++#define GREG_IP_RST_RELEASE (0x00000001 << 11) ++#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) ++#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) ++#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) ++#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) ++#define GREG_CGU_RST_RELEASE (0x00000001 << 6) ++#define GREG_IP_RST_ASSERT (0x00000001 << 5) ++#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) ++#define GREG_RST_ASSERT (0x00000001 << 3) ++#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) ++#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) ++#define GREG_CGU_RST_ASSERT (0x00000001 << 0) ++ ++#define GREG_I2C_CTRL 0x01c ++#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) ++ ++#define GREG_OVFLW_CTRL 0x020 ++#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) ++ ++#define GREG_TAG_ACK_FLEN 0x024 ++#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) ++#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) ++#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) ++#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) ++ ++#define GREG_VIDEO_IN_CTRL 0x028 ++ ++#define GREG_SPARE_1 0x02c ++#define GREG_SPARE_2 0x030 ++#define GREG_SPARE_3 0x034 ++#define GREG_SPARE_4 0x038 ++#define GREG_SPARE_5 0x03c ++#define GREG_SPARE_6 0x040 ++#define GREG_SPARE_7 0x044 ++#define GREG_SPARE_8 0x048 ++#define GREG_SPARE_9 0x04c ++#define GREG_SPARE_10 0x050 ++#define GREG_SPARE_11 0x054 ++#define GREG_SPARE_12 0x058 ++#define GREG_SPARE_13 0x05c ++#define GREG_SPARE_14 0x060 ++#define GREG_SPARE_15 0x064 ++ ++#define GREG_FAIL_DISABLE 0x068 ++#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) ++ ++#define GREG_SW_RST 0xff0 ++#define GREG_SW_RESET (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_GREG_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_hybrid.c b/drivers/media/common/saa716x/saa716x_hybrid.c +new file mode 100644 +index 0000000..27e5e71 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_hybrid.c +@@ -0,0 +1,726 @@ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_gpio_reg.h" ++#include "saa716x_greg_reg.h" ++#include "saa716x_msi_reg.h" ++ ++#include "saa716x_adap.h" ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_hybrid.h" ++#include "saa716x_gpio.h" ++#include "saa716x_rom.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#include "zl10353.h" ++#include "mb86a16.h" ++#include "tda1004x.h" ++#include "tda827x.h" ++ ++unsigned int verbose; ++module_param(verbose, int, 0644); ++MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); ++ ++unsigned int int_type; ++module_param(int_type, int, 0644); ++MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); ++ ++#define DRIVER_NAME "SAA716x Hybrid" ++ ++static int saa716x_hybrid_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) ++{ ++ struct saa716x_dev *saa716x; ++ int err = 0; ++ ++ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); ++ if (saa716x == NULL) { ++ printk(KERN_ERR "saa716x_hybrid_pci_probe ERROR: out of memory\n"); ++ err = -ENOMEM; ++ goto fail0; ++ } ++ ++ saa716x->verbose = verbose; ++ saa716x->int_type = int_type; ++ saa716x->pdev = pdev; ++ saa716x->config = (struct saa716x_config *) pci_id->driver_data; ++ ++ err = saa716x_pci_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_cgu_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_core_boot(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); ++ goto fail2; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); ++ ++ err = saa716x_msi_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); ++ goto fail2; ++ } ++ ++ err = saa716x_jetpack_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core Initialization failed"); ++ goto fail1; ++ } ++ ++ err = saa716x_i2c_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); ++ goto fail3; ++ } ++ ++ saa716x_gpio_init(saa716x); ++ ++ err = saa716x_dump_eeprom(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ err = saa716x_eeprom_data(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); ++ } ++ ++ /* enable decoders on 7162 */ ++ if (pdev->device == SAA7162) { ++ saa716x_gpio_set_output(saa716x, 24); ++ saa716x_gpio_set_output(saa716x, 25); ++ ++ saa716x_gpio_write(saa716x, 24, 0); ++ saa716x_gpio_write(saa716x, 25, 0); ++ ++ msleep(10); ++ ++ saa716x_gpio_write(saa716x, 24, 1); ++ saa716x_gpio_write(saa716x, 25, 1); ++ } ++ ++ /* set default port mapping */ ++ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F44); ++ /* enable FGPI3 and FGPI0 for TS input from Port 3 and 6 */ ++ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x894); ++ ++ err = saa716x_dvb_init(saa716x); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); ++ goto fail4; ++ } ++ ++ return 0; ++ ++fail4: ++ saa716x_dvb_exit(saa716x); ++fail3: ++ saa716x_i2c_exit(saa716x); ++fail2: ++ saa716x_pci_exit(saa716x); ++fail1: ++ kfree(saa716x); ++fail0: ++ return err; ++} ++ ++static void saa716x_hybrid_pci_remove(struct pci_dev *pdev) ++{ ++ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); ++ ++ saa716x_dvb_exit(saa716x); ++ saa716x_i2c_exit(saa716x); ++ saa716x_pci_exit(saa716x); ++ kfree(saa716x); ++} ++ ++static irqreturn_t saa716x_hybrid_pci_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ u32 stat_h, stat_l, mask_h, mask_l; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ ++ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ stat_l, stat_h, mask_l, mask_h); ++ ++ if (!((stat_l & mask_l) || (stat_h & mask_h))) ++ return IRQ_NONE; ++ ++ if (stat_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); ++ ++ if (stat_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); ++ ++ saa716x_msi_event(saa716x, stat_l, stat_h); ++#if 0 ++ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(VI0, INT_STATUS), ++ SAA716x_EPRD(VI1, INT_STATUS), ++ SAA716x_EPRD(VI0, INT_ENABLE), ++ SAA716x_EPRD(VI1, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", ++ SAA716x_EPRD(FGPI0, INT_STATUS), ++ SAA716x_EPRD(FGPI1, INT_STATUS), ++ SAA716x_EPRD(FGPI0, INT_ENABLE), ++ SAA716x_EPRD(FGPI0, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", ++ SAA716x_EPRD(FGPI2, INT_STATUS), ++ SAA716x_EPRD(FGPI3, INT_STATUS), ++ SAA716x_EPRD(FGPI2, INT_ENABLE), ++ SAA716x_EPRD(FGPI3, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(AI0, AI_STATUS), ++ SAA716x_EPRD(AI1, AI_STATUS), ++ SAA716x_EPRD(AI0, AI_CTL), ++ SAA716x_EPRD(AI1, AI_CTL)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_ENABLE), ++ SAA716x_EPRD(I2C_B, INT_ENABLE)); ++ ++ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", ++ SAA716x_EPRD(DCS, DCSC_INT_STATUS), ++ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); ++#endif ++ ++ if (stat_l) { ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) { ++ tasklet_schedule(&saa716x->fgpi[0].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) { ++ tasklet_schedule(&saa716x->fgpi[1].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) { ++ tasklet_schedule(&saa716x->fgpi[2].tasklet); ++ } ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) { ++ tasklet_schedule(&saa716x->fgpi[3].tasklet); ++ } ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static void demux_worker(unsigned long data) ++{ ++ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; ++ struct saa716x_dev *saa716x = fgpi_entry->saa716x; ++ struct dvb_demux *demux; ++ u32 fgpi_index; ++ u32 i; ++ u32 write_index; ++ ++ fgpi_index = fgpi_entry->dma_channel - 6; ++ demux = NULL; ++ for (i = 0; i < saa716x->config->adapters; i++) { ++ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { ++ demux = &saa716x->saa716x_adap[i].demux; ++ break; ++ } ++ } ++ if (demux == NULL) { ++ printk(KERN_ERR "%s: unexpected channel %u\n", ++ __func__, fgpi_entry->dma_channel); ++ return; ++ } ++ ++ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); ++ if (write_index < 0) ++ return; ++ ++ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); ++ ++ if (write_index == fgpi_entry->read_index) { ++ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); ++ return; ++ } ++ ++ do { ++ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; ++ ++ pci_dma_sync_sg_for_cpu(saa716x->pdev, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, ++ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, ++ PCI_DMA_FROMDEVICE); ++ ++ dvb_dmx_swfilter(demux, data, 348 * 188); ++ ++ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; ++ } while (write_index != fgpi_entry->read_index); ++} ++ ++/* ++ * Twinhan/Azurewave VP-6090 ++ * DVB-S Frontend: 2x MB86A16 ++ * DVB-T Frontend: 2x TDA10046 + TDA8275 ++ */ ++#define SAA716x_MODEL_TWINHAN_VP6090 "Twinhan/Azurewave VP-6090" ++#define SAA716x_DEV_TWINHAN_VP6090 "2xDVB-S + 2xDVB-T + 2xAnalog" ++ ++static int tda1004x_vp6090_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_vp6090_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_4M, ++ .agc_config = TDA10046_AGC_DEFAULT, ++ .if_freq = TDA10046_FREQ_3617, ++ .request_firmware = tda1004x_vp6090_request_firmware, ++}; ++ ++static int vp6090_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct saa716x_dev *saa716x = fe->dvb->priv; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); ++ break; ++ case SEC_VOLTAGE_18: ++ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); ++ break; ++ case SEC_VOLTAGE_OFF: ++ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); ++ break; ++ default: ++ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++struct mb86a16_config vp6090_mb86a16_config = { ++ .demod_address = 0x08, ++ .set_voltage = vp6090_dvbs_set_voltage, ++}; ++ ++static int saa716x_vp6090_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c = &saa716x->i2c[count]; ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); ++ ++ saa716x_gpio_set_output(saa716x, 11); ++ saa716x_gpio_set_output(saa716x, 10); ++ saa716x_gpio_write(saa716x, 11, 1); ++ saa716x_gpio_write(saa716x, 10, 1); ++ msleep(100); ++#if 0 ++ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); ++ adapter->fe = mb86a16_attach(&vp6090_mb86a16_config, &i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", ++ vp6090_mb86a16_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++#endif ++ adapter->fe = tda10046_attach(&tda1004x_vp6090_config, &i2c->i2c_adapter); ++ if (adapter->fe == NULL) { ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++ } else { ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++ ++ return 0; ++} ++ ++static struct saa716x_config saa716x_vp6090_config = { ++ .model_name = SAA716x_MODEL_TWINHAN_VP6090, ++ .dev_type = SAA716x_DEV_TWINHAN_VP6090, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_vp6090_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++/* ++ * NXP Reference design (Atlantis) ++ * 2x DVB-T Frontend: 2x TDA10046 ++ * Analog Decoder: 2x Internal ++ */ ++#define SAA716x_MODEL_NXP_ATLANTIS "Atlantis reference board" ++#define SAA716x_DEV_NXP_ATLANTIS "2x DVB-T + 2x Analog" ++ ++static int tda1004x_atlantis_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_atlantis_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_16M, ++ .agc_config = TDA10046_AGC_TDA827X, ++ .if_freq = TDA10046_FREQ_045, ++ .request_firmware = tda1004x_atlantis_request_firmware, ++ .tuner_address = 0x60, ++}; ++ ++static struct tda827x_config tda827x_atlantis_config = { ++ .init = NULL, ++ .sleep = NULL, ++ .config = 0, ++ .switch_addr = 0, ++ .agcf = NULL, ++}; ++ ++static int saa716x_atlantis_frontend_attach(struct saa716x_adapter *adapter, ++ int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *i2c; ++ u8 i2c_buf[3] = { 0x05, 0x23, 0x01 }; /* activate the silent I2C bus */ ++ struct i2c_msg msg = { ++ .addr = 0x42 >> 1, ++ .flags = 0, ++ .buf = i2c_buf, ++ .len = sizeof(i2c_buf) ++ }; ++ ++ if (count < saa716x->config->adapters) { ++ u32 reset_gpio; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", ++ count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, ++ saa716x->pdev->subsystem_device); ++ ++ if (count == 0) { ++ reset_gpio = 14; ++ i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; ++ } else { ++ reset_gpio = 15; ++ i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ } ++ ++ /* activate the silent I2C bus */ ++ i2c_transfer(&i2c->i2c_adapter, &msg, 1); ++ ++ saa716x_gpio_set_output(saa716x, reset_gpio); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, reset_gpio, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, reset_gpio, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, reset_gpio, 1); ++ msleep(10); ++ ++ adapter->fe = tda10046_attach(&tda1004x_atlantis_config, ++ &i2c->i2c_adapter); ++ if (adapter->fe == NULL) ++ goto exit; ++ ++ dprintk(SAA716x_ERROR, 1, ++ "found TDA10046 DVB-T frontend @0x%02x", ++ tda1004x_atlantis_config.demod_address); ++ ++ if (dvb_attach(tda827x_attach, adapter->fe, ++ tda1004x_atlantis_config.tuner_address, ++ &i2c->i2c_adapter, &tda827x_atlantis_config)) { ++ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", ++ tda1004x_atlantis_config.tuner_address); ++ } else { ++ goto exit; ++ } ++ ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ return 0; ++ } ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_atlantis_config = { ++ .model_name = SAA716x_MODEL_NXP_ATLANTIS, ++ .dev_type = SAA716x_DEV_NXP_ATLANTIS, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 2, ++ .frontend_attach = saa716x_atlantis_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ }, ++ { ++ /* Adapter 1 */ ++ .ts_port = 0, /* using FGPI 0 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++/* ++ * NXP Reference design (NEMO) ++ * DVB-T Frontend: 1x TDA10046 + TDA8275 ++ * Analog Decoder: External SAA7136 ++ */ ++#define SAA716x_MODEL_NXP_NEMO "NEMO reference board" ++#define SAA716x_DEV_NXP_NEMO "DVB-T + Analog" ++ ++static int tda1004x_nemo_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, ++ char *name) ++{ ++ struct saa716x_adapter *adapter = fe->dvb->priv; ++ ++ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); ++} ++ ++static struct tda1004x_config tda1004x_nemo_config = { ++ .demod_address = 0x8, ++ .invert = 0, ++ .invert_oclk = 0, ++ .xtal_freq = TDA10046_XTAL_16M, ++ .agc_config = TDA10046_AGC_TDA827X, ++ .if_freq = TDA10046_FREQ_045, ++ .request_firmware = tda1004x_nemo_request_firmware, ++ .tuner_address = 0x60, ++}; ++ ++static struct tda827x_config tda827x_nemo_config = { ++ .init = NULL, ++ .sleep = NULL, ++ .config = 0, ++ .switch_addr = 0, ++ .agcf = NULL, ++}; ++ ++static int saa716x_nemo_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ struct saa716x_i2c *demod_i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; ++ struct saa716x_i2c *tuner_i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; ++ ++ ++ if (count == 0) { ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); ++ ++ /* GPIO 26 controls a +15dB gain */ ++ saa716x_gpio_set_output(saa716x, 26); ++ saa716x_gpio_write(saa716x, 26, 0); ++ ++ saa716x_gpio_set_output(saa716x, 14); ++ ++ /* Reset the demodulator */ ++ saa716x_gpio_write(saa716x, 14, 1); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 14, 0); ++ msleep(10); ++ saa716x_gpio_write(saa716x, 14, 1); ++ msleep(10); ++ ++ adapter->fe = tda10046_attach(&tda1004x_nemo_config, ++ &demod_i2c->i2c_adapter); ++ if (adapter->fe) { ++ dprintk(SAA716x_ERROR, 1, "found TDA10046 DVB-T frontend @0x%02x", ++ tda1004x_nemo_config.demod_address); ++ ++ } else { ++ goto exit; ++ } ++ if (dvb_attach(tda827x_attach, adapter->fe, ++ tda1004x_nemo_config.tuner_address, ++ &tuner_i2c->i2c_adapter, &tda827x_nemo_config)) { ++ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", ++ tda1004x_nemo_config.tuner_address); ++ } else { ++ goto exit; ++ } ++ dprintk(SAA716x_ERROR, 1, "Done!"); ++ } ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_nemo_config = { ++ .model_name = SAA716x_MODEL_NXP_NEMO, ++ .dev_type = SAA716x_DEV_NXP_NEMO, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_nemo_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++ ++ .adap_config = { ++ { ++ /* Adapter 0 */ ++ .ts_port = 3, /* using FGPI 3 */ ++ .worker = demux_worker ++ } ++ } ++}; ++ ++ ++#define SAA716x_MODEL_AVERMEDIA_HC82 "Avermedia HC82 Express-54" ++#define SAA716x_DEV_AVERMEDIA_HC82 "DVB-T + Analog" ++ ++#if 0 ++static struct zl10353_config saa716x_averhc82_zl10353_config = { ++ .demod_address = 0x1f, ++ .adc_clock = 450560, ++ .if2 = 361667, ++ .no_tuner = 1, ++ .parallel_ts = 1, ++}; ++#endif ++ ++static int saa716x_averhc82_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++// adapter->fe = zl10353_attach(&saa716x_averhc82_zl10353_config, &i2c->i2c_adapter); ++ ++ ++ return 0; ++} ++ ++static struct saa716x_config saa716x_averhc82_config = { ++ .model_name = SAA716x_MODEL_AVERMEDIA_HC82, ++ .dev_type = SAA716x_DEV_AVERMEDIA_HC82, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_averhc82_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++#define SAA716x_MODEL_AVERMEDIA_H788 "Avermedia H788" ++#define SAA716x_DEV_AVERMEDIA_H788 "DVB-T + Analaog" ++ ++static int saa716x_averh88_frontend_attach(struct saa716x_adapter *adapter, int count) ++{ ++ struct saa716x_dev *saa716x = adapter->saa716x; ++ ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); ++ ++ return -ENODEV; ++} ++ ++static struct saa716x_config saa716x_averh788_config = { ++ .model_name = SAA716x_MODEL_AVERMEDIA_H788, ++ .dev_type = SAA716x_DEV_AVERMEDIA_H788, ++ .boot_mode = SAA716x_EXT_BOOT, ++ .adapters = 1, ++ .frontend_attach = saa716x_averh88_frontend_attach, ++ .irq_handler = saa716x_hybrid_pci_irq, ++ .i2c_rate = SAA716x_I2C_RATE_100, ++}; ++ ++static struct pci_device_id saa716x_hybrid_pci_table[] = { ++ ++ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6090, SAA7162, &saa716x_vp6090_config), ++ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_HC82, SAA7160, &saa716x_averhc82_config), ++ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_H788, SAA7160, &saa716x_averh788_config), ++ MAKE_ENTRY(KWORLD, KWORLD_DVB_T_PE310, SAA7162, &saa716x_atlantis_config), ++ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7162, &saa716x_atlantis_config), ++ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7160, &saa716x_nemo_config), ++ { } ++}; ++MODULE_DEVICE_TABLE(pci, saa716x_hybrid_pci_table); ++ ++static struct pci_driver saa716x_hybrid_pci_driver = { ++ .name = DRIVER_NAME, ++ .id_table = saa716x_hybrid_pci_table, ++ .probe = saa716x_hybrid_pci_probe, ++ .remove = saa716x_hybrid_pci_remove, ++}; ++ ++static int saa716x_hybrid_init(void) ++{ ++ return pci_register_driver(&saa716x_hybrid_pci_driver); ++} ++ ++static void saa716x_hybrid_exit(void) ++{ ++ return pci_unregister_driver(&saa716x_hybrid_pci_driver); ++} ++ ++module_init(saa716x_hybrid_init); ++module_exit(saa716x_hybrid_exit); ++ ++MODULE_DESCRIPTION("SAA716x Hybrid driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/common/saa716x/saa716x_hybrid.h b/drivers/media/common/saa716x/saa716x_hybrid.h +new file mode 100644 +index 0000000..df34a59 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_hybrid.h +@@ -0,0 +1,13 @@ ++#ifndef __SAA716x_HYBRID_H ++#define __SAA716x_HYBRID_H ++ ++#define TWINHAN_TECHNOLOGIES 0x1822 ++#define AVERMEDIA 0x1461 ++#define KWORLD 0x17DE ++ ++#define TWINHAN_VP_6090 0x0027 ++#define AVERMEDIA_HC82 0x2355 ++#define AVERMEDIA_H788 0x1455 ++#define KWORLD_DVB_T_PE310 0x7521 ++ ++#endif /* __SAA716x_HYBRID_H */ +diff --git a/drivers/media/common/saa716x/saa716x_i2c.c b/drivers/media/common/saa716x/saa716x_i2c.c +new file mode 100644 +index 0000000..91a091d +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_i2c.c +@@ -0,0 +1,734 @@ ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_i2c_reg.h" ++#include "saa716x_msi_reg.h" ++#include "saa716x_cgu_reg.h" ++ ++#include "saa716x_i2c.h" ++#include "saa716x_msi.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#define SAA716x_I2C_TXFAIL (I2C_ERROR_IBE | \ ++ I2C_ACK_INTER_MTNA | \ ++ I2C_FAILURE_INTER_MAF) ++ ++#define SAA716x_I2C_TXBUSY (I2C_TRANSMIT | \ ++ I2C_TRANSMIT_PROG) ++ ++#define SAA716x_I2C_RXBUSY (I2C_RECEIVE | \ ++ I2C_RECEIVE_CLEAR) ++ ++static const char* state[] = { ++ "Idle", ++ "DoneStop", ++ "Busy", ++ "TOscl", ++ "TOarb", ++ "DoneWrite", ++ "DoneRead", ++ "DoneWriteTO", ++ "DoneReadTO", ++ "NoDevice", ++ "NoACK", ++ "BUSErr", ++ "ArbLost", ++ "SEQErr", ++ "STErr" ++}; ++ ++int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus) ++{ ++ u32 stat, mask; ++ u32 *I2C_DEV; ++ ++ BUG_ON(saa716x == NULL); ++ I2C_DEV = saa716x->I2C_DEV; ++ ++ stat = SAA716x_EPRD(I2C_DEV[bus], INT_STATUS); ++ mask = SAA716x_EPRD(I2C_DEV[bus], INT_ENABLE); ++ saa716x->i2c[bus].i2c_stat = stat; ++ dprintk(SAA716x_DEBUG, 0, "Bus(%d) I2C event: Status=<%s> --> Stat=<%02x> Mask=<%02x>", ++ bus, state[stat], stat, mask); ++ ++ if (!(stat & mask)) ++ return -1; ++ ++ SAA716x_EPWR(I2C_DEV[bus], INT_CLR_STATUS, stat); ++ ++ if (stat & I2C_INTERRUPT_STFNF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPT_MTFNF) { ++ dprintk(SAA716x_DEBUG, 0, " "); ++ } ++ ++ if (stat & I2C_INTERRUPT_RFDA) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPTE_RFF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_INTERRUPT_STDR) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_MASTER_INTERRUPT_MTDR) { ++ dprintk(SAA716x_DEBUG, 0, " "); ++ } ++ ++ if (stat & I2C_ERROR_IBE) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_MODE_CHANGE_INTER_MSMC) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_RECEIVE_INTER_SRSD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_SLAVE_TRANSMIT_INTER_STSD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_ACK_INTER_MTNA) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_FAILURE_INTER_MAF) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ if (stat & I2C_INTERRUPT_MTD) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ return 0; ++} ++ ++static irqreturn_t saa716x_i2c_irq(int irq, void *dev_id) ++{ ++ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; ++ ++ if (unlikely(saa716x == NULL)) { ++ printk("%s: saa716x=NULL", __func__); ++ return IRQ_NONE; ++ } ++ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), ++ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_L), ++ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); ++ ++ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", ++ SAA716x_EPRD(I2C_A, INT_STATUS), ++ SAA716x_EPRD(I2C_B, INT_STATUS), ++ SAA716x_EPRD(I2C_A, INT_CLR_STATUS), ++ SAA716x_EPRD(I2C_B, INT_CLR_STATUS)); ++ ++ return IRQ_HANDLED; ++} ++ ++static void saa716x_term_xfer(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); /* Start: SCL/SDA High */ ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x00); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); ++ msleep(10); ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); ++ ++ return; ++} ++ ++static void saa716x_i2c_hwdeinit(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++} ++ ++static int saa716x_i2c_hwinit(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ struct i2c_adapter *adapter = &i2c->i2c_adapter; ++ ++ int i, err = 0; ++ u32 reg; ++ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & 0xd)) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed, Exiting !", ++ I2C_DEV, adapter->name); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* Flush queue */ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xcc); ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ ++ /* Reset I2C Core and generate a delay */ ++ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc1); ++ ++ for (i = 0; i < 100; i++) { ++ reg = SAA716x_EPRD(I2C_DEV, I2C_CONTROL); ++ if (reg == 0xc0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET", ++ I2C_DEV, adapter->name); ++ break; ++ } ++ msleep(1); ++ ++ if (i == 99) ++ err = -EIO; ++ } ++ ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed", ++ I2C_DEV, adapter->name); ++ ++ saa716x_term_xfer(i2c, I2C_DEV); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* I2C Rate Setup */ ++ switch (i2c->i2c_rate) { ++ case SAA716x_I2C_RATE_400: ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 400k", adapter->name); ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x1a); /* 0.5 * 27MHz/400kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x21); /* 0.5 * 27MHz/400kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x19); ++ break; ++ ++ case SAA716x_I2C_RATE_100: ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 100k", adapter->name); ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x68); /* 0.5 * 27MHz/100kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x87); /* 0.5 * 27MHz/100kHz */ ++ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x60); ++ break; ++ ++ default: ++ ++ dprintk(SAA716x_ERROR, 1, "Adapter %s Unknown Rate (Rate=0x%02x)", ++ adapter->name, ++ i2c->i2c_rate); ++ ++ break; ++ } ++ ++ /* Disable all interrupts and clear status */ ++ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ ++ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ /* Enabled interrupts: ++ * Master Transaction Done, ++ * Master Transaction Data Request ++ * (0x81) ++ */ ++ msleep(5); ++ ++ SAA716x_EPWR(I2C_DEV, INT_SET_ENABLE, ++ I2C_SET_ENABLE_MTDR | I2C_SET_ENABLE_MTD); ++ ++ /* Check interrupt enable status */ ++ reg = SAA716x_EPRD(I2C_DEV, INT_ENABLE); ++ if (reg != 0x81) { ++ ++ dprintk(SAA716x_ERROR, 1, ++ "Adapter (%d) %s Interrupt enable failed, Exiting !", ++ i, ++ adapter->name); ++ ++ err = -EIO; ++ goto exit; ++ } ++ } ++ ++ /* Check status */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & 0xd)) { ++ ++ dprintk(SAA716x_ERROR, 1, ++ "Adapter (%02x) %s has bad state, Exiting !", ++ I2C_DEV, ++ adapter->name); ++ ++ err = -EIO; ++ goto exit; ++ } ++#if 0 ++ saa716x_add_irqvector(saa716x, ++ i2c_vec[i].vector, ++ i2c_vec[i].edge, ++ i2c_vec[i].handler, ++ SAA716x_I2C_ADAPTER(i)); ++#endif ++ reg = SAA716x_EPRD(CGU, CGU_SCR_3); ++ dprintk(SAA716x_DEBUG, 1, "Adapter (%02x) Autowake <%d> Active <%d>", ++ I2C_DEV, ++ (reg >> 1) & 0x01, ++ reg & 0x01); ++ ++ return 0; ++exit: ++ return err; ++} ++ ++static int saa716x_i2c_send(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 data) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ int i, err = 0; ++ u32 reg; ++ ++ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ /* Write to FIFO */ ++ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); ++ return 0; ++ } ++ ++ /* Check FIFO status before TX */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ i2c->stat_tx_prior = reg; ++ if (reg & SAA716x_I2C_TXBUSY) { ++ for (i = 0; i < 100; i++) { ++ /* TODO! check for hotplug devices */ ++ msleep(10); ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ ++ if (reg & SAA716x_I2C_TXBUSY) { ++ dprintk(SAA716x_ERROR, 1, "FIFO full or Blocked"); ++ ++ err = saa716x_i2c_hwinit(i2c, I2C_DEV); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Error Reinit"); ++ err = -EIO; ++ goto exit; ++ } ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Write to FIFO */ ++ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); ++ ++ /* Check for data write */ ++ for (i = 0; i < 1000; i++) { ++ /* TODO! check for hotplug devices */ ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (reg & I2C_TRANSMIT_CLEAR) { ++ break; ++ } ++ } ++ i2c->stat_tx_done = reg; ++ ++ if (!(reg & I2C_TRANSMIT_CLEAR)) { ++ dprintk(SAA716x_ERROR, 1, "TXFIFO not empty after Timeout, tried %d loops!", i); ++ err = -EIO; ++ goto exit; ++ } ++ ++ return err; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "I2C Send failed (Err=%d)", err); ++ return err; ++} ++ ++static int saa716x_i2c_recv(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 *data) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ int i, err = 0; ++ u32 reg; ++ ++ /* Check FIFO status before RX */ ++ for (i = 0; i < 1000; i++) { ++ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); ++ if (!(reg & SAA716x_I2C_RXBUSY)) { ++ break; ++ } ++ } ++ if (reg & SAA716x_I2C_RXBUSY) { ++ dprintk(SAA716x_INFO, 1, "FIFO empty"); ++ err = -EIO; ++ goto exit; ++ } ++ ++ /* Read from FIFO */ ++ *data = SAA716x_EPRD(I2C_DEV, RX_FIFO); ++ ++ return 0; ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error Reading data, err=%d", err); ++ return err; ++} ++ ++static void saa716x_i2c_irq_start(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) ++ return; ++ ++ i2c->i2c_op = 1; ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++} ++ ++static int saa716x_i2c_irq_wait(struct saa716x_i2c *i2c, u32 I2C_DEV) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ unsigned long timeout; ++ int err = 0; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) ++ return 0; ++ ++ timeout = HZ/100 + 1; /* 10ms */ ++ timeout = wait_event_interruptible_timeout(i2c->i2c_wq, i2c->i2c_op == 0, timeout); ++ if (timeout == -ERESTARTSYS || i2c->i2c_op) { ++ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); ++ if (timeout == -ERESTARTSYS) { ++ /* a signal arrived */ ++ err = -ERESTARTSYS; ++ } else { ++ dprintk(SAA716x_ERROR, 1, "timed out waiting for end of xfer!"); ++ err = -EIO; ++ } ++ } ++ return err; ++} ++ ++static int saa716x_i2c_write_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, ++ u16 addr, u8 *buf, u16 len, u8 add_stop) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ u32 data; ++ int err; ++ int i; ++ int bytes; ++ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ ++ /* first write START with I2C address */ ++ data = I2C_START_BIT | (addr << 1); ++ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Address write failed"); ++ goto exit; ++ } ++ ++ bytes = i2c->block_size - 1; ++ ++ /* now write the data */ ++ while (len > 0) { ++ if (bytes == i2c->block_size) { ++ /* this is not the first round, so restart irq */ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ } ++ ++ if (bytes > len) ++ bytes = len; ++ ++ for (i = 0; i < bytes; i++) { ++ data = buf[i]; ++ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n", i, data); ++ if (add_stop && i == (len - 1)) ++ data |= I2C_STOP_BIT; ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data send failed"); ++ goto exit; ++ } ++ } ++ ++ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); ++ if (err < 0) { ++ goto exit; ++ } ++ ++ len -= bytes; ++ buf += bytes; ++ bytes = i2c->block_size; ++ } ++ ++ return 0; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error writing data, err=%d", err); ++ return err; ++} ++ ++static int saa716x_i2c_read_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, ++ u16 addr, u8 *buf, u16 len, u8 add_stop) ++{ ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ u32 data; ++ int err; ++ int i; ++ int bytes; ++ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ ++ /* first write START with I2C address */ ++ data = I2C_START_BIT | (addr << 1) | 1; ++ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Address write failed"); ++ goto exit; ++ } ++ ++ bytes = i2c->block_size - 1; ++ ++ /* now read the data */ ++ while (len > 0) { ++ if (bytes == i2c->block_size) { ++ /* this is not the first round, so restart irq */ ++ saa716x_i2c_irq_start(i2c, I2C_DEV); ++ } ++ ++ if (bytes > len) ++ bytes = len; ++ ++ for (i = 0; i < bytes; i++) { ++ data = 0x00; /* dummy write for reading */ ++ if (add_stop && i == (len - 1)) ++ data |= I2C_STOP_BIT; ++ err = saa716x_i2c_send(i2c, I2C_DEV, data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data send failed"); ++ goto exit; ++ } ++ } ++ ++ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); ++ if (err < 0) { ++ goto exit; ++ } ++ ++ for (i = 0; i < bytes; i++) { ++ err = saa716x_i2c_recv(i2c, I2C_DEV, &data); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Data receive failed"); ++ goto exit; ++ } ++ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n\n", i, data); ++ buf[i] = data; ++ } ++ ++ len -= bytes; ++ buf += bytes; ++ bytes = i2c->block_size; ++ } ++ ++ return 0; ++ ++exit: ++ dprintk(SAA716x_ERROR, 1, "Error reading data, err=%d", err); ++ return err; ++} ++ ++static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) ++{ ++ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); ++ struct saa716x_dev *saa716x = i2c->saa716x; ++ ++ u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); ++ int i, j, err = 0; ++ int t; ++ ++ dprintk(SAA716x_DEBUG, 0, "\n"); ++ dprintk(SAA716x_DEBUG, 1, "Bus(%02x) I2C transfer", DEV); ++ mutex_lock(&i2c->i2c_lock); ++ ++ for (t = 0; t < 3; t++) { ++ for (i = 0; i < num; i++) { ++ if (msgs[i].flags & I2C_M_RD) ++ err = saa716x_i2c_read_msg(i2c, DEV, ++ msgs[i].addr, msgs[i].buf, msgs[i].len, ++ i == (num - 1)); ++ else ++ err = saa716x_i2c_write_msg(i2c, DEV, ++ msgs[i].addr, msgs[i].buf, msgs[i].len, ++ i == (num - 1)); ++ if (err < 0) { ++ err = -EIO; ++ goto retry; ++ } ++ } ++ break; ++retry: ++ dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); ++ for (i = 0; i < num; i++) { ++ dprintk(SAA716x_INFO, 1, "msg %d, addr = 0x%02x, len=%d, flags=0x%x", ++ i, msgs[i].addr, msgs[i].len, msgs[i].flags); ++ if (!(msgs[i].flags & I2C_M_RD)) { ++ for (j = 0; j < msgs[i].len; j++) { ++ dprintk(SAA716x_INFO, 1, " 0x%02x", ++ j, msgs[i].buf[j]); ++ } ++ } ++ } ++ err = saa716x_i2c_hwinit(i2c, DEV); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Error Reinit"); ++ err = -EIO; ++ goto bail_out; ++ } ++ } ++ ++ mutex_unlock(&i2c->i2c_lock); ++ return num; ++ ++bail_out: ++ dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); ++ mutex_unlock(&i2c->i2c_lock); ++ return err; ++} ++ ++static u32 saa716x_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_SMBUS_EMUL; ++} ++ ++static const struct i2c_algorithm saa716x_algo = { ++ .master_xfer = saa716x_i2c_xfer, ++ .functionality = saa716x_i2c_func, ++}; ++ ++struct saa716x_i2cvec { ++ u32 vector; ++ enum saa716x_edge edge; ++ irqreturn_t (*handler)(int irq, void *dev_id); ++}; ++ ++static const struct saa716x_i2cvec i2c_vec[] = { ++ { ++ .vector = I2CINT_0, ++ .edge = SAA716x_EDGE_RISING, ++ .handler = saa716x_i2c_irq ++ }, { ++ .vector = I2CINT_1, ++ .edge = SAA716x_EDGE_RISING, ++ .handler = saa716x_i2c_irq ++ } ++}; ++ ++int saa716x_i2c_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = NULL; ++ ++ int i, err = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", ++ saa716x->pdev->device); ++ ++ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { ++ ++ mutex_init(&i2c->i2c_lock); ++ ++ init_waitqueue_head(&i2c->i2c_wq); ++ i2c->i2c_op = 0; ++ ++ i2c->i2c_dev = i; ++ i2c->i2c_rate = saa716x->config->i2c_rate; ++ i2c->i2c_mode = saa716x->config->i2c_mode; ++ adapter = &i2c->i2c_adapter; ++ ++ if (i2c->i2c_mode == SAA716x_I2C_MODE_IRQ_BUFFERED) ++ i2c->block_size = 8; ++ else ++ i2c->block_size = 1; ++ ++ if (adapter != NULL) { ++ ++ i2c_set_adapdata(adapter, i2c); ++ ++ strcpy(adapter->name, SAA716x_I2C_ADAPTER(i)); ++ ++ adapter->owner = THIS_MODULE; ++ adapter->algo = &saa716x_algo; ++ adapter->algo_data = NULL; ++ adapter->timeout = 500; /* FIXME ! */ ++ adapter->retries = 3; /* FIXME ! */ ++ adapter->dev.parent = &pdev->dev; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing adapter (%d) %s", ++ i, ++ adapter->name); ++ ++ err = i2c_add_adapter(adapter); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s init failed", i, adapter->name); ++ goto exit; ++ } ++ ++ i2c->saa716x = saa716x; ++ saa716x_i2c_hwinit(i2c, SAA716x_I2C_BUS(i)); ++ } ++ i2c++; ++ } ++ ++ if (saa716x->config->i2c_mode >= SAA716x_I2C_MODE_IRQ) { ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_0); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_1); ++ } ++ ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully initialized", ++ saa716x->pdev->device); ++ ++ return 0; ++exit: ++ return err; ++} ++EXPORT_SYMBOL_GPL(saa716x_i2c_init); ++ ++int saa716x_i2c_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = NULL; ++ int i, err = 0; ++ ++ dprintk(SAA716x_DEBUG, 1, "Removing SAA%02x I2C Core", saa716x->pdev->device); ++ ++ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { ++ ++ adapter = &i2c->i2c_adapter; ++#if 0 ++ saa716x_remove_irqvector(saa716x, i2c_vec[i].vector); ++#endif ++ saa716x_i2c_hwdeinit(i2c, SAA716x_I2C_BUS(i)); ++ dprintk(SAA716x_DEBUG, 1, "Removing adapter (%d) %s", i, adapter->name); ++ ++ i2c_del_adapter(adapter); ++ i2c++; ++ } ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully removed", saa716x->pdev->device); ++ ++ return 0; ++ ++exit: ++ return err; ++} ++EXPORT_SYMBOL_GPL(saa716x_i2c_exit); +diff --git a/drivers/media/common/saa716x/saa716x_i2c.h b/drivers/media/common/saa716x/saa716x_i2c.h +new file mode 100644 +index 0000000..da767ac +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_i2c.h +@@ -0,0 +1,52 @@ ++#ifndef __SAA716x_I2C_H ++#define __SAA716x_I2C_H ++ ++#define SAA716x_I2C_ADAPTERS 2 ++ ++#define SAA716x_I2C_ADAPTER(__dev) (( \ ++ (__dev == 1) ? \ ++ "SAA716x I2C Core 1" : \ ++ "SAA716x I2C Core 0")) ++ ++#define SAA716x_I2C_BUS(__x) ((__x == 1) ? 0x0000c000 : 0x0000b000) ++ ++#define SAA716x_I2C_BUS_A 0x01 ++#define SAA716x_I2C_BUS_B 0x00 ++ ++struct saa716x_dev; ++ ++enum saa716x_i2c_rate { ++ SAA716x_I2C_RATE_400 = 1, ++ SAA716x_I2C_RATE_100, ++}; ++ ++enum saa716x_i2c_mode { ++ SAA716x_I2C_MODE_POLLING = 0, ++ SAA716x_I2C_MODE_IRQ, ++ SAA716x_I2C_MODE_IRQ_BUFFERED ++}; ++ ++struct saa716x_i2c { ++ struct i2c_adapter i2c_adapter; ++ struct mutex i2c_lock; ++ struct saa716x_dev *saa716x; ++ u8 i2c_dev; ++ ++ enum saa716x_i2c_rate i2c_rate; /* run time */ ++ enum saa716x_i2c_mode i2c_mode; ++ u32 block_size; /* block size for buffered ++ mode, 1 otherwise */ ++ u32 i2c_stat; ++ ++ u32 stat_tx_prior; ++ u32 stat_tx_done; ++ wait_queue_head_t i2c_wq; ++ int i2c_op; ++}; ++ ++extern int saa716x_i2c_init(struct saa716x_dev *saa716x); ++extern int saa716x_i2c_exit(struct saa716x_dev *saa716x); ++extern void saa716x_i2cint_disable(struct saa716x_dev *saa716x); ++extern int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus); ++ ++#endif /* __SAA716x_I2C_H */ +diff --git a/drivers/media/common/saa716x/saa716x_i2c_reg.h b/drivers/media/common/saa716x/saa716x_i2c_reg.h +new file mode 100644 +index 0000000..8fa992c +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_i2c_reg.h +@@ -0,0 +1,145 @@ ++#ifndef __SAA716x_I2C_REG_H ++#define __SAA716x_I2C_REG_H ++ ++/* -------------- I2C Registers -------------- */ ++ ++#define RX_FIFO 0x000 ++#define I2C_RX_BYTE (0x000000ff << 0) ++ ++#define TX_FIFO 0x000 ++#define I2C_STOP_BIT (0x00000001 << 9) ++#define I2C_START_BIT (0x00000001 << 8) ++#define I2C_TX_BYTE (0x000000ff << 0) ++ ++#define I2C_STATUS 0x008 ++#define I2C_TRANSMIT (0x00000001 << 11) ++#define I2C_RECEIVE (0x00000001 << 10) ++#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) ++#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) ++#define I2C_TRANSMIT_PROG (0x00000001 << 7) ++#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) ++#define I2C_RECEIVE_PROG (0x00000001 << 5) ++#define I2C_RECEIVE_CLEAR (0x00000001 << 4) ++#define I2C_SDA_LINE (0x00000001 << 3) ++#define I2C_SCL_LINE (0x00000001 << 2) ++#define I2C_START_STOP_FLAG (0x00000001 << 1) ++#define I2C_MODE_STATUS (0x00000001 << 0) ++ ++#define I2C_CONTROL 0x00c ++#define I2C_SCL_CONTROL (0x00000001 << 7) ++#define I2C_SDA_CONTROL (0x00000001 << 6) ++#define I2C_RECEIVE_PROTECT (0x00000001 << 5) ++#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) ++#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) ++#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) ++#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) ++#define I2C_RESET (0x00000001 << 0) ++ ++#define I2C_CLOCK_DIVISOR_HIGH 0x010 ++#define I2C_CLOCK_HIGH (0x0000ffff << 0) ++ ++#define I2C_CLOCK_DIVISOR_LOW 0x014 ++#define I2C_CLOCK_LOW (0x0000ffff << 0) ++ ++#define I2C_RX_LEVEL 0x01c ++#define I2C_RECEIVE_RANGE (0x0000007f << 0) ++ ++#define I2C_TX_LEVEL 0x020 ++#define I2C_TRANSMIT_RANGE (0x0000007f << 0) ++ ++#define I2C_SDA_HOLD 0x028 ++#define I2C_HOLD_TIME (0x0000007f << 0) ++ ++#define MODULE_CONF 0xfd4 ++#define INT_CLR_ENABLE 0xfd8 ++#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) ++#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) ++#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) ++#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) ++#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) ++#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_SET_ENABLE 0xfdc ++#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_SET_ENABLE_RFF (0x00000001 << 9) ++#define I2C_SET_ENABLE_STDR (0x00000001 << 8) ++#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_SET_ENABLE_IBE (0x00000001 << 6) ++#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_SET_ENABLE_STSD (0x00000001 << 3) ++#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_SET_ENABLE_MAF (0x00000001 << 1) ++#define I2C_SET_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_STATUS 0xfe0 ++#define I2C_INTERRUPT_STFNF (0x00000001 << 12) ++#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) ++#define I2C_INTERRUPT_RFDA (0x00000001 << 10) ++#define I2C_INTERRUPTE_RFF (0x00000001 << 9) ++#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) ++#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) ++#define I2C_ERROR_IBE (0x00000001 << 6) ++#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) ++#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) ++#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) ++#define I2C_ACK_INTER_MTNA (0x00000001 << 2) ++#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) ++#define I2C_INTERRUPT_MTD (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define I2C_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_ENABLE_RFF (0x00000001 << 9) ++#define I2C_ENABLE_STDR (0x00000001 << 8) ++#define I2C_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_ENABLE_IBE (0x00000001 << 6) ++#define I2C_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_ENABLE_STSD (0x00000001 << 3) ++#define I2C_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_ENABLE_MAF (0x00000001 << 1) ++#define I2C_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) ++#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) ++#define I2C_CLR_STATUS_RFF (0x00000001 << 9) ++#define I2C_CLR_STATUS_STDR (0x00000001 << 8) ++#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) ++#define I2C_CLR_STATUS_IBE (0x00000001 << 6) ++#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) ++#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) ++#define I2C_CLR_STATUS_STSD (0x00000001 << 3) ++#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) ++#define I2C_CLR_STATUS_MAF (0x00000001 << 1) ++#define I2C_CLR_STATIS_MTD (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define I2C_SET_STATUS_STFNF (0x00000001 << 12) ++#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_SET_STATUS_RFDA (0x00000001 << 10) ++#define I2C_SET_STATUS_RFF (0x00000001 << 9) ++#define I2C_SET_STATUS_STDR (0x00000001 << 8) ++#define I2C_SET_STATUS_MTDR (0x00000001 << 7) ++#define I2C_SET_STATUS_IBE (0x00000001 << 6) ++#define I2C_SET_STATUS_MSMC (0x00000001 << 5) ++#define I2C_SET_STATUS_SRSD (0x00000001 << 4) ++#define I2C_SET_STATUS_STSD (0x00000001 << 3) ++#define I2C_SET_STATUS_MTNA (0x00000001 << 2) ++#define I2C_SET_STATUS_MAF (0x00000001 << 1) ++#define I2C_SET_STATIS_MTD (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_I2C_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_mod.h b/drivers/media/common/saa716x/saa716x_mod.h +new file mode 100644 +index 0000000..273efdd +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_mod.h +@@ -0,0 +1,50 @@ ++#ifndef __SAA716x_MOD_H ++#define __SAA716x_MOD_H ++ ++/* BAR = 17 bits */ ++/* ++ VI0 0x00000000 ++ VI1 0x00001000 ++ FGPI0 0x00002000 ++ FGPI1 0x00003000 ++ FGPI2 0x00004000 ++ FGPI3 0x00005000 ++ AI0 0x00006000 ++ AI1 0x00007000 ++ BAM 0x00008000 ++ MMU 0x00009000 ++ MSI 0x0000a000 ++ I2C_B 0x0000b000 ++ I2C_A 0x0000c000 ++ SPI 0x0000d000 ++ GPIO 0x0000e000 ++ PHI_0 0x0000f000 ++ CGU 0x00013000 ++ DCS 0x00014000 ++ GREG 0x00012000 ++ ++ PHI_1 0x00020000 ++*/ ++ ++#define VI0 0x00000000 ++#define VI1 0x00001000 ++#define FGPI0 0x00002000 ++#define FGPI1 0x00003000 ++#define FGPI2 0x00004000 ++#define FGPI3 0x00005000 ++#define AI0 0x00006000 ++#define AI1 0x00007000 ++#define BAM 0x00008000 ++#define MMU 0x00009000 ++#define MSI 0x0000a000 ++#define I2C_B 0x0000b000 ++#define I2C_A 0x0000c000 ++#define SPI 0x0000d000 ++#define GPIO 0x0000e000 ++#define PHI_0 0x0000f000 ++#define GREG 0x00012000 ++#define CGU 0x00013000 ++#define DCS 0x00014000 ++#define PHI_1 0x00020000 ++ ++#endif /* __SAA716x_MOD_H */ +diff --git a/drivers/media/common/saa716x/saa716x_msi.c b/drivers/media/common/saa716x/saa716x_msi.c +new file mode 100644 +index 0000000..b0f05a2 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_msi.c +@@ -0,0 +1,479 @@ ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_msi_reg.h" ++#include "saa716x_msi.h" ++#include "saa716x_spi.h" ++ ++#include "saa716x_priv.h" ++ ++#define SAA716x_MSI_VECTORS 50 ++ ++static const char *vector_name[] = { ++ "TAGACK_VI0_0", ++ "TAGACK_VI0_1", ++ "TAGACK_VI0_2", ++ "TAGACK_VI1_0", ++ "TAGACK_VI1_1", ++ "TAGACK_VI1_2", ++ "TAGACK_FGPI_0", ++ "TAGACK_FGPI_1", ++ "TAGACK_FGPI_2", ++ "TAGACK_FGPI_3", ++ "TAGACK_AI_0", ++ "TAGACK_AI_1", ++ "OVRFLW_VI0_0", ++ "OVRFLW_VI0_1", ++ "OVRFLW_VI0_2", ++ "OVRFLW_VI1_0", ++ "OVRFLW_VI1_1", ++ "OVRFLW_VI1_2", ++ "OVRFLW_FGPI_O", ++ "OVRFLW_FGPI_1", ++ "OVRFLW_FGPI_2", ++ "OVRFLW_FGPI_3", ++ "OVRFLW_AI_0", ++ "OVRFLW_AI_1", ++ "AVINT_VI0", ++ "AVINT_VI1", ++ "AVINT_FGPI_0", ++ "AVINT_FGPI_1", ++ "AVINT_FGPI_2", ++ "AVINT_FGPI_3", ++ "AVINT_AI_0", ++ "AVINT_AI_1", ++ "UNMAPD_TC_INT", ++ "EXTINT_0", ++ "EXTINT_1", ++ "EXTINT_2", ++ "EXTINT_3", ++ "EXTINT_4", ++ "EXTINT_5", ++ "EXTINT_6", ++ "EXTINT_7", ++ "EXTINT_8", ++ "EXTINT_9", ++ "EXTINT_10", ++ "EXTINT_11", ++ "EXTINT_12", ++ "EXTINT_13", ++ "EXTINT_14", ++ "EXTINT_15", ++ "I2CINT_0", ++ "I2CINT_1" ++}; ++ ++static u32 MSI_CONFIG_REG[51] = { ++ MSI_CONFIG0, ++ MSI_CONFIG1, ++ MSI_CONFIG2, ++ MSI_CONFIG3, ++ MSI_CONFIG4, ++ MSI_CONFIG5, ++ MSI_CONFIG6, ++ MSI_CONFIG7, ++ MSI_CONFIG8, ++ MSI_CONFIG9, ++ MSI_CONFIG10, ++ MSI_CONFIG11, ++ MSI_CONFIG12, ++ MSI_CONFIG13, ++ MSI_CONFIG14, ++ MSI_CONFIG15, ++ MSI_CONFIG16, ++ MSI_CONFIG17, ++ MSI_CONFIG18, ++ MSI_CONFIG19, ++ MSI_CONFIG20, ++ MSI_CONFIG21, ++ MSI_CONFIG22, ++ MSI_CONFIG23, ++ MSI_CONFIG24, ++ MSI_CONFIG25, ++ MSI_CONFIG26, ++ MSI_CONFIG27, ++ MSI_CONFIG28, ++ MSI_CONFIG29, ++ MSI_CONFIG30, ++ MSI_CONFIG31, ++ MSI_CONFIG32, ++ MSI_CONFIG33, ++ MSI_CONFIG34, ++ MSI_CONFIG35, ++ MSI_CONFIG36, ++ MSI_CONFIG37, ++ MSI_CONFIG38, ++ MSI_CONFIG39, ++ MSI_CONFIG40, ++ MSI_CONFIG41, ++ MSI_CONFIG42, ++ MSI_CONFIG43, ++ MSI_CONFIG44, ++ MSI_CONFIG45, ++ MSI_CONFIG46, ++ MSI_CONFIG47, ++ MSI_CONFIG48, ++ MSI_CONFIG49, ++ MSI_CONFIG50 ++}; ++ ++int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h) ++{ ++ dprintk(SAA716x_DEBUG, 0, "%s: MSI event ", __func__); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[0]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[1]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI0_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[2]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[3]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[4]); ++ ++ if (stat_l & MSI_INT_TAGACK_VI1_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[5]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[6]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[7]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[8]); ++ ++ if (stat_l & MSI_INT_TAGACK_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[9]); ++ ++ if (stat_l & MSI_INT_TAGACK_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[10]); ++ ++ if (stat_l & MSI_INT_TAGACK_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[11]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[12]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[13]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI0_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[14]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[15]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[16]); ++ ++ if (stat_l & MSI_INT_OVRFLW_VI1_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[17]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[18]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[19]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[20]); ++ ++ if (stat_l & MSI_INT_OVRFLW_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[21]); ++ ++ if (stat_l & MSI_INT_OVRFLW_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[22]); ++ ++ if (stat_l & MSI_INT_OVRFLW_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[23]); ++ ++ if (stat_l & MSI_INT_AVINT_VI0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[24]); ++ ++ if (stat_l & MSI_INT_AVINT_VI1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[25]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[26]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[27]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[28]); ++ ++ if (stat_l & MSI_INT_AVINT_FGPI_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[29]); ++ ++ if (stat_l & MSI_INT_AVINT_AI_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[30]); ++ ++ if (stat_l & MSI_INT_AVINT_AI_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[31]); ++ ++ if (stat_h & MSI_INT_UNMAPD_TC_INT) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[32]); ++ ++ if (stat_h & MSI_INT_EXTINT_0) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[33]); ++ ++ if (stat_h & MSI_INT_EXTINT_1) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[34]); ++ ++ if (stat_h & MSI_INT_EXTINT_2) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[35]); ++ ++ if (stat_h & MSI_INT_EXTINT_3) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[36]); ++ ++ if (stat_h & MSI_INT_EXTINT_4) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[37]); ++ ++ if (stat_h & MSI_INT_EXTINT_5) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[38]); ++ ++ if (stat_h & MSI_INT_EXTINT_6) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[39]); ++ ++ if (stat_h & MSI_INT_EXTINT_7) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[40]); ++ ++ if (stat_h & MSI_INT_EXTINT_8) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[41]); ++ ++ if (stat_h & MSI_INT_EXTINT_9) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[42]); ++ ++ if (stat_h & MSI_INT_EXTINT_10) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[43]); ++ ++ if (stat_h & MSI_INT_EXTINT_11) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[44]); ++ ++ if (stat_h & MSI_INT_EXTINT_12) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[45]); ++ ++ if (stat_h & MSI_INT_EXTINT_13) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[46]); ++ ++ if (stat_h & MSI_INT_EXTINT_14) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[47]); ++ ++ if (stat_h & MSI_INT_EXTINT_15) ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[48]); ++ ++ if (stat_h & MSI_INT_I2CINT_0) { ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[49]); ++ saa716x_i2c_irqevent(saa716x, 0); ++ } ++ ++ if (stat_h & MSI_INT_I2CINT_1) { ++ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[50]); ++ saa716x_i2c_irqevent(saa716x, 1); ++ } ++ ++ dprintk(SAA716x_DEBUG, 0, "\n"); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_msi_event); ++ ++int saa716x_msi_init(struct saa716x_dev *saa716x) ++{ ++ u32 ena_l, ena_h, sta_l, sta_h, mid; ++ int i; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing MSI .."); ++ saa716x->handlers = 0; ++ ++ /* get module id & version */ ++ mid = SAA716x_EPRD(MSI, MSI_MODULE_ID); ++ if (mid != 0x30100) ++ dprintk(SAA716x_ERROR, 1, "MSI Id<%04x> is not supported", mid); ++ ++ /* let HW take care of MSI race */ ++ SAA716x_EPWR(MSI, MSI_DELAY_TIMER, 0x0); ++ ++ /* INTA Polarity: Active High */ ++ SAA716x_EPWR(MSI, MSI_INTA_POLARITY, MSI_INTA_POLARITY_HIGH); ++ ++ /* ++ * IRQ Edge Rising: 25:24 = 0x01 ++ * Traffic Class: 18:16 = 0x00 ++ * MSI ID: 4:0 = 0x00 ++ */ ++ for (i = 0; i < SAA716x_MSI_VECTORS; i++) ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[i], MSI_INT_POL_EDGE_RISE); ++ ++ /* get Status */ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ ++ /* disable and clear enabled and asserted IRQ's */ ++ if (sta_l) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, sta_l); ++ ++ if (sta_h) ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, sta_h); ++ ++ if (ena_l) ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, ena_l); ++ ++ if (ena_h) ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, ena_h); ++ ++ msleep(5); ++ ++ /* Check IRQ's really disabled */ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); ++ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); ++ ++ if ((ena_l == 0) && (ena_h == 0) && (sta_l == 0) && (sta_h == 0)) { ++ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x> sta_l <%02x> sta_h <%02x>", ++ ena_l, ena_h, sta_l, sta_h); ++ ++ return 0; ++ } else { ++ dprintk(SAA716x_DEBUG, 1, "I/O error"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_msi_init); ++ ++void saa716x_msiint_disable(struct saa716x_dev *saa716x) ++{ ++ dprintk(SAA716x_DEBUG, 1, "Disabling Interrupts ..."); ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_L, 0x0); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_H, 0x0); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0xffffffff); ++ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0x0000ffff); ++} ++EXPORT_SYMBOL_GPL(saa716x_msiint_disable); ++ ++ ++/* Map the given vector Id to the hardware bitmask. */ ++static void saa716x_map_vector(struct saa716x_dev *saa716x, int vector, u32 *mask_l, u32 *mask_h) ++{ ++ u32 tmp = 1; ++ ++ if (vector < 32) { ++ /* Bits 0 - 31 */ ++ tmp <<= vector; ++ *mask_l = tmp; ++ *mask_h = 0; ++ } else { ++ /* Bits 32 - 48 */ ++ tmp <<= vector - 32; ++ *mask_l = 0; ++ *mask_h = tmp; ++ } ++} ++ ++int saa716x_add_irqvector(struct saa716x_dev *saa716x, ++ int vector, ++ enum saa716x_edge edge, ++ irqreturn_t (*handler)(int irq, void *dev_id), ++ char *desc) ++{ ++ struct saa716x_msix_entry *msix_handler = NULL; ++ ++ u32 config, mask_l, mask_h, ena_l, ena_h; ++ ++ BUG_ON(saa716x == NULL); ++ BUG_ON(vector > SAA716x_MSI_VECTORS); ++ dprintk(SAA716x_DEBUG, 1, "Adding Vector %d <%s>", vector, vector_name[vector]); ++ ++ if ((vector > 32) && (vector < 49)) { ++ config = SAA716x_EPRD(MSI, MSI_CONFIG_REG[vector]); ++ config &= 0xfcffffff; /* clear polarity */ ++ ++ switch (edge) { ++ default: ++ case SAA716x_EDGE_RISING: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x01000000); ++ break; ++ ++ case SAA716x_EDGE_FALLING: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x02000000); ++ break; ++ ++ case SAA716x_EDGE_ANY: ++ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x03000000); ++ break; ++ } ++ } ++ ++ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); ++ ++ /* add callback */ ++ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; ++ strcpy(msix_handler->desc, desc); ++ msix_handler->vector = vector; ++ msix_handler->handler = handler; ++ saa716x->handlers++; ++ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, mask_l); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, mask_h); ++ ++ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); ++ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); ++ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x>", ena_l, ena_h); ++ ++ return 0; ++} ++ ++int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector) ++{ ++ struct saa716x_msix_entry *msix_handler; ++ int i; ++ u32 mask_l, mask_h; ++ ++ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; ++ BUG_ON(msix_handler == NULL); ++ dprintk(SAA716x_DEBUG, 1, "Removing Vector %d <%s>", vector, vector_name[vector]); ++ ++ /* loop through the registered handlers */ ++ for (i = 0; i < saa716x->handlers; i++) { ++ ++ /* we found our vector */ ++ if (msix_handler->vector == vector) { ++ BUG_ON(msix_handler->handler == NULL); /* no handler yet */ ++ dprintk(SAA716x_DEBUG, 1, "Vector %d <%s> removed", ++ msix_handler->vector, ++ msix_handler->desc); ++ ++ /* check whether it is already released */ ++ if (msix_handler->handler) { ++ msix_handler->vector = 0; ++ msix_handler->handler = NULL; ++ saa716x->handlers--; ++ } ++ } ++ } ++ ++ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); ++ ++ /* disable vector */ ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, mask_l); ++ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, mask_h); ++ ++ return 0; ++} +diff --git a/drivers/media/common/saa716x/saa716x_msi.h b/drivers/media/common/saa716x/saa716x_msi.h +new file mode 100644 +index 0000000..8eb72d7 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_msi.h +@@ -0,0 +1,87 @@ ++#ifndef __SAA716x_MSI_H ++#define __SAA716x_MSI_H ++ ++#define TAGACK_VI0_0 0x000 ++#define TAGACK_VI0_1 0x001 ++#define TAGACK_VI0_2 0x002 ++#define TAGACK_VI1_0 0x003 ++#define TAGACK_VI1_1 0x004 ++#define TAGACK_VI1_2 0x005 ++#define TAGACK_FGPI_0 0x006 ++#define TAGACK_FGPI_1 0x007 ++#define TAGACK_FGPI_2 0x008 ++#define TAGACK_FGPI_3 0x009 ++#define TAGACK_AI_0 0x00a ++#define TAGACK_AI_1 0x00b ++#define OVRFLW_VI0_0 0x00c ++#define OVRFLW_VI0_1 0x00d ++#define OVRFLW_VI0_2 0x00e ++#define OVRFLW_VI1_0 0x00f ++#define OVRFLW_VI1_1 0x010 ++#define OVRFLW_VI1_2 0x011 ++#define OVRFLW_FGPI_O 0x012 ++#define OVRFLW_FGPI_1 0x013 ++#define OVRFLW_FGPI_2 0x014 ++#define OVRFLW_FGPI_3 0x015 ++#define OVRFLW_AI_0 0x016 ++#define OVRFLW_AI_1 0x017 ++#define AVINT_VI0 0x018 ++#define AVINT_VI1 0x019 ++#define AVINT_FGPI_0 0x01a ++#define AVINT_FGPI_1 0x01b ++#define AVINT_FGPI_2 0x01c ++#define AVINT_FGPI_3 0x01d ++#define AVINT_AI_0 0x01e ++#define AVINT_AI_1 0x01f ++#define UNMAPD_TC_INT 0x020 ++#define EXTINT_0 0x021 ++#define EXTINT_1 0x022 ++#define EXTINT_2 0x023 ++#define EXTINT_3 0x024 ++#define EXTINT_4 0x025 ++#define EXTINT_5 0x026 ++#define EXTINT_6 0x027 ++#define EXTINT_7 0x028 ++#define EXTINT_8 0x029 ++#define EXTINT_9 0x02a ++#define EXTINT_10 0x02b ++#define EXTINT_11 0x02c ++#define EXTINT_12 0x02d ++#define EXTINT_13 0x02e ++#define EXTINT_14 0x02f ++#define EXTINT_15 0x030 ++#define I2CINT_0 0x031 ++#define I2CINT_1 0x032 ++ ++#define SAA716x_TC0 0x000 ++#define SAA716x_TC1 0x001 ++#define SAA716x_TC2 0x002 ++#define SAA716x_TC3 0x003 ++#define SAA716x_TC4 0x004 ++#define SAA716x_TC5 0x005 ++#define SAA716x_TC6 0x006 ++#define SAA716x_TC7 0x007 ++ ++ ++enum saa716x_edge { ++ SAA716x_EDGE_RISING = 1, ++ SAA716x_EDGE_FALLING = 2, ++ SAA716x_EDGE_ANY = 3 ++}; ++ ++struct saa716x_dev; ++ ++extern int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h); ++ ++extern int saa716x_msi_init(struct saa716x_dev *saa716x); ++extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); ++ ++extern int saa716x_add_irqvector(struct saa716x_dev *saa716x, ++ int vector, ++ enum saa716x_edge edge, ++ irqreturn_t (*handler)(int irq, void *dev_id), ++ char *desc); ++ ++extern int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector); ++ ++#endif /* __SAA716x_MSI_H */ +diff --git a/drivers/media/common/saa716x/saa716x_msi_reg.h b/drivers/media/common/saa716x/saa716x_msi_reg.h +new file mode 100644 +index 0000000..d9a12c7 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_msi_reg.h +@@ -0,0 +1,143 @@ ++#ifndef __SAA716x_MSI_REG_H ++#define __SAA716x_MSI_REG_H ++ ++/* -------------- MSI Registers -------------- */ ++ ++#define MSI_DELAY_TIMER 0x000 ++#define MSI_DELAY_1CLK (0x00000001 << 0) ++#define MSI_DELAY_2CLK (0x00000002 << 0) ++ ++#define MSI_INTA_POLARITY 0x004 ++#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) ++ ++#define MSI_CONFIG0 0x008 ++#define MSI_CONFIG1 0x00c ++#define MSI_CONFIG2 0x010 ++#define MSI_CONFIG3 0x014 ++#define MSI_CONFIG4 0x018 ++#define MSI_CONFIG5 0x01c ++#define MSI_CONFIG6 0x020 ++#define MSI_CONFIG7 0x024 ++#define MSI_CONFIG8 0x028 ++#define MSI_CONFIG9 0x02c ++#define MSI_CONFIG10 0x030 ++#define MSI_CONFIG11 0x034 ++#define MSI_CONFIG12 0x038 ++#define MSI_CONFIG13 0x03c ++#define MSI_CONFIG14 0x040 ++#define MSI_CONFIG15 0x044 ++#define MSI_CONFIG16 0x048 ++#define MSI_CONFIG17 0x04c ++#define MSI_CONFIG18 0x050 ++#define MSI_CONFIG19 0x054 ++#define MSI_CONFIG20 0x058 ++#define MSI_CONFIG21 0x05c ++#define MSI_CONFIG22 0x060 ++#define MSI_CONFIG23 0x064 ++#define MSI_CONFIG24 0x068 ++#define MSI_CONFIG25 0x06c ++#define MSI_CONFIG26 0x070 ++#define MSI_CONFIG27 0x074 ++#define MSI_CONFIG28 0x078 ++#define MSI_CONFIG29 0x07c ++#define MSI_CONFIG30 0x080 ++#define MSI_CONFIG31 0x084 ++#define MSI_CONFIG32 0x088 ++#define MSI_CONFIG33 0x08c ++#define MSI_CONFIG34 0x090 ++#define MSI_CONFIG35 0x094 ++#define MSI_CONFIG36 0x098 ++#define MSI_CONFIG37 0x09c ++#define MSI_CONFIG38 0x0a0 ++#define MSI_CONFIG39 0x0a4 ++#define MSI_CONFIG40 0x0a8 ++#define MSI_CONFIG41 0x0ac ++#define MSI_CONFIG42 0x0b0 ++#define MSI_CONFIG43 0x0b4 ++#define MSI_CONFIG44 0x0b8 ++#define MSI_CONFIG45 0x0bc ++#define MSI_CONFIG46 0x0c0 ++#define MSI_CONFIG47 0x0c4 ++#define MSI_CONFIG48 0x0c8 ++#define MSI_CONFIG49 0x0cc ++#define MSI_CONFIG50 0x0d0 ++ ++#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) ++#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) ++#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) ++#define MSI_TC (0x00000007 << 16) ++#define MSI_ID (0x0000000f << 0) ++ ++#define MSI_INT_STATUS_L 0xfc0 ++#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) ++#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) ++#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) ++#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) ++#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) ++#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) ++#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) ++#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) ++#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) ++#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) ++#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) ++#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) ++#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) ++#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) ++#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) ++#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) ++#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) ++#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) ++#define MSI_INT_OVRFLW_FGPI_0 (0x00000001 << 18) ++#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) ++#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) ++#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) ++#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) ++#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) ++#define MSI_INT_AVINT_VI0 (0x00000001 << 24) ++#define MSI_INT_AVINT_VI1 (0x00000001 << 25) ++#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) ++#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) ++#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) ++#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) ++#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) ++#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) ++ ++#define MSI_INT_STATUS_H 0xfc4 ++#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) ++#define MSI_INT_EXTINT_0 (0x00000001 << 1) ++#define MSI_INT_EXTINT_1 (0x00000001 << 2) ++#define MSI_INT_EXTINT_2 (0x00000001 << 3) ++#define MSI_INT_EXTINT_3 (0x00000001 << 4) ++#define MSI_INT_EXTINT_4 (0x00000001 << 5) ++#define MSI_INT_EXTINT_5 (0x00000001 << 6) ++#define MSI_INT_EXTINT_6 (0x00000001 << 7) ++#define MSI_INT_EXTINT_7 (0x00000001 << 8) ++#define MSI_INT_EXTINT_8 (0x00000001 << 9) ++#define MSI_INT_EXTINT_9 (0x00000001 << 10) ++#define MSI_INT_EXTINT_10 (0x00000001 << 11) ++#define MSI_INT_EXTINT_11 (0x00000001 << 12) ++#define MSI_INT_EXTINT_12 (0x00000001 << 13) ++#define MSI_INT_EXTINT_13 (0x00000001 << 14) ++#define MSI_INT_EXTINT_14 (0x00000001 << 15) ++#define MSI_INT_EXTINT_15 (0x00000001 << 16) ++#define MSI_INT_I2CINT_0 (0x00000001 << 17) ++#define MSI_INT_I2CINT_1 (0x00000001 << 18) ++ ++#define MSI_INT_STATUS_CLR_L 0xfc8 ++#define MSI_INT_STATUS_CLR_H 0xfcc ++#define MSI_INT_STATUS_SET_L 0xfd0 ++#define MSI_INT_STATUS_SET_H 0xfd4 ++#define MSI_INT_ENA_L 0xfd8 ++#define MSI_INT_ENA_H 0xfdc ++#define MSI_INT_ENA_CLR_L 0xfe0 ++#define MSI_INT_ENA_CLR_H 0xfe4 ++#define MSI_INT_ENA_SET_L 0xfe8 ++#define MSI_INT_ENA_SET_H 0xfec ++ ++#define MSI_SW_RST 0xff0 ++#define MSI_SW_RESET (0x0001 << 0) ++ ++#define MSI_MODULE_ID 0xffc ++ ++ ++#endif /* __SAA716x_MSI_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_pci.c b/drivers/media/common/saa716x/saa716x_pci.c +new file mode 100644 +index 0000000..7fa6bad +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_pci.c +@@ -0,0 +1,275 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "saa716x_spi.h" ++#include "saa716x_msi.h" ++#include "saa716x_priv.h" ++ ++#define DRIVER_NAME "SAA716x Core" ++ ++static irqreturn_t saa716x_msi_handler(int irq, void *dev_id) ++{ ++ return IRQ_HANDLED; ++} ++ ++static int saa716x_enable_msi(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int err; ++ ++ err = pci_enable_msi(pdev); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "MSI enable failed <%d>", err); ++ return err; ++ } ++ ++ return err; ++} ++ ++static int saa716x_enable_msix(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int i, ret = 0; ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) ++ saa716x->msix_entries[i].entry = i; ++ ++ ret = pci_enable_msix(pdev, saa716x->msix_entries, SAA716x_MSI_MAX_VECTORS); ++ if (ret < 0) ++ dprintk(SAA716x_ERROR, 1, "MSI-X request failed <%d>", ret); ++ if (ret > 0) ++ dprintk(SAA716x_ERROR, 1, "Request exceeds available IRQ's <%d>", ret); ++ ++ return ret; ++} ++ ++static int saa716x_request_irq(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct saa716x_config *config = saa716x->config; ++ int i, ret = 0; ++ ++ if (saa716x->int_type == MODE_MSI) { ++ dprintk(SAA716x_DEBUG, 1, "Using MSI mode"); ++ ret = saa716x_enable_msi(saa716x); ++ } else if (saa716x->int_type == MODE_MSI_X) { ++ dprintk(SAA716x_DEBUG, 1, "Using MSI-X mode"); ++ ret = saa716x_enable_msix(saa716x); ++ } ++ ++ if (ret) { ++ dprintk(SAA716x_ERROR, 1, "INT-A Mode"); ++ saa716x->int_type = MODE_INTA; ++ } ++ ++ if (saa716x->int_type == MODE_MSI) { ++ ret = request_irq(pdev->irq, ++ config->irq_handler, ++ 0, ++ DRIVER_NAME, ++ saa716x); ++ ++ if (ret) { ++ pci_disable_msi(pdev); ++ dprintk(SAA716x_ERROR, 1, "MSI registration failed"); ++ ret = -EIO; ++ } ++ } ++ ++ if (saa716x->int_type == MODE_MSI_X) { ++ for (i = 0; SAA716x_MSI_MAX_VECTORS; i++) { ++ ret = request_irq(saa716x->msix_entries[i].vector, ++ saa716x->saa716x_msix_handler[i].handler, ++ IRQF_SHARED, ++ saa716x->saa716x_msix_handler[i].desc, ++ saa716x); ++ ++ dprintk(SAA716x_ERROR, 1, "%s @ 0x%p", saa716x->saa716x_msix_handler[i].desc, saa716x->saa716x_msix_handler[i].handler); ++ if (ret) { ++ dprintk(SAA716x_ERROR, 1, "%s MSI-X-%d registration failed <%d>", saa716x->saa716x_msix_handler[i].desc, i, ret); ++ return -1; ++ } ++ } ++ } ++ ++ if (saa716x->int_type == MODE_INTA) { ++ ret = request_irq(pdev->irq, ++ config->irq_handler, ++ IRQF_SHARED, ++ DRIVER_NAME, ++ saa716x); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed <%d>", ret); ++ ret = -ENODEV; ++ } ++ } ++ ++ return ret; ++} ++ ++static void saa716x_free_irq(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int i, vector; ++ ++ if (saa716x->int_type == MODE_MSI_X) { ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) { ++ vector = saa716x->msix_entries[i].vector; ++ free_irq(vector, saa716x); ++ } ++ ++ pci_disable_msix(pdev); ++ ++ } else { ++ free_irq(pdev->irq, saa716x); ++ if (saa716x->int_type == MODE_MSI) ++ pci_disable_msi(pdev); ++ } ++} ++ ++int saa716x_pci_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ int err = 0, ret = -ENODEV, i, use_dac, pm_cap; ++ u32 msi_cap; ++ u8 revision; ++ ++ dprintk(SAA716x_ERROR, 1, "found a %s PCIe card", saa716x->config->model_name); ++ ++ err = pci_enable_device(pdev); ++ if (err != 0) { ++ ret = -ENODEV; ++ dprintk(SAA716x_ERROR, 1, "ERROR: PCI enable failed (%i)", err); ++ goto fail0; ++ } ++ ++ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { ++ use_dac = 1; ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); ++ if (err) { ++ dprintk(SAA716x_ERROR, 1, "Unable to obtain 64bit DMA"); ++ goto fail1; ++ } ++ } else if ((err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { ++ dprintk(SAA716x_ERROR, 1, "Unable to obtain 32bit DMA"); ++ goto fail1; ++ } ++ ++ pci_set_master(pdev); ++ ++ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); ++ if (pm_cap == 0) { ++ dprintk(SAA716x_ERROR, 1, "Cannot find Power Management Capability"); ++ err = -EIO; ++ goto fail1; ++ } ++ ++ if (!request_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0), ++ DRIVER_NAME)) { ++ ++ dprintk(SAA716x_ERROR, 1, "BAR0 Request failed"); ++ ret = -ENODEV; ++ goto fail1; ++ } ++ saa716x->mmio = ioremap(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++ if (!saa716x->mmio) { ++ dprintk(SAA716x_ERROR, 1, "Mem 0 remap failed"); ++ ret = -ENODEV; ++ goto fail2; ++ } ++ ++ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) ++ saa716x->msix_entries[i].entry = i; ++ ++ err = saa716x_request_irq(saa716x); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed, err=%d", err); ++ ret = -ENODEV; ++ goto fail3; ++ } ++ ++ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); ++ pci_read_config_dword(pdev, 0x40, &msi_cap); ++ ++ saa716x->revision = revision; ++ ++ dprintk(SAA716x_ERROR, 0, " SAA%02x Rev %d [%04x:%04x], ", ++ saa716x->pdev->device, ++ revision, ++ saa716x->pdev->subsystem_vendor, ++ saa716x->pdev->subsystem_device); ++ ++ dprintk(SAA716x_ERROR, 0, ++ "irq: %d,\n mmio: 0x%p\n", ++ saa716x->pdev->irq, ++ saa716x->mmio); ++ ++ dprintk(SAA716x_ERROR, 0, " SAA%02x %sBit, MSI %s, MSI-X=%d msgs", ++ saa716x->pdev->device, ++ (((msi_cap >> 23) & 0x01) == 1 ? "64":"32"), ++ (((msi_cap >> 16) & 0x01) == 1 ? "Enabled" : "Disabled"), ++ (1 << ((msi_cap >> 17) & 0x07))); ++ ++ dprintk(SAA716x_ERROR, 0, "\n"); ++ ++ pci_set_drvdata(pdev, saa716x); ++ ++ return 0; ++ ++fail3: ++ dprintk(SAA716x_ERROR, 1, "Err: IO Unmap"); ++ if (saa716x->mmio) ++ iounmap(saa716x->mmio); ++fail2: ++ dprintk(SAA716x_ERROR, 1, "Err: Release regions"); ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ ++fail1: ++ dprintk(SAA716x_ERROR, 1, "Err: Disabling device"); ++ pci_disable_device(pdev); ++ ++fail0: ++ pci_set_drvdata(pdev, NULL); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(saa716x_pci_init); ++ ++void saa716x_pci_exit(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ ++ saa716x_free_irq(saa716x); ++ ++ dprintk(SAA716x_NOTICE, 1, "SAA%02x mem0: 0x%p", ++ saa716x->pdev->device, ++ saa716x->mmio); ++ ++ if (saa716x->mmio) { ++ iounmap(saa716x->mmio); ++ release_mem_region(pci_resource_start(pdev, 0), ++ pci_resource_len(pdev, 0)); ++ } ++ ++ pci_disable_device(pdev); ++ pci_set_drvdata(pdev, NULL); ++} ++EXPORT_SYMBOL_GPL(saa716x_pci_exit); ++ ++MODULE_DESCRIPTION("SAA716x bridge driver"); ++MODULE_AUTHOR("Manu Abraham"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/media/common/saa716x/saa716x_phi.c b/drivers/media/common/saa716x/saa716x_phi.c +new file mode 100644 +index 0000000..7df9a98 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_phi.c +@@ -0,0 +1,152 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_phi_reg.h" ++ ++#include "saa716x_spi.h" ++#include "saa716x_phi.h" ++#include "saa716x_priv.h" ++ ++u32 PHI_0_REGS[] = { ++ PHI_0_MODE, ++ PHI_0_0_CONFIG, ++ PHI_0_1_CONFIG, ++ PHI_0_2_CONFIG, ++ PHI_0_3_CONFIG ++}; ++ ++u32 PHI_1_REGS[] = { ++ PHI_1_MODE, ++ PHI_1_0_CONFIG, ++ PHI_1_1_CONFIG, ++ PHI_1_2_CONFIG, ++ PHI_1_3_CONFIG, ++ PHI_1_4_CONFIG, ++ PHI_1_5_CONFIG, ++ PHI_1_6_CONFIG, ++ PHI_1_7_CONFIG ++}; ++ ++#define PHI_BASE(__port) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_BASE : \ ++ PHI_0_BASE \ ++)) ++ ++#define PHI_APERTURE(_port) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_APERTURE: \ ++ PHI_0_APERTURE \ ++)) ++ ++#define PHI_REG(__port, __reg) (( \ ++ (__port == PHI_1) ? \ ++ PHI_1_REGS[__reg] : \ ++ PHI_0_REGS[__reg] \ ++)) ++ ++#define PHI_SLAVE(__port, __slave) (( \ ++ PHI_BASE(__port) + (__slave * (PHI_APERTURE(__port))) \ ++)) ++ ++/* // Read SAA716x registers ++ * SAA716x_EPRD(PHI_0, PHI_REG(__port, __reg)) ++ * SAA716x_EPWR(PHI_1, PHI_REG(__port, __reg), __data) ++ * ++ * // Read slave registers ++ * SAA716x_EPRD(PHI_0, PHI_SLAVE(__port, __slave, __offset)) ++ * SAA716x_EPWR(PHI_1, PHI_SLAVE(__port, __slave, _offset), __data) ++ */ ++ ++int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave) ++{ ++ int i; ++ ++ /* Reset */ ++ SAA716x_EPWR(PHI_0, PHI_SW_RST, 0x1); ++ ++ for (i = 0; i < 20; i++) { ++ msleep(1); ++ if (!(SAA716x_EPRD(PHI_0, PHI_SW_RST))) ++ break; ++ } ++ ++ return 0; ++} ++ ++int saa716x_phi_init(struct saa716x_dev *saa716x) ++{ ++ uint32_t value; ++ ++ /* init PHI 0 to FIFO mode */ ++ value = 0; ++ value |= PHI_FIFO_MODE; ++ SAA716x_EPWR(PHI_0, PHI_0_MODE, value); ++ ++ value = 0; ++ value |= 0x02; /* chip select 1 */ ++ value |= 0x00 << 8; /* ready mask */ ++ value |= 0x03 << 12; /* strobe time */ ++ value |= 0x06 << 20; /* cycle time */ ++ SAA716x_EPWR(PHI_0, PHI_0_0_CONFIG, value); ++ ++ /* init PHI 1 to SRAM mode, auto increment on */ ++ value = 0; ++ value |= PHI_AUTO_INCREMENT; ++ SAA716x_EPWR(PHI_0, PHI_1_MODE, value); ++ ++ value = 0; ++ value |= 0x01; /* chip select 0 */ ++ value |= 0x00 << 8; /* ready mask */ ++ value |= 0x03 << 12; /* strobe time */ ++ value |= 0x05 << 20; /* cycle time */ ++ SAA716x_EPWR(PHI_0, PHI_1_0_CONFIG, value); ++ ++ value = 0; ++ value |= PHI_ALE_POL; /* ALE is active high */ ++ SAA716x_EPWR(PHI_0, PHI_POLARITY, value); ++ ++ SAA716x_EPWR(PHI_0, PHI_TIMEOUT, 0x2a); ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_init); ++ ++int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ SAA716x_EPWR(PHI_1, address, *((u32 *) &data[i])); ++ address += 4; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_write); ++ ++int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ *((u32 *) &data[i]) = SAA716x_EPRD(PHI_1, address); ++ address += 4; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_read); ++ ++int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length) ++{ ++ int i; ++ ++ for (i = 0; i < length; i += 4) { ++ SAA716x_EPWR(PHI_0, PHI_0_0_RW_0, *((u32 *) &data[i])); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_phi_write_fifo); +diff --git a/drivers/media/common/saa716x/saa716x_phi.h b/drivers/media/common/saa716x/saa716x_phi.h +new file mode 100644 +index 0000000..ff5cda2 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_phi.h +@@ -0,0 +1,39 @@ ++#ifndef __SAA716x_PHI_H ++#define __SAA716x_PHI_H ++ ++/* PHI SLAVE */ ++#define PHI_SLAVE_0 0 ++#define PHI_SLAVE_1 1 ++#define PHI_SLAVE_2 2 ++#define PHI_SLAVE_3 3 ++#define PHI_SLAVE_4 4 ++#define PHI_SLAVE_5 5 ++#define PHI_SLAVE_6 6 ++#define PHI_SLAVE_7 7 ++ ++/* PHI_REG */ ++#define PHI_MODE 0 ++#define PHI_CONFIG_0 1 ++#define PHI_CONFIG_1 2 ++#define PHI_CONFIG_2 3 ++#define PHI_CONFIG_3 4 ++#define PHI_CONFIG_4 5 ++#define PHI_CONFIG_5 6 ++#define PHI_CONFIG_6 7 ++#define PHI_CONFIG_7 8 ++ ++#define PHI_0_BASE 0x1000 ++#define PHI_0_APERTURE 0x0800 ++ ++#define PHI_1_BASE 0x0000 ++#define PHI_1_APERTURE 0xfffc ++ ++struct saa716x_dev; ++ ++extern int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave); ++extern int saa716x_phi_init(struct saa716x_dev *saa716x); ++extern int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 *data, int length); ++extern int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 *data, int length); ++extern int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length); ++ ++#endif /* __SAA716x_PHI_H */ +diff --git a/drivers/media/common/saa716x/saa716x_phi_reg.h b/drivers/media/common/saa716x/saa716x_phi_reg.h +new file mode 100644 +index 0000000..08f0aa7 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_phi_reg.h +@@ -0,0 +1,100 @@ ++#ifndef __SAA716x_PHI_REG_H ++#define __SAA716x_PHI_REG_H ++ ++/* -------------- PHI_0 Registers -------------- */ ++ ++#define PHI_0_MODE 0x0000 ++#define PHI_0_0_CONFIG 0x0008 ++#define PHI_0_1_CONFIG 0x000c ++#define PHI_0_2_CONFIG 0x0010 ++#define PHI_0_3_CONFIG 0x0014 ++ ++#define PHI_POLARITY 0x0038 ++#define PHI_TIMEOUT 0x003c ++#define PHI_SW_RST 0x0ff0 ++ ++#define PHI_0_0_RW_0 0x1000 ++#define PHI_0_0_RW_511 0x17fc ++ ++#define PHI_0_1_RW_0 0x1800 ++#define PHI_0_1_RW_511 0x1ffc ++ ++#define PHI_0_2_RW_0 0x2000 ++#define PHI_0_2_RW_511 0x27fc ++ ++#define PHI_0_3_RW_0 0x2800 ++#define PHI_0_3_RW_511 0x2ffc ++ ++#define PHI_CSN_DEASSERT (0x00000001 << 2) ++#define PHI_AUTO_INCREMENT (0x00000001 << 1) ++#define PHI_FIFO_MODE (0x00000001 << 0) ++ ++#define PHI_DELAY_RD_WR (0x0000001f << 27) ++#define PHI_EXTEND_RDY3 (0x00000003 << 25) ++#define PHI_EXTEND_RDY2 (0x00000003 << 23) ++#define PHI_EXTEND_RDY1 (0x00000003 << 21) ++#define PHI_EXTEND_RDY0 (0x00000003 << 19) ++#define PHI_RDY3_OD (0x00000001 << 18) ++#define PHI_RDY2_OD (0x00000001 << 17) ++#define PHI_RDY1_OD (0x00000001 << 16) ++#define PHI_RDY0_OD (0x00000001 << 15) ++#define PHI_ALE_POL (0x00000001 << 14) ++#define PHI_WRN_POL (0x00000001 << 13) ++#define PHI_RDN_POL (0x00000001 << 12) ++#define PHI_RDY3_POL (0x00000001 << 11) ++#define PHI_RDY2_POL (0x00000001 << 10) ++#define PHI_RDY1_POL (0x00000001 << 9) ++#define PHI_RDY0_POL (0x00000001 << 8) ++#define PHI_CSN7_POL (0x00000001 << 7) ++#define PHI_CSN6_POL (0x00000001 << 6) ++#define PHI_CSN5_POL (0x00000001 << 5) ++#define PHI_CSN4_POL (0x00000001 << 4) ++#define PHI_CSN3_POL (0x00000001 << 3) ++#define PHI_CSN2_POL (0x00000001 << 2) ++#define PHI_CSN1_POL (0x00000001 << 1) ++#define PHI_CSN0_POL (0x00000001 << 0) ++ ++/* -------------- PHI_1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++#define PHI_1_MODE 0x00004 ++#define PHI_1_0_CONFIG 0x00018 ++#define PHI_1_1_CONFIG 0x0001c ++#define PHI_1_2_CONFIG 0x00020 ++#define PHI_1_3_CONFIG 0x00024 ++#define PHI_1_4_CONFIG 0x00028 ++#define PHI_1_5_CONFIG 0x0002c ++#define PHI_1_6_CONFIG 0x00030 ++#define PHI_1_7_CONFIG 0x00034 ++ ++#define PHI_1_0_RW_0 0x00000 ++#define PHI_1_0_RW_16383 0x0fffc ++ ++#define PHI_1_1_RW_0 0x1000 ++#define PHI_1_1_RW_16383 0x1ffc ++ ++#define PHI_1_2_RW_0 0x2000 ++#define PHI_1_2_RW_16383 0x2ffc ++ ++#define PHI_1_3_RW_0 0x3000 ++#define PHI_1_3_RW_16383 0x3ffc ++ ++#define PHI_1_4_RW_0 0x4000 ++#define PHI_1_4_RW_16383 0x4ffc ++ ++#define PHI_1_5_RW_0 0x5000 ++#define PHI_1_5_RW_16383 0x5ffc ++ ++#define PHI_1_6_RW_0 0x6000 ++#define PHI_1_6_RW_16383 0x6ffc ++ ++#define PHI_1_7_RW_0 0x7000 ++#define PHI_1_7_RW_16383 0x7ffc ++ ++ ++/* BAR = 20 bits */ ++/* -------------- PHI1 Registers -------------- */ ++ ++ ++#endif /* __SAA716x_PHI_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_priv.h b/drivers/media/common/saa716x/saa716x_priv.h +new file mode 100644 +index 0000000..1ad1d9c +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_priv.h +@@ -0,0 +1,194 @@ ++#ifndef __SAA716x_PRIV_H ++#define __SAA716x_PRIV_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include "saa716x_i2c.h" ++#include "saa716x_boot.h" ++#include "saa716x_cgu.h" ++#include "saa716x_dma.h" ++#include "saa716x_fgpi.h" ++ ++#include "dvbdev.h" ++#include "dvb_demux.h" ++#include "dmxdev.h" ++#include "dvb_frontend.h" ++#include "dvb_net.h" ++ ++#define SAA716x_ERROR 0 ++#define SAA716x_NOTICE 1 ++#define SAA716x_INFO 2 ++#define SAA716x_DEBUG 3 ++ ++#define SAA716x_DEV (saa716x)->num ++#define SAA716x_VERBOSE (saa716x)->verbose ++#define SAA716x_MAX_ADAPTERS 4 ++ ++#define dprintk(__x, __y, __fmt, __arg...) do { \ ++ if (__y) { \ ++ if ((SAA716x_VERBOSE > SAA716x_ERROR) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_ERR "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_NOTICE) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_NOTICE "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_INFO) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_INFO "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ else if ((SAA716x_VERBOSE > SAA716x_DEBUG) && (SAA716x_VERBOSE > __x)) \ ++ printk(KERN_DEBUG "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ ++ } else { \ ++ if (SAA716x_VERBOSE > __x) \ ++ printk(__fmt , ##__arg); \ ++ } \ ++} while(0) ++ ++ ++#define NXP_SEMICONDUCTOR 0x1131 ++#define SAA7160 0x7160 ++#define SAA7161 0x7161 ++#define SAA7162 0x7162 ++ ++#define NXP_REFERENCE_BOARD 0x1131 ++ ++#define MAKE_ENTRY(__subven, __subdev, __chip, __configptr) { \ ++ .vendor = NXP_SEMICONDUCTOR, \ ++ .device = (__chip), \ ++ .subvendor = (__subven), \ ++ .subdevice = (__subdev), \ ++ .driver_data = (unsigned long) (__configptr) \ ++} ++ ++#define SAA716x_EPWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) ++#define SAA716x_EPRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) ++ ++#define SAA716x_RCWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) ++#define SAA716x_RCRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) ++ ++ ++#define SAA716x_MSI_MAX_VECTORS 16 ++ ++struct saa716x_msix_entry { ++ int vector; ++ u8 desc[32]; ++ irqreturn_t (*handler)(int irq, void *dev_id); ++}; ++ ++struct saa716x_dev; ++struct saa716x_adapter; ++struct saa716x_spi_config; ++ ++struct saa716x_adap_config { ++ u32 ts_port; ++ void (*worker)(unsigned long); ++}; ++ ++struct saa716x_config { ++ char *model_name; ++ char *dev_type; ++ ++ enum saa716x_boot_mode boot_mode; ++ ++ int adapters; ++ int frontends; ++ ++ int (*frontend_attach)(struct saa716x_adapter *adapter, int count); ++ irqreturn_t (*irq_handler)(int irq, void *dev_id); ++ ++ struct saa716x_adap_config adap_config[SAA716x_MAX_ADAPTERS]; ++ enum saa716x_i2c_rate i2c_rate; ++ enum saa716x_i2c_mode i2c_mode; ++}; ++ ++struct saa716x_adapter { ++ struct dvb_adapter dvb_adapter; ++ struct dvb_frontend *fe; ++ struct dvb_demux demux; ++ struct dmxdev dmxdev; ++ struct dmx_frontend fe_hw; ++ struct dmx_frontend fe_mem; ++ struct dvb_net dvb_net; ++ ++ struct saa716x_dev *saa716x; ++ ++ u8 feeds; ++ u8 count; ++}; ++ ++struct saa716x_dev { ++ struct saa716x_config *config; ++ struct pci_dev *pdev; ++ ++ int num; /* device count */ ++ int verbose; ++ ++ u8 revision; ++ ++ /* PCI */ ++ void __iomem *mmio; ++ ++#define MODE_INTA 0 ++#define MODE_MSI 1 ++#define MODE_MSI_X 2 ++ u8 int_type; ++ ++ struct msix_entry msix_entries[SAA716x_MSI_MAX_VECTORS]; ++ struct saa716x_msix_entry saa716x_msix_handler[56]; ++ u8 handlers; /* no. of active handlers */ ++ ++ /* I2C */ ++ struct saa716x_i2c i2c[2]; ++ u32 i2c_rate; /* init time */ ++ u32 I2C_DEV[2]; ++ ++ struct saa716x_spi_state *saa716x_spi; ++ struct saa716x_spi_config spi_config; ++ ++ struct saa716x_adapter saa716x_adap[SAA716x_MAX_ADAPTERS]; ++ struct mutex adap_lock; ++ struct saa716x_cgu cgu; ++ ++ spinlock_t gpio_lock; ++ /* DMA */ ++ ++ struct saa716x_fgpi_stream_port fgpi[4]; ++ ++ u32 id_offst; ++ u32 id_len; ++ void *priv; ++ ++ /* remote control */ ++ void *ir_priv; ++}; ++ ++/* PCI */ ++extern int saa716x_pci_init(struct saa716x_dev *saa716x); ++extern void saa716x_pci_exit(struct saa716x_dev *saa716x); ++ ++/* MSI */ ++extern int saa716x_msi_init(struct saa716x_dev *saa716x); ++extern void saa716x_msi_exit(struct saa716x_dev *saa716x); ++extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); ++ ++/* DMA */ ++extern int saa716x_dma_init(struct saa716x_dev *saa716x); ++extern void saa716x_dma_exit(struct saa716x_dev *saa716x); ++ ++/* AUDIO */ ++extern int saa716x_audio_init(struct saa716x_dev *saa716x); ++extern void saa716x_audio_exit(struct saa716x_dev *saa716x); ++ ++/* Boot */ ++extern int saa716x_core_boot(struct saa716x_dev *saa716x); ++extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); ++ ++/* Remote control */ ++extern int saa716x_ir_init(struct saa716x_dev *saa716x); ++extern void saa716x_ir_exit(struct saa716x_dev *saa716x); ++extern void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd); ++ ++#endif /* __SAA716x_PRIV_H */ +diff --git a/drivers/media/common/saa716x/saa716x_reg.h b/drivers/media/common/saa716x/saa716x_reg.h +new file mode 100644 +index 0000000..effd966 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_reg.h +@@ -0,0 +1,1279 @@ ++#ifndef __SAA716x_REG_H ++#define __SAA716x_REG_H ++ ++/* BAR = 17 bits */ ++/* ++ VI0 0x00000000 ++ VI1 0x00001000 ++ FGPI0 0x00002000 ++ FGPI1 0x00003000 ++ FGPI2 0x00004000 ++ FGPI3 0x00005000 ++ AI0 0x00006000 ++ AI1 0x00007000 ++ BAM 0x00008000 ++ MMU 0x00009000 ++ MSI 0x0000a000 ++ I2C_B 0x0000b000 ++ I2C_A 0x0000c000 ++ SPI 0x0000d000 ++ GPIO 0x0000e000 ++ PHI_0 0x0000f000 ++ CGU 0x00013000 ++ DCS 0x00014000 ++ GREG 0x00012000 ++ ++ PHI_1 0x00020000 ++*/ ++ ++/* -------------- VIP Registers -------------- */ ++ ++#define VI0 0x00000000 ++#define VI1 0x00001000 ++ ++#define VI_MODE 0x000 ++#define VID_CFEN (0x00000003 << 30) ++#define VID_OSM (0x00000001 << 29) ++#define VID_FSEQ (0x00000001 << 28) ++#define AUX_CFEN (0x00000003 << 26) ++#define AUX_OSM (0x00000001 << 25) ++#define AUX_FSEQ (0x00000001 << 24) ++#define AUX_ANC_DATA (0x00000003 << 22) ++#define AUX_ANC_RAW (0x00000001 << 21) ++#define RST_ON_ERR (0x00000001 << 17) ++#define SOFT_RESET (0x00000001 << 16) ++#define IFF_CLAMP (0x00000001 << 14) ++#define IFF_MODE (0x00000003 << 12) ++#define DFF_CLAMP (0x00000001 << 10) ++#define DFF_MODE (0x00000003 << 8) ++#define HSP_CLAMP (0x00000001 << 3) ++#define HSP_RGB (0x00000001 << 2) ++#define HSP_MODE (0x00000003 << 0) ++ ++#define RCRB_CTRL 0x004 ++#define RCRB_CFG_ADDR 0x008 ++#define RCRB_CFG_EXT_ADDR 0x00c ++#define RCRB_IO_ADDR 0x010 ++#define RCRB_MEM_LADDR 0x014 ++#define RCRB_MEM_UADDR 0x018 ++#define RCRB_DATA 0x01c ++#define RCRB_MASK 0x020 ++#define RCRB_MSG_HDR 0x040 ++#define RCRB_MSG_PL0 0x044 ++#define RCRB_MSG_PL1 0x048 ++ ++#define ID_MASK0 0x020 ++#define VI_ID_MASK_0 (0x000000ff << 8) ++#define VI_DATA_ID_0 (0x000000ff << 0) ++ ++#define ID_MASK1 0x024 ++#define VI_ID_MASK_1 (0x000000ff << 8) ++#define VI_DATA_ID_1 (0x000000ff << 0) ++ ++#define VIP_LINE_THRESH 0x040 ++#define VI_LCTHR (0x000007ff << 0) ++ ++#define VIN_FORMAT 0x100 ++#define VI_VSRA (0x00000003 << 30) ++#define VI_SYNCHD (0x00000001 << 25) ++#define VI_DUAL_STREAM (0x00000001 << 24) ++#define VI_NHDAUX (0x00000001 << 20) ++#define VI_NPAR (0x00000001 << 19) ++#define VI_VSEL (0x00000003 << 14) ++#define VI_TWOS (0x00000001 << 13) ++#define VI_TPG (0x00000001 << 12) ++#define VI_FREF (0x00000001 << 10) ++#define VI_FTGL (0x00000001 << 9) ++#define VI_SF (0x00000001 << 3) ++#define VI_FZERO (0x00000001 << 2) ++#define VI_REVS (0x00000001 << 1) ++#define VI_REHS (0x00000001 << 0) ++ ++#define TC76543210 0x800 ++#define TCFEDCBA98 0x804 ++#define PHYCFG 0x900 ++#define CONFIG 0xfd4 ++#define INT_ENABLE_CLR 0xfd8 ++#define INT_ENABLE_SET 0xfdc ++ ++ ++#define INT_STATUS 0xfe0 ++#define VI_STAT_FID_AUX (0x00000001 << 31) ++#define VI_STAT_FID_VID (0x00000001 << 30) ++#define VI_STAT_FID_VPI (0x00000001 << 29) ++#define VI_STAT_LINE_COUNT (0x00000fff << 16) ++#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) ++#define VI_STAT_VID_OVRFLW (0x00000001 << 8) ++#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) ++#define VI_STAT_FID_SEQBRK (0x00000001 << 6) ++#define VI_STAT_LINE_THRESH (0x00000001 << 5) ++#define VI_STAT_AUX_WRAP (0x00000001 << 4) ++#define VI_STAT_AUX_START_IN (0x00000001 << 3) ++#define VI_STAT_AUX_END_OUT (0x00000001 << 2) ++#define VI_STAT_VID_START_IN (0x00000001 << 1) ++#define VI_STAT_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) ++#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) ++#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) ++#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) ++#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) ++#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) ++#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) ++#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) ++#define VI_ENABLE_VID_START_IN (0x00000001 << 1) ++#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define VIP_POWER_DOWN 0xff4 ++#define VI_PWR_DWN (0x00000001 << 31) ++ ++ ++ ++ ++/* -------------- FGPI Registers -------------- */ ++ ++#define FGPI0 0x00002000 ++#define FGPI1 0x00003000 ++#define FGPI2 0x00004000 ++#define FGPI3 0x00005000 ++ ++#define FGPI_CONTROL 0x000 ++#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) ++#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) ++#define FGPI_MODE (0x00000001 << 11) ++#define FGPI_SAMPLE_SIZE (0x00000003 << 8) ++#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) ++#define FGPI_REC_START_MSG_START (0x00000003 << 2) ++#define FGPI_TSTAMP_SELECT (0x00000001 << 1) ++#define FGPI_VAR_LENGTH (0x00000001 << 0) ++ ++#define FGPI_BASE_1 0x004 ++#define FGPI_BASE_2 0x008 ++#define FGPI_SIZE 0x00c ++#define FGPI_REC_SIZE 0x010 ++#define FGPI_STRIDE 0x014 ++#define FGPI_NUM_RECORD_1 0x018 ++#define FGPI_NUM_RECORD_2 0x01c ++#define FGPI_THRESHOLD_1 0x020 ++#define FGPI_THRESHOLD_2 0x024 ++#define FGPI_D1_XY_START 0x028 ++#define FGPI_D1_XY_END 0x02c ++ ++#define INT_STATUS 0xfe0 ++#define FGPI_BUF1_ACTIVE (0x00000001 << 7) ++#define FGPI_OVERFLOW (0x00000001 << 6) ++#define FGPI_MBE (0x00000001 << 5) ++#define FGPI_UNDERRUN (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED (0x00000001 << 2) ++#define FGPI_BUF2_FULL (0x00000001 << 1) ++#define FGPI_BUF1_FULL (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define FGPI_OVERFLOW_ENA (0x00000001 << 6) ++#define FGPI_MBE_ENA (0x00000001 << 5) ++#define FGPI_UNDERRUN_ENA (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) ++#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) ++#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define FGPI_OVERFLOW_ACK (0x00000001 << 6) ++#define FGPI_MBE_ACK (0x00000001 << 5) ++#define FGPI_UNDERRUN_ACK (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) ++#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) ++#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define FGPI_OVERFLOW_SET (0x00000001 << 6) ++#define FGPI_MBE_SET (0x00000001 << 5) ++#define FGPI_UNDERRUN_SET (0x00000001 << 4) ++#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) ++#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) ++#define FGPI_BUF2_DONE_SET (0x00000001 << 1) ++#define FGPI_BUF1_DONE_SET (0x00000001 << 0) ++ ++#define FGPI_SOFT_RESET 0xff0 ++#define FGPI_SOFTWARE_RESET (0x00000001 << 0) ++ ++#define FGPI_INTERFACE 0xff4 ++#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) ++ ++#define FGPI_MOD_ID_EXT 0xff8 ++#define FGPI_MODULE_ID 0xffc ++ ++ ++/* -------------- AI Registers ---------------- */ ++ ++#define AI0 0x00006000 ++#define AI1 0x00007000 ++ ++#define AI_STATUS 0x000 ++#define AI_BUF1_ACTIVE (0x00000001 << 4) ++#define AI_OVERRUN (0x00000001 << 3) ++#define AI_HBE (0x00000001 << 2) ++#define AI_BUF2_FULL (0x00000001 << 1) ++#define AI_BUF1_FULL (0x00000001 << 0) ++ ++#define AI_CTL 0x004 ++#define AI_RESET (0x00000001 << 31) ++#define AI_CAP_ENABLE (0x00000001 << 30) ++#define AI_CAP_MODE (0x00000003 << 28) ++#define AI_SIGN_CONVERT (0x00000001 << 27) ++#define AI_EARLYMODE (0x00000001 << 26) ++#define AI_DIAGMODE (0x00000001 << 25) ++#define AI_RAWMODE (0x00000001 << 24) ++#define AI_OVR_INTEN (0x00000001 << 7) ++#define AI_HBE_INTEN (0x00000001 << 6) ++#define AI_BUF2_INTEN (0x00000001 << 5) ++#define AI_BUF1_INTEN (0x00000001 << 4) ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_SERIAL 0x008 ++#define AI_SER_MASTER (0x00000001 << 31) ++#define AI_DATAMODE (0x00000001 << 30) ++#define AI_FRAMEMODE (0x00000003 << 28) ++#define AI_CLOCK_EDGE (0x00000001 << 27) ++#define AI_SSPOS4 (0x00000001 << 19) ++#define AI_NR_CHAN (0x00000003 << 17) ++#define AI_WSDIV (0x000001ff << 8) ++#define AI_SCKDIV (0x000000ff << 0) ++ ++#define AI_FRAMING 0x00c ++#define AI_VALIDPOS (0x000001ff << 22) ++#define AI_LEFTPOS (0x000001ff << 13) ++#define AI_RIGHTPOS (0x000001ff << 4) ++#define AI_SSPOS_3_0 (0x0000000f << 0) ++ ++#define AI_BASE1 0x014 ++#define AI_BASE2 0x018 ++#define AI_BASE (0x03ffffff << 6) ++ ++#define AI_SIZE 0x01c ++#define AI_SAMPLE_SIZE (0x03ffffff << 6) ++ ++#define AI_INT_ACK 0x020 ++#define AI_ACK_OVR (0x00000001 << 3) ++#define AI_ACK_HBE (0x00000001 << 2) ++#define AI_ACK2 (0x00000001 << 1) ++#define AI_ACK1 (0x00000001 << 0) ++ ++#define AI_PWR_DOWN 0xff4 ++#define AI_PWR_DWN (0x00000001 << 0) ++ ++/* -------------- BAM Registers -------------- */ ++ ++#define BAM 0x00008000 ++ ++#define BAM_VI0_0_DMA_BUF_MODE 0x000 ++ ++#define BAM_VI0_0_ADDR_OFFST_0 0x004 ++#define BAM_VI0_0_ADDR_OFFST_1 0x008 ++#define BAM_VI0_0_ADDR_OFFST_2 0x00c ++#define BAM_VI0_0_ADDR_OFFST_3 0x010 ++#define BAM_VI0_0_ADDR_OFFST_4 0x014 ++#define BAM_VI0_0_ADDR_OFFST_5 0x018 ++#define BAM_VI0_0_ADDR_OFFST_6 0x01c ++#define BAM_VI0_0_ADDR_OFFST_7 0x020 ++ ++#define BAM_VI0_1_DMA_BUF_MODE 0x024 ++#define BAM_VI0_1_ADDR_OFFST_0 0x028 ++#define BAM_VI0_1_ADDR_OFFST_1 0x02c ++#define BAM_VI0_1_ADDR_OFFST_2 0x030 ++#define BAM_VI0_1_ADDR_OFFST_3 0x034 ++#define BAM_VI0_1_ADDR_OFFST_4 0x038 ++#define BAM_VI0_1_ADDR_OFFST_5 0x03c ++#define BAM_VI0_1_ADDR_OFFST_6 0x040 ++#define BAM_VI0_1_ADDR_OFFST_7 0x044 ++ ++#define BAM_VI0_2_DMA_BUF_MODE 0x048 ++#define BAM_VI0_2_ADDR_OFFST_0 0x04c ++#define BAM_VI0_2_ADDR_OFFST_1 0x050 ++#define BAM_VI0_2_ADDR_OFFST_2 0x054 ++#define BAM_VI0_2_ADDR_OFFST_3 0x058 ++#define BAM_VI0_2_ADDR_OFFST_4 0x05c ++#define BAM_VI0_2_ADDR_OFFST_5 0x060 ++#define BAM_VI0_2_ADDR_OFFST_6 0x064 ++#define BAM_VI0_2_ADDR_OFFST_7 0x068 ++ ++ ++#define BAM_VI1_0_DMA_BUF_MODE 0x06c ++#define BAM_VI1_0_ADDR_OFFST_0 0x070 ++#define BAM_VI1_0_ADDR_OFFST_1 0x074 ++#define BAM_VI1_0_ADDR_OFFST_2 0x078 ++#define BAM_VI1_0_ADDR_OFFST_3 0x07c ++#define BAM_VI1_0_ADDR_OFFST_4 0x080 ++#define BAM_VI1_0_ADDR_OFFST_5 0x084 ++#define BAM_VI1_0_ADDR_OFFST_6 0x088 ++#define BAM_VI1_0_ADDR_OFFST_7 0x08c ++ ++#define BAM_VI1_1_DMA_BUF_MODE 0x090 ++#define BAM_VI1_1_ADDR_OFFST_0 0x094 ++#define BAM_VI1_1_ADDR_OFFST_1 0x098 ++#define BAM_VI1_1_ADDR_OFFST_2 0x09c ++#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 ++#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 ++#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 ++#define BAM_VI1_1_ADDR_OFFST_6 0x0ac ++#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 ++ ++#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 ++#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 ++#define BAM_VI1_2_ADDR_OFFST_1 0x0bc ++#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 ++#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 ++#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 ++#define BAM_VI1_2_ADDR_OFFST_5 0x0cc ++#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 ++#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 ++ ++ ++#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 ++#define BAM_FGPI0_ADDR_OFFST_0 0x0dc ++#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 ++#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 ++#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 ++#define BAM_FGPI0_ADDR_OFFST_4 0x0ec ++#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 ++#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 ++#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 ++ ++#define BAM_FGPI1_DMA_BUF_MODE 0x0fc ++#define BAM_FGPI1_ADDR_OFFST_0 0x100 ++#define BAM_FGPI1_ADDR_OFFST_1 0x104 ++#define BAM_FGPI1_ADDR_OFFST_2 0x108 ++#define BAM_FGPI1_ADDR_OFFST_3 0x10c ++#define BAM_FGPI1_ADDR_OFFST_4 0x110 ++#define BAM_FGPI1_ADDR_OFFST_5 0x114 ++#define BAM_FGPI1_ADDR_OFFST_6 0x118 ++#define BAM_FGPI1_ADDR_OFFST_7 0x11c ++ ++#define BAM_FGPI2_DMA_BUF_MODE 0x120 ++#define BAM_FGPI2_ADDR_OFFST_0 0x124 ++#define BAM_FGPI2_ADDR_OFFST_1 0x128 ++#define BAM_FGPI2_ADDR_OFFST_2 0x12c ++#define BAM_FGPI2_ADDR_OFFST_3 0x130 ++#define BAM_FGPI2_ADDR_OFFST_4 0x134 ++#define BAM_FGPI2_ADDR_OFFST_5 0x138 ++#define BAM_FGPI2_ADDR_OFFST_6 0x13c ++#define BAM_FGPI2_ADDR_OFFST_7 0x140 ++ ++#define BAM_FGPI3_DMA_BUF_MODE 0x144 ++#define BAM_FGPI3_ADDR_OFFST_0 0x148 ++#define BAM_FGPI3_ADDR_OFFST_1 0x14c ++#define BAM_FGPI3_ADDR_OFFST_2 0x150 ++#define BAM_FGPI3_ADDR_OFFST_3 0x154 ++#define BAM_FGPI3_ADDR_OFFST_4 0x158 ++#define BAM_FGPI3_ADDR_OFFST_5 0x15c ++#define BAM_FGPI3_ADDR_OFFST_6 0x160 ++#define BAM_FGPI3_ADDR_OFFST_7 0x164 ++ ++ ++#define BAM_AI0_DMA_BUF_MODE 0x168 ++#define BAM_AI0_ADDR_OFFST_0 0x16c ++#define BAM_AI0_ADDR_OFFST_1 0x170 ++#define BAM_AI0_ADDR_OFFST_2 0x174 ++#define BAM_AI0_ADDR_OFFST_3 0x178 ++#define BAM_AI0_ADDR_OFFST_4 0x17c ++#define BAM_AIO_ADDR_OFFST_5 0x180 ++#define BAM_AI0_ADDR_OFFST_6 0x184 ++#define BAM_AIO_ADDR_OFFST_7 0x188 ++ ++#define BAM_AI1_DMA_BUF_MODE 0x18c ++#define BAM_AI1_ADDR_OFFST_0 0x190 ++#define BAM_AI1_ADDR_OFFST_1 0x194 ++#define BAM_AI1_ADDR_OFFST_2 0x198 ++#define BAM_AI1_ADDR_OFFST_3 0x19c ++#define BAM_AI1_ADDR_OFFST_4 0x1a0 ++#define BAM_AI1_ADDR_OFFST_5 0x1a4 ++#define BAM_AI1_ADDR_OFFST_6 0x1a8 ++#define BAM_AI1_ADDR_OFFST_7 0x1ac ++ ++#define BAM_SW_RST 0xff0 ++#define BAM_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++ ++/* -------------- MMU Registers -------------- */ ++ ++#define MMU 0x00009000 ++ ++#define MMU_MODE 0x000 ++ ++#define MMU_DMA_CONFIG0 0x004 ++#define MMU_DMA_CONFIG1 0x008 ++#define MMU_DMA_CONFIG2 0x00c ++#define MMU_DMA_CONFIG3 0x010 ++#define MMU_DMA_CONFIG4 0x014 ++#define MMU_DMA_CONFIG5 0x018 ++#define MMU_DMA_CONFIG6 0x01c ++#define MMU_DMA_CONFIG7 0x020 ++#define MMU_DMA_CONFIG8 0x024 ++#define MMU_DMA_CONFIG9 0x028 ++#define MMU_DMA_CONFIG10 0x02c ++#define MMU_DMA_CONFIG11 0x030 ++#define MMU_DMA_CONFIG12 0x034 ++#define MMU_DMA_CONFIG13 0x038 ++#define MMU_DMA_CONFIG14 0x03c ++#define MMU_DMA_CONFIG15 0x040 ++ ++#define MMU_SW_RST 0xff0 ++#define MMU_SW_RESET (0x0001 << 0) ++ ++#define MMU_PTA_BASE0 0x044 /* DMA 0 */ ++#define MMU_PTA_BASE1 0x084 /* DMA 1 */ ++#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ ++#define MMU_PTA_BASE3 0x104 /* DMA 3 */ ++#define MMU_PTA_BASE4 0x144 /* DMA 4 */ ++#define MMU_PTA_BASE5 0x184 /* DMA 5 */ ++#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ ++#define MMU_PTA_BASE7 0x204 /* DMA 7 */ ++#define MMU_PTA_BASE8 0x244 /* DMA 8 */ ++#define MMU_PTA_BASE9 0x284 /* DMA 9 */ ++#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ ++#define MMU_PTA_BASE11 0x304 /* DMA 11 */ ++#define MMU_PTA_BASE12 0x344 /* DMA 12 */ ++#define MMU_PTA_BASE13 0x384 /* DMA 13 */ ++#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ ++#define MMU_PTA_BASE15 0x404 /* DMA 15 */ ++ ++#define MMU_PTA_BASE 0x044 /* DMA 0 */ ++#define MMU_PTA_OFFSET 0x40 ++ ++#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) ++ ++#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 ++#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 ++#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 ++#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c ++#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 ++#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 ++#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 ++#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c ++#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 ++#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 ++#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 ++#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c ++#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 ++#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 ++#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 ++#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c ++ ++ ++/* -------------- MSI Registers -------------- */ ++ ++#define MSI 0x0000a000 ++ ++#define MSI_DELAY_TIMER 0x000 ++#define MSI_DELAY_1CLK (0x00000001 << 0) ++#define MSI_DELAY_2CLK (0x00000002 << 0) ++ ++#define MSI_INTA_POLARITY 0x004 ++#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) ++ ++#define MSI_CONFIG0 0x008 ++#define MSI_CONFIG1 0x00c ++#define MSI_CONFIG2 0x010 ++#define MSI_CONFIG3 0x014 ++#define MSI_CONFIG4 0x018 ++#define MSI_CONFIG5 0x01c ++#define MSI_CONFIG6 0x020 ++#define MSI_CONFIG7 0x024 ++#define MSI_CONFIG8 0x028 ++#define MSI_CONFIG9 0x02c ++#define MSI_CONFIG10 0x030 ++#define MSI_CONFIG11 0x034 ++#define MSI_CONFIG12 0x038 ++#define MSI_CONFIG13 0x03c ++#define MSI_CONFIG14 0x040 ++#define MSI_CONFIG15 0x044 ++#define MSI_CONFIG16 0x048 ++#define MSI_CONFIG17 0x04c ++#define MSI_CONFIG18 0x050 ++#define MSI_CONFIG19 0x054 ++#define MSI_CONFIG20 0x058 ++#define MSI_CONFIG21 0x05c ++#define MSI_CONFIG22 0x060 ++#define MSI_CONFIG23 0x064 ++#define MSI_CONFIG24 0x068 ++#define MSI_CONFIG25 0x06c ++#define MSI_CONFIG26 0x070 ++#define MSI_CONFIG27 0x074 ++#define MSI_CONFIG28 0x078 ++#define MSI_CONFIG29 0x07c ++#define MSI_CONFIG30 0x080 ++#define MSI_CONFIG31 0x084 ++#define MSI_CONFIG32 0x088 ++#define MSI_CONFIG33 0x08c ++#define MSI_CONFIG34 0x090 ++#define MSI_CONFIG35 0x094 ++#define MSI_CONFIG36 0x098 ++#define MSI_CONFIG37 0x09c ++#define MSI_CONFIG38 0x0a0 ++#define MSI_CONFIG39 0x0a4 ++#define MSI_CONFIG40 0x0a8 ++#define MSI_CONFIG41 0x0ac ++#define MSI_CONFIG42 0x0b0 ++#define MSI_CONFIG43 0x0b4 ++#define MSI_CONFIG44 0x0b8 ++#define MSI_CONFIG45 0x0bc ++#define MSI_CONFIG46 0x0c0 ++#define MSI_CONFIG47 0x0c4 ++#define MSI_CONFIG48 0x0c8 ++#define MSI_CONFIG49 0x0cc ++#define MSI_CONFIG50 0x0d0 ++ ++#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) ++#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) ++#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) ++#define MSI_TC (0x00000007 << 16) ++#define MSI_ID (0x0000000f << 0) ++ ++#define MSI_INT_STATUS_L 0xfc0 ++#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) ++#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) ++#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) ++#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) ++#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) ++#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) ++#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) ++#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) ++#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) ++#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) ++#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) ++#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) ++#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) ++#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) ++#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) ++#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) ++#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) ++#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) ++#define MSI_INT_OVRFLW_FGPI_O (0x00000001 << 18) ++#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) ++#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) ++#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) ++#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) ++#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) ++#define MSI_INT_AVINT_VI0 (0x00000001 << 24) ++#define MSI_INT_AVINT_VI1 (0x00000001 << 25) ++#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) ++#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) ++#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) ++#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) ++#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) ++#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) ++ ++#define MSI_INT_STATUS_H 0xfc4 ++#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) ++#define MSI_INT_EXTINT_0 (0x00000001 << 1) ++#define MSI_INT_EXTINT_1 (0x00000001 << 2) ++#define MSI_INT_EXTINT_2 (0x00000001 << 3) ++#define MSI_INT_EXTINT_3 (0x00000001 << 4) ++#define MSI_INT_EXTINT_4 (0x00000001 << 5) ++#define MSI_INT_EXTINT_5 (0x00000001 << 6) ++#define MSI_INT_EXTINT_6 (0x00000001 << 7) ++#define MSI_INT_EXTINT_7 (0x00000001 << 8) ++#define MSI_INT_EXTINT_8 (0x00000001 << 9) ++#define MSI_INT_EXTINT_9 (0x00000001 << 10) ++#define MSI_INT_EXTINT_10 (0x00000001 << 11) ++#define MSI_INT_EXTINT_11 (0x00000001 << 12) ++#define MSI_INT_EXTINT_12 (0x00000001 << 13) ++#define MSI_INT_EXTINT_13 (0x00000001 << 14) ++#define MSI_INT_EXTINT_14 (0x00000001 << 15) ++#define MSI_INT_EXTINT_15 (0x00000001 << 16) ++#define MSI_INT_I2CINT_0 (0x00000001 << 17) ++#define MSI_INT_I2CINT_1 (0x00000001 << 18) ++ ++#define MSI_INT_STATUS_CLR_L 0xfc8 ++#define MSI_INT_STATUS_CLR_H 0xfcc ++#define MSI_INT_STATUS_SET_L 0xfd0 ++#define MSI_INT_STATUS_SET_H 0xfd4 ++#define MSI_INT_ENA_L 0xfd8 ++#define MSI_INT_ENA_H 0xfdc ++#define MSI_INT_ENA_CLR_L 0xfe0 ++#define MSI_INT_ENA_CLR_H 0xfe4 ++#define MSI_INT_ENA_SET_L 0xfe8 ++#define MSI_INT_ENA_SET_H 0xfec ++ ++#define MSI_SW_RST 0xff0 ++#define MSI_SW_RESET (0x0001 << 0) ++ ++#define MSI_MODULE_ID 0xffc ++ ++ ++/* -------------- I2C Registers -------------- */ ++ ++#define I2C_B 0x0000b000 ++#define I2C_A 0x0000c000 ++ ++#define RX_FIFO 0x000 ++#define I2C_RX_BYTE (0x000000ff << 0) ++ ++#define TX_FIFO 0x000 ++#define I2C_STOP_BIT (0x00000001 << 9) ++#define I2C_START_BIT (0x00000001 << 8) ++#define I2C_TX_BYTE (0x000000ff << 0) ++ ++#define I2C_STATUS 0x008 ++#define I2C_TRANSMIT (0x00000001 << 11) ++#define I2C_RECEIVE (0x00000001 << 10) ++#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) ++#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) ++#define I2C_TRANSMIT_PROG (0x00000001 << 7) ++#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) ++#define I2C_RECEIVE_PROG (0x00000001 << 5) ++#define I2C_RECEIVE_CLEAR (0x00000001 << 4) ++#define I2C_SDA_LINE (0x00000001 << 3) ++#define I2C_SCL_LINE (0x00000001 << 2) ++#define I2C_START_STOP_FLAG (0x00000001 << 1) ++#define I2C_MODE_STATUS (0x00000001 << 0) ++ ++#define I2C_CONTROL 0x00c ++#define I2C_SCL_CONTROL (0x00000001 << 7) ++#define I2C_SDA_CONTROL (0x00000001 << 6) ++#define I2C_RECEIVE_PROTECT (0x00000001 << 5) ++#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) ++#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) ++#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) ++#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) ++#define I2C_RESET (0x00000001 << 0) ++ ++#define I2C_CLOCK_DIVISOR_HIGH 0x010 ++#define I2C_CLOCK_HIGH (0x0000ffff << 0) ++ ++#define I2C_CLOCK_DIVISOR_LOW 0x014 ++#define I2C_CLOCK_LOW (0x0000ffff << 0) ++ ++#define I2C_RX_LEVEL 0x01c ++#define I2C_RECEIVE_RANGE (0x0000007f << 0) ++ ++#define I2C_TX_LEVEL 0x020 ++#define I2C_TRANSMIT_RANGE (0x0000007f << 0) ++ ++#define I2C_SDA_HOLD 0x028 ++#define I2C_HOLD_TIME (0x0000007f << 0) ++ ++#define MODULE_CONF 0xfd4 ++#define INT_CLR_ENABLE 0xfd8 ++#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) ++#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) ++#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) ++#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) ++#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) ++#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_SET_ENABLE 0xfdc ++#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_SET_ENABLE_RFF (0x00000001 << 9) ++#define I2C_SET_ENABLE_STDR (0x00000001 << 8) ++#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_SET_ENABLE_IBE (0x00000001 << 6) ++#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_SET_ENABLE_STSD (0x00000001 << 3) ++#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_SET_ENABLE_MAF (0x00000001 << 1) ++#define I2C_SET_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_STATUS 0xfe0 ++#define I2C_INTERRUPT_STFNF (0x00000001 << 12) ++#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) ++#define I2C_INTERRUPT_RFDA (0x00000001 << 10) ++#define I2C_INTERRUPTE_RFF (0x00000001 << 9) ++#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) ++#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) ++#define I2C_ERROR_IBE (0x00000001 << 6) ++#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) ++#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) ++#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) ++#define I2C_ACK_INTER_MTNA (0x00000001 << 2) ++#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) ++#define I2C_INTERRUPT_MTD (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define I2C_ENABLE_STFNF (0x00000001 << 12) ++#define I2C_ENABLE_MTFNF (0x00000001 << 11) ++#define I2C_ENABLE_RFDA (0x00000001 << 10) ++#define I2C_ENABLE_RFF (0x00000001 << 9) ++#define I2C_ENABLE_STDR (0x00000001 << 8) ++#define I2C_ENABLE_MTDR (0x00000001 << 7) ++#define I2C_ENABLE_IBE (0x00000001 << 6) ++#define I2C_ENABLE_MSMC (0x00000001 << 5) ++#define I2C_ENABLE_SRSD (0x00000001 << 4) ++#define I2C_ENABLE_STSD (0x00000001 << 3) ++#define I2C_ENABLE_MTNA (0x00000001 << 2) ++#define I2C_ENABLE_MAF (0x00000001 << 1) ++#define I2C_ENABLE_MTD (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) ++#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) ++#define I2C_CLR_STATUS_RFF (0x00000001 << 9) ++#define I2C_CLR_STATUS_STDR (0x00000001 << 8) ++#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) ++#define I2C_CLR_STATUS_IBE (0x00000001 << 6) ++#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) ++#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) ++#define I2C_CLR_STATUS_STSD (0x00000001 << 3) ++#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) ++#define I2C_CLR_STATUS_MAF (0x00000001 << 1) ++#define I2C_CLR_STATIS_MTD (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define I2C_SET_STATUS_STFNF (0x00000001 << 12) ++#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) ++#define I2C_SET_STATUS_RFDA (0x00000001 << 10) ++#define I2C_SET_STATUS_RFF (0x00000001 << 9) ++#define I2C_SET_STATUS_STDR (0x00000001 << 8) ++#define I2C_SET_STATUS_MTDR (0x00000001 << 7) ++#define I2C_SET_STATUS_IBE (0x00000001 << 6) ++#define I2C_SET_STATUS_MSMC (0x00000001 << 5) ++#define I2C_SET_STATUS_SRSD (0x00000001 << 4) ++#define I2C_SET_STATUS_STSD (0x00000001 << 3) ++#define I2C_SET_STATUS_MTNA (0x00000001 << 2) ++#define I2C_SET_STATUS_MAF (0x00000001 << 1) ++#define I2C_SET_STATIS_MTD (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- SPI Registers -------------- */ ++ ++#define SPI 0x0000d000 ++ ++#define SPI_CONTROL_REG 0x000 ++#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) ++#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) ++#define SPI_MODE_SELECT (0x00000001 << 5) ++#define SPI_CLOCK_POLARITY (0x00000001 << 4) ++#define SPI_CLOCK_PHASE (0x00000001 << 3) ++ ++#define SPI_STATUS 0x004 ++#define SPI_TRANSFER_FLAG (0x00000001 << 7) ++#define SPI_WRITE_COLLISSION (0x00000001 << 6) ++#define SPI_READ_OVERRUN (0x00000001 << 5) ++#define SPI_MODE_FAULT (0x00000001 << 4) ++#define SPI_SLAVE_ABORT (0x00000001 << 3) ++ ++#define SPI_DATA 0x008 ++#define SPI_BIDI_DATA (0x000000ff << 0) ++ ++#define SPI_CLOCK_COUNTER 0x00c ++#define SPI_CLOCK (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- GPIO Registers -------------- */ ++ ++#define GPIO 0x0000e000 ++ ++#define GPIO_RD 0x000 ++#define GPIO_WR 0x004 ++#define GPIO_WR_MODE 0x008 ++#define GPIO_OEN 0x00c ++ ++#define GPIO_SW_RST 0xff0 ++#define GPIO_SW_RESET (0x00000001 << 0) ++ ++#define GPIO_31 (1 << 31) ++#define GPIO_30 (1 << 30) ++#define GPIO_29 (1 << 29) ++#define GPIO_28 (1 << 28) ++#define GPIO_27 (1 << 27) ++#define GPIO_26 (1 << 26) ++#define GPIO_25 (1 << 25) ++#define GPIO_24 (1 << 24) ++#define GPIO_23 (1 << 23) ++#define GPIO_22 (1 << 22) ++#define GPIO_21 (1 << 21) ++#define GPIO_20 (1 << 20) ++#define GPIO_19 (1 << 19) ++#define GPIO_18 (1 << 18) ++#define GPIO_17 (1 << 17) ++#define GPIO_16 (1 << 16) ++#define GPIO_15 (1 << 15) ++#define GPIO_14 (1 << 14) ++#define GPIO_13 (1 << 13) ++#define GPIO_12 (1 << 12) ++#define GPIO_11 (1 << 11) ++#define GPIO_10 (1 << 10) ++#define GPIO_09 (1 << 9) ++#define GPIO_08 (1 << 8) ++#define GPIO_07 (1 << 7) ++#define GPIO_06 (1 << 6) ++#define GPIO_05 (1 << 5) ++#define GPIO_04 (1 << 4) ++#define GPIO_03 (1 << 3) ++#define GPIO_02 (1 << 2) ++#define GPIO_01 (1 << 1) ++#define GPIO_00 (1 << 0) ++ ++/* -------------- PHI_0 Registers -------------- */ ++ ++#define PHI_0 0x0000f000 ++ ++#define PHI_0_MODE 0x0000 ++#define PHI_0_0_CONFIG 0x0008 ++#define PHI_0_1_CONFIG 0x000c ++#define PHI_0_2_CONFIG 0x0010 ++#define PHI_0_3_CONFIG 0x0014 ++ ++#define PHI_POLARITY 0x0038 ++#define PHI_TIMEOUT 0x003c ++#define PHI_SW_RST 0x0ff0 ++ ++#define PHI_0_0_RW_0 0x1000 ++#define PHI_0_0_RW_511 0x17fc ++ ++#define PHI_0_1_RW_0 0x1800 ++#define PHI_0_1_RW_511 0x1ffc ++ ++#define PHI_0_2_RW_0 0x2000 ++#define PHI_0_2_RW_511 0x27fc ++ ++#define PHI_0_3_RW_0 0x2800 ++#define PHI_0_3_RW_511 0x2ffc ++ ++#define PHI_CSN_DEASSERT (0x00000001 << 2) ++#define PHI_AUTO_INCREMENT (0x00000001 << 1) ++#define PHI_FIFO_MODE (0x00000001 << 0) ++ ++#define PHI_DELAY_RD_WR (0x0000001f << 27) ++#define PHI_EXTEND_RDY3 (0x00000003 << 25) ++#define PHI_EXTEND_RDY2 (0x00000003 << 23) ++#define PHI_EXTEND_RDY1 (0x00000003 << 21) ++#define PHI_EXTEND_RDY0 (0x00000003 << 19) ++#define PHI_RDY3_OD (0x00000001 << 18) ++#define PHI_RDY2_OD (0x00000001 << 17) ++#define PHI_RDY1_OD (0x00000001 << 16) ++#define PHI_RDY0_OD (0x00000001 << 15) ++#define PHI_ALE_POL (0x00000001 << 14) ++#define PHI_WRN_POL (0x00000001 << 13) ++#define PHI_RDN_POL (0x00000001 << 12) ++#define PHI_RDY3_POL (0x00000001 << 11) ++#define PHI_RDY2_POL (0x00000001 << 10) ++#define PHI_RDY1_POL (0x00000001 << 9) ++#define PHI_RDY0_POL (0x00000001 << 8) ++#define PHI_CSN7_POL (0x00000001 << 7) ++#define PHI_CSN6_POL (0x00000001 << 6) ++#define PHI_CSN5_POL (0x00000001 << 5) ++#define PHI_CSN4_POL (0x00000001 << 4) ++#define PHI_CSN3_POL (0x00000001 << 3) ++#define PHI_CSN2_POL (0x00000001 << 2) ++#define PHI_CSN1_POL (0x00000001 << 1) ++#define PHI_CSN0_POL (0x00000001 << 0) ++ ++/* -------------- PHI_1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++#define PHI_1_MODE 0x00004 ++#define PHI_1_0_CONFIG 0x00018 ++#define PHI_1_1_CONFIG 0x0001c ++#define PHI_1_2_CONFIG 0x00020 ++#define PHI_1_3_CONFIG 0x00024 ++#define PHI_1_4_CONFIG 0x00028 ++#define PHI_1_5_CONFIG 0x0002c ++#define PHI_1_6_CONFIG 0x00030 ++#define PHI_1_7_CONFIG 0x00034 ++ ++#define PHI_1_0_RW_0 0x00000 ++#define PHI_1_0_RW_16383 0x0fffc ++ ++#define PHI_1_1_RW_0 0x1000 ++#define PHI_1_1_RW_16383 0x1ffc ++ ++#define PHI_1_2_RW_0 0x2000 ++#define PHI_1_2_RW_16383 0x2ffc ++ ++#define PHI_1_3_RW_0 0x3000 ++#define PHI_1_3_RW_16383 0x3ffc ++ ++#define PHI_1_4_RW_0 0x4000 ++#define PHI_1_4_RW_16383 0x4ffc ++ ++#define PHI_1_5_RW_0 0x5000 ++#define PHI_1_5_RW_16383 0x5ffc ++ ++#define PHI_1_6_RW_0 0x6000 ++#define PHI_1_6_RW_16383 0x6ffc ++ ++#define PHI_1_7_RW_0 0x7000 ++#define PHI_1_7_RW_16383 0x7ffc ++ ++/* -------------- CGU Registers -------------- */ ++ ++#define CGU 0x00013000 ++ ++#define CGU_SCR_0 0x000 ++#define CGU_SCR_1 0x004 ++#define CGU_SCR_2 0x008 ++#define CGU_SCR_3 0x00c ++#define CGU_SCR_4 0x010 ++#define CGU_SCR_5 0x014 ++#define CGU_SCR_6 0x018 ++#define CGU_SCR_7 0x01c ++#define CGU_SCR_8 0x020 ++#define CGU_SCR_9 0x024 ++#define CGU_SCR_10 0x028 ++#define CGU_SCR_11 0x02c ++#define CGU_SCR_12 0x030 ++#define CGU_SCR_13 0x034 ++#define CGU_SCR_STOP (0x00000001 << 3) ++#define CGU_SCR_RESET (0x00000001 << 2) ++#define CGU_SCR_ENF2 (0x00000001 << 1) ++#define CGU_SCR_ENF1 (0x00000001 << 0) ++ ++#define CGU_FS1_0 0x038 ++#define CGU_FS1_1 0x03c ++#define CGU_FS1_2 0x040 ++#define CGU_FS1_3 0x044 ++#define CGU_FS1_4 0x048 ++#define CGU_FS1_5 0x04c ++#define CGU_FS1_6 0x050 ++#define CGU_FS1_7 0x054 ++#define CGU_FS1_8 0x058 ++#define CGU_FS1_9 0x05c ++#define CGU_FS1_10 0x060 ++#define CGU_FS1_11 0x064 ++#define CGU_FS1_12 0x068 ++#define CGU_FS1_13 0x06c ++#define CGU_FS1_PLL (0x00000000 << 0) ++ ++ ++#define CGU_FS2_0 0x070 ++#define CGU_FS2_1 0x074 ++#define CGU_FS2_2 0x078 ++#define CGU_FS2_3 0x07c ++#define CGU_FS2_4 0x080 ++#define CGU_FS2_5 0x084 ++#define CGU_FS2_6 0x088 ++#define CGU_FS2_7 0x08c ++#define CGU_FS2_8 0x090 ++#define CGU_FS2_9 0x094 ++#define CGU_FS2_10 0x098 ++#define CGU_FS2_11 0x09c ++#define CGU_FS2_12 0x0a0 ++#define CGU_FS2_13 0x0a4 ++ ++#define CGU_SSR_0 0x0a8 ++#define CGU_SSR_1 0x0ac ++#define CGU_SSR_2 0x0b0 ++#define CGU_SSR_3 0x0b4 ++#define CGU_SSR_4 0x0b8 ++#define CGU_SSR_5 0x0bc ++#define CGU_SSR_6 0x0c0 ++#define CGU_SSR_7 0x0c4 ++#define CGU_SSR_8 0x0c8 ++#define CGU_SSR_9 0x0cc ++#define CGU_SSR_10 0x0d0 ++#define CGU_SSR_11 0x0d4 ++#define CGU_SSR_12 0x0d8 ++#define CGU_SSR_13 0x0dc ++ ++#define CGU_PCR_0_0 0x0e0 ++#define CGU_PCR_0_1 0x0e4 ++#define CGU_PCR_0_2 0x0e8 ++#define CGU_PCR_0_3 0x0ec ++#define CGU_PCR_0_4 0x0f0 ++#define CGU_PCR_0_5 0x0f4 ++#define CGU_PCR_0_6 0x0f8 ++#define CGU_PCR_0_7 0x0fc ++#define CGU_PCR_1_0 0x100 ++#define CGU_PCR_1_1 0x104 ++#define CGU_PCR_2_0 0x108 ++#define CGU_PCR_2_1 0x10c ++#define CGU_PCR_3_0 0x110 ++#define CGU_PCR_3_1 0x114 ++#define CGU_PCR_3_2 0x118 ++#define CGU_PCR_4_0 0x11c ++#define CGU_PCR_4_1 0x120 ++#define CGU_PCR_5 0x124 ++#define CGU_PCR_6 0x128 ++#define CGU_PCR_7 0x12c ++#define CGU_PCR_8 0x130 ++#define CGU_PCR_9 0x134 ++#define CGU_PCR_10 0x138 ++#define CGU_PCR_11 0x13c ++#define CGU_PCR_12 0x140 ++#define CGU_PCR_13 0x144 ++#define CGU_PCR_WAKE_EN (0x00000001 << 2) ++#define CGU_PCR_AUTO (0x00000001 << 1) ++#define CGU_PCR_RUN (0x00000001 << 0) ++ ++ ++#define CGU_PSR_0_0 0x148 ++#define CGU_PSR_0_1 0x14c ++#define CGU_PSR_0_2 0x150 ++#define CGU_PSR_0_3 0x154 ++#define CGU_PSR_0_4 0x158 ++#define CGU_PSR_0_5 0x15c ++#define CGU_PSR_0_6 0x160 ++#define CGU_PSR_0_7 0x164 ++#define CGU_PSR_1_0 0x168 ++#define CGU_PSR_1_1 0x16c ++#define CGU_PSR_2_0 0x170 ++#define CGU_PSR_2_1 0x174 ++#define CGU_PSR_3_0 0x178 ++#define CGU_PSR_3_1 0x17c ++#define CGU_PSR_3_2 0x180 ++#define CGU_PSR_4_0 0x184 ++#define CGU_PSR_4_1 0x188 ++#define CGU_PSR_5 0x18c ++#define CGU_PSR_6 0x190 ++#define CGU_PSR_7 0x194 ++#define CGU_PSR_8 0x198 ++#define CGU_PSR_9 0x19c ++#define CGU_PSR_10 0x1a0 ++#define CGU_PSR_11 0x1a4 ++#define CGU_PSR_12 0x1a8 ++#define CGU_PSR_13 0x1ac ++ ++#define CGU_ESR_0_0 0x1b0 ++#define CGU_ESR_0_1 0x1b4 ++#define CGU_ESR_0_2 0x1b8 ++#define CGU_ESR_0_3 0x1bc ++#define CGU_ESR_0_4 0x1c0 ++#define CGU_ESR_0_5 0x1c4 ++#define CGU_ESR_0_6 0x1c8 ++#define CGU_ESR_0_7 0x1cc ++#define CGU_ESR_1_0 0x1d0 ++#define CGU_ESR_1_1 0x1d4 ++#define CGU_ESR_2_0 0x1d8 ++#define CGU_ESR_2_1 0x1dc ++#define CGU_ESR_3_0 0x1e0 ++#define CGU_ESR_3_1 0x1e4 ++#define CGU_ESR_3_2 0x1e8 ++#define CGU_ESR_4_0 0x1ec ++#define CGU_ESR_4_1 0x1f0 ++#define CGU_ESR_5 0x1f4 ++#define CGU_ESR_6 0x1f8 ++#define CGU_ESR_7 0x1fc ++#define CGU_ESR_8 0x200 ++#define CGU_ESR_9 0x204 ++#define CGU_ESR_10 0x208 ++#define CGU_ESR_11 0x20c ++#define CGU_ESR_12 0x210 ++#define CGU_ESR_13 0x214 ++#define CGU_ESR_FD_EN (0x00000001 << 0) ++ ++#define CGU_FDC_0 0x218 ++#define CGU_FDC_1 0x21c ++#define CGU_FDC_2 0x220 ++#define CGU_FDC_3 0x224 ++#define CGU_FDC_4 0x228 ++#define CGU_FDC_5 0x22c ++#define CGU_FDC_6 0x230 ++#define CGU_FDC_7 0x234 ++#define CGU_FDC_8 0x238 ++#define CGU_FDC_9 0x23c ++#define CGU_FDC_10 0x240 ++#define CGU_FDC_11 0x244 ++#define CGU_FDC_12 0x248 ++#define CGU_FDC_13 0x24c ++#define CGU_FDC_STRETCH (0x00000001 << 0) ++#define CGU_FDC_RESET (0x00000001 << 1) ++#define CGU_FDC_RUN1 (0x00000001 << 2) ++#define CGU_FDC_MADD (0x000000ff << 3) ++#define CGU_FDC_MSUB (0x000000ff << 11) ++ ++/* -------------- DCS Registers -------------- */ ++ ++#define DCS 0x00014000 ++ ++#define DCSC_CTRL 0x000 ++#define DCSC_SEL_PLLDI (0x03ffffff << 5) ++#define DCSC_TOUT_SEL (0x0000000f << 1) ++#define DCSC_TOUT_OFF (0x00000001 << 0) ++ ++#define DCSC_ADDR 0x00c ++#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) ++ ++#define DCSC_STAT 0x010 ++#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) ++#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) ++#define DCSC_ERR_TOUT_READ (0x00000001 << 8) ++#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) ++#define DCSC_ERR_ACK (0x00000001 << 1) ++ ++#define DCSC_FEATURES 0x040 ++#define DCSC_UNIQUE_ID (0x00000007 << 16) ++#define DCSC_SECURITY (0x00000001 << 14) ++#define DCSC_NUM_BASE_REGS (0x00000003 << 11) ++#define DCSC_NUM_TARGETS (0x0000001f << 5) ++#define DCSC_NUM_INITIATORS (0x0000001f << 0) ++ ++#define DCSC_BASE_REG0 0x100 ++#define DCSC_BASE_N_REG (0x00000fff << 20) ++ ++#define DCSC_INT_CLR_ENABLE 0xfd8 ++#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_ENABLE 0xfdc ++#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_STATUS 0xfe0 ++#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) ++#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_ENABLE 0xfe4 ++#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) ++#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_CLR_STATUS 0xfe8 ++#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) ++#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) ++ ++#define DCSC_INT_SET_STATUS 0xfec ++#define DCSC_INT_SET_TOUT (0x00000001 << 1) ++#define DCSC_INT_SET_ERROR (0x00000001 << 0) ++ ++ ++ ++ ++/* -------------- GREG Registers -------------- */ ++ ++#define GREG 0x00012000 ++ ++#define GREG_SUBSYS_CONFIG 0x000 ++#define GREG_SUBSYS_ID (0x0000ffff << 16) ++#define GREG_SUBSYS_VID (0x0000ffff << 0) ++ ++#define GREG_MSI_BAR_PMCSR 0x004 ++#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) ++#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) ++#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) ++#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) ++#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) ++#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) ++#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) ++#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) ++ ++#define GREG_BAR_WIDTH_17 (0x0000001e << 8) ++#define GREG_BAR_WIDTH_18 (0x0000001c << 8) ++#define GREG_BAR_WIDTH_19 (0x00000018 << 8) ++#define GREG_BAR_WIDTH_20 (0x00000010 << 8) ++ ++#define GREG_BAR_PREFETCH (0x00000001 << 3) ++#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! ++#define GREG_MSI_MM_CAP2 (0x00000001 << 0) ++#define GREG_MSI_MM_CAP4 (0x00000002 << 0) ++#define GREG_MSI_MM_CAP8 (0x00000003 << 0) ++#define GREG_MSI_MM_CAP16 (0x00000004 << 0) ++#define GREG_MSI_MM_CAP32 (0x00000005 << 0) ++ ++#define GREG_PMCSR_DATA_1 0x008 ++#define GREG_PMCSR_DATA_2 0x00c ++#define GREG_VI_CTRL 0x010 ++#define GREG_FGPI_CTRL 0x014 ++ ++#define GREG_RSTU_CTRL 0x018 ++#define GREG_BOOT_READY (0x00000001 << 13) ++#define GREG_RESET_REQ (0x00000001 << 12) ++#define GREG_IP_RST_RELEASE (0x00000001 << 11) ++#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) ++#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) ++#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) ++#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) ++#define GREG_CGU_RST_RELEASE (0x00000001 << 6) ++#define GREG_IP_RST_ASSERT (0x00000001 << 5) ++#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) ++#define GREG_RST_ASSERT (0x00000001 << 3) ++#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) ++#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) ++#define GREG_CGU_RST_ASSERT (0x00000001 << 0) ++ ++#define GREG_I2C_CTRL 0x01c ++#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) ++ ++#define GREG_OVFLW_CTRL 0x020 ++#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) ++ ++#define GREG_TAG_ACK_FLEN 0x024 ++#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) ++#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) ++#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) ++#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) ++ ++#define GREG_VIDEO_IN_CTRL 0x028 ++ ++#define GREG_SPARE_1 0x02c ++#define GREG_SPARE_2 0x030 ++#define GREG_SPARE_3 0x034 ++#define GREG_SPARE_4 0x038 ++#define GREG_SPARE_5 0x03c ++#define GREG_SPARE_6 0x040 ++#define GREG_SPARE_7 0x044 ++#define GREG_SPARE_8 0x048 ++#define GREG_SPARE_9 0x04c ++#define GREG_SPARE_10 0x050 ++#define GREG_SPARE_11 0x054 ++#define GREG_SPARE_12 0x058 ++#define GREG_SPARE_13 0x05c ++#define GREG_SPARE_14 0x060 ++#define GREG_SPARE_15 0x064 ++ ++#define GREG_FAIL_DISABLE 0x068 ++#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) ++ ++#define GREG_SW_RST 0xff0 ++#define GREG_SW_RESET (0x00000001 << 0) ++ ++ ++ ++ ++/* BAR = 20 bits */ ++ ++/* -------------- PHI1 Registers -------------- */ ++ ++#define PHI_1 0x00020000 ++ ++ ++ ++#endif /* __SAA716x_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_rom.c b/drivers/media/common/saa716x/saa716x_rom.c +new file mode 100644 +index 0000000..7f8dbe1 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_rom.c +@@ -0,0 +1,1071 @@ ++#include ++#include ++ ++#include "saa716x_rom.h" ++#include "saa716x_adap.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++int i; ++ ++static int eeprom_read_bytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ ++ u8 b0[] = { MSB(reg), LSB(reg) }; ++ int ret; ++ ++ struct i2c_msg msg[] = { ++ { .addr = 0x50, .flags = 0, .buf = b0, .len = sizeof (b0) }, ++ { .addr = 0x50, .flags = I2C_M_RD, .buf = val, .len = len } ++ }; ++ ++ ret = i2c_transfer(adapter, msg, 2); ++ if (ret != 2) { ++ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); ++ return -EREMOTEIO; ++ } ++ ++ return ret; ++} ++ ++static int saa716x_read_rombytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) ++{ ++ struct saa716x_i2c *i2c = saa716x->i2c; ++ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; ++ struct i2c_msg msg[2]; ++ ++ u8 b0[2]; ++ int ret, count; ++ ++ count = len / DUMP_BYTES; ++ if (len % DUMP_BYTES) ++ count++; ++ ++ count *= 2; ++ ++ for (i = 0; i < count; i += 2) { ++ dprintk(SAA716x_DEBUG, 1, "Length=%d, Count=%d, Reg=0x%02x", ++ len, ++ count, ++ reg); ++ ++ b0[0] = MSB(reg); ++ b0[1] = LSB(reg); ++ ++ /* Write */ ++ msg[0].addr = 0x50; ++ msg[0].flags = 0; ++ msg[0].buf = b0; ++ msg[0].len = 2; ++ ++ /* Read */ ++ msg[1].addr = 0x50; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = val; ++ ++ if (i == (count - 2)) { ++ /* last message */ ++ if (len % DUMP_BYTES) { ++ msg[1].len = len % DUMP_BYTES; ++ dprintk(SAA716x_DEBUG, 1, "Last Message length=%d", len % DUMP_BYTES); ++ } else { ++ msg[1].len = DUMP_BYTES; ++ } ++ } else { ++ msg[1].len = DUMP_BYTES; ++ } ++ ++ ret = i2c_transfer(adapter, msg, 2); ++ if (ret != 2) { ++ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); ++ return -EREMOTEIO; ++ } ++ ++ reg += DUMP_BYTES; ++ val += DUMP_BYTES; ++ } ++ ++ return 0; ++} ++ ++static int saa716x_get_offset(struct saa716x_dev *saa716x, u8 *buf, u32 *offset) ++{ ++ int i; ++ ++ *offset = 0; ++ for (i = 0; i < 256; i++) { ++ if (!(strncmp("START", buf + i, 5))) ++ break; ++ } ++ dprintk(SAA716x_INFO, 1, "Offset @ %d", i); ++ *offset = i; ++ ++ return 0; ++} ++ ++static int saa716x_eeprom_header(struct saa716x_dev *saa716x, ++ struct saa716x_romhdr *rom_header, ++ u8 *buf, ++ u32 *offset) ++{ ++ memcpy(rom_header, &buf[*offset], sizeof (struct saa716x_romhdr)); ++ if (rom_header->header_size != sizeof (struct saa716x_romhdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ (int)sizeof (struct saa716x_romhdr), ++ rom_header->header_size); ++ ++ return -1; ++ } ++ *offset += sizeof (struct saa716x_romhdr); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Data=%d bytes\n", ++ saa716x->pdev->device, ++ rom_header->data_size); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Version=%d\n", ++ saa716x->pdev->device, ++ rom_header->version); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Devices=%d\n", ++ saa716x->pdev->device, ++ rom_header->devices); ++ ++ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Compressed=%d\n\n", ++ saa716x->pdev->device, ++ rom_header->compression); ++ ++ return 0; ++} ++ ++int saa716x_dump_eeprom(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_romhdr rom_header; ++ u8 buf[DUMP_BYTES]; ++ int i, err = 0; ++ u32 offset = 0; ++ ++ err = eeprom_read_bytes(saa716x, DUMP_OFFST, DUMP_BYTES, buf); ++ if (err < 0) { ++ dprintk(SAA716x_ERROR, 1, "EEPROM Read error"); ++ return err; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, " Card: %s\n", ++ saa716x->config->model_name); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " ---------------- SAA%02x ROM @ Offset 0x%02x ----------------", ++ saa716x->pdev->device, ++ DUMP_OFFST); ++ ++ for (i = 0; i < DUMP_BYTES; i++) { ++ if ((i % 16) == 0) { ++ dprintk(SAA716x_NOTICE, 0, "\n "); ++ dprintk(SAA716x_NOTICE, 0, "%04x: ", i); ++ } ++ ++ if ((i % 8) == 0) ++ dprintk(SAA716x_NOTICE, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_NOTICE, 0, " "); ++ dprintk(SAA716x_NOTICE, 0, "%02x ", buf[i]); ++ } ++ dprintk(SAA716x_NOTICE, 0, "\n"); ++ dprintk(SAA716x_NOTICE, 0, ++ " ---------------- SAA%02x ROM Dump end ---------------------\n\n", ++ saa716x->pdev->device); ++ ++ err = saa716x_get_offset(saa716x, buf, &offset); ++ if (err != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Descriptor not found <%d>", err); ++ return err; ++ } ++ offset += 5; ++ saa716x->id_offst = offset; ++ /* Get header */ ++ err = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); ++ if (err != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", err); ++ return -1; ++ } ++ saa716x->id_len = rom_header.data_size; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(saa716x_dump_eeprom); ++ ++static void saa716x_descriptor_dbg(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset, ++ u8 size, ++ u8 ext_size) ++{ ++ int i; ++ ++ dprintk(SAA716x_INFO, 0, " "); ++ for (i = 0; i < 49; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ ++ for (i = 0; i < size + ext_size; i++) { ++ if ((i % 16) == 0) ++ dprintk(SAA716x_INFO, 0, "\n "); ++ if ((i % 8) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ ++ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); ++ } ++ ++ dprintk(SAA716x_INFO, 0, "\n "); ++ for (i = 0; i < 49; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ dprintk(SAA716x_INFO, 0, "\n"); ++ ++} ++ ++static int saa716x_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext Data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_gpio_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_gpio_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_gpio_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_gpio_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_gpio_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Pins=%d\n", ++ saa716x->pdev->device, ++ header.pins); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ ++ return 0; ++} ++ ++static int saa716x_video_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_video_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_video_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_video_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_video_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 0=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port0); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 1=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port1); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: PORT 2=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port2); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI PORT ID=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_port_id); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Video PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Encoder PORT Type=0x%02x\n", ++ saa716x->pdev->device, ++ header.encoder_port_type); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Video Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.video_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: VBI Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.vbi_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Encoder Output=0x%02x\n", ++ saa716x->pdev->device, ++ header.encoder_output); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_audio_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_audio_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_audio_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_audio_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_audio_decoder_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_event_source_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_evsrc_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_evsrc_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_evsrc_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_evsrc_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_crossbar_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_xbar_hdr header; ++ struct saa716x_xbar_pair_info pair_info; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_xbar_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_xbar_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_xbar_hdr)); ++ ++ return -1; ++ } ++ ++ memcpy(&pair_info, &buf[*offset], sizeof (struct saa716x_xbar_pair_info)); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Pairs=%d\n", ++ saa716x->pdev->device, ++ header.pair_inputs); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data + (sizeof (struct saa716x_xbar_pair_info) * header.pair_inputs); ++ return 0; ++} ++ ++static int saa716x_tuner_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_tuner_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_tuner_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_tuner_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_tuner_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_pll_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_pll_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_pll_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_pll_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_pll_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_channel_decoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_channel_decoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_channel_decoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_channel_decoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_channel_decoder_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_encoder_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_encoder_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_encoder_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_encoder_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_encoder_hdr)); ++ ++ return -1; ++ } ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_ir_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_ir_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_ir_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_ir_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_ir_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_eeprom_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_eeprom_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_eeprom_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_eeprom_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof (struct saa716x_eeprom_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_filter_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_filter_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_filter_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_filter_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof(struct saa716x_filter_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_streamdev_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ struct saa716x_streamdev_hdr header; ++ ++ memcpy(&header, &buf[*offset], sizeof (struct saa716x_streamdev_hdr)); ++ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); ++ if (header.size != sizeof (struct saa716x_streamdev_hdr)) { ++ dprintk(SAA716x_ERROR, 1, ++ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", ++ header.size, ++ (int)sizeof(struct saa716x_streamdev_hdr)); ++ ++ return -1; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ header.size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n", ++ saa716x->pdev->device, ++ header.ext_data); ++ ++ *offset += header.size + header.ext_data; ++ return 0; ++} ++ ++static int saa716x_unknown_device_info(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset) ++{ ++ u8 size; ++ u8 ext_size = 0; ++ ++ size = buf[*offset]; ++ if (size > 1) ++ ext_size = buf[*offset + size -1]; ++ ++ saa716x_descriptor_dbg(saa716x, buf, offset, size, ext_size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ size); ++ ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Ext data=%d bytes\n\n", ++ saa716x->pdev->device, ++ ext_size); ++ ++ *offset += size + ext_size; ++ return 0; ++} ++ ++ ++static void saa716x_device_dbg(struct saa716x_dev *saa716x, ++ u8 *buf, ++ u32 *offset, ++ u8 size, ++ u8 ext_size, ++ u8 addr_size) ++{ ++ int i; ++ ++ dprintk(SAA716x_INFO, 0, " "); ++ for (i = 0; i < 53; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ ++ for (i = 0; i < size + ext_size + addr_size; i++) { ++ if ((i % 16) == 0) ++ dprintk(SAA716x_INFO, 0, "\n "); ++ if ((i % 8) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ if ((i % 4) == 0) ++ dprintk(SAA716x_INFO, 0, " "); ++ ++ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); ++ } ++ ++ dprintk(SAA716x_INFO, 0, "\n "); ++ for (i = 0; i < 53; i++) ++ dprintk(SAA716x_INFO, 0, "-"); ++ dprintk(SAA716x_INFO, 0, "\n"); ++ ++} ++ ++ ++static int saa716x_device_info(struct saa716x_dev *saa716x, ++ struct saa716x_devinfo *device, ++ u8 *buf, ++ u32 *offset) ++{ ++ u8 address = 0; ++ ++ memcpy(device, &buf[*offset], sizeof(struct saa716x_devinfo)); ++ if (device->struct_size != sizeof(struct saa716x_devinfo)) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Device size mismatch! Read=%d bytes, expected=%d bytes", ++ device->struct_size, ++ (int)sizeof(struct saa716x_devinfo)); ++ ++ return -1; ++ } ++ ++ saa716x_device_dbg(saa716x, ++ buf, ++ offset, ++ device->struct_size, ++ device->extd_data_size, ++ device->addr_size); ++ ++ *offset += device->struct_size; ++ ++ if (device->addr_size) { ++ address = buf[*offset]; ++ address >>= 1; ++ *offset += device->addr_size; ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device @ 0x%02x\n", ++ saa716x->pdev->device, ++ address); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Size=%d bytes\n", ++ saa716x->pdev->device, ++ device->struct_size); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->device_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Master ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->master_devid); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Bus ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->master_busid); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device type=0x%02x\n", ++ saa716x->pdev->device, ++ device->device_type); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Implementation ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->implem_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Path ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->path_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: GPIO ID=0x%02x\n", ++ saa716x->pdev->device, ++ device->gpio_id); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Address=%d bytes\n", ++ saa716x->pdev->device, ++ device->addr_size); ++ ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Extended data=%d bytes\n\n", ++ saa716x->pdev->device, ++ device->extd_data_size); ++ ++ if (device->extd_data_size) { ++ u32 mask; ++ ++ mask = 0x00000001; ++ while (mask) { ++ if (device->device_type & mask) { ++ switch (mask) { ++ case DECODER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case GPIO_SOURCE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found GPIO device\n", ++ saa716x->pdev->device); ++ ++ saa716x_gpio_info(saa716x, buf, offset); ++ break; ++ ++ case VIDEO_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Video Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_video_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case AUDIO_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Audio Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_audio_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case EVENT_SOURCE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Event source\n", ++ saa716x->pdev->device); ++ ++ saa716x_event_source_info(saa716x, buf, offset); ++ break; ++ ++ case CROSSBAR: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Crossbar device\n", ++ saa716x->pdev->device); ++ ++ saa716x_crossbar_info(saa716x, buf, offset); ++ break; ++ ++ case TUNER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Tuner device\n", ++ saa716x->pdev->device); ++ ++ saa716x_tuner_info(saa716x, buf, offset); ++ break; ++ ++ case PLL_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found PLL device\n", ++ saa716x->pdev->device); ++ ++ saa716x_pll_info(saa716x, buf, offset); ++ break; ++ ++ case CHANNEL_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Channel Demodulator device\n", ++ saa716x->pdev->device); ++ ++ saa716x_channel_decoder_info(saa716x, buf, offset); ++ break; ++ ++ case RDS_DECODER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found RDS Decoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ case ENCODER_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Encoder device\n", ++ saa716x->pdev->device); ++ ++ saa716x_encoder_info(saa716x, buf, offset); ++ break; ++ ++ case IR_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found IR device\n", ++ saa716x->pdev->device); ++ ++ saa716x_ir_info(saa716x, buf, offset); ++ break; ++ ++ case EEPROM_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found EEPROM device\n", ++ saa716x->pdev->device); ++ ++ saa716x_eeprom_info(saa716x, buf, offset); ++ break; ++ ++ case NOISE_FILTER: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Noise filter device\n", ++ saa716x->pdev->device); ++ ++ saa716x_filter_info(saa716x, buf, offset); ++ break; ++ ++ case LNx_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found LNx device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ case STREAM_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found streaming device\n", ++ saa716x->pdev->device); ++ ++ saa716x_streamdev_info(saa716x, buf, offset); ++ break; ++ ++ case CONFIGSPACE_DEVICE: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found Configspace device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ ++ default: ++ dprintk(SAA716x_NOTICE, 0, ++ " SAA%02x ROM: Found unknown device\n", ++ saa716x->pdev->device); ++ ++ saa716x_unknown_device_info(saa716x, buf, offset); ++ break; ++ } ++ } ++ mask <<= 1; ++ } ++ } ++ ++ dprintk(SAA716x_NOTICE, 0, "\n"); ++ ++ return 0; ++} ++ ++int saa716x_eeprom_data(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_romhdr rom_header; ++ struct saa716x_devinfo *device; ++ ++ u8 buf[1024]; ++ int i, ret = 0; ++ u32 offset = 0; ++ ++ /* dump */ ++ ret = saa716x_read_rombytes(saa716x, saa716x->id_offst, saa716x->id_len + 8, buf); ++ if (ret < 0) { ++ dprintk(SAA716x_ERROR, 1, "EEPROM Read error <%d>", ret); ++ goto err0; ++ } ++ ++ /* Get header */ ++ ret = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", ret); ++ goto err0; ++ } ++ ++ /* allocate for device info */ ++ device = kzalloc(sizeof (struct saa716x_devinfo) * rom_header.devices, GFP_KERNEL); ++ if (device == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: out of memory"); ++ goto err0; ++ } ++ ++ for (i = 0; i < rom_header.devices; i++) { ++ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: ===== Device %d =====\n", ++ saa716x->pdev->device, ++ i); ++ ++ ret = saa716x_device_info(saa716x, &device[i], buf, &offset); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Device info read failed <%d>", ret); ++ goto err1; ++ } ++ } ++ ++ kfree(device); ++ ++ return 0; ++ ++err1: ++ kfree(device); ++ ++err0: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(saa716x_eeprom_data); +diff --git a/drivers/media/common/saa716x/saa716x_rom.h b/drivers/media/common/saa716x/saa716x_rom.h +new file mode 100644 +index 0000000..6bb317f +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_rom.h +@@ -0,0 +1,253 @@ ++#ifndef __SAA716x_ROM_H ++#define __SAA716x_ROM_H ++ ++ ++#define MSB(__x) ((__x >> 8) & 0xff) ++#define LSB(__x) (__x & 0xff) ++ ++#define DUMP_BYTES 0xf0 ++#define DUMP_OFFST 0x000 ++ ++struct saa716x_dev; ++ ++struct saa716x_romhdr { ++ u16 header_size; ++ u8 compression; ++ u8 version; ++ u16 data_size; ++ u8 devices; ++ u8 checksum; ++} __attribute__((packed)); ++ ++struct saa716x_devinfo { ++ u8 struct_size; ++ u8 device_id; ++ u8 master_devid; ++ u8 master_busid; ++ u32 device_type; ++ u16 implem_id; ++ u8 path_id; ++ u8 gpio_id; ++ u16 addr_size; ++ u16 extd_data_size; ++} __attribute__((packed)); ++ ++enum saa716x_device_types { ++ DECODER_DEVICE = 0x00000001, ++ GPIO_SOURCE = 0x00000002, ++ VIDEO_DECODER = 0x00000004, ++ AUDIO_DECODER = 0x00000008, ++ EVENT_SOURCE = 0x00000010, ++ CROSSBAR = 0x00000020, ++ TUNER_DEVICE = 0x00000040, ++ PLL_DEVICE = 0x00000080, ++ CHANNEL_DECODER = 0x00000100, ++ RDS_DECODER = 0x00000200, ++ ENCODER_DEVICE = 0x00000400, ++ IR_DEVICE = 0x00000800, ++ EEPROM_DEVICE = 0x00001000, ++ NOISE_FILTER = 0x00002000, ++ LNx_DEVICE = 0x00004000, ++ STREAM_DEVICE = 0x00010000, ++ CONFIGSPACE_DEVICE = 0x80000000 ++}; ++ ++struct saa716x_decoder_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_decoder_info { ++ struct saa716x_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_gpio_hdr { ++ u8 size; ++ u8 pins; ++ u8 rsvd; ++ u8 ext_data; ++}; ++ ++struct saa716x_gpio_info { ++ struct saa716x_gpio_hdr gpio_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_video_decoder_hdr { ++ u8 size; ++ u8 video_port0; ++ u8 video_port1; ++ u8 video_port2; ++ u8 vbi_port_id; ++ u8 video_port_type; ++ u8 vbi_port_type; ++ u8 encoder_port_type; ++ u8 video_output; ++ u8 vbi_output; ++ u8 encoder_output; ++ u8 ext_data; ++}; ++ ++struct saa716x_video_decoder_info { ++ struct saa716x_video_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_audio_decoder_hdr { ++ u8 size; ++ u8 port; ++ u8 output; ++ u8 ext_data; ++}; ++ ++struct saa716x_audio_decoder_info { ++ struct saa716x_audio_decoder_hdr decoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_evsrc_hdr { ++ u8 size; ++ u8 master_devid; ++ u16 condition_id; ++ u8 rsvd; ++ u8 ext_data; ++}; ++ ++struct saa716x_evsrc_info { ++ struct saa716x_evsrc_hdr evsrc_hdr; ++ u8 *ext_data; ++}; ++ ++enum saa716x_input_pair_type { ++ TUNER_SIF = 0x00, ++ TUNER_LINE = 0x01, ++ TUNER_SPDIF = 0x02, ++ TUNER_NONE = 0x03, ++ CVBS_LINE = 0x04, ++ CVBS_SPDIF = 0x05, ++ CVBS_NONE = 0x06, ++ YC_LINE = 0x07, ++ YC_SPDIF = 0x08, ++ YC_NONE = 0x09, ++ YPbPr_LINE = 0x0a, ++ YPbPr_SPDIF = 0x0b, ++ YPbPr_NONE = 0x0c, ++ NO_LINE = 0x0d, ++ NO_SPDIF = 0x0e, ++ RGB_LINE = 0x0f, ++ RGB_SPDIF = 0x10, ++ RGB_NONE = 0x11 ++}; ++ ++struct saa716x_xbar_pair_info { ++ u8 pair_input_type; ++ u8 video_input_id; ++ u8 audio_input_id; ++}; ++ ++struct saa716x_xbar_hdr { ++ u8 size; ++ u8 pair_inputs; ++ u8 pair_route_default; ++ u8 ext_data; ++}; ++ ++struct saa716x_xbar_info { ++ struct saa716x_xbar_hdr xbar_hdr; ++ struct saa716x_xbar_pair_info *pair_info; ++ u8 *ext_data; ++}; ++ ++struct saa716x_tuner_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_tuner_info { ++ struct saa716x_tuner_hdr tuner_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_pll_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_pll_info { ++ struct saa716x_pll_hdr pll_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_channel_decoder_hdr { ++ u8 size; ++ u8 port; ++ u8 ext_data; ++}; ++ ++struct saa716x_channel_decoder_info { ++ struct saa716x_channel_decoder_hdr channel_dec_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_encoder_hdr { ++ u8 size; ++ u8 stream_port0; ++ u8 stream_port1; ++ u8 ext_data; ++}; ++ ++struct saa716x_encoder_info { ++ struct saa716x_encoder_hdr encoder_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_ir_hdr { ++ u8 size; ++ u8 ir_caps; ++ u8 ext_data; ++}; ++ ++struct saa716x_ir_info { ++ struct saa716x_ir_hdr ir_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_eeprom_hdr { ++ u8 size; ++ u8 rel_device; ++ u8 ext_data; ++}; ++ ++struct saa716x_eeprom_info { ++ struct saa716x_eeprom_hdr eeprom_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_filter_hdr { ++ u8 size; ++ u8 video_decoder; ++ u8 audio_decoder; ++ u8 event_source; ++ u8 ext_data; ++}; ++ ++struct saa716x_filter_info { ++ struct saa716x_filter_hdr filter_hdr; ++ u8 *ext_data; ++}; ++ ++struct saa716x_streamdev_hdr { ++ u8 size; ++ u8 ext_data; ++}; ++ ++struct saa716x_streamdev_info { ++ struct saa716x_streamdev_hdr streamdev_hdr; ++ u8 *ext_data; ++}; ++ ++extern int saa716x_dump_eeprom(struct saa716x_dev *saa716x); ++extern int saa716x_eeprom_data(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_ROM_H */ +diff --git a/drivers/media/common/saa716x/saa716x_spi.c b/drivers/media/common/saa716x/saa716x_spi.c +new file mode 100644 +index 0000000..8859454 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_spi.c +@@ -0,0 +1,313 @@ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_spi_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++#if 0 // not needed atm ++int saa716x_spi_irqevent(struct saa716x_dev *saa716x) ++{ ++ u32 stat, mask; ++ ++ BUG_ON(saa716x == NULL); ++ ++ stat = SAA716x_EPRD(SPI, SPI_STATUS); ++ mask = SAA716x_EPRD(SPI, SPI_CONTROL_REG) & SPI_SERIAL_INTER_ENABLE; ++ if ((!stat && !mask)) ++ return -1; ++ ++ dprintk(SAA716x_DEBUG, 0, "SPI event: Stat=<%02x>", stat); ++ ++ if (stat & SPI_TRANSFER_FLAG) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_WRITE_COLLISSION) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_READ_OVERRUN) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_MODE_FAULT) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ if (stat & SPI_SLAVE_ABORT) ++ dprintk(SAA716x_DEBUG, 0, " "); ++ ++ return 0; ++} ++#endif ++ ++void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length) ++{ ++ int i; ++ u32 value; ++ int rounds; ++ ++ for (i = 0; i < length; i++) { ++ SAA716x_EPWR(SPI, SPI_DATA, data[i]); ++ rounds = 0; ++ value = SAA716x_EPRD(SPI, SPI_STATUS); ++ ++ while ((value & SPI_TRANSFER_FLAG) == 0 && rounds < 5000) { ++ value = SAA716x_EPRD(SPI, SPI_STATUS); ++ rounds++; ++ } ++ } ++} ++EXPORT_SYMBOL_GPL(saa716x_spi_write); ++ ++#if 0 // not needed atm ++static int saa716x_spi_status(struct saa716x_dev *saa716x, u32 *status) ++{ ++ u32 stat; ++ ++ stat = SAA716x_EPRD(SPI, SPI_STATUS); ++ ++ if (stat & SPI_TRANSFER_FLAG) ++ dprintk(SAA716x_DEBUG, 1, "Transfer complete <%02x>", stat); ++ ++ if (stat & SPI_WRITE_COLLISSION) ++ dprintk(SAA716x_DEBUG, 1, "Write collission <%02x>", stat); ++ ++ if (stat & SPI_READ_OVERRUN) ++ dprintk(SAA716x_DEBUG, 1, "Read Overrun <%02x>", stat); ++ ++ if (stat & SPI_MODE_FAULT) ++ dprintk(SAA716x_DEBUG, 1, "MODE fault <%02x>", stat); ++ ++ if (stat & SPI_SLAVE_ABORT) ++ dprintk(SAA716x_DEBUG, 1, "SLAVE abort <%02x>", stat); ++ ++ *status = stat; ++ ++ return 0; ++} ++ ++#define SPI_CYCLE_TIMEOUT 100 ++ ++static int saa716x_spi_xfer(struct saa716x_dev *saa716x, u32 *data) ++{ ++ u32 i, status = 0; ++ ++ /* write data and wait for completion */ ++ SAA716x_EPWR(SPI, SPI_DATA, data[i]); ++ for (i = 0; i < SPI_CYCLE_TIMEOUT; i++) { ++ msleep(10); ++ saa716x_spi_status(saa716x, &status); ++#if 0 ++ if (status & SPI_TRANSFER_FLAG) { ++ data = SAA716x_EPRD(SPI, SPI_DATA); ++ return 0; ++ } ++#endif ++ if (status & (SPI_WRITE_COLLISSION | ++ SPI_READ_OVERRUN | ++ SPI_MODE_FAULT | ++ SPI_SLAVE_ABORT)) ++ ++ return -EIO; ++ } ++ ++ return -EIO; ++} ++ ++#if 0 ++static int saa716x_spi_wr(struct saa716x_dev *saa716x, const u8 *data, int length) ++{ ++ struct saa716x_spi_config *config = saa716x->spi_config; ++ u32 gpio_mask; ++ int ret = 0; ++ ++ // protect against multiple access ++ spin_lock(&saa716x->gpio_lock); ++ ++ // configure the module ++ saa716x_spi_config(saa716x); ++ ++ // check input ++ ++ // change polarity of GPIO if active high ++ if (config->active_hi) { ++ select = 1; ++ release = 0; ++ } ++ ++ // configure GPIO, first set output register to low selected level ++ saa716x_gpio_write(saa716x, gpio, select); ++ ++ // set mode register to register controlled (0) ++ gpio_mask = (1 << gpio); ++ saa716x_set_gpio_mode(saa716x, gpio_mask, 0); ++ ++ // configure bit as output (0) ++ saa716x_gpio_ctl(saa716x, gpio_mask, 0); ++ ++ // wait at least 500ns before sending a byte ++ msleep(1); ++ ++ // send command ++ for (i = 0; i < dwCommandSize; i++) { ++ ucData = 0; ++// dwStatus = TransferData(pucCommand[i], &ucData); ++ ret = saa716x_spi_xfer(saa716x); ++ //tmDBGPRINTEx(4,("Info: Command 0x%x ", pucCommand[i] )); ++ ++ /* If command length > 1, disable CS at the end of each command. ++ * But after the last command byte CS must be left active! ++ */ ++ if ((dwCommandSize > 1) && (i < dwCommandSize - 1)) { ++ ++ saa716x_gpio_write(saa716x, gpio, release); ++ msleep(1); /* 500 nS minimum */ ++ saa716x_gpio_write(saa716x, gpio, select); ++ } ++ ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Command transfer failed"); ++ msleep(1); /* 500 nS minimum */ ++ saa716x_gpio_write(saa716x, gpio, release); /* release GPIO */ ++ spin_unlock(&saa716x->spi_lock); ++ return ret; ++ } ++ ++ if (config->LSB_first) ++ dwTransferByte++; ++ else ++ dwTransferByte--; ++ } ++ ++// assume that the byte order is the same as the bit order ++ ++// send read address ++ ++// send data ++ ++// wait at least 500ns before releasing slave ++ ++// release GPIO pin ++ ++ // release spinlock ++ spin_unlock(&saa716x->gpio_lock); ++} ++#endif ++ ++#define MODEBITS (SPI_CPOL | SPI_CPHA) ++ ++static int saa716x_spi_setup(struct spi_device *spi) ++{ ++ struct spi_master *master = spi->master; ++ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); ++ struct saa716x_dev *saa716x = saa716x_spi->saa716x; ++ struct saa716x_spi_config *config = &saa716x->spi_config; ++ ++ u8 control = 0; ++ ++ if (spi->mode & ~MODEBITS) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Unsupported MODE bits <%x>", ++ spi->mode & ~MODEBITS); ++ ++ return -EINVAL; ++ } ++ ++ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, config->clk_count); ++ ++ control |= SPI_MODE_SELECT; /* SPI Master */ ++ ++ if (config->LSB_first) ++ control |= SPI_LSB_FIRST_ENABLE; ++ ++ if (config->clk_pol) ++ control |= SPI_CLOCK_POLARITY; ++ ++ if (config->clk_pha) ++ control |= SPI_CLOCK_PHASE; ++ ++ SAA716x_EPWR(SPI, SPI_CONTROL_REG, control); ++ ++ return 0; ++} ++ ++static void saa716x_spi_cleanup(struct spi_device *spi) ++{ ++ ++} ++ ++static int saa716x_spi_transfer(struct spi_device *spi, struct spi_message *msg) ++{ ++ struct spi_master *master = spi->master; ++ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); ++ struct saa716x_dev *saa716x = saa716x_spi->saa716x; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&saa716x->gpio_lock, flags); ++#if 0 ++ if (saa716x_spi->run == QUEUE_STOPPED) { ++ spin_unlock_irqrestore(&saa716x_spi->lock, flags); ++ return -ESHUTDOWN; ++ } ++ ++ msg->actual_length = 0; ++ msg->status = -EINPROGRESS; ++ msg->state = START_STATE; ++ ++ list_add_tail(&msg->queue, &saa716x_spi->queue); ++ ++ if (saa716x_spi->run == QUEUE_RUNNING && !saa716x_spi->busy) ++ queue_work(saa716x_spi->workqueue, &saa716x_spi->pump_messages); ++#endif ++ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); ++ ++ return 0; ++} ++ ++int saa716x_spi_init(struct saa716x_dev *saa716x) ++{ ++ struct pci_dev *pdev = saa716x->pdev; ++ struct spi_master *master; ++ struct saa716x_spi_state *saa716x_spi; ++ int ret; ++ ++ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", ++ saa716x->pdev->device); ++ ++ master = spi_alloc_master(&pdev->dev, sizeof (struct saa716x_spi_state)); ++ if (master == NULL) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: Cannot allocate SPI Master!"); ++ return -ENOMEM; ++ } ++ ++ saa716x_spi = spi_master_get_devdata(master); ++ saa716x_spi->master = master; ++ saa716x_spi->saa716x = saa716x; ++ saa716x->saa716x_spi = saa716x_spi; ++ ++ master->bus_num = pdev->bus->number; ++ master->num_chipselect = 1; /* TODO! use config */ ++ master->cleanup = saa716x_spi_cleanup; ++ master->setup = saa716x_spi_setup; ++ master->transfer = saa716x_spi_transfer; ++ ++ ret = spi_register_master(master); ++ if (ret != 0) { ++ dprintk(SAA716x_ERROR, 1, "ERROR: registering SPI Master!"); ++ goto err; ++ } ++err: ++ spi_master_put(master); ++ return ret; ++} ++EXPORT_SYMBOL(saa716x_spi_init); ++ ++void saa716x_spi_exit(struct saa716x_dev *saa716x) ++{ ++ struct saa716x_spi_state *saa716x_spi = saa716x->saa716x_spi; ++ ++ spi_unregister_master(saa716x_spi->master); ++ dprintk(SAA716x_DEBUG, 1, "SAA%02x SPI succesfully removed", saa716x->pdev->device); ++} ++EXPORT_SYMBOL(saa716x_spi_exit); ++#endif ++ +diff --git a/drivers/media/common/saa716x/saa716x_spi.h b/drivers/media/common/saa716x/saa716x_spi.h +new file mode 100644 +index 0000000..0060c22 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_spi.h +@@ -0,0 +1,23 @@ ++#ifndef __SAA716x_SPI_H ++#define __SAA716x_SPI_H ++ ++struct saa716x_dev; ++ ++struct saa716x_spi_config { ++ u8 clk_count; ++ u8 clk_pol:1; ++ u8 clk_pha:1; ++ u8 LSB_first:1; ++}; ++ ++struct saa716x_spi_state { ++ struct spi_master *master; ++ struct saa716x_dev *saa716x; ++}; ++ ++extern void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length); ++ ++extern int saa716x_spi_init(struct saa716x_dev *saa716x); ++extern void saa716x_spi_exit(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_SPI_H */ +diff --git a/drivers/media/common/saa716x/saa716x_spi_reg.h b/drivers/media/common/saa716x/saa716x_spi_reg.h +new file mode 100644 +index 0000000..c51abce +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_spi_reg.h +@@ -0,0 +1,27 @@ ++#ifndef __SAA716x_SPI_REG_H ++#define __SAA716x_SPI_REG_H ++ ++/* -------------- SPI Registers -------------- */ ++ ++#define SPI_CONTROL_REG 0x000 ++#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) ++#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) ++#define SPI_MODE_SELECT (0x00000001 << 5) ++#define SPI_CLOCK_POLARITY (0x00000001 << 4) ++#define SPI_CLOCK_PHASE (0x00000001 << 3) ++ ++#define SPI_STATUS 0x004 ++#define SPI_TRANSFER_FLAG (0x00000001 << 7) ++#define SPI_WRITE_COLLISSION (0x00000001 << 6) ++#define SPI_READ_OVERRUN (0x00000001 << 5) ++#define SPI_MODE_FAULT (0x00000001 << 4) ++#define SPI_SLAVE_ABORT (0x00000001 << 3) ++ ++#define SPI_DATA 0x008 ++#define SPI_BIDI_DATA (0x000000ff << 0) ++ ++#define SPI_CLOCK_COUNTER 0x00c ++#define SPI_CLOCK (0x00000001 << 0) ++ ++ ++#endif /* __SAA716x_SPI_REG_H */ +diff --git a/drivers/media/common/saa716x/saa716x_vip.c b/drivers/media/common/saa716x/saa716x_vip.c +new file mode 100644 +index 0000000..4cd4c81 +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_vip.c +@@ -0,0 +1,23 @@ ++#include ++ ++#include "saa716x_mod.h" ++ ++#include "saa716x_vip_reg.h" ++#include "saa716x_spi.h" ++#include "saa716x_priv.h" ++ ++void saa716x_vipint_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(VI0, INT_ENABLE, 0); /* disable VI 0 IRQ */ ++ SAA716x_EPWR(VI1, INT_ENABLE, 0); /* disable VI 1 IRQ */ ++ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ ++ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ ++} ++EXPORT_SYMBOL_GPL(saa716x_vipint_disable); ++ ++void saa716x_vip_disable(struct saa716x_dev *saa716x) ++{ ++ SAA716x_EPWR(VI0, VIP_POWER_DOWN, VI_PWR_DWN); ++ SAA716x_EPWR(VI1, VIP_POWER_DOWN, VI_PWR_DWN); ++} ++EXPORT_SYMBOL_GPL(saa716x_vip_disable); +diff --git a/drivers/media/common/saa716x/saa716x_vip.h b/drivers/media/common/saa716x/saa716x_vip.h +new file mode 100644 +index 0000000..55c6a1a +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_vip.h +@@ -0,0 +1,9 @@ ++#ifndef __SAA716x_VIP_H ++#define __SAA716x_VIP_H ++ ++struct saa716x_dev; ++ ++extern void saa716x_vipint_disable(struct saa716x_dev *saa716x); ++extern void saa716x_vip_disable(struct saa716x_dev *saa716x); ++ ++#endif /* __SAA716x_VIP_H */ +diff --git a/drivers/media/common/saa716x/saa716x_vip_reg.h b/drivers/media/common/saa716x/saa716x_vip_reg.h +new file mode 100644 +index 0000000..2d773bd +--- /dev/null ++++ b/drivers/media/common/saa716x/saa716x_vip_reg.h +@@ -0,0 +1,127 @@ ++#ifndef __SAA716x_VIP_REG_H ++#define __SAA716x_VIP_REG_H ++ ++/* -------------- VIP Registers -------------- */ ++ ++#define VI_MODE 0x000 ++#define VID_CFEN (0x00000003 << 30) ++#define VID_OSM (0x00000001 << 29) ++#define VID_FSEQ (0x00000001 << 28) ++#define AUX_CFEN (0x00000003 << 26) ++#define AUX_OSM (0x00000001 << 25) ++#define AUX_FSEQ (0x00000001 << 24) ++#define AUX_ANC_DATA (0x00000003 << 22) ++#define AUX_ANC_RAW (0x00000001 << 21) ++#define RST_ON_ERR (0x00000001 << 17) ++#define SOFT_RESET (0x00000001 << 16) ++#define IFF_CLAMP (0x00000001 << 14) ++#define IFF_MODE (0x00000003 << 12) ++#define DFF_CLAMP (0x00000001 << 10) ++#define DFF_MODE (0x00000003 << 8) ++#define HSP_CLAMP (0x00000001 << 3) ++#define HSP_RGB (0x00000001 << 2) ++#define HSP_MODE (0x00000003 << 0) ++ ++#define RCRB_CTRL 0x004 ++#define RCRB_CFG_ADDR 0x008 ++#define RCRB_CFG_EXT_ADDR 0x00c ++#define RCRB_IO_ADDR 0x010 ++#define RCRB_MEM_LADDR 0x014 ++#define RCRB_MEM_UADDR 0x018 ++#define RCRB_DATA 0x01c ++#define RCRB_MASK 0x020 ++#define RCRB_MSG_HDR 0x040 ++#define RCRB_MSG_PL0 0x044 ++#define RCRB_MSG_PL1 0x048 ++ ++#define ID_MASK0 0x020 ++#define VI_ID_MASK_0 (0x000000ff << 8) ++#define VI_DATA_ID_0 (0x000000ff << 0) ++ ++#define ID_MASK1 0x024 ++#define VI_ID_MASK_1 (0x000000ff << 8) ++#define VI_DATA_ID_1 (0x000000ff << 0) ++ ++#define VIP_LINE_THRESH 0x040 ++#define VI_LCTHR (0x000007ff << 0) ++ ++#define VIN_FORMAT 0x100 ++#define VI_VSRA (0x00000003 << 30) ++#define VI_SYNCHD (0x00000001 << 25) ++#define VI_DUAL_STREAM (0x00000001 << 24) ++#define VI_NHDAUX (0x00000001 << 20) ++#define VI_NPAR (0x00000001 << 19) ++#define VI_VSEL (0x00000003 << 14) ++#define VI_TWOS (0x00000001 << 13) ++#define VI_TPG (0x00000001 << 12) ++#define VI_FREF (0x00000001 << 10) ++#define VI_FTGL (0x00000001 << 9) ++#define VI_SF (0x00000001 << 3) ++#define VI_FZERO (0x00000001 << 2) ++#define VI_REVS (0x00000001 << 1) ++#define VI_REHS (0x00000001 << 0) ++ ++#define TC76543210 0x800 ++#define TCFEDCBA98 0x804 ++#define PHYCFG 0x900 ++#define CONFIG 0xfd4 ++#define INT_ENABLE_CLR 0xfd8 ++#define INT_ENABLE_SET 0xfdc ++ ++ ++#define INT_STATUS 0xfe0 ++#define VI_STAT_FID_AUX (0x00000001 << 31) ++#define VI_STAT_FID_VID (0x00000001 << 30) ++#define VI_STAT_FID_VPI (0x00000001 << 29) ++#define VI_STAT_LINE_COUNT (0x00000fff << 16) ++#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) ++#define VI_STAT_VID_OVRFLW (0x00000001 << 8) ++#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) ++#define VI_STAT_FID_SEQBRK (0x00000001 << 6) ++#define VI_STAT_LINE_THRESH (0x00000001 << 5) ++#define VI_STAT_AUX_WRAP (0x00000001 << 4) ++#define VI_STAT_AUX_START_IN (0x00000001 << 3) ++#define VI_STAT_AUX_END_OUT (0x00000001 << 2) ++#define VI_STAT_VID_START_IN (0x00000001 << 1) ++#define VI_STAT_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_ENABLE 0xfe4 ++#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) ++#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) ++#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) ++#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) ++#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) ++#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) ++#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) ++#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) ++#define VI_ENABLE_VID_START_IN (0x00000001 << 1) ++#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_CLR_STATUS 0xfe8 ++#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define INT_SET_STATUS 0xfec ++#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) ++#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) ++#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) ++#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) ++#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) ++#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) ++#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) ++#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) ++#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) ++#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) ++ ++#define VIP_POWER_DOWN 0xff4 ++#define VI_PWR_DWN (0x00000001 << 31) ++ ++#endif /* __SAA716x_VIP_REG_H */ +diff --git a/drivers/media/dvb-frontends/ds3103.h b/drivers/media/dvb-frontends/ds3103.h +new file mode 100644 +index 0000000..e52740c +--- /dev/null ++++ b/drivers/media/dvb-frontends/ds3103.h +@@ -0,0 +1,47 @@ ++/* ++ Montage Technology DS3103 - DVBS/S2 Demodulator driver ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef DS3103_H ++#define DS3103_H ++ ++#include ++ ++struct ds3103_config { ++ /* the demodulator's i2c address */ ++ u8 demod_address; ++ u8 ci_mode; ++ /* Set device param to start dma */ ++ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); ++ /* Hook for Lock LED */ ++ void (*set_lock_led)(struct dvb_frontend *fe, int offon); ++}; ++ ++#if defined(CONFIG_DVB_DS3103) || \ ++ (defined(CONFIG_DVB_DS3103_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, ++ struct i2c_adapter *i2c); ++#else ++static inline ++struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_DS3103 */ ++#endif /* DS3103_H */ +diff --git a/drivers/media/dvb-frontends/ts2022.h b/drivers/media/dvb-frontends/ts2022.h +new file mode 100644 +index 0000000..c894edb +--- /dev/null ++++ b/drivers/media/dvb-frontends/ts2022.h +@@ -0,0 +1,51 @@ ++ /* ++ Driver for Montage TS2022 DVBS/S2 Silicon tuner ++ ++ Copyright (C) 2012 Tomazzo Muzumici ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ ++ */ ++ ++#ifndef __DVB_TS2022_H__ ++#define __DVB_TS2022_H__ ++ ++#include ++#include "dvb_frontend.h" ++ ++/** ++ * Attach a ts2022 tuner to the supplied frontend structure. ++ * ++ * @param fe Frontend to attach to. ++ * @param addr i2c address of the tuner. ++ * @param i2c i2c adapter to use. ++ * @return FE pointer on success, NULL on failure. ++ */ ++#if defined(CONFIG_DVB_TS2022) || (defined(CONFIG_DVB_TS2022_MODULE) \ ++ && defined(MODULE)) ++extern struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, int addr, ++ struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, ++ int addr, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_TS2022 */ ++ ++#endif /* __DVB_TS2022_H__ */ +diff --git a/include/uapi/linux/dvb/osd.h b/include/uapi/linux/dvb/osd.h +index 880e684..edd728c 100644 +--- a/include/uapi/linux/dvb/osd.h ++++ b/include/uapi/linux/dvb/osd.h +@@ -141,4 +141,20 @@ typedef struct osd_cap_s { + #define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t) + #define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t) + ++typedef struct osd_raw_cmd_s { ++ const void __user *cmd_data; ++ int cmd_len; ++ void __user *result_data; ++ int result_len; ++} osd_raw_cmd_t; ++ ++typedef struct osd_raw_data_s { ++ const void __user *data_buffer; ++ int data_length; ++ int data_handle; ++} osd_raw_data_t; ++ ++#define OSD_RAW_CMD _IOWR('o', 162, osd_raw_cmd_t) ++#define OSD_RAW_DATA _IOWR('o', 163, osd_raw_data_t) ++ + #endif diff --git a/packages/linux/patches/3.10/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch b/packages/linux/patches/3.10/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch new file mode 100644 index 0000000000..93bf4fbef1 --- /dev/null +++ b/packages/linux/patches/3.10/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch @@ -0,0 +1,78 @@ +commit aad0b407edfef6e2527a9bb877ce754e1efb7b10 +Author: Stefan Saraev +Date: Mon Jul 1 13:06:10 2013 +0300 + + ALSA: hda - Avoid outputting HDMI audio before prepare() and after close() + + adapted to 3.10 + + From a6024295fd3290a8c9c5519a03316081ee82378a Mon Sep 17 00:00:00 2001 + From: Anssi Hannula + Date: Sat, 16 Feb 2013 17:42:46 +0200 + Subject: [PATCH] ALSA: hda - Avoid outputting HDMI audio before prepare() and + after close() + + Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) start + transmitting an empty audio stream as soon as PIN_OUT and AC_DIG1_ENABLE + are enabled. + + Since commit 6169b673618bf0b2518ce413b54925782a603f06 ("ALSA: hda - + Always turn on pins for HDMI/DP") this happens at first open() time, and + will continue even after close(). + + Additionally, some codecs (at least Intel PantherPoint HDMI) currently + continue transmitting HDMI audio even after close() in case some actual + audio was output after open() (this happens regardless of PIN_OUT). + + Empty HDMI audio transmission when not intended has the effect that a + possible HDMI audio sink/receiver may prefer the empty HDMI audio stream + over an actual audio stream on its S/PDIF inputs. + + To avoid the issue before first prepare(), set stream format to 0 on + codec initialization. 0 is not a valid format value for HDMI and will + prevent the audio stream from being output. + + Additionally, at close() time, make sure that the stream is cleaned up. + This will ensure that the format is reset to 0 at that time, preventing + audio from being output in that case. + + Thanks to OpenELEC developers and users for their help in investigating + this issue on the affected NVIDIA "ION2" hardware. Testing of the final + version on NVIDIA ION2 was done by OpenELEC user "MrXIII". Testing on + Intel PantherPoint was done by myself. + + Signed-off-by: Anssi Hannula + Cc: stable@vger.kernel.org + +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index e12f7a0..9bfdd51 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1360,6 +1360,14 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) + if (err < 0) + return err; + ++ /* ++ * Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) ++ * start transmitting an empty audio stream as soon as PIN_OUT and ++ * AC_DIG1_ENABLE are enabled, which happens at open() time. ++ * To avoid that, set format to 0, which is not valid for HDMI. ++ */ ++ snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); ++ + if (spec->num_cvts < ARRAY_SIZE(spec->cvt_nids)) + spec->cvt_nids[spec->num_cvts] = cvt_nid; + spec->num_cvts++; +@@ -1474,6 +1482,12 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, + struct hdmi_spec_per_pin *per_pin; + + if (hinfo->nid) { ++ /* ++ * Make sure no empty audio is output after this point by ++ * setting stream format to 0, which is not valid for HDMI. ++ */ ++ __snd_hda_codec_cleanup_stream(codec, hinfo->nid, 1); ++ + cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); + if (snd_BUG_ON(cvt_idx < 0)) + return -EINVAL; diff --git a/packages/linux/patches/3.10/linux-995-CX24120-13Z_frontend.patch b/packages/linux/patches/3.10/linux-995-CX24120-13Z_frontend.patch new file mode 100755 index 0000000000..41d0f1d9d2 --- /dev/null +++ b/packages/linux/patches/3.10/linux-995-CX24120-13Z_frontend.patch @@ -0,0 +1,1577 @@ +http://patchwork.linuxtv.org/patch/10575/ +modified for 3.7.10 + +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:23:44.824143495 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:26:40.756140116 +0400 +@@ -91,6 +91,8 @@ + int feedcount; + int pid_filtering; + int fullts_streaming_state; ++ /* the stream will be activated by an externally (by the fe for example) */ ++ int need_external_stream_control; + + /* bus specific callbacks */ + flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *, +@@ -177,6 +179,8 @@ + struct dvb_demux_feed *dvbdmxfeed, int onoff); + void flexcop_hw_filter_init(struct flexcop_device *fc); + ++extern void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff); ++ + void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); + + void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:23:44.828143388 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:26:40.760141513 +0400 +@@ -12,6 +12,7 @@ + #include "cx24113.h" + #include "cx24123.h" + #include "isl6421.h" ++#include "cx24120.h" + #include "mt352.h" + #include "bcm3510.h" + #include "nxt200x.h" +@@ -26,6 +27,15 @@ + #define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \ + (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE))) + ++#if FE_SUPPORTED(BCM3510) || FE_SUPPORTED(CX24120) ++static int flexcop_fe_request_firmware(struct dvb_frontend *fe, ++ const struct firmware **fw, char* name) ++{ ++ struct flexcop_device *fc = fe->dvb->priv; ++ return request_firmware(fw, name, fc->dev); ++} ++#endif ++ + /* lnb control */ + #if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) + static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +@@ -445,13 +455,6 @@ + + /* AirStar ATSC 1st generation */ + #if FE_SUPPORTED(BCM3510) +-static int flexcop_fe_request_firmware(struct dvb_frontend *fe, +- const struct firmware **fw, char* name) +-{ +- struct flexcop_device *fc = fe->dvb->priv; +- return request_firmware(fw, name, fc->dev); +-} +- + static struct bcm3510_config air2pc_atsc_first_gen_config = { + .demod_address = 0x0f, + .request_firmware = flexcop_fe_request_firmware, +@@ -619,10 +622,40 @@ + #define cablestar2_attach NULL + #endif + ++/* SkyStar S2 PCI DVB-S/S2 card based on Conexant cx24120/cx24118 */ ++#if FE_SUPPORTED(CX24120) && FE_SUPPORTED(ISL6421) ++static const struct cx24120_config skystar2_rev3_3_cx24120_config = { ++ .i2c_addr = 0x55, ++ .request_firmware = flexcop_fe_request_firmware, ++}; ++ ++static int skystarS2_rev33_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) ++{ ++// struct dvb_frontend_ops *ops; ++ ++ fc->fe = dvb_attach(cx24120_attach, ++ &skystar2_rev3_3_cx24120_config, i2c); ++ if (fc->fe == NULL) return 0; ++ fc->dev_type = FC_SKYS2_REV33; ++ fc->fc_i2c_adap[2].no_base_addr = 1; ++ if ( (dvb_attach(isl6421_attach, fc->fe, ++ &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0, false) == NULL) ) { ++ err("ISL6421 could NOT be attached!"); ++ return 0; ++ } ++ info("ISL6421 successfully attached."); ++// ops = &fc->fe->ops; ++ return 1; ++} ++#else ++#define skystarS2_rev33_attach NULL ++#endif ++ + static struct { + flexcop_device_type_t type; + int (*attach)(struct flexcop_device *, struct i2c_adapter *); + } flexcop_frontends[] = { ++ { FC_SKYS2_REV33, skystarS2_rev33_attach }, + { FC_SKY_REV27, skystar2_rev27_attach }, + { FC_SKY_REV28, skystar2_rev28_attach }, + { FC_SKY_REV26, skystar2_rev26_attach }, +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:23:44.828143388 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:26:40.760141513 +0400 +@@ -11,6 +11,12 @@ + deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); + } + ++void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff) ++{ ++ struct flexcop_device *fc = fe->dvb->priv; ++ flexcop_rcv_data_ctrl(fc, onoff); ++} ++ + void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) + { + flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff); +@@ -199,6 +205,7 @@ + + /* if it was the first or last feed request change the stream-status */ + if (fc->feedcount == onoff) { ++ if (!fc->need_external_stream_control) + flexcop_rcv_data_ctrl(fc, onoff); + if (fc->stream_control) /* device specific stream control */ + fc->stream_control(fc, onoff); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:23:44.832143280 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:26:40.760141513 +0400 +@@ -56,6 +56,7 @@ + [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6", + [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", + [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8", ++ [FC_SKYS2_REV33]= "Sky2PC/SkyStar S2 DVB-S/S2 rev 3.3", + }; + + static const char *flexcop_bus_names[] = { +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h +--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:23:44.832143280 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:26:40.760141513 +0400 +@@ -24,6 +24,7 @@ + FC_SKY_REV26, + FC_SKY_REV27, + FC_SKY_REV28, ++ FC_SKYS2_REV33, + } flexcop_device_type_t; + + typedef enum { +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/Kconfig linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig +--- linux-3.4-r1/drivers/media/common/b2c2/Kconfig 2012-04-03 15:23:44.824143495 +0400 ++++ linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig 2012-04-03 15:26:40.760141513 +0400 +@@ -3,6 +3,7 @@ + depends on DVB_CORE && I2C + depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB + default y ++ select DVB_CX24120 if !DVB_FE_CUSTOMISE + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c 2012-04-03 16:10:59.000000000 +0400 +@@ -0,0 +1,1053 @@ ++/* ++ Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner driver ++ Version 0.0.4a 03.04.2012 ++ ++ Copyright (C) 2009 Sergey Tyurin ++ Updated 2012 by Jannis Achstetter ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dvb_frontend.h" ++#include "cx24120.h" ++#include "cx24120_const.h" ++ ++//========================== ++#define dbginfo(args...) do { if(cx24120_debug) { printk(KERN_DEBUG "CX24120: %s: >>> ", __func__); \ ++ printk(args); } } while (0) ++#define info(args...) do { printk(KERN_INFO "CX24120: %s: -> ", __func__); \ ++ printk(args); } while (0) ++#define err(args...) do { printk(KERN_ERR "CX24120: %s: ### ERROR: ", __func__); \ ++ printk(args); } while (0) ++//========================== ++ ++static int cx24120_debug=0; ++static int reg_debug=0; ++MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24120/CX24118 hardware"); ++module_param(cx24120_debug, int, 0644); ++MODULE_PARM_DESC(cx24120_debug, "Activates frontend debugging (default:0)"); ++ ++// ############################## ++struct cx24120_state { ++ struct i2c_adapter *i2c; ++ const struct cx24120_config *config; ++ struct dvb_frontend frontend; ++ u8 need_set_mpeg_out; ++ u8 attached; ++ u8 dvb_s2_mode; ++ u8 cold_init; ++}; ++// ##################################### ++// #### Command message to firmware #### ++struct cx24120_cmd { // total size = 36 ++ u8 id; // [00] - message id ++ u8 arg[30]; // [04] - message first byte ++ u8 len; // [34] - message lengh or first registers to read ++ u8 reg; // [35] - number of registers to read ++}; ++ ++//=================================================================== ++static int cx24120_readreg(struct cx24120_state *state, u8 reg) ++{ ++ int ret; ++ u8 buf = 0; ++ struct i2c_msg msg[] = { ++ { .addr = state->config->i2c_addr, ++ .flags = 0, ++ .len = 1, ++ .buf = ® }, ++ ++ { .addr = state->config->i2c_addr, ++ .flags = I2C_M_RD, ++ .len = 1, ++ .buf = &buf } ++ }; ++ ret = i2c_transfer(state->i2c, msg, 2); ++ if (ret != 2) { ++ err("Read error: reg=0x%02x, ret=0x%02x)\n", reg, ret); ++ return ret; ++ } ++ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, buf); ++ return buf; ++} // end cx24120_readreg ++//=================================================================== ++static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data) ++{ ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { ++ .addr = state->config->i2c_addr, ++ .flags = 0, ++ .buf = buf, ++ .len = 2 }; ++ int ret; ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ if (ret != 1) { ++ err("Write error: i2c_write error(err == %i, 0x%02x: 0x%02x)\n", ret, reg, data); ++ return ret; ++ } ++ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, data); ++ return 0; ++} // end cx24120_writereg ++//=================================================================== ++static int cx24120_writeregN(struct cx24120_state *state, u8 reg, const u8 *values, u16 len, u8 incr) ++{ ++ u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation (very limited i2c-interface this one) */ ++ struct i2c_msg msg = { ++ .addr = state->config->i2c_addr, ++ .flags = 0, ++ .buf = buf, ++ .len = len }; ++ int ret; ++ ++ do { ++ buf[0] = reg; ++ msg.len = len > 4 ? 4 : len; ++ memcpy(&buf[1], values, msg.len); ++ len -= msg.len; // data length revers counter ++ values += msg.len; // incr data pointer ++ if (incr) reg += msg.len; ++ msg.len++; /* don't forget the addr byte */ ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ if (ret != 1) { ++ err("i2c_write error(err == %i, 0x%02x)\n", ret, reg); ++ return ret; ++ } ++ if (reg_debug) { ++ if( !(reg == 0xFA) && !(reg == 0x20) && !(reg == 0x21)) { // Exclude firmware upload & diseqc messages ++ dbginfo("reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n", // from debug ++ reg, buf[1], buf[2], buf[3], buf[4]); ++ } ++ } ++ } while (len); ++ return 0; ++} // end cx24120_writeregN ++//=================================================================== ++static struct dvb_frontend_ops cx24120_ops; ++//=================================================================== ++struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, struct i2c_adapter *i2c) ++{ ++ struct cx24120_state *state = NULL; ++ int demod_rev; ++ ++ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner\n"); ++ info("Driver version: 'SVT - 0.0.4a 03.04.2012'\n"); ++ state = kzalloc(sizeof(struct cx24120_state), ++ GFP_KERNEL); ++ if (state == NULL) { ++ err("### Unable to allocate memory for cx24120_state structure. :(\n"); ++ goto error; ++ } ++ /* setup the state */ ++ state->config = config; ++ state->i2c = i2c; ++ /* check if the demod is present and has proper type */ ++ demod_rev = cx24120_readreg(state, CX24120_REG_REVISION); ++ switch (demod_rev) { ++ case 0x07: ++ info("Demod CX24120 rev. 0x07 detected.\n"); ++ break; ++ case 0x05: ++ info("Demod CX24120 rev. 0x05 detected.\n"); ++ break; ++ default: ++ err("### Unsupported demod revision: 0x%x detected. Exit.\n", demod_rev); ++ goto error; ++ } ++ /* create dvb_frontend */ ++ state->attached = 0x10; // set attached flag ++ state->cold_init=0; ++ memcpy(&state->frontend.ops, &cx24120_ops, sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner ATTACHED.\n"); ++ return &state->frontend; ++ ++error: ++ kfree(state); ++ return NULL; ++} ++EXPORT_SYMBOL(cx24120_attach); // end cx24120_attach ++//=================================================================== ++static int cx24120_test_rom(struct cx24120_state *state) ++{ ++ int err, ret; ++ err = cx24120_readreg(state, 0xFD); ++ if (err & 4 ) ++ { ++ ret = cx24120_readreg(state, 0xDF) & 0xFE; ++ err = cx24120_writereg(state, 0xDF, ret); ++ } ++ return err; ++} // end cx24120_test_rom ++//=================================================================== ++static int cx24120_read_snr(struct dvb_frontend *fe, u16 *snr) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *snr = (cx24120_readreg(state, CX24120_REG_QUALITY_H)<<8) | ++ (cx24120_readreg(state, CX24120_REG_QUALITY_L)); ++ dbginfo("read SNR index = %d\n", *snr); ++ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_snr); // end cx24120_read_snr ++//=================================================================== ++static int cx24120_read_ber(struct dvb_frontend *fe, u32 *ber) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *ber = (cx24120_readreg(state, CX24120_REG_BER_HH) << 24) | // BER high byte of high word ++ (cx24120_readreg(state, CX24120_REG_BER_HL) << 16) | // BER low byte of high word ++ (cx24120_readreg(state, CX24120_REG_BER_LH) << 8) | // BER high byte of low word ++ cx24120_readreg(state, CX24120_REG_BER_LL); // BER low byte of low word ++ dbginfo("read BER index = %d\n", *ber); ++ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_ber); // end cx24120_read_ber ++//=================================================================== ++static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd); ++//=================================================================== ++static int cx24120_msg_mpeg_output_global_config(struct cx24120_state *state, u8 flag) ++{ ++ u8 tristate; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = 0x13; // (19) message Enable/Disable mpeg output ??? ++ cmd.arg[0] = 1; ++ cmd.arg[1] = 0; ++ tristate = flag ? 0 : (u8)(-1); ++ cmd.arg[2] = tristate; ++ cmd.arg[3] = 1; ++ cmd.len = 4; ++ ++ if(flag) dbginfo("MPEG output DISABLED\n"); ++ else dbginfo("MPEG output ENABLED\n"); ++ ++ return cx24120_message_send(state, &cmd); ++} // end cx24120_msg_mpeg_output_global_config ++//=================================================================== ++static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd) ++{ ++ u8 xxzz; ++ u32 msg_cmd_mask; ++ int ret, ficus; ++ ++ if(state->dvb_s2_mode & 0x02) { // is MPEG enabled? ++ // if yes: ++ xxzz = cmd->id - 0x11; // look for specific message id ++ if ( xxzz <= 0x13 ) { ++ msg_cmd_mask = 1 << xxzz; ++ //0x0F8021 // if cmd_id 17 or 22 or 33-36, 42, 47, 57-61 etc. disable mpeg output ++ if ( msg_cmd_mask & 0x0F8021 ) { // 000011111000000000100001b ++ cx24120_msg_mpeg_output_global_config(state, 0); ++ msleep(100); ++ state->dvb_s2_mode &= 0xFD; // reset mpeg out enable flag ++ } ++ } ++ } ++ ret = cx24120_writereg(state, 0x00 /* reg id*/, cmd->id /* value */); // message start & target ++ ret = cx24120_writeregN(state, 0x01 /* reg msg*/, &cmd->arg[0], cmd->len /* len*/, 1 /* incr */); // message data ++ ret = cx24120_writereg(state, 0x1F /* reg msg_end */, 0x01 /* value */); // message end ++ ++ ficus = 1000; ++ while ( cx24120_readreg(state, 0x1F)) { // is command done??? ++ msleep(1); ++ if( !(--ficus)) { ++ err("Too long waiting 'done' state from reg(0x1F). :(\n"); ++ return -EREMOTEIO; ++ } ++ } ++ dbginfo("Successfully send message 0x%02x\n", cmd->id); ++ ++ if ( cmd->reg > 30 ) { ++ err("Too much registers to read. cmd->reg = %d", cmd->reg); ++ return -EREMOTEIO; ++ } ++ ficus = 0; ++ if ( cmd->reg ) { // cmd->reg - qty consecutive regs to read ++ while ( ficus < cmd->reg ){ // starts from reg No cmd->len ++ // number of registers to read is cmd->reg ++ // and write results starts from cmd->arg[0]. ++ cmd->arg[ficus] = cx24120_readreg(state, (cmd->len+ficus+1)); ++ ++ficus; ++ } ++ } ++ return 0; ++} // end cx24120_message_send ++//=================================================================== ++static int cx24120_set_frontend(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ u32 srate, freq; ++ fe_code_rate_t fec; ++ fe_spectral_inversion_t inversion; ++ u8 smbr1, smbr2; ++ int ret; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_TUNEREQUEST; // 0x11 set tuner parametrs ++ cmd.len = 15; ++ ++ freq = p->frequency; ++ srate = p->symbol_rate; ++ fec = p->fec_inner; ++ inversion = p->inversion; ++ ++ // check symbol rate ++ if ( srate > 31000000 ) { // if symbol rate > 31 000 ++ smbr1 = (-(srate < 31000001) & 3) + 2; // ebp ++ smbr2 = (-(srate < 31000001) & 6) + 4; // edi ++ } else { ++ smbr1 = 3; ++ smbr2 = 6; ++ } ++ ++ ret = cx24120_writereg(state, 0xE6, smbr1); ++ ret = cx24120_readreg(state, 0xF0); ++ ret &= 0xFFFFFFF0; ++ ret |= smbr2; ++ ret = cx24120_writereg(state, 0xF0, ret); ++ ++ cmd.arg[0] = 0; // CMD_TUNER_REQUEST ++ ++ // Frequency ++ cmd.arg[1] = (freq & 0xFF0000) >> 16; /* intermediate frequency in kHz */ ++ cmd.arg[2] = (freq & 0x00FF00) >> 8; ++ cmd.arg[3] = (freq & 0x0000FF); ++ ++ // Symbol Rate ++ cmd.arg[4] = ((srate/1000) & 0xFF00) >> 8; ++ cmd.arg[5] = ((srate/1000) & 0x00FF); ++ ++ // Inversion ++ if ( inversion ) { ++ if ( inversion == 1 ) cmd.arg[6] = 4; ++ else cmd.arg[6] = 0x0C; ++ } else { ++ cmd.arg[6] = 0; ++ } ++ ++ // FEC ++ switch ( fec ) // fec = p->u.qpsk.fec_inner ++ { ++ case 1: // FEC_1_2 ++ cmd.arg[7] = 0x2E; break; // [11] = 0 by memset ++ case 2: // FEC_2_3 ++ cmd.arg[7] = 0x2F; break; ++ case 3: // FEC_3_4 ++ cmd.arg[7] = 0x30; break; ++ case 5: // FEC_5_6 ++ cmd.arg[7] = 0x31; break; ++ case 7: // FEC_7_8 ++ cmd.arg[7] = 0x32; break; ++ default: // FEC_NONE, FEC_4_5, FEC_6_7, FEC_8_9, ++ // FEC_AUTO, FEC_3_5, FEC_9_10 ++ if ( state->dvb_s2_mode & 1 ) { // if DVB-S2 mode ++ cmd.arg[7] = 0; ++ cmd.arg[11] = 0; ++ } else { ++ cmd.arg[7] = 0x2E; ++ cmd.arg[11] = 0xAC; ++ } ++ break; ++ } ++ cmd.arg[8] = 0x13; ++ cmd.arg[9] = 0x88; ++ cmd.arg[10] = 0; ++ cmd.arg[12] = smbr2; ++ cmd.arg[13] = smbr1; ++ cmd.arg[14] = 0; ++ ++ state->need_set_mpeg_out |= 0x01; // after tune we need restart mpeg out ????? ++ ++ return cx24120_message_send(state, &cmd); ++ ++} ++EXPORT_SYMBOL(cx24120_set_frontend); // end cx24120_set_frontend ++//=================================================================== ++void cx24120_message_fill(struct cx24120_cmd *cmd, ++ u8 msg_id, ++ u8 *msg_addr, ++ u8 msg_len, ++ u8 num_regs) ++{ ++ cmd->id = msg_id; ++ memcpy(&cmd->arg[0], msg_addr, msg_len); ++ cmd->len = msg_len; ++ cmd->reg = num_regs; ++} // end cx24120_message_fill ++//=================================================================== ++static int cx24120_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int result, sigstr_h, sigstr_l; ++ ++ cx24120_message_fill(&cmd, 0x1A/*msg_id*/, &cx24120_msg_read_sigstr[0], 1/*msg_len*/, 0/*num_regs*/); ++ ++ if( !(cx24120_message_send(state, &cmd)) ) { ++ sigstr_h = (cx24120_readreg(state, CX24120_REG_SIGSTR_H) >> 6) << 8; ++ sigstr_l = cx24120_readreg(state, CX24120_REG_SIGSTR_L ); ++ dbginfo("Signal strength from firmware= 0x%x\n", (sigstr_h | sigstr_l)); ++ *signal_strength = ((sigstr_h | sigstr_l) << 5) & 0x0000FFFF; ++ dbginfo("Signal strength= 0x%x\n", *signal_strength); ++ result = 0; ++ } else { ++ err("error reading signal strength\n"); ++ result = -EREMOTEIO; ++ } ++ return result; ++} ++EXPORT_SYMBOL(cx24120_read_signal_strength); // end cx24120_read_signal_strength ++//=================================================================== ++static int cx24120_msg_mpeg_output_config(struct cx24120_state *state, u8 num, ++ struct cx24120_skystar2_mpeg_config *config_msg) ++{ ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_MPEG_INIT; // cmd->id=20 - message id ++ cmd.len = 7; ++ cmd.arg[0] = num; // sequental number - can be 0,1,2 ++ cmd.arg[1] = ((config_msg->x1 & 0x01) << 1) | ++ ((config_msg->x1 >> 1) & 0x01); ++ cmd.arg[2] = 0x05; ++ cmd.arg[3] = 0x02; ++ cmd.arg[4] = ((config_msg->x2 >> 1) & 0x01); ++ cmd.arg[5] = (config_msg->x2 & 0xF0) | (config_msg->x3 & 0x0F); ++ cmd.arg[6] = state->attached; /* 0x10 if succesfully attached */ ++ ++ return cx24120_message_send(state, &cmd); ++} // end cx24120_msg_mpeg_output_config ++//=================================================================== ++static int cx24120_diseqc_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_DISEQC_BURST; ++ cmd.arg[0] = 0x00; ++ if (burst) ++ cmd.arg[1] = 0x01; ++ dbginfo("burst sent.\n"); ++ ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_diseqc_send_burst); // end cx24120_diseqc_send_burst ++//=================================================================== ++static int cx24120_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ dbginfo("cmd(0x23,4) - tone = %d\n", tone); ++ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { ++ err("Invalid tone=%d\n", tone); ++ return -EINVAL; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_SETTONE; // 0x23 ++ cmd.len = 4; ++ if (!tone) ++ cmd.arg[3] = 0x01; ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_set_tone); // end cx24120_set_tone ++//=================================================================== ++static int cx24120_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_SETVOLTAGE; // ++ cmd.len = 2; ++ if (!(voltage - 1)) ++ cmd.arg[1] = 0x01; ++ return cx24120_message_send(state, &cmd); ++} ++EXPORT_SYMBOL(cx24120_set_voltage); // end cx24120_set_voltage ++//=================================================================== ++static int cx24120_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *d) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int back_count; ++ ++ dbginfo("Start sending diseqc sequence===============\n"); ++ ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_DISEQC_MSG1; // 0x20 ++ cmd.len = 11; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x00; ++ cmd.arg[2] = 0x03; ++ cmd.arg[3] = 0x16; ++ cmd.arg[4] = 0x28; ++ cmd.arg[5] = 0x01; ++ cmd.arg[6] = 0x01; ++ cmd.arg[7] = 0x14; ++ cmd.arg[8] = 0x19; ++ cmd.arg[9] = 0x14; ++ cmd.arg[10] = 0x1E; ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("send 1st message(0x%x) filed==========\n", cmd.id); ++ return -EREMOTEIO; ++ } ++ cmd.id = CMD_DISEQC_MSG2; // 0x21 ++ cmd.len = d->msg_len + 6; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x01; ++ cmd.arg[2] = 0x02; ++ cmd.arg[3] = 0x00; ++ cmd.arg[4] = 0x00; ++ cmd.arg[5] = d->msg_len; ++ ++ memcpy(&cmd.arg[6], &d->msg, d->msg_len); ++ ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("send 2d message(0x%x) filed========\n", cmd.id); ++ return -EREMOTEIO; ++ } ++ back_count = 100; ++ do { ++ if ( !(cx24120_readreg(state, 0x93) & 0x01) ) { ++ dbginfo("diseqc sequence sent success==========.\n"); ++ return 0; ++ } ++ msleep(5); ++ --back_count; ++ } while ( back_count ); ++ err("Too long waiting for diseqc.=============\n"); ++ return -ETIMEDOUT; ++} ++EXPORT_SYMBOL(cx24120_send_diseqc_msg); // end cx24120_send_diseqc_msg ++//=================================================================== ++static int cx24120_read_status(struct dvb_frontend *fe, fe_status_t *status) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ int ret, clock_seq_num, GettedFEC; ++ u8 mode_code, mode_8PSK_flag, attached_flag, clock_id; ++ ++ ret = cx24120_readreg(state, CX24120_REG_STATUS); //0x3A ++ dbginfo("status = 0x%x\n", ret); ++ *status = 0; ++ if ( ret & CX24120_HAS_SIGNAL ) *status = FE_HAS_SIGNAL; ++ if ( ret & CX24120_HAS_CARRIER) *status |= FE_HAS_CARRIER; ++ if ( ret & CX24120_HAS_VITERBI) *status |= (FE_HAS_VITERBI + FE_HAS_SYNC); ++ ++ if ( ret & CX24120_HAS_LOCK ) { // 0x08 ++ *status |= FE_HAS_LOCK; ++ if ( state->need_set_mpeg_out & 1 ) { // just tuned??? ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ cmd.id = CMD_CLOCK_READ; ++ cmd.arg[0] = 0x00; ++ cmd.len = 1; // cmd.reg != 0, so it is first register to read ++ cmd.reg = 6; // number of registers to read (0x01-0x06) ++ if ( !cx24120_message_send(state, &cmd) ) { // in cmd[0]-[5] - result ++ // 0x02-0x07 ++ ret = cx24120_readreg(state, CX24120_REG_FECMODE) & 0x3F; // ntv - 0x8E(142) & 3F = 14 ++ GettedFEC = ret; // 0x0d= 13 ++ dbginfo("Get FEC: %d\n", ret); ++ if ( state->dvb_s2_mode & 0x01 ) { // is DVB-S2? ++ switch (ret-4) { ++ case 0: ++ mode_code = 0x01; goto mode_QPSK; // FEC_1_2 - qpsk only ++ case 1: ++ case 8: ++ mode_code = 0x64; goto mode_8PSK; // FEC_3_5 (10)- 8PSK only ++ case 2: ++ case 9: ++ mode_code = 0x02; goto mode_8PSK; // FEC_2_3 ++ case 3: ++ case 10: ++ mode_code = 0x03; goto mode_8PSK; // FEC_3_4 // 14-4=10 - ntv+ ++ case 4: ++ mode_code = 0x04; goto mode_QPSK; // FEC_4_5 - qpsk only ++ case 5: ++ case 11: ++ mode_code = 0x05; goto mode_8PSK; // FEC_5_6 ++ case 6: ++ case 12: ++ mode_code = 0x08; goto mode_8PSK; // FEC_8_9 ++ case 7: ++ case 13: ++ mode_code = 0x65; goto mode_8PSK; // FEC_9_10 (11)- 8PSK only ++ default: ++ info("Unknown DVB-S2 modefec (not QPSK or 8PSK): %d\n", ret-4); ++ mode_code = 0x01; // set like for mode 0 ++ mode_8PSK: ++ if ( ret > 11 ) { // 14 ++ mode_8PSK_flag = 0x63; // DVB-S2-8PSK flag ++ dbginfo("DVB-S2: 8PSK mode: %d, mode_code= 0x%x\n", ret-4, mode_code); ++ } else { ++ mode_QPSK: ++ mode_8PSK_flag = 0x00; ++ dbginfo("DVB-S2: QPSK mode: %d\n", ret-4); ++ } ++ break; ++ } // end switch ++ } // end if dvb_s2_mode // dvb-s2 ++ else { // state->dvb_s2_mode & 1 = 0 -> #### DVB-S ++ switch ( ret - 2 ) { ++ case 0: ++ mode_code = 2; break; // FEC_2_3 ++ case 1: ++ mode_code = 3; break; // FEC_3_4 ++ case 2: ++ mode_code = 4; break; // FEC_4_5 ++ case 3: ++ mode_code = 5; break; // FEC_5_6 ++ case 4: ++ mode_code = 6; break; // FEC_6_7 ++ case 5: ++ mode_code = 7; break; // FEC_7_8 ++ default: ++ mode_code = 1;break; // FEC_1_2 ++ } ++ mode_8PSK_flag = 0; ++ } // end of switch for dvb-s ++ ++ attached_flag = 0x10; ++ if (state->attached == 0x10) // must be 0x10 if successfully attached in flexcop_fe_tuner ++ attached_flag = 0; ++ ret = 0; ++ if ( state->dvb_s2_mode & 0x01 ) // if dvb-s2 ++ ret = (cx24120_readreg(state, CX24120_REG_FECMODE) >> 7) & 0x01; // QPSK or 8PSK ??? ++ // bit 4 bit 5 bit 0 bit 3 ++ clock_id = (ret << 3) | attached_flag | (state->dvb_s2_mode & 1) | 4; // possible id: 4, 5, 13. 12-impossible, ++ // ntv S2 = 0x8E -> 8 | 1 | 4 = 13 // because 7th bit of ret - is S2 flag ++ // 1/2 S2 = 0x0d -> 0 | 1 | 4 = 5 ++ dbginfo("Check clock table for: clock_id=0x%x, 8PSK_mask=0x%x, mode_code=0x%x\n", ++ clock_id, mode_8PSK_flag, mode_code); ++ ++ clock_seq_num = 0; ++ while ( (clock_ratios_table[clock_seq_num].ratio_id != clock_id) || ++ (clock_ratios_table[clock_seq_num].mode_xPSK != mode_8PSK_flag) || ++ (clock_ratios_table[clock_seq_num].fec_mode != mode_code) ) ++ { ++ /* dbginfo("Check table string(%d): clock_id=%d, 8PSK_flag=%d, mode_code=%d\n", clock_seq_num, ++ * clock_ratios_table[clock_seq_num].ratio_id, ++ * clock_ratios_table[clock_seq_num].mode_xPSK, ++ * clock_ratios_table[clock_seq_num].fec_mode); ++ */ ++ ++clock_seq_num; ++ if ( clock_seq_num == ARRAY_SIZE(clock_ratios_table) ) { ++ info("Check in clock table filed: unsupported modulation tuned - data reception in danger. :(\n"); ++ goto settings_end; ++ } ++ } ++ //############################### ++ dbginfo("Check succesful: GetFEC: %d; post lock: m=%d, n=%d; clock_seq_idx: %d m=%d, n=%d, rate=%d\n", ++ GettedFEC, ++ cmd.arg[2] | (cmd.arg[1] << 8) | (cmd.arg[0] << 16), // registers was readed early ++ cmd.arg[5] | (cmd.arg[4] << 8) | (cmd.arg[3] << 16), // in message with id = 0x16 ++ clock_seq_num, ++ clock_ratios_table[clock_seq_num].m_rat, ++ clock_ratios_table[clock_seq_num].n_rat, ++ clock_ratios_table[clock_seq_num].rate); ++ //############################### ++ cmd.id = CMD_CLOCK_SET; ++ cmd.len = 10; ++ cmd.reg = 0; ++ cmd.arg[0] = 0; ++ cmd.arg[1] = state->attached; // must be 0x10 if successfully attached in flexcop_fe_tuner ++ ++ cmd.arg[2] = (clock_ratios_table[clock_seq_num].m_rat >> 16) & 0xFF; ++ cmd.arg[3] = (clock_ratios_table[clock_seq_num].m_rat >> 8) & 0xFF; ++ cmd.arg[4] = (clock_ratios_table[clock_seq_num].m_rat >> 0) & 0xFF; ++ ++ cmd.arg[5] = (clock_ratios_table[clock_seq_num].n_rat >> 16) & 0xFF; ++ cmd.arg[6] = (clock_ratios_table[clock_seq_num].n_rat >> 8) & 0xFF; ++ cmd.arg[7] = (clock_ratios_table[clock_seq_num].n_rat >> 0) & 0xFF; ++ ++ cmd.arg[8] = (clock_ratios_table[clock_seq_num].rate >> 8) & 0xFF; ++ cmd.arg[9] = (clock_ratios_table[clock_seq_num].rate >> 0) & 0xFF; ++ ++ cx24120_message_send(state, &cmd); ++ ++ settings_end: ++ msleep(200); ++ cx24120_msg_mpeg_output_global_config(state, 1); ++ state->dvb_s2_mode |= 0x02; // set mpeg flag ++ state->need_set_mpeg_out &= 0xFE; // clocks set done -> clear flag ++ } ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_status); // end cx24120_read_status ++//=================================================================== ++int cx24120_init(struct dvb_frontend *fe) ++{ ++ const struct firmware *fw; ++ struct cx24120_state *state = fe->demodulator_priv; ++ struct cx24120_cmd cmd; ++ u8 ret, ret_EA, reg1, fL, fH; ++ u32 vco, xtal_khz; ++ u64 inv_vco, res, xxyyzz; ++ int reset_result; ++ ++ if( state->cold_init ) return 0; ++ ++ ret = cx24120_writereg(state, 0xEA, 0x00); ++ ret = cx24120_test_rom(state); ++ ret = cx24120_readreg(state, 0xFB) & 0xFE; ++ ret = cx24120_writereg(state, 0xFB, ret); ++ ret = cx24120_readreg(state, 0xFC) & 0xFE; ++ ret = cx24120_writereg(state, 0xFC, ret); ++ ret = cx24120_writereg(state, 0xC3, 0x04); ++ ret = cx24120_writereg(state, 0xC4, 0x04); ++ ret = cx24120_writereg(state, 0xCE, 0x00); ++ ret = cx24120_writereg(state, 0xCF, 0x00); ++ ret_EA = cx24120_readreg(state, 0xEA) & 0xFE; ++ ret = cx24120_writereg(state, 0xEA, ret_EA); ++ ret = cx24120_writereg(state, 0xEB, 0x0C); ++ ret = cx24120_writereg(state, 0xEC, 0x06); ++ ret = cx24120_writereg(state, 0xED, 0x05); ++ ret = cx24120_writereg(state, 0xEE, 0x03); ++ ret = cx24120_writereg(state, 0xEF, 0x05); ++ ret = cx24120_writereg(state, 0xF3, 0x03); ++ ret = cx24120_writereg(state, 0xF4, 0x44); ++ ++ reg1 = 0xF0; ++ do { ++ cx24120_writereg(state, reg1, 0x04); ++ cx24120_writereg(state, reg1 - 10, 0x02); ++ ++reg1; ++ } while ( reg1 != 0xF3 ); ++ ++ ret = cx24120_writereg(state, 0xEA, (ret_EA | 0x01)); ++ reg1 = 0xC5; ++ do { ++ ret = cx24120_writereg(state, reg1, 0x00); ++ ret = cx24120_writereg(state, reg1 + 1, 0x00); ++ reg1 += 2; ++ } while ( reg1 != 0xCB ); ++ ++ ret = cx24120_writereg(state, 0xE4, 0x03); ++ ret = cx24120_writereg(state, 0xEB, 0x0A); ++ ++ dbginfo("Requesting firmware (%s) to download...\n", CX24120_FIRMWARE); ++ ret = state->config->request_firmware(fe, &fw, CX24120_FIRMWARE); ++ if (ret) { ++ err("Could not load firmware (%s): %d\n", CX24120_FIRMWARE, ret); ++ return ret; ++ } ++ dbginfo("Firmware found and it size is %d bytes (%02x %02x .. %02x %02x)\n", ++ (int)fw->size, // firmware_size in bytes u32* ++ fw->data[0], // fw 1st byte ++ fw->data[1], // fw 2d byte ++ fw->data[fw->size - 2], // fw before last byte ++ fw->data[fw->size - 1]); // fw last byte ++ ++ ret = cx24120_test_rom(state); ++ ret = cx24120_readreg(state, 0xFB) & 0xFE; ++ ret = cx24120_writereg(state, 0xFB, ret); ++ ret = cx24120_writereg(state, 0xE0, 0x76); ++ ret = cx24120_writereg(state, 0xF7, 0x81); ++ ret = cx24120_writereg(state, 0xF8, 0x00); ++ ret = cx24120_writereg(state, 0xF9, 0x00); ++ ret = cx24120_writeregN(state, 0xFA, fw->data, (fw->size - 1), 0x00); ++ ret = cx24120_writereg(state, 0xF7, 0xC0); ++ ret = cx24120_writereg(state, 0xE0, 0x00); ++ ret = (fw->size - 2) & 0x00FF; ++ ret = cx24120_writereg(state, 0xF8, ret); // ret now is 0x7a ++ ret = ((fw->size - 2) >> 8) & 0x00FF; ++ ret = cx24120_writereg(state, 0xF9, ret); // ret now is 0xaf ++ ret = cx24120_writereg(state, 0xF7, 0x00); ++ ret = cx24120_writereg(state, 0xDC, 0x00); ++ ret = cx24120_writereg(state, 0xDC, 0x07); ++ msleep(500); ++ ++ ret = cx24120_readreg(state, 0xE1); // now is 0xd5 - last byte of the firmware ++ if ( ret == fw->data[fw->size - 1] ) { ++ dbginfo("Firmware uploaded successfully\n"); ++ reset_result = 0; ++ } else { ++ err("Firmware upload failed. Last byte returned=0x%x\n", ret ); ++ reset_result = -EREMOTEIO; ++ } ++ ret = cx24120_writereg(state, 0xDC, 0x00); ++ release_firmware(fw); ++ if (reset_result) ++ return reset_result; ++ ++ //================== Start tuner ++ cx24120_message_fill(&cmd, CMD_START_TUNER, &cx24120_msg_tuner_init[0], 3, 0); // 0x1B ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error tuner start! :(\n"); ++ return -EREMOTEIO; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ ++ cmd.id = CMD_VCO_SET; // 0x10 ++ cmd.len = 12; ++ ++ // ###################### ++ // Calc VCO ++ xtal_khz = 10111; ++ xxyyzz = 0x400000000ULL; // 17179869184 ++ vco = xtal_khz * 10 * 4; // 404440 ++ inv_vco = xxyyzz / vco; // 42478 = 0x00A5EE ++ res = xxyyzz % vco; // 66864 = 0x010530 ++ ++ if( inv_vco > xtal_khz * 10 * 2) ++inv_vco; ++ ++ fH = (inv_vco >> 8) & 0xFF; ++ fL = (inv_vco) & 0xFF; ++ dbginfo("vco= %d, inv_vco= %lld, res= %lld, fL= 0x%x, fH= 0x%x\n", vco, inv_vco, res, fL, fH); ++ // ###################### ++ ++ cmd.arg[0] = 0x06; ++ cmd.arg[1] = 0x2B; ++ cmd.arg[2] = 0xD8; ++ cmd.arg[3] = fH; // 0xA5 ++ cmd.arg[4] = fL; // 0xEE ++ cmd.arg[5] = 0x03; ++ cmd.arg[6] = 0x9D; ++ cmd.arg[7] = 0xFC; ++ cmd.arg[8] = 0x06; ++ cmd.arg[9] = 0x03; ++ cmd.arg[10] = 0x27; ++ cmd.arg[11] = 0x7F; ++ ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error set VCO! :(\n"); ++ return -EREMOTEIO; ++ } ++ memset(&cmd, 0, sizeof(struct cx24120_cmd)); ++ // set bandwidth ++ cmd.id = CMD_BANDWIDTH; // 0x15 ++ cmd.len = 12; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x00; ++ cmd.arg[2] = 0x00; ++ cmd.arg[3] = 0x00; ++ cmd.arg[4] = 0x05; ++ cmd.arg[5] = 0x02; ++ cmd.arg[6] = 0x02; ++ cmd.arg[7] = 0x00; ++ cmd.arg[8] = 0x05; ++ cmd.arg[9] = 0x02; ++ cmd.arg[10] = 0x02; ++ cmd.arg[11] = 0x00; ++ ++ if ( cx24120_message_send(state, &cmd) ) { ++ err("Error set bandwidth! :(\n"); ++ return -EREMOTEIO; ++ } ++ ret = cx24120_readreg(state, 0xBA); ++ if ( ret > 3) { ++ dbginfo("Reset-readreg 0xBA: %x\n", ret); ++ err("Error intitilizing tuner! :(\n"); ++ return -EREMOTEIO; ++ } ++ dbginfo("Tuner initialized correctly.\n"); ++ ++ ret = cx24120_writereg(state, 0xEB, 0x0A); ++ if (cx24120_msg_mpeg_output_global_config(state, 0) || ++ cx24120_msg_mpeg_output_config(state, 0, &initial_mpeg_config) || ++ cx24120_msg_mpeg_output_config(state, 1, &initial_mpeg_config) || ++ cx24120_msg_mpeg_output_config(state, 2, &initial_mpeg_config) ) ++ { ++ err("Error initilizing mpeg output. :(\n"); ++ return -EREMOTEIO; ++ } else { ++ cmd.id = 0x3C; // 60 ++ cmd.len = 0x03; ++ cmd.arg[0] = 0x00; ++ cmd.arg[1] = 0x10; ++ cmd.arg[2] = 0x10; ++ if(cx24120_message_send(state, &cmd)) { ++ err("Error sending final init message. :(\n"); ++ return -EREMOTEIO; ++ } ++ } ++ state->cold_init=1; ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_init); // end cx24120_reset ++//=================================================================== ++static int cx24120_tune(struct dvb_frontend *fe, bool re_tune, ++ unsigned int mode_flags, unsigned int *delay, fe_status_t *p_status) ++{ ++ struct dtv_frontend_properties *p = &fe->dtv_property_cache; ++ struct cx24120_state *state = fe->demodulator_priv; ++ int delay_cnt, sd_idx = 0; ++ fe_status_t status; ++ ++ if (re_tune) { ++ ++// dbginfo("Compare symrate with table: symrate= %d, in table= %d\n", ++// p->u.qpsk.symbol_rate, symrates_pairs[sd_idx].symrate); ++ ++ while ( p->symbol_rate > symrates_pairs[sd_idx].symrate ) { ++ ++sd_idx; ++ } ++ dbginfo("Found symrate delay = %d\n", symrates_pairs[sd_idx].delay); ++ state->dvb_s2_mode &= 0xFE; // clear bit -> try not DVB-S2 ++ dbginfo("trying DVB-S =================\n"); ++ cx24120_set_frontend(fe); ++ ++ delay_cnt = symrates_pairs[sd_idx].delay; ++ dbginfo("Wait for LOCK for DVB-S =================\n"); ++ while (delay_cnt >= 0) { ++ cx24120_read_status(fe, &status); ++ if (status & FE_HAS_LOCK) { ++ dbginfo("DVB-S LOCKED================\n"); ++ break; ++ } ++ msleep(100); ++ delay_cnt -=100; ++ } ++ dbginfo("Waiting finished - NO lock for DVB-S =================\n"); ++ ++ cx24120_read_status(fe, &status); ++ if ( !(status & FE_HAS_LOCK) ) { // if no lock on S ++ dbginfo("trying DVB-S2 ++++++++++++++++++++++++++\n"); ++ state->dvb_s2_mode |= 0x01; // may be it locked on S2 ? ++ p->fec_inner = FEC_AUTO; ++ cx24120_set_frontend(fe); ++ delay_cnt = symrates_pairs[sd_idx].delay; ++ dbginfo("Wait for LOCK for DVB-S2 ++++++++++++++++\n"); ++ while (delay_cnt >= 0) { ++ cx24120_read_status(fe, &status); ++ if (status & FE_HAS_LOCK) { ++ dbginfo("DVB-S2 LOCKED++++++++++++++++\n"); ++ break; ++ } ++ msleep(100); ++ delay_cnt -=100; ++ } ++ dbginfo("Waiting finished - NO lock for DVB-S2 ++++++++++++++++\n"); ++ } ++ } ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_tune); // end of cx24120_tune ++//=================================================================== ++static int cx24120_get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++EXPORT_SYMBOL(cx24120_get_algo); ++//=================================================================== ++static int cx24120_sleep(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_sleep); ++//=================================================================== ++/*static int cx24120_wakeup(struct dvb_frontend *fe) ++ * { ++ * return 0; ++ * } ++ * EXPORT_SYMBOL(cx24120_wakeup); ++ */ ++//=================================================================== ++static int cx24120_get_frontend(struct dvb_frontend *fe) ++{ ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_get_frontend); ++//=================================================================== ++static void cx24120_release(struct dvb_frontend *fe) ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ dbginfo("Clear state structure\n"); ++ kfree(state); ++} ++EXPORT_SYMBOL(cx24120_release); ++//=================================================================== ++static int cx24120_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) // UNCORRECTED_BLOCKS ++{ ++ struct cx24120_state *state = fe->demodulator_priv; ++ ++ *ucblocks = (cx24120_readreg(state, CX24120_REG_UCB_H) << 8) | ++ cx24120_readreg(state, CX24120_REG_UCB_L); ++ dbginfo("Blocks = %d\n", *ucblocks); ++ return 0; ++} ++EXPORT_SYMBOL(cx24120_read_ucblocks); ++// ######################################################################################## ++static struct dvb_frontend_ops cx24120_ops = { ++ ++ .delsys = { SYS_DVBS2 }, ++ .info = { ++ .name = "Conexant CX24120/CX24118", ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ ++ .frequency_tolerance = 5000, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .caps = // 0x500006ff ++ FE_CAN_INVERSION_AUTO | //0x00 000 001 ++ FE_CAN_FEC_1_2 | //0x00 000 002 ++ FE_CAN_FEC_2_3 | //0x00 000 004 ++ FE_CAN_FEC_3_4 | //0x00 000 008 ++ FE_CAN_FEC_4_5 | //0x00 000 010 ++ FE_CAN_FEC_5_6 | //0x00 000 020 ++ FE_CAN_FEC_6_7 | //0x00 000 040 ++ FE_CAN_FEC_7_8 | //0x00 000 080 ++ FE_CAN_FEC_AUTO | //0x00 000 200 ++ FE_CAN_QPSK | //0x00 000 400 ++//??? FE_HAS_EXTENDED_CAPS | //0x00 800 000 /* We need more bitspace for newer APIs, indicate this. */ ++ FE_CAN_2G_MODULATION | //0x10 000 000 /* frontend supports "2nd generation modulation" (DVB-S2) */ ++ FE_CAN_RECOVER //0x40 000 000 /* frontend can recover from a cable unplug automatically */ ++ }, //sum=50 000 6FF ++ .release = cx24120_release, ++ ++ .init = cx24120_init, ++ .sleep = cx24120_sleep, ++ ++ .tune = cx24120_tune, ++ .get_frontend_algo = cx24120_get_algo, ++ .set_frontend = cx24120_set_frontend, ++ ++ .get_frontend = cx24120_get_frontend, ++ .read_status = cx24120_read_status, ++ .read_ber = cx24120_read_ber, ++ .read_signal_strength = cx24120_read_signal_strength, ++ .read_snr = cx24120_read_snr, ++ .read_ucblocks = cx24120_read_ucblocks, ++ ++ .diseqc_send_master_cmd = cx24120_send_diseqc_msg, ++ ++ .diseqc_send_burst = cx24120_diseqc_send_burst, ++ .set_tone = cx24120_set_tone, ++ .set_voltage = cx24120_set_voltage, ++}; ++//=================================================================== ++MODULE_PARM_DESC(cx24120_debug, "prints some verbose debugging information (default:0)"); ++MODULE_AUTHOR("Sergey Tyurin"); ++MODULE_LICENSE("GPL"); +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h 2012-04-03 16:37:20.684139905 +0400 +@@ -0,0 +1,259 @@ ++/* ++ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver ++ * DVBS/S2 Satellite demod/tuner driver static definitins ++ * ++ * Copyright (C) 2009 Sergey Tyurin ++ * Updated 2012 by Jannis Achstetter ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#define CX24120_FIRMWARE "dvb-fe-cx24120-1.20.58.2.fw" ++ ++// ############################## ++// ### cx24120 i2c registers ### ++#define CX24120_REG_CMD_START (0x00) // write cmd_id, and then start write args to next register: ++#define CX24120_REG_CMD_ARGS (0x01) // write command arguments, max 4 at once, then next 4, etc. ++#define CX24120_REG_CMD_END (0x1F) // write 0x01 for end, and read it for command result ++ ++#define CX24120_REG_FECMODE (0x39) // FEC status ++#define CX24120_REG_STATUS (0x3A) // Tuner status - signal, carrier, sync, lock ... ++#define CX24120_REG_QUALITY_H (0x40) // SNR high byte ++#define CX24120_REG_QUALITY_L (0x41) // SNR low byte ++ ++#define CX24120_REG_BER_HH (0x47) // BER high byte of high word ++#define CX24120_REG_BER_HL (0x48) // BER low byte of high word ++#define CX24120_REG_BER_LH (0x49) // BER high byte of low word ++#define CX24120_REG_BER_LL (0x4A) // BER low byte of low word ++ ++#define CX24120_REG_SIGSTR_H (0x3A) // Signal strength high byte & ??? status register ??? ++#define CX24120_REG_SIGSTR_L (0x3B) // Signal strength low byte ++ ++#define CX24120_REG_UCB_H (0x50) // UCB high byte ++#define CX24120_REG_UCB_L (0x51) // UCB low byte ++ ++#define CX24120_REG_REVISION (0xFF) // Chip revision (ro). Must be 0x7 or 0x5 ++ ++// ############################## ++/* Command messages */ ++enum command_message_id { ++ CMD_VCO_SET = 0x10, // cmdlen = 12; ++ CMD_TUNEREQUEST = 0x11, // cmd.len = 15; ++ ++ CMD_MPEG_ONOFF = 0x13, // cmd.len = 4; ++ CMD_MPEG_INIT = 0x14, // cmd.len = 7; ++ CMD_BANDWIDTH = 0x15, // cmd.len = 12; ++ CMD_CLOCK_READ = 0x16, // read clock from registers 0x01-0x06 ++ CMD_CLOCK_SET = 0x17, // cmd.len = 10; ++ ++ CMD_DISEQC_MSG1 = 0x20, // cmd.len = 11; ++ CMD_DISEQC_MSG2 = 0x21, // cmd.len = d->msg_len + 6; ++ CMD_SETVOLTAGE = 0x22, // cmd.len = 2; ++ CMD_SETTONE = 0x23, // cmd.len = 4; ++ CMD_DISEQC_BURST = 0x24, // cmd.len not used !!! ++ ++ CMD_READ_SNR = 0x1A, // Read signal strength ++ CMD_START_TUNER = 0x1B, // ??? ++ ++ CMD_TUNER_INIT = 0x3C, // cmd.len = 0x03; ++}; ++// ############################## ++/* signal status */ ++#define CX24120_HAS_SIGNAL (0x01) ++#define CX24120_HAS_CARRIER (0x02) ++#define CX24120_HAS_VITERBI (0x04) ++#define CX24120_HAS_LOCK (0x08) ++#define CX24120_HAS_UNK1 (0x10) ++#define CX24120_HAS_UNK2 (0x20) ++#define CX24120_STATUS_MASK (0x0f) ++#define CX24120_SIGNAL_MASK (0xc0) ++ ++static u8 cx24120_msg_tuner_init[] = { 0,0,0,0,0,0 }; ++static u8 cx24120_msg_read_sigstr[] = {0,0}; ++ ++static struct cx24120_skystar2_mpeg_config { ++ u8 x1; ++ u8 x2; ++ u8 x3; ++} initial_mpeg_config = { ++ 0xA1, // 10100001 ++ 0x76, // 01110110 ++ 0x07, // 00000111 ++}; ++ ++static struct cx24120_symrate_delay { ++ u32 symrate; ++ u32 delay; ++} symrates_pairs[] = { ++ { 3000000, 15000 }, ++ { 6000000, 10000 }, ++ { 8000000, 5000 }, ++ { 10000000, 2000 }, ++ {0x0FFFFFFFF, 400 }, ++}; ++ ++static struct cx24120_clock_ratios_table { ++ u32 ratio_id; ++ u32 mode_xPSK; ++ u32 fec_mode; ++ u32 m_rat; ++ u32 n_rat; ++ u32 rate; ++} clock_ratios_table[] = { ++{ 21 , 0 , 1 , 770068 , 763515 , 258 }, ++{ 21 , 0 , 100 , 97409 , 80370 , 310 }, ++{ 21 , 0 , 2 , 137293 , 101802 , 345 }, ++{ 21 , 0 , 3 , 4633447 , 3054060 , 388 }, ++{ 21 , 0 , 4 , 2472041 , 1527030 , 414 }, ++{ 21 , 0 , 5 , 85904 , 50901 , 432 }, ++{ 21 , 0 , 8 , 2751229 , 1527030 , 461 }, ++{ 21 , 0 , 101 , 1392872 , 763515 , 467 }, ++{ 21 , 99 , 100 , 1850771 , 1019430 , 464 }, ++{ 21 , 99 , 2 , 137293 , 67962 , 517 }, ++{ 21 , 99 , 3 , 4633447 , 2038860 , 581 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 21 , 99 , 5 , 85904 , 33981 , 647 }, ++{ 21 , 99 , 8 , 2751229 , 1019430 , 690 }, ++{ 21 , 99 , 101 , 1392872 , 509715 , 699 }, ++{ 29 , 0 , 1 , 770068 , 782127 , 252 }, ++{ 29 , 0 , 100 , 1850771 , 1564254 , 302 }, ++{ 29 , 0 , 2 , 686465 , 521418 , 337 }, ++{ 29 , 0 , 3 , 4633447 , 3128508 , 379 }, ++{ 29 , 0 , 4 , 2472041 , 1564254 , 404 }, ++{ 29 , 0 , 5 , 429520 , 260709 , 421 }, ++{ 29 , 0 , 8 , 2751229 , 1564254 , 450 }, ++{ 29 , 0 , 101 , 1392872 , 782127 , 455 }, ++{ 29 , 99 , 100 , 1850771 , 1043118 , 454 }, ++{ 29 , 99 , 2 , 686465 , 347706 , 505 }, ++{ 29 , 99 , 3 , 4633447 , 2086236 , 568 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 29 , 99 , 5 , 429520 , 173853 , 632 }, ++{ 29 , 99 , 8 , 2751229 , 1043118 , 675 }, ++{ 29 , 99 , 101 , 1392872 , 521559 , 683 }, ++{ 17 , 0 , 1 , 766052 , 763515 , 256 }, ++{ 17 , 0 , 100 , 96901 , 80370 , 308 }, ++{ 17 , 0 , 2 , 136577 , 101802 , 343 }, ++{ 17 , 0 , 3 , 4609283 , 3054060 , 386 }, ++{ 17 , 0 , 4 , 2459149 , 1527030 , 412 }, ++{ 17 , 0 , 5 , 85456 , 50901 , 429 }, ++{ 17 , 0 , 8 , 2736881 , 1527030 , 458 }, ++{ 17 , 0 , 101 , 1385608 , 763515 , 464 }, ++{ 17 , 99 , 100 , 1841119 , 1019430 , 462 }, ++{ 17 , 99 , 2 , 136577 , 67962 , 514 }, ++{ 17 , 99 , 3 , 4609283 , 2038860 , 578 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 17 , 99 , 5 , 85456 , 33981 , 643 }, ++{ 17 , 99 , 8 , 2736881 , 1019430 , 687 }, ++{ 17 , 99 , 101 , 1385608 , 509715 , 695 }, ++{ 25 , 0 , 1 , 766052 , 782127 , 250 }, ++{ 25 , 0 , 100 , 1841119 , 1564254 , 301 }, ++{ 25 , 0 , 2 , 682885 , 521418 , 335 }, ++{ 25 , 0 , 3 , 4609283 , 3128508 , 377 }, ++{ 25 , 0 , 4 , 2459149 , 1564254 , 402 }, ++{ 25 , 0 , 5 , 427280 , 260709 , 419 }, ++{ 25 , 0 , 8 , 2736881 , 1564254 , 447 }, ++{ 25 , 0 , 101 , 1385608 , 782127 , 453 }, ++{ 25 , 99 , 100 , 1841119 , 1043118 , 451 }, ++{ 25 , 99 , 2 , 682885 , 347706 , 502 }, ++{ 25 , 99 , 3 , 4609283 , 2086236 , 565 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 25 , 99 , 5 , 427280 , 173853 , 629 }, ++{ 25 , 99 , 8 , 2736881 , 1043118 , 671 }, ++{ 25 , 99 , 101 , 1385608 , 521559 , 680 }, ++{ 5 , 0 , 1 , 273088 , 254505 , 274 }, ++{ 5 , 0 , 100 , 17272 , 13395 , 330 }, ++{ 5 , 0 , 2 , 24344 , 16967 , 367 }, ++{ 5 , 0 , 3 , 410788 , 254505 , 413 }, ++{ 5 , 0 , 4 , 438328 , 254505 , 440 }, ++{ 5 , 0 , 5 , 30464 , 16967 , 459 }, ++{ 5 , 0 , 8 , 487832 , 254505 , 490 }, ++{ 5 , 0 , 101 , 493952 , 254505 , 496 }, ++{ 5 , 99 , 100 , 328168 , 169905 , 494 }, ++{ 5 , 99 , 2 , 24344 , 11327 , 550 }, // work for 0x0d - 11278V - DVB-S2 - 8PSK MPEG-4/HD ++{ 5 , 99 , 3 , 410788 , 169905 , 618 }, // 0x0e S2 8psk // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 5 , 99 , 5 , 30464 , 11327 , 688 }, ++{ 5 , 99 , 8 , 487832 , 169905 , 735 }, ++{ 5 , 99 , 101 , 493952 , 169905 , 744 }, ++{ 13 , 0 , 1 , 273088 , 260709 , 268 }, ++{ 13 , 0 , 100 , 328168 , 260709 , 322 }, ++{ 13 , 0 , 2 , 121720 , 86903 , 358 }, ++{ 13 , 0 , 3 , 410788 , 260709 , 403 }, ++{ 13 , 0 , 4 , 438328 , 260709 , 430 }, ++{ 13 , 0 , 5 , 152320 , 86903 , 448 }, ++{ 13 , 0 , 8 , 487832 , 260709 , 479 }, ++{ 13 , 0 , 101 , 493952 , 260709 , 485 }, ++{ 13 , 99 , 100 , 328168 , 173853 , 483 }, ++{ 13 , 99 , 2 , 121720 , 57951 , 537 }, // work for 0x8d - dvb-s2 8psk ++{ 13 , 99 , 3 , 410788 , 173853 , 604 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 13 , 99 , 5 , 152320 , 57951 , 672 }, ++{ 13 , 99 , 8 , 487832 , 173853 , 718 }, ++{ 13 , 99 , 101 , 493952 , 173853 , 727 }, ++{ 1 , 0 , 1 , 815248 , 763515 , 273 }, ++{ 1 , 0 , 100 , 51562 , 40185 , 328 }, ++{ 1 , 0 , 2 , 72674 , 50901 , 365 }, ++{ 1 , 0 , 3 , 1226323 , 763515 , 411 }, ++{ 1 , 0 , 4 , 1308538 , 763515 , 438 }, ++{ 1 , 0 , 5 , 90944 , 50901 , 457 }, ++{ 1 , 0 , 8 , 1456322 , 763515 , 488 }, ++{ 1 , 0 , 101 , 1474592 , 763515 , 494 }, ++{ 1 , 99 , 100 , 979678 , 509715 , 492 }, ++{ 1 , 99 , 2 , 72674 , 33981 , 547 }, ++{ 1 , 99 , 3 , 1226323 , 509715 , 615 }, // was 4 - ERRORR!? FEC_4_5 not in DVB-S2 ++{ 1 , 99 , 5 , 90944 , 33981 , 685 }, ++{ 1 , 99 , 8 , 1456322 , 509715 , 731 }, ++{ 1 , 99 , 101 , 1474592 , 509715 , 740 }, ++{ 9 , 0 , 1 , 815248 , 782127 , 266 }, ++{ 9 , 0 , 100 , 979678 , 782127 , 320 }, ++{ 9 , 0 , 2 , 363370 , 260709 , 356 }, ++{ 9 , 0 , 3 , 1226323 , 782127 , 401 }, ++{ 9 , 0 , 4 , 1308538 , 782127 , 428 }, ++{ 9 , 0 , 5 , 454720 , 260709 , 446 }, ++{ 9 , 0 , 8 , 1456322 , 782127 , 476 }, ++{ 9 , 0 , 101 , 1474592 , 782127 , 482 }, ++{ 9 , 99 , 100 , 979678 , 521559 , 480 }, ++{ 9 , 99 , 2 , 363370 , 173853 , 535 }, ++{ 9 , 99 , 3 , 1226323 , 521559 , 601 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 ++{ 9 , 99 , 5 , 454720 , 173853 , 669 }, ++{ 9 , 99 , 8 , 1456322 , 521559 , 714 }, ++{ 9 , 99 , 101 , 1474592 , 521559 , 723 }, ++{ 18 , 0 , 1 , 535 , 588 , 233 }, ++{ 18 , 0 , 2 , 1070 , 882 , 311 }, ++{ 18 , 0 , 6 , 3210 , 2058 , 399 }, ++{ 16 , 0 , 1 , 763 , 816 , 239 }, ++{ 16 , 0 , 2 , 1526 , 1224 , 319 }, ++{ 16 , 0 , 3 , 2289 , 1632 , 359 }, ++{ 16 , 0 , 5 , 3815 , 2448 , 399 }, ++{ 16 , 0 , 7 , 5341 , 3264 , 419 }, ++{ 22 , 0 , 1 , 535 , 588 , 233 }, ++{ 22 , 0 , 2 , 1070 , 882 , 311 }, ++{ 22 , 0 , 6 , 3210 , 2058 , 399 }, ++{ 20 , 0 , 1 , 143429 , 152592 , 241 }, ++{ 20 , 0 , 2 , 286858 , 228888 , 321 }, ++{ 20 , 0 , 3 , 430287 , 305184 , 361 }, ++{ 20 , 0 , 5 , 717145 , 457776 , 401 }, ++{ 20 , 0 , 7 , 1004003 , 610368 , 421 }, ++{ 2 , 0 , 1 , 584 , 588 , 254 }, ++{ 2 , 0 , 2 , 1169 , 882 , 339 }, ++{ 2 , 0 , 6 , 3507 , 2058 , 436 }, ++{ 0 , 0 , 1 , 812 , 816 , 255 }, ++{ 0 , 0 , 2 , 1624 , 1224 , 340 }, ++{ 0 , 0 , 3 , 2436 , 1632 , 382 }, ++{ 0 , 0 , 5 , 4060 , 2448 , 425 }, ++{ 0 , 0 , 7 , 5684 , 3264 , 446 }, ++{ 6 , 0 , 1 , 584 , 588 , 254 }, ++{ 6 , 0 , 2 , 1168 , 882 , 339 }, ++{ 6 , 0 , 6 , 3504 , 2058 , 436 }, ++{ 4 , 0 , 1 , 152592 , 152592 , 256 }, ++{ 4 , 0 , 2 , 305184 , 228888 , 341 }, ++{ 4 , 0 , 3 , 457776 , 305184 , 384 }, ++{ 4 , 0 , 5 , 762960 , 457776 , 427 }, ++{ 4 , 0 , 7 , 1068144 , 610368 , 448 }, ++}; +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h +--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h 1970-01-01 03:00:00.000000000 +0300 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h 2012-04-03 10:27:59.000000000 +0400 +@@ -0,0 +1,59 @@ ++/* ++ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver ++ * ++ * Copyright (C) 2008 Patrick Boettcher ++ * Copyright (C) 2009 Sergey Tyurin ++ * Updated 2012 by Jannis Achstetter ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef CX24120_H ++#define CX24120_H ++ ++#include ++ ++struct firmware; ++struct dvb_frontend; ++struct i2c_adapter; ++ ++struct cx24120_config ++{ ++ u8 i2c_addr; ++ int (*request_firmware)(struct dvb_frontend *fe, const struct firmware **fw, char *name); ++ void (*stream_control)(struct dvb_frontend *fe, u8 onoff); ++}; ++ ++#if defined(CONFIG_DVB_CX24120) || \ ++ (defined(CONFIG_DVB_CX24120_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, ++ struct i2c_adapter *i2c); ++extern int cx24120_reset(struct dvb_frontend *fe); ++#else ++static inline ++struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++static inline int cx24120_reset(struct dvb_frontend *fe) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return -ENODEV; ++} ++#endif ++ ++#endif +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Kconfig linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig +--- linux-3.4-r1/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:23:44.976143444 +0400 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:26:40.760141513 +0400 +@@ -4,6 +4,13 @@ + comment "Multistandard (satellite) frontends" + depends on DVB_CORE + ++config DVB_CX24120 ++ tristate "Conexant CX24120 based" ++ depends on DVB_CORE && I2C ++ default m if DVB_FE_CUSTOMISE ++ help ++ A DVB-S/DVB-S2 tuner module. Say Y when you want to support this frontend. ++ + config DVB_STB0899 + tristate "STB0899 based" + depends on DVB_CORE && I2C +diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Makefile linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile +--- linux-3.4-r1/drivers/media/dvb-frontends/Makefile 2012-04-03 15:23:44.976143444 +0400 ++++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile 2012-04-03 15:26:40.760141513 +0400 +@@ -19,6 +19,10 @@ + obj-$(CONFIG_DVB_CX22700) += cx22700.o + obj-$(CONFIG_DVB_S5H1432) += s5h1432.o + obj-$(CONFIG_DVB_CX24110) += cx24110.o ++ ++# inserted by Custler ++obj-$(CONFIG_DVB_CX24120) += cx24120.o ++ + obj-$(CONFIG_DVB_TDA8083) += tda8083.o + obj-$(CONFIG_DVB_L64781) += l64781.o + obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o diff --git a/packages/linux/patches/3.10/linux-996-macmini2012-ethernet.patch b/packages/linux/patches/3.10/linux-996-macmini2012-ethernet.patch new file mode 100644 index 0000000000..298260ea69 --- /dev/null +++ b/packages/linux/patches/3.10/linux-996-macmini2012-ethernet.patch @@ -0,0 +1,11 @@ +--- linux-3.9.2/drivers/net/ethernet/broadcom/tg3.c 2013-05-11 18:19:28.000000000 +0400 ++++ linux-3.9.2/drivers/net/ethernet/broadcom/tg3.c 2013-05-25 20:55:00.282972605 +0400 +@@ -333,6 +333,8 @@ + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57766)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57782)}, ++ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57786)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5762)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5725)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5727)}, diff --git a/packages/linux/patches/3.10/linux-997-disable-rc6-on-sandybridge-gt1.patch b/packages/linux/patches/3.10/linux-997-disable-rc6-on-sandybridge-gt1.patch new file mode 100644 index 0000000000..c0a9067fe1 --- /dev/null +++ b/packages/linux/patches/3.10/linux-997-disable-rc6-on-sandybridge-gt1.patch @@ -0,0 +1,13 @@ +--- a/drivers/gpu/drm/i915/intel_pm.c 2013-05-30 22:57:09.098080381 +0200 ++++ b/drivers/gpu/drm/i915/intel_pm.c 2013-05-30 23:31:31.644308032 +0200 +@@ -2503,8 +2503,8 @@ + if (i915_enable_rc6 >= 0) + return i915_enable_rc6; + +- /* Disable RC6 on Ironlake */ +- if (INTEL_INFO(dev)->gen == 5) ++ /* Disable RC6 on Ironlake and Sandybridge GT1 */ ++ if (INTEL_INFO(dev)->gen == 5 || IS_SNB_GT1(dev)) + return 0; + + if (IS_HASWELL(dev)) { diff --git a/projects/RPi/options b/projects/RPi/options index c77db212d2..cc3a150a2e 100755 --- a/projects/RPi/options +++ b/projects/RPi/options @@ -109,7 +109,7 @@ # Kernel to use. values can be: # default: default mainline kernel # ti-omap4: Ti's OMAP4 kernel - LINUX="default" + LINUX="3.9" # use linux-next (latest rc) instead latest released version LINUX_NEXT="no" From 4a837a3358ace6065512de510fd7ff921058342b Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 1 Jul 2013 23:14:22 +0300 Subject: [PATCH 06/61] bcm_sta: add support for kernel 3.10 --- ...sta-010-add-support-for-linux-3.10.0.patch | 256 ++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 packages/linux-drivers/bcm_sta/patches/6.20.155.1/bcm_sta-010-add-support-for-linux-3.10.0.patch diff --git a/packages/linux-drivers/bcm_sta/patches/6.20.155.1/bcm_sta-010-add-support-for-linux-3.10.0.patch b/packages/linux-drivers/bcm_sta/patches/6.20.155.1/bcm_sta-010-add-support-for-linux-3.10.0.patch new file mode 100644 index 0000000000..e3b35a31c4 --- /dev/null +++ b/packages/linux-drivers/bcm_sta/patches/6.20.155.1/bcm_sta-010-add-support-for-linux-3.10.0.patch @@ -0,0 +1,256 @@ +diff --git a/x86-32/src/wl/sys/wl_linux.c b/x86-32/src/wl/sys/wl_linux.c +index 9ee69e1..409bda7 100644 +--- a/x86-32/src/wl/sys/wl_linux.c ++++ b/x86-32/src/wl/sys/wl_linux.c +@@ -2693,7 +2693,7 @@ wl_tkip_keyset(wl_info_t *wl, wsec_key_t *key) + void + wl_tkip_printstats(wl_info_t *wl, bool group_key) + { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) + char debug_buf[512]; + int idx; + if (wl->tkipmodops) { +@@ -2855,6 +2855,7 @@ wl_linux_watchdog(void *ctx) + return 0; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) + static int + wl_proc_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data) + { +@@ -2909,18 +2910,89 @@ wl_proc_write(struct file *filp, const char *buff, unsigned long length, void *d + return length; + } + ++#else ++ ++static int ++wl_proc_read(struct seq_file *seq, void *offset) ++{ ++ wl_info_t * wl = (wl_info_t *)seq->private; ++ int bcmerror, to_user; ++ ++ WL_LOCK(wl); ++ bcmerror = wlc_ioctl(wl->wlc, WLC_GET_MONITOR, &to_user, sizeof(int), NULL); ++ WL_UNLOCK(wl); ++ ++ seq_printf(seq, "%d\n", to_user); ++ return bcmerror; ++} ++ ++static ssize_t wl_proc_write(struct file *file, const char __user *buff, ++ size_t length, loff_t *ppos) ++{ ++ struct seq_file *seq = file->private_data; ++ wl_info_t * wl = (wl_info_t *)seq->private; ++ int bcmerror, from_user = 0; ++ ++ if (length != 1) { ++ WL_ERROR(("%s: Invalid data length\n", __FUNCTION__)); ++ return -EIO; ++ } ++ ++ if (copy_from_user(&from_user, buff, 1)) { ++ WL_ERROR(("%s: copy from user failed\n", __FUNCTION__)); ++ return -EFAULT; ++ } ++ ++ if (from_user >= 0x30) ++ from_user -= 0x30; ++ ++ WL_LOCK(wl); ++ bcmerror = wlc_ioctl(wl->wlc, WLC_SET_MONITOR, &from_user, sizeof(int), NULL); ++ WL_UNLOCK(wl); ++ ++ if (bcmerror < 0) { ++ WL_ERROR(("%s: SET_MONITOR failed with %d\n", __FUNCTION__, bcmerror)); ++ return -EIO; ++ } ++ *ppos += length; ++ return length; ++} ++ ++static int wl_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, wl_proc_read, PDE_DATA(inode)); ++} ++ ++static const struct file_operations wl_proc_fops = { ++ .owner = THIS_MODULE, ++ .open = wl_proc_open, ++ .read = seq_read, ++ .write = wl_proc_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ + static int + wl_reg_proc_entry(wl_info_t *wl) + { + char tmp[32]; + sprintf(tmp, "%s%d", HYBRID_PROC, wl->pub->unit); +- if ((wl->proc_entry = create_proc_entry(tmp, 0644, NULL)) == NULL) { ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) ++ wl->proc_entry = create_proc_entry(tmp, 0644, NULL); ++ if (wl->proc_entry) { ++ wl->proc_entry->read_proc = wl_proc_read; ++ wl->proc_entry->write_proc = wl_proc_write; ++ wl->proc_entry->data = wl; ++ } ++#else ++ wl->proc_entry = proc_create_data(tmp, 0644, NULL, &wl_proc_fops, wl); ++#endif ++ if (!wl->proc_entry) { + WL_ERROR(("%s: create_proc_entry %s failed\n", __FUNCTION__, tmp)); + ASSERT(0); + return -1; + } +- wl->proc_entry->read_proc = wl_proc_read; +- wl->proc_entry->write_proc = wl_proc_write; +- wl->proc_entry->data = wl; + return 0; + } +diff --git a/x86-32/src/wl/sys/wl_linux.c.orig b/x86-32/src/wl/sys/wl_linux.c.orig +index 38206ab..9ee69e1 100644 +--- a/x86-32/src/wl/sys/wl_linux.c.orig ++++ b/x86-32/src/wl/sys/wl_linux.c.orig +@@ -219,7 +219,7 @@ module_param(nompc, int, 0); + #define quote_str(s) to_str(s) + + #ifndef BRCM_WLAN_IFNAME +-#define BRCM_WLAN_IFNAME eth%d ++#define BRCM_WLAN_IFNAME wlan%d + #endif + + static char intf_name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME); +diff --git a/x86-64/src/wl/sys/wl_linux.c b/x86-64/src/wl/sys/wl_linux.c +index 9ee69e1..409bda7 100644 +--- a/x86-64/src/wl/sys/wl_linux.c ++++ b/x86-64/src/wl/sys/wl_linux.c +@@ -2693,7 +2693,7 @@ wl_tkip_keyset(wl_info_t *wl, wsec_key_t *key) + void + wl_tkip_printstats(wl_info_t *wl, bool group_key) + { +-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) + char debug_buf[512]; + int idx; + if (wl->tkipmodops) { +@@ -2855,6 +2855,7 @@ wl_linux_watchdog(void *ctx) + return 0; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) + static int + wl_proc_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data) + { +@@ -2909,18 +2910,89 @@ wl_proc_write(struct file *filp, const char *buff, unsigned long length, void *d + return length; + } + ++#else ++ ++static int ++wl_proc_read(struct seq_file *seq, void *offset) ++{ ++ wl_info_t * wl = (wl_info_t *)seq->private; ++ int bcmerror, to_user; ++ ++ WL_LOCK(wl); ++ bcmerror = wlc_ioctl(wl->wlc, WLC_GET_MONITOR, &to_user, sizeof(int), NULL); ++ WL_UNLOCK(wl); ++ ++ seq_printf(seq, "%d\n", to_user); ++ return bcmerror; ++} ++ ++static ssize_t wl_proc_write(struct file *file, const char __user *buff, ++ size_t length, loff_t *ppos) ++{ ++ struct seq_file *seq = file->private_data; ++ wl_info_t * wl = (wl_info_t *)seq->private; ++ int bcmerror, from_user = 0; ++ ++ if (length != 1) { ++ WL_ERROR(("%s: Invalid data length\n", __FUNCTION__)); ++ return -EIO; ++ } ++ ++ if (copy_from_user(&from_user, buff, 1)) { ++ WL_ERROR(("%s: copy from user failed\n", __FUNCTION__)); ++ return -EFAULT; ++ } ++ ++ if (from_user >= 0x30) ++ from_user -= 0x30; ++ ++ WL_LOCK(wl); ++ bcmerror = wlc_ioctl(wl->wlc, WLC_SET_MONITOR, &from_user, sizeof(int), NULL); ++ WL_UNLOCK(wl); ++ ++ if (bcmerror < 0) { ++ WL_ERROR(("%s: SET_MONITOR failed with %d\n", __FUNCTION__, bcmerror)); ++ return -EIO; ++ } ++ *ppos += length; ++ return length; ++} ++ ++static int wl_proc_open(struct inode *inode, struct file *file) ++{ ++ return single_open(file, wl_proc_read, PDE_DATA(inode)); ++} ++ ++static const struct file_operations wl_proc_fops = { ++ .owner = THIS_MODULE, ++ .open = wl_proc_open, ++ .read = seq_read, ++ .write = wl_proc_write, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++#endif ++ + static int + wl_reg_proc_entry(wl_info_t *wl) + { + char tmp[32]; + sprintf(tmp, "%s%d", HYBRID_PROC, wl->pub->unit); +- if ((wl->proc_entry = create_proc_entry(tmp, 0644, NULL)) == NULL) { ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) ++ wl->proc_entry = create_proc_entry(tmp, 0644, NULL); ++ if (wl->proc_entry) { ++ wl->proc_entry->read_proc = wl_proc_read; ++ wl->proc_entry->write_proc = wl_proc_write; ++ wl->proc_entry->data = wl; ++ } ++#else ++ wl->proc_entry = proc_create_data(tmp, 0644, NULL, &wl_proc_fops, wl); ++#endif ++ if (!wl->proc_entry) { + WL_ERROR(("%s: create_proc_entry %s failed\n", __FUNCTION__, tmp)); + ASSERT(0); + return -1; + } +- wl->proc_entry->read_proc = wl_proc_read; +- wl->proc_entry->write_proc = wl_proc_write; +- wl->proc_entry->data = wl; + return 0; + } +diff --git a/x86-64/src/wl/sys/wl_linux.c.orig b/x86-64/src/wl/sys/wl_linux.c.orig +index 38206ab..9ee69e1 100644 +--- a/x86-64/src/wl/sys/wl_linux.c.orig ++++ b/x86-64/src/wl/sys/wl_linux.c.orig +@@ -219,7 +219,7 @@ module_param(nompc, int, 0); + #define quote_str(s) to_str(s) + + #ifndef BRCM_WLAN_IFNAME +-#define BRCM_WLAN_IFNAME eth%d ++#define BRCM_WLAN_IFNAME wlan%d + #endif + + static char intf_name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME); From 9ad1d9ebdee600eae633d6233b22dc284c283a20 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 1 Jul 2013 23:14:55 +0300 Subject: [PATCH 07/61] bcm_sta: remove old patches --- .../5.100.82.112/bcm_sta-001-license.patch | 21 --- .../5.100.82.112/bcm_sta-002-user-ioctl.patch | 58 ------- .../bcm_sta-003-linux-recent.patch | 162 ------------------ .../bcm_sta-004-rename-device.patch | 22 --- .../bcm_sta-005-linux-3.8-support.patch | 158 ----------------- .../bcm_sta-006-linux-3.9-support.patch | 30 ---- 6 files changed, 451 deletions(-) delete mode 100644 packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-001-license.patch delete mode 100644 packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-002-user-ioctl.patch delete mode 100644 packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-003-linux-recent.patch delete mode 100644 packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-004-rename-device.patch delete mode 100644 packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-005-linux-3.8-support.patch delete mode 100644 packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-006-linux-3.9-support.patch diff --git a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-001-license.patch b/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-001-license.patch deleted file mode 100644 index a76ee1293c..0000000000 --- a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-001-license.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/x86-32/src/wl/sys/wl_linux.c 2010-12-15 02:58:07.000000000 +0100 -+++ b/x86-32/src/wl/sys/wl_linux.c 2010-12-25 18:15:43.356676382 +0100 -@@ -240,6 +240,7 @@ - - static int nompc = 0; - module_param(nompc, int, 0); -+MODULE_LICENSE("MIXED/Proprietary"); - - #ifdef quote_str - #undef quote_str ---- a/x86-64/src/wl/sys/wl_linux.c 2010-12-15 02:58:07.000000000 +0100 -+++ b/x86-64/src/wl/sys/wl_linux.c 2010-12-25 18:15:43.356676382 +0100 -@@ -240,6 +240,7 @@ - - static int nompc = 0; - module_param(nompc, int, 0); -+MODULE_LICENSE("MIXED/Proprietary"); - - #ifdef quote_str - #undef quote_str - diff --git a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-002-user-ioctl.patch b/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-002-user-ioctl.patch deleted file mode 100644 index 1209a320de..0000000000 --- a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-002-user-ioctl.patch +++ /dev/null @@ -1,58 +0,0 @@ ---- a/x86-32/src/wl/sys/wl_cfg80211.c 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-32/src/wl/sys/wl_cfg80211.c 2013-01-31 07:47:40.000000000 +0100 -@@ -1466,7 +1466,10 @@ - scb_val.val = 0; - err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); - if (err) { -- WL_ERR(("Could not get rssi (%d)\n", err)); -+ if (err != -EINVAL) { -+ // Don't fill syslog with EINVAL error -+ WL_ERR(("Could not get rssi (%d)\n", err)); -+ } - return err; - } - rssi = dtoh32(scb_val.val); ---- a/x86-32/src/wl/sys/wl_linux.c 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-32/src/wl/sys/wl_linux.c 2013-01-31 07:47:40.000000000 +0100 -@@ -1579,11 +1579,7 @@ - } - - WL_LOCK(wl); -- if (!capable(CAP_NET_ADMIN)) { -- bcmerror = BCME_EPERM; -- } else { -- bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif); -- } -+ bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif); - WL_UNLOCK(wl); - - done1: ---- a/x86-64/src/wl/sys/wl_cfg80211.c 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-64/src/wl/sys/wl_cfg80211.c 2013-01-31 07:49:06.000000000 +0100 -@@ -1466,7 +1466,10 @@ - scb_val.val = 0; - err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); - if (err) { -- WL_ERR(("Could not get rssi (%d)\n", err)); -+ if (err != -EINVAL) { -+ // Don't fill syslog with EINVAL error -+ WL_ERR(("Could not get rssi (%d)\n", err)); -+ } - return err; - } - rssi = dtoh32(scb_val.val); ---- a/x86-64/src/wl/sys/wl_linux.c 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-64/src/wl/sys/wl_linux.c 2013-01-31 07:50:03.000000000 +0100 -@@ -1579,11 +1579,7 @@ - } - - WL_LOCK(wl); -- if (!capable(CAP_NET_ADMIN)) { -- bcmerror = BCME_EPERM; -- } else { -- bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif); -- } -+ bcmerror = wlc_ioctl(wl->wlc, ioc.cmd, buf, ioc.len, wlif->wlcif); - WL_UNLOCK(wl); - - done1: diff --git a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-003-linux-recent.patch b/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-003-linux-recent.patch deleted file mode 100644 index 57bc7e30ef..0000000000 --- a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-003-linux-recent.patch +++ /dev/null @@ -1,162 +0,0 @@ ---- a/x86-32/Makefile 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-32/Makefile 2013-01-31 10:00:10.000000000 +0100 -@@ -15,21 +15,9 @@ - - ifneq ($(KERNELRELEASE),) - -- LINUXVER_GOODFOR_CFG80211:=$(strip $(shell \ -- if [ "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "32" ]; then \ -- echo TRUE; \ -- else \ -- echo FALSE; \ -- fi \ -- )) -- -- LINUXVER_WEXT_ONLY:=$(strip $(shell \ -- if [ "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "17" ]; then \ -- echo FALSE; \ -- else \ -- echo TRUE; \ -- fi \ -- )) -+ LINUXVER_GOODFOR_CFG80211:=TRUE -+ -+ LINUXVER_WEXT_ONLY:=FALSE - - ifneq ($(API),) - ifeq ($(API), CFG80211) ---- a/x86-32/src/wl/sys/wl_cfg80211.c 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-32/src/wl/sys/wl_cfg80211.c 2013-01-31 10:00:10.000000000 +0100 -@@ -42,7 +42,7 @@ - enum nl80211_iftype type, u32 *flags, struct vif_params *params); - static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid); --static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, -+static s32 wl_cfg80211_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request); - static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed); - static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, -@@ -570,10 +570,12 @@ - } - - static s32 --wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, -+wl_cfg80211_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request) - { - s32 err = 0; -+ struct wl_priv *wl = wiphy_to_wl(wiphy); -+ struct net_device *ndev = wl_to_ndev(wl); - - CHECK_SYS_UP(); - err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); ---- a/x86-32/src/wl/sys/wl_iw.h 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-32/src/wl/sys/wl_iw.h 2013-01-31 10:00:10.000000000 +0100 -@@ -15,6 +15,7 @@ - #ifndef _wl_iw_h_ - #define _wl_iw_h_ - -+#include - #include - - #include ---- a/x86-32/src/wl/sys/wl_linux.c 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-32/src/wl/sys/wl_linux.c 2013-01-31 10:00:10.000000000 +0100 -@@ -40,7 +40,6 @@ - #include - #define WLC_MAXBSSCFG 1 - --#include - #include - #include - #include -@@ -385,7 +384,7 @@ - #endif - .ndo_get_stats = wl_get_stats, - .ndo_set_mac_address = wl_set_mac_address, -- .ndo_set_multicast_list = wl_set_multicast_list, -+ .ndo_set_rx_mode = wl_set_multicast_list, - .ndo_do_ioctl = wl_ioctl - }; - ---- a/x86-64/Makefile 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-64/Makefile 2013-01-31 10:06:20.000000000 +0100 -@@ -15,21 +15,9 @@ - - ifneq ($(KERNELRELEASE),) - -- LINUXVER_GOODFOR_CFG80211:=$(strip $(shell \ -- if [ "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "32" ]; then \ -- echo TRUE; \ -- else \ -- echo FALSE; \ -- fi \ -- )) -- -- LINUXVER_WEXT_ONLY:=$(strip $(shell \ -- if [ "$(VERSION)" -ge "2" -a "$(PATCHLEVEL)" -ge "6" -a "$(SUBLEVEL)" -ge "17" ]; then \ -- echo FALSE; \ -- else \ -- echo TRUE; \ -- fi \ -- )) -+ LINUXVER_GOODFOR_CFG80211:=TRUE -+ -+ LINUXVER_WEXT_ONLY:=FALSE - - ifneq ($(API),) - ifeq ($(API), CFG80211) ---- a/x86-64/src/wl/sys/wl_cfg80211.c 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-64/src/wl/sys/wl_cfg80211.c 2013-01-31 10:07:35.000000000 +0100 -@@ -42,7 +42,7 @@ - enum nl80211_iftype type, u32 *flags, struct vif_params *params); - static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid); --static s32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, -+static s32 wl_cfg80211_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request); - static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed); - static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, -@@ -570,10 +570,12 @@ - } - - static s32 --wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, -+wl_cfg80211_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request) - { - s32 err = 0; -+ struct wl_priv *wl = wiphy_to_wl(wiphy); -+ struct net_device *ndev = wl_to_ndev(wl); - - CHECK_SYS_UP(); - err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); ---- a/x86-64/src/wl/sys/wl_iw.h 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-64/src/wl/sys/wl_iw.h 2013-01-31 10:07:58.000000000 +0100 -@@ -15,6 +15,7 @@ - #ifndef _wl_iw_h_ - #define _wl_iw_h_ - -+#include - #include - - #include ---- a/x86-64/src/wl/sys/wl_linux.c 2013-01-25 13:59:21.000000000 +0100 -+++ b/x86-64/src/wl/sys/wl_linux.c 2013-01-31 10:08:30.000000000 +0100 -@@ -40,7 +40,6 @@ - #include - #define WLC_MAXBSSCFG 1 - --#include - #include - #include - #include -@@ -385,7 +384,7 @@ - #endif - .ndo_get_stats = wl_get_stats, - .ndo_set_mac_address = wl_set_mac_address, -- .ndo_set_multicast_list = wl_set_multicast_list, -+ .ndo_set_rx_mode = wl_set_multicast_list, - .ndo_do_ioctl = wl_ioctl - }; - diff --git a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-004-rename-device.patch b/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-004-rename-device.patch deleted file mode 100644 index c469beab7d..0000000000 --- a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-004-rename-device.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/x86-32/src/wl/sys/wl_linux.c 2010-12-15 02:58:07.000000000 +0100 -+++ b/x86-32/src/wl/sys/wl_linux.c 2010-12-27 22:14:38.679428984 +0100 -@@ -251,7 +251,7 @@ - #define quote_str(s) to_str(s) - - #ifndef BRCM_WLAN_IFNAME --#define BRCM_WLAN_IFNAME eth%d -+#define BRCM_WLAN_IFNAME wlan%d - #endif - - static char name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME); ---- a/x86-64/src/wl/sys/wl_linux.c 2010-12-15 03:01:09.000000000 +0100 -+++ b/x86-64/src/wl/sys/wl_linux.c 2010-12-27 22:15:18.273865927 +0100 -@@ -251,7 +251,7 @@ - #define quote_str(s) to_str(s) - - #ifndef BRCM_WLAN_IFNAME --#define BRCM_WLAN_IFNAME eth%d -+#define BRCM_WLAN_IFNAME wlan%d - #endif - - static char name[IFNAMSIZ] = quote_str(BRCM_WLAN_IFNAME); diff --git a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-005-linux-3.8-support.patch b/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-005-linux-3.8-support.patch deleted file mode 100644 index 2f8caf7e8a..0000000000 --- a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-005-linux-3.8-support.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 00da4982e9175921cfb26d1377bf49ece3bb41cb Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Tue, 26 Mar 2013 23:10:17 +0200 -Subject: [PATCH] linux 3.8 support - ---- - x86-32/src/include/bcmutils.h | 5 +++++ - x86-32/src/wl/sys/wl_cfg80211.c | 25 ++++++++++++++++++++++++- - x86-64/src/include/bcmutils.h | 4 ++++ - x86-64/src/wl/sys/wl_cfg80211.c | 25 ++++++++++++++++++++++++- - 4 files changed, 57 insertions(+), 2 deletions(-) - -diff --git a/x86-32/src/include/bcmutils.h b/x86-32/src/include/bcmutils.h -index fa6df04..9a8cab4 100644 ---- a/x86-32/src/include/bcmutils.h -+++ b/x86-32/src/include/bcmutils.h -@@ -555,7 +555,12 @@ extern void printbig(char *buf); - extern void prhex(const char *msg, uchar *buf, uint len); - - extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); -+#else -+extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(const void *buf, int buflen, uint key); -+#endif -+ - extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key); - - extern const char *bcmerrorstr(int bcmerror); -diff --git a/x86-32/src/wl/sys/wl_cfg80211.c b/x86-32/src/wl/sys/wl_cfg80211.c -index 09d04ed..698b004 100644 ---- a/x86-32/src/wl/sys/wl_cfg80211.c -+++ b/x86-32/src/wl/sys/wl_cfg80211.c -@@ -744,7 +744,11 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, - else - memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - wl_ch_to_chanspec(params->channel, &join_params, &join_params_size); -+#else -+ wl_ch_to_chanspec(params->chandef.chan, &join_params, &join_params_size); -+#endif - - err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size); - if (err) { -@@ -2047,9 +2051,14 @@ static s32 wl_update_bss_info(struct wl_priv *wl) - struct bcm_tlv *tim; - u16 beacon_interval; - s32 dtim_period; -+ s32 err = 0; - size_t ie_len; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - u8 *ie; -- s32 err = 0; -+#else -+ const u8 *ie; -+ const struct cfg80211_bss_ies *ies; -+#endif - - ssid = &wl->profile->ssid; - bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid, -@@ -2079,8 +2088,22 @@ static s32 wl_update_bss_info(struct wl_priv *wl) - beacon_interval = cpu_to_le16(bi->beacon_period); - } else { - WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid)); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - ie = bss->information_elements; - ie_len = bss->len_information_elements; -+#else -+ rcu_read_lock(); -+ ies = (const struct cfg80211_bss_ies*)rcu_dereference(bss->ies); -+ if (!ies) { -+ /* This should never happen */ -+ rcu_read_unlock(); -+ err = -EIO; -+ goto update_bss_info_out; -+ } -+ ie = ies->data; -+ ie_len = (size_t)(ies->len); -+ rcu_read_unlock(); -+#endif - beacon_interval = bss->beacon_interval; - cfg80211_put_bss(bss); - } -diff --git a/x86-64/src/include/bcmutils.h b/x86-64/src/include/bcmutils.h -index fa6df04..1200bf0 100644 ---- a/x86-64/src/include/bcmutils.h -+++ b/x86-64/src/include/bcmutils.h -@@ -555,7 +555,11 @@ extern void printbig(char *buf); - extern void prhex(const char *msg, uchar *buf, uint len); - - extern bcm_tlv_t *BCMROMFN(bcm_next_tlv)(bcm_tlv_t *elt, int *buflen); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(void *buf, int buflen, uint key); -+#else -+extern bcm_tlv_t *BCMROMFN(bcm_parse_tlvs)(const void *buf, int buflen, uint key); -+#endif - extern bcm_tlv_t *BCMROMFN(bcm_parse_ordered_tlvs)(void *buf, int buflen, uint key); - - extern const char *bcmerrorstr(int bcmerror); -diff --git a/x86-64/src/wl/sys/wl_cfg80211.c b/x86-64/src/wl/sys/wl_cfg80211.c -index 94aac25..244243f 100644 ---- a/x86-64/src/wl/sys/wl_cfg80211.c -+++ b/x86-64/src/wl/sys/wl_cfg80211.c -@@ -744,7 +744,11 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, - else - memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - wl_ch_to_chanspec(params->channel, &join_params, &join_params_size); -+#else -+ wl_ch_to_chanspec(params->chandef.chan, &join_params, &join_params_size); -+#endif - - err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size); - if (err) { -@@ -2047,9 +2051,14 @@ static s32 wl_update_bss_info(struct wl_priv *wl) - struct bcm_tlv *tim; - u16 beacon_interval; - s32 dtim_period; -+ s32 err = 0; - size_t ie_len; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - u8 *ie; -- s32 err = 0; -+#else -+ const u8 *ie; -+ const struct cfg80211_bss_ies *ies; -+#endif - - ssid = &wl->profile->ssid; - bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid, -@@ -2079,8 +2088,22 @@ static s32 wl_update_bss_info(struct wl_priv *wl) - beacon_interval = cpu_to_le16(bi->beacon_period); - } else { - WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid)); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) - ie = bss->information_elements; - ie_len = bss->len_information_elements; -+#else -+ rcu_read_lock(); -+ ies = (const struct cfg80211_bss_ies*)rcu_dereference(bss->ies); -+ if (!ies) { -+ /* This should never happen */ -+ rcu_read_unlock(); -+ err = -EIO; -+ goto update_bss_info_out; -+ } -+ ie = ies->data; -+ ie_len = (size_t)(ies->len); -+ rcu_read_unlock(); -+#endif - beacon_interval = bss->beacon_interval; - cfg80211_put_bss(bss); - } --- -1.7.2.5 - diff --git a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-006-linux-3.9-support.patch b/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-006-linux-3.9-support.patch deleted file mode 100644 index 4a97a1bce2..0000000000 --- a/packages/linux-drivers/bcm_sta/patches/5.100.82.112/bcm_sta-006-linux-3.9-support.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff -Naur bcm_sta-5.100.82.112/x86-32/src/wl/sys/wl_cfg80211.c bcm_sta-5.100.82.112.patch/x86-32/src/wl/sys/wl_cfg80211.c ---- bcm_sta-5.100.82.112/x86-32/src/wl/sys/wl_cfg80211.c 2011-10-22 18:55:54.000000000 +0200 -+++ bcm_sta-5.100.82.112.patch/x86-32/src/wl/sys/wl_cfg80211.c 2013-05-06 07:03:19.146764181 +0200 -@@ -2077,7 +2077,11 @@ - ie = bss->information_elements; - ie_len = bss->len_information_elements; - beacon_interval = bss->beacon_interval; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) - cfg80211_put_bss(bss); -+#else -+ cfg80211_put_bss(wl_to_wiphy(wl), bss); -+#endif - } - - tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM); -diff -Naur bcm_sta-5.100.82.112/x86-64/src/wl/sys/wl_cfg80211.c bcm_sta-5.100.82.112.patch/x86-64/src/wl/sys/wl_cfg80211.c ---- bcm_sta-5.100.82.112/x86-64/src/wl/sys/wl_cfg80211.c 2011-10-22 18:56:55.000000000 +0200 -+++ bcm_sta-5.100.82.112.patch/x86-64/src/wl/sys/wl_cfg80211.c 2013-05-06 07:03:55.443652962 +0200 -@@ -2077,7 +2077,11 @@ - ie = bss->information_elements; - ie_len = bss->len_information_elements; - beacon_interval = bss->beacon_interval; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0) - cfg80211_put_bss(bss); -+#else -+ cfg80211_put_bss(wl_to_wiphy(wl), bss); -+#endif - } - - tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM); From ed59081473ba55344c4160279555d18b3b4c351a Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 1 Jul 2013 23:16:23 +0300 Subject: [PATCH 08/61] xf86-video-fglrx: add support for kernel 3.10 --- .../replace_old_procfs_calls.patch | 371 ++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 packages/x11/driver/xf86-video-fglrx/patches.upstream/replace_old_procfs_calls.patch diff --git a/packages/x11/driver/xf86-video-fglrx/patches.upstream/replace_old_procfs_calls.patch b/packages/x11/driver/xf86-video-fglrx/patches.upstream/replace_old_procfs_calls.patch new file mode 100644 index 0000000000..a1f3a6ab73 --- /dev/null +++ b/packages/x11/driver/xf86-video-fglrx/patches.upstream/replace_old_procfs_calls.patch @@ -0,0 +1,371 @@ +From 455d3759e6d732a4e382dbdeca35afaedaf3f52e Mon Sep 17 00:00:00 2001 +From: Alberto Milone +Date: Thu, 20 Jun 2013 16:02:12 +0200 +Subject: [PATCH 1/1] Add support for Linux 3.10 + +source: http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/x11-drivers/ati-drivers/files/ati-drivers-13.6-linux-3.10-proc.diff +--- + drmP.h | 4 - + drm_proc.h | 55 ------------ + firegl_public.c | 252 +++++++++++++++++++++++++++++++++++++++++++------------ + 3 files changed, 197 insertions(+), 114 deletions(-) + +diff --git a/drmP.h b/drmP.h +index 81546b2..4e74526 100755 +--- a/common/lib/modules/fglrx/build_mod/drmP.h ++++ b/common/lib/modules/fglrx/build_mod//drmP.h +@@ -901,10 +901,6 @@ int DRM(stub_register)(const char *name, + int DRM(stub_unregister)(int minor); + + /* Proc support (drm_proc.h) */ +-extern struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev, +- int minor, +- struct proc_dir_entry *root, +- struct proc_dir_entry **dev_root); + extern int DRM(proc_cleanup)(int minor, + struct proc_dir_entry *root, + struct proc_dir_entry *dev_root); +diff --git a/drm_proc.h b/drm_proc.h +index 1e3ab4a..c52ad7e 100755 +--- a/common/lib/modules/fglrx/build_mod/drm_proc.h ++++ b/common/lib/modules/fglrx/build_mod//drm_proc.h +@@ -75,61 +75,6 @@ struct drm_proc_list { + #define DRM_PROC_ENTRIES (sizeof(DRM(proc_list))/sizeof(DRM(proc_list)[0])) + + /** +- * Initialize the DRI proc filesystem for a device. +- * +- * \param dev DRM device. +- * \param minor device minor number. +- * \param root DRI proc dir entry. +- * \param dev_root resulting DRI device proc dir entry. +- * \return root entry pointer on success, or NULL on failure. +- * +- * Create the DRI proc root entry "/proc/ati", the device proc root entry +- * "/proc/ati/%minor%/", and each entry in proc_list as +- * "/proc/ati/%minor%/%name%". +- */ +-struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev, int minor, +- struct proc_dir_entry *root, +- struct proc_dir_entry **dev_root) +-{ +- struct proc_dir_entry *ent; +- int i, j; +- char name[64]; +- +- if (!minor) root = create_proc_entry("dri", S_IFDIR, NULL); +- if (!root) { +- DRM_ERROR("Cannot create /proc/ati\n"); +- return NULL; +- } +- +- sprintf(name, "%d", minor); +- *dev_root = create_proc_entry(name, S_IFDIR, root); +- if (!*dev_root) { +- DRM_ERROR("Cannot create /proc/ati/%s\n", name); +- return NULL; +- } +- +- for (i = 0; i < DRM_PROC_ENTRIES; i++) { +- ent = create_proc_entry(DRM(proc_list)[i].name, +- S_IFREG|S_IRUGO, *dev_root); +- if (!ent) { +- DRM_ERROR("Cannot create /proc/ati/%s/%s\n", +- name, DRM(proc_list)[i].name); +- for (j = 0; j < i; j++) +- remove_proc_entry(DRM(proc_list)[i].name, +- *dev_root); +- remove_proc_entry(name, root); +- if (!minor) remove_proc_entry("dri", NULL); +- return NULL; +- } +- ent->read_proc = DRM(proc_list)[i].f; +- ent->data = dev; +- } +- +- return root; +-} +- +- +-/** + * Cleanup the proc filesystem resources. + * + * \param minor device minor number. +diff --git a/firegl_public.c b/firegl_public.c +index d3ad3ce..890a0aa 100755 +--- a/common/lib/modules/fglrx/build_mod/firegl_public.c ++++ b/common/lib/modules/fglrx/build_mod//firegl_public.c +@@ -583,6 +583,202 @@ kcl_proc_list_t KCL_PROC_FileList[] = + { "NULL", NULL, NULL} // Terminate List!!! + }; + ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ++typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data); ++typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data); ++#else ++#define PDE_DATA(inode) (PDE((inode))->data) ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ++typedef struct { ++ read_proc_t *read_func; ++ write_proc_t *write_func; ++ void *data; ++} gentoo_proc_wrapper_t; ++ ++#define GENTOO_PROC_WRAPPER_OVERFLOW_MAGIC 939750305 ++ ++static ssize_t gentoo_proc_wrapper_read (struct file *myfile, char __user *buffer, size_t count, loff_t *offset) { ++ int is_eof=0, retval; ++ char *start, *usebuffer=NULL; ++ gentoo_proc_wrapper_t* wrapper_data=(gentoo_proc_wrapper_t*)(myfile->private_data); ++ if (PAGE_SIZE<*offset) { ++ printk(KERN_ERR "Trying to read beyond 4k on proc\n"); ++ return -EIO; ++ } ++ //printk(KERN_NOTICE " call with: dev %p, func %p\n", wrapper_data->data, wrapper_data->read_func); ++ ++ usebuffer=kmalloc(2*PAGE_SIZE, GFP_KERNEL); ++ if (!usebuffer) ++ return -ENOMEM; ++ ((u32*)usebuffer)[1024]=GENTOO_PROC_WRAPPER_OVERFLOW_MAGIC; ++ ++ retval=wrapper_data->read_func(usebuffer, &start, *offset, count, &is_eof, wrapper_data->data); ++ ++ BUG_ON(GENTOO_PROC_WRAPPER_OVERFLOW_MAGIC != ((u32*)usebuffer)[1024]); ++ ++ if (0 > retval) ++ { ++ printk(KERN_ERR "Proc read failed with %d", retval); ++ goto out; ++ } ++ ++ if (copy_to_user(buffer, start, retval)) { ++ printk(KERN_NOTICE "copy to user failed in amd drivers proc code\n"); ++ retval=-EFAULT; ++ goto out; ++ } ++ *offset+=retval; ++ ++out: ++ if (usebuffer) ++ kfree(usebuffer); ++ return retval; ++} ++static ssize_t gentoo_proc_wrapper_write (struct file *myfile, const char __user *buffer, size_t count, loff_t *offset) { ++ gentoo_proc_wrapper_t* wrapper_data=(gentoo_proc_wrapper_t*)(myfile->private_data); ++ int retval=0; ++ void *usebuffer=NULL; ++ ++ BUG_ON(*offset); ++ if (!wrapper_data->write_func) ++ return -EPERM; ++ ++ usebuffer=kmalloc(count, GFP_KERNEL); ++ if (!usebuffer) ++ return -ENOMEM; ++ if (copy_from_user(usebuffer, buffer, count)) { ++ printk(KERN_NOTICE "copy from user failed in amd drivers proc code\n"); ++ retval=-EFAULT; ++ goto out; ++ } ++ ++ retval=wrapper_data->write_func(myfile, buffer, count, wrapper_data->data); ++ *offset+=retval; ++out: ++ if (usebuffer) ++ kfree(usebuffer); ++ return retval; ++} ++static int gentoo_proc_wrapper_open(struct inode *myinode, struct file *myfile) { ++ myfile->private_data=PDE_DATA(myinode); ++ return generic_file_open(myinode, myfile); ++} ++struct file_operations gentoo_proc_fops = { ++ .read=gentoo_proc_wrapper_read, ++ .write=gentoo_proc_wrapper_write, ++ .open=gentoo_proc_wrapper_open, ++}; ++ ++static void *gentoo_proc_wrapper_data(read_proc_t *reader, write_proc_t *writer, void *mydata) { ++ gentoo_proc_wrapper_t *retval=kmalloc(sizeof(gentoo_proc_wrapper_t), GFP_KERNEL); ++ if (!retval) ++ return retval; ++ retval->read_func=reader; ++ retval->write_func=writer; ++ retval->data=mydata; ++ return retval; ++} ++ ++static struct proc_dir_entry *firegl_proc_init( device_t *dev, ++ int minor, ++ struct proc_dir_entry *root, ++ struct proc_dir_entry **dev_root, ++ kcl_proc_list_t *proc_list ) // proc_list must be terminated! ++{ ++ struct proc_dir_entry *ent; ++ char name[64]; ++ kcl_proc_list_t *list = proc_list; ++ void *tempdata; ++ KCL_DEBUG1(FN_FIREGL_PROC, "minor %d, proc_list 0x%08lx\n", minor, (unsigned long)proc_list); ++ if (!minor) ++ { ++ root = proc_mkdir("ati", NULL); ++ } ++ ++ if (!root) ++ { ++ KCL_DEBUG_ERROR("Cannot create /proc/ati\n"); ++ return NULL; ++ } ++ ++ if (minor == 0) ++ { ++ // Global major debice number entry ++ tempdata=gentoo_proc_wrapper_data((read_proc_t*)firegl_major_proc_read, NULL, NULL); ++ if (!tempdata) ++ return NULL; ++ ent = proc_create_data("major", S_IFREG|S_IRUGO, root, &gentoo_proc_fops, tempdata); ++ if (!ent) ++ { ++ remove_proc_entry("ati", NULL); ++ KCL_DEBUG_ERROR("Cannot create /proc/ati/major\n"); ++ return NULL; ++ } ++ } ++ ++ sprintf(name, "%d", minor); ++ *dev_root = proc_mkdir(name, root); ++ if (!*dev_root) { ++ remove_proc_entry("major", root); ++ remove_proc_entry("ati", NULL); ++ KCL_DEBUG_ERROR("Cannot create /proc/ati/%s\n", name); ++ return NULL; ++ } ++ ++ while (list->f || list->fops) ++ { ++ struct file_operations *my_fops = &gentoo_proc_fops; ++ if (list->fops) ++ { ++ my_fops = (struct file_operations*)list->fops; ++ tempdata=(dev->pubdev.signature == FGL_DEVICE_SIGNATURE)? firegl_find_device(minor) : (dev); ++ } ++ else { ++ BUG_ON(!list->f); ++ tempdata=gentoo_proc_wrapper_data((read_proc_t*)list->f, NULL, (dev->pubdev.signature == FGL_DEVICE_SIGNATURE)? firegl_find_device(minor) : (dev) ); ++ if (!tempdata) ++ return NULL; ++ } ++ //printk(KERN_NOTICE "name %s, dev %p, func %p, data %p\n", list->name, (dev->pubdev.signature == FGL_DEVICE_SIGNATURE)? firegl_find_device(minor) : (dev), list->f, tempdata); ++ ent = proc_create_data(list->name, S_IFREG|S_IRUGO, *dev_root, my_fops, tempdata); ++ ++ if (!ent) ++ { ++ KCL_DEBUG_ERROR("Cannot create /proc/ati/%s/%s\n", name, list->name); ++ while (proc_list != list) ++ { ++ remove_proc_entry(proc_list->name, *dev_root); ++ proc_list++; ++ } ++ remove_proc_entry(name, root); ++ if (!minor) ++ { ++ remove_proc_entry("major", root); ++ remove_proc_entry("ati", NULL); ++ } ++ return NULL; ++ } ++ ++ list++; ++ } ++ ++ if (minor == 0) ++ { ++ // Global debug entry, only create it once ++ tempdata=gentoo_proc_wrapper_data((read_proc_t*)firegl_debug_proc_read_wrap, (write_proc_t*)firegl_debug_proc_write_wrap, dev); ++ if (!tempdata) ++ return NULL; ++ ent=proc_create_data("debug", S_IFREG|S_IRUGO, root, &gentoo_proc_fops, tempdata); ++ if (!ent) ++ return NULL; ++ } ++ ++ return root; ++} ++#else + static struct proc_dir_entry *firegl_proc_init( device_t *dev, + int minor, + struct proc_dir_entry *root, +@@ -677,6 +873,7 @@ static struct proc_dir_entry *firegl_proc_init( device_t *dev, + + return root; + } ++#endif + + static int firegl_proc_cleanup( int minor, + struct proc_dir_entry *root, +@@ -6135,59 +6332,4 @@ void ATI_API_CALL KCL_fpu_end(void) + kernel_fpu_end(); + } + +-/** Create new directory entry under "/proc/ati/...." +- * Where +- * root_dir - Root directory. If NULL then we should use "/proc/ati" root. +- * name - Pointer to the name of directory +- * access - Access attribute. We could use it to disable access to the directory for everybody accept owner. +- * By default owner is root. +- * Return NULL if failure. Pointer to proc_dir_entry otherwise +- */ +-void * KCL_create_proc_dir(void *root_dir, const char *name, unsigned int access) +-{ +- struct proc_dir_entry *dir = NULL; +- +- if (root_dir == NULL) +- dir = create_proc_entry(name, S_IFDIR | access, firegl_stub_root); +- else +- dir = create_proc_entry(name, S_IFDIR | access, (struct proc_dir_entry *)root_dir); +- +- return dir; +-} +- +-/* Remove proc directory entry +- * root - Pointer to directory proc entry or NULL if for "/proc/ati" +- * name - Name to delete +- */ +-void KCL_remove_proc_dir_entry(void *root, const char *name) +-{ +- if (root == NULL) +- remove_proc_entry(name, firegl_stub_root); +- else +- remove_proc_entry(name, (struct proc_dir_entry *)root); +-} +- +- +-/* Create proc_entry under "root_dir" +- * read_fn - Function which will be called on read request +- * write_fn - Function which will be called on write request +- * private_data - Pointer to private data which will be passed +- */ +-void KCL_create_proc_entry(void *root_dir, const char *name, unsigned int access_mode, void *read_fn, void *write_fn, void *private_data) +-{ +- struct proc_dir_entry *ent = NULL; +- +- if (root_dir == NULL || name == NULL) +- return; +- +- ent = create_proc_entry(name, access_mode, (struct proc_dir_entry *)root_dir); +- +- if (ent) +- { +- ent->read_proc = (read_proc_t *)read_fn; +- ent->write_proc = (write_proc_t *)write_fn; +- ent->data = private_data; +- } +-} +- + #endif /* __KERNEL__ */ +-- +1.7.9.5 + From a52ecda16e95dcf6f14c024bfcf0cd29098a6b82 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 1 Jul 2013 23:18:17 +0300 Subject: [PATCH 09/61] xf86-video-fglrx-legacy: add support for kernel 3.10 --- .../replace_old_procfs_calls.patch | 371 ++++++++++++++++++ 1 file changed, 371 insertions(+) create mode 100644 packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/replace_old_procfs_calls.patch diff --git a/packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/replace_old_procfs_calls.patch b/packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/replace_old_procfs_calls.patch new file mode 100644 index 0000000000..a1f3a6ab73 --- /dev/null +++ b/packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/replace_old_procfs_calls.patch @@ -0,0 +1,371 @@ +From 455d3759e6d732a4e382dbdeca35afaedaf3f52e Mon Sep 17 00:00:00 2001 +From: Alberto Milone +Date: Thu, 20 Jun 2013 16:02:12 +0200 +Subject: [PATCH 1/1] Add support for Linux 3.10 + +source: http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/x11-drivers/ati-drivers/files/ati-drivers-13.6-linux-3.10-proc.diff +--- + drmP.h | 4 - + drm_proc.h | 55 ------------ + firegl_public.c | 252 +++++++++++++++++++++++++++++++++++++++++++------------ + 3 files changed, 197 insertions(+), 114 deletions(-) + +diff --git a/drmP.h b/drmP.h +index 81546b2..4e74526 100755 +--- a/common/lib/modules/fglrx/build_mod/drmP.h ++++ b/common/lib/modules/fglrx/build_mod//drmP.h +@@ -901,10 +901,6 @@ int DRM(stub_register)(const char *name, + int DRM(stub_unregister)(int minor); + + /* Proc support (drm_proc.h) */ +-extern struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev, +- int minor, +- struct proc_dir_entry *root, +- struct proc_dir_entry **dev_root); + extern int DRM(proc_cleanup)(int minor, + struct proc_dir_entry *root, + struct proc_dir_entry *dev_root); +diff --git a/drm_proc.h b/drm_proc.h +index 1e3ab4a..c52ad7e 100755 +--- a/common/lib/modules/fglrx/build_mod/drm_proc.h ++++ b/common/lib/modules/fglrx/build_mod//drm_proc.h +@@ -75,61 +75,6 @@ struct drm_proc_list { + #define DRM_PROC_ENTRIES (sizeof(DRM(proc_list))/sizeof(DRM(proc_list)[0])) + + /** +- * Initialize the DRI proc filesystem for a device. +- * +- * \param dev DRM device. +- * \param minor device minor number. +- * \param root DRI proc dir entry. +- * \param dev_root resulting DRI device proc dir entry. +- * \return root entry pointer on success, or NULL on failure. +- * +- * Create the DRI proc root entry "/proc/ati", the device proc root entry +- * "/proc/ati/%minor%/", and each entry in proc_list as +- * "/proc/ati/%minor%/%name%". +- */ +-struct proc_dir_entry *DRM(proc_init)(drm_device_t *dev, int minor, +- struct proc_dir_entry *root, +- struct proc_dir_entry **dev_root) +-{ +- struct proc_dir_entry *ent; +- int i, j; +- char name[64]; +- +- if (!minor) root = create_proc_entry("dri", S_IFDIR, NULL); +- if (!root) { +- DRM_ERROR("Cannot create /proc/ati\n"); +- return NULL; +- } +- +- sprintf(name, "%d", minor); +- *dev_root = create_proc_entry(name, S_IFDIR, root); +- if (!*dev_root) { +- DRM_ERROR("Cannot create /proc/ati/%s\n", name); +- return NULL; +- } +- +- for (i = 0; i < DRM_PROC_ENTRIES; i++) { +- ent = create_proc_entry(DRM(proc_list)[i].name, +- S_IFREG|S_IRUGO, *dev_root); +- if (!ent) { +- DRM_ERROR("Cannot create /proc/ati/%s/%s\n", +- name, DRM(proc_list)[i].name); +- for (j = 0; j < i; j++) +- remove_proc_entry(DRM(proc_list)[i].name, +- *dev_root); +- remove_proc_entry(name, root); +- if (!minor) remove_proc_entry("dri", NULL); +- return NULL; +- } +- ent->read_proc = DRM(proc_list)[i].f; +- ent->data = dev; +- } +- +- return root; +-} +- +- +-/** + * Cleanup the proc filesystem resources. + * + * \param minor device minor number. +diff --git a/firegl_public.c b/firegl_public.c +index d3ad3ce..890a0aa 100755 +--- a/common/lib/modules/fglrx/build_mod/firegl_public.c ++++ b/common/lib/modules/fglrx/build_mod//firegl_public.c +@@ -583,6 +583,202 @@ kcl_proc_list_t KCL_PROC_FileList[] = + { "NULL", NULL, NULL} // Terminate List!!! + }; + ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ++typedef int (read_proc_t)(char *page, char **start, off_t off, int count, int *eof, void *data); ++typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data); ++#else ++#define PDE_DATA(inode) (PDE((inode))->data) ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ++typedef struct { ++ read_proc_t *read_func; ++ write_proc_t *write_func; ++ void *data; ++} gentoo_proc_wrapper_t; ++ ++#define GENTOO_PROC_WRAPPER_OVERFLOW_MAGIC 939750305 ++ ++static ssize_t gentoo_proc_wrapper_read (struct file *myfile, char __user *buffer, size_t count, loff_t *offset) { ++ int is_eof=0, retval; ++ char *start, *usebuffer=NULL; ++ gentoo_proc_wrapper_t* wrapper_data=(gentoo_proc_wrapper_t*)(myfile->private_data); ++ if (PAGE_SIZE<*offset) { ++ printk(KERN_ERR "Trying to read beyond 4k on proc\n"); ++ return -EIO; ++ } ++ //printk(KERN_NOTICE " call with: dev %p, func %p\n", wrapper_data->data, wrapper_data->read_func); ++ ++ usebuffer=kmalloc(2*PAGE_SIZE, GFP_KERNEL); ++ if (!usebuffer) ++ return -ENOMEM; ++ ((u32*)usebuffer)[1024]=GENTOO_PROC_WRAPPER_OVERFLOW_MAGIC; ++ ++ retval=wrapper_data->read_func(usebuffer, &start, *offset, count, &is_eof, wrapper_data->data); ++ ++ BUG_ON(GENTOO_PROC_WRAPPER_OVERFLOW_MAGIC != ((u32*)usebuffer)[1024]); ++ ++ if (0 > retval) ++ { ++ printk(KERN_ERR "Proc read failed with %d", retval); ++ goto out; ++ } ++ ++ if (copy_to_user(buffer, start, retval)) { ++ printk(KERN_NOTICE "copy to user failed in amd drivers proc code\n"); ++ retval=-EFAULT; ++ goto out; ++ } ++ *offset+=retval; ++ ++out: ++ if (usebuffer) ++ kfree(usebuffer); ++ return retval; ++} ++static ssize_t gentoo_proc_wrapper_write (struct file *myfile, const char __user *buffer, size_t count, loff_t *offset) { ++ gentoo_proc_wrapper_t* wrapper_data=(gentoo_proc_wrapper_t*)(myfile->private_data); ++ int retval=0; ++ void *usebuffer=NULL; ++ ++ BUG_ON(*offset); ++ if (!wrapper_data->write_func) ++ return -EPERM; ++ ++ usebuffer=kmalloc(count, GFP_KERNEL); ++ if (!usebuffer) ++ return -ENOMEM; ++ if (copy_from_user(usebuffer, buffer, count)) { ++ printk(KERN_NOTICE "copy from user failed in amd drivers proc code\n"); ++ retval=-EFAULT; ++ goto out; ++ } ++ ++ retval=wrapper_data->write_func(myfile, buffer, count, wrapper_data->data); ++ *offset+=retval; ++out: ++ if (usebuffer) ++ kfree(usebuffer); ++ return retval; ++} ++static int gentoo_proc_wrapper_open(struct inode *myinode, struct file *myfile) { ++ myfile->private_data=PDE_DATA(myinode); ++ return generic_file_open(myinode, myfile); ++} ++struct file_operations gentoo_proc_fops = { ++ .read=gentoo_proc_wrapper_read, ++ .write=gentoo_proc_wrapper_write, ++ .open=gentoo_proc_wrapper_open, ++}; ++ ++static void *gentoo_proc_wrapper_data(read_proc_t *reader, write_proc_t *writer, void *mydata) { ++ gentoo_proc_wrapper_t *retval=kmalloc(sizeof(gentoo_proc_wrapper_t), GFP_KERNEL); ++ if (!retval) ++ return retval; ++ retval->read_func=reader; ++ retval->write_func=writer; ++ retval->data=mydata; ++ return retval; ++} ++ ++static struct proc_dir_entry *firegl_proc_init( device_t *dev, ++ int minor, ++ struct proc_dir_entry *root, ++ struct proc_dir_entry **dev_root, ++ kcl_proc_list_t *proc_list ) // proc_list must be terminated! ++{ ++ struct proc_dir_entry *ent; ++ char name[64]; ++ kcl_proc_list_t *list = proc_list; ++ void *tempdata; ++ KCL_DEBUG1(FN_FIREGL_PROC, "minor %d, proc_list 0x%08lx\n", minor, (unsigned long)proc_list); ++ if (!minor) ++ { ++ root = proc_mkdir("ati", NULL); ++ } ++ ++ if (!root) ++ { ++ KCL_DEBUG_ERROR("Cannot create /proc/ati\n"); ++ return NULL; ++ } ++ ++ if (minor == 0) ++ { ++ // Global major debice number entry ++ tempdata=gentoo_proc_wrapper_data((read_proc_t*)firegl_major_proc_read, NULL, NULL); ++ if (!tempdata) ++ return NULL; ++ ent = proc_create_data("major", S_IFREG|S_IRUGO, root, &gentoo_proc_fops, tempdata); ++ if (!ent) ++ { ++ remove_proc_entry("ati", NULL); ++ KCL_DEBUG_ERROR("Cannot create /proc/ati/major\n"); ++ return NULL; ++ } ++ } ++ ++ sprintf(name, "%d", minor); ++ *dev_root = proc_mkdir(name, root); ++ if (!*dev_root) { ++ remove_proc_entry("major", root); ++ remove_proc_entry("ati", NULL); ++ KCL_DEBUG_ERROR("Cannot create /proc/ati/%s\n", name); ++ return NULL; ++ } ++ ++ while (list->f || list->fops) ++ { ++ struct file_operations *my_fops = &gentoo_proc_fops; ++ if (list->fops) ++ { ++ my_fops = (struct file_operations*)list->fops; ++ tempdata=(dev->pubdev.signature == FGL_DEVICE_SIGNATURE)? firegl_find_device(minor) : (dev); ++ } ++ else { ++ BUG_ON(!list->f); ++ tempdata=gentoo_proc_wrapper_data((read_proc_t*)list->f, NULL, (dev->pubdev.signature == FGL_DEVICE_SIGNATURE)? firegl_find_device(minor) : (dev) ); ++ if (!tempdata) ++ return NULL; ++ } ++ //printk(KERN_NOTICE "name %s, dev %p, func %p, data %p\n", list->name, (dev->pubdev.signature == FGL_DEVICE_SIGNATURE)? firegl_find_device(minor) : (dev), list->f, tempdata); ++ ent = proc_create_data(list->name, S_IFREG|S_IRUGO, *dev_root, my_fops, tempdata); ++ ++ if (!ent) ++ { ++ KCL_DEBUG_ERROR("Cannot create /proc/ati/%s/%s\n", name, list->name); ++ while (proc_list != list) ++ { ++ remove_proc_entry(proc_list->name, *dev_root); ++ proc_list++; ++ } ++ remove_proc_entry(name, root); ++ if (!minor) ++ { ++ remove_proc_entry("major", root); ++ remove_proc_entry("ati", NULL); ++ } ++ return NULL; ++ } ++ ++ list++; ++ } ++ ++ if (minor == 0) ++ { ++ // Global debug entry, only create it once ++ tempdata=gentoo_proc_wrapper_data((read_proc_t*)firegl_debug_proc_read_wrap, (write_proc_t*)firegl_debug_proc_write_wrap, dev); ++ if (!tempdata) ++ return NULL; ++ ent=proc_create_data("debug", S_IFREG|S_IRUGO, root, &gentoo_proc_fops, tempdata); ++ if (!ent) ++ return NULL; ++ } ++ ++ return root; ++} ++#else + static struct proc_dir_entry *firegl_proc_init( device_t *dev, + int minor, + struct proc_dir_entry *root, +@@ -677,6 +873,7 @@ static struct proc_dir_entry *firegl_proc_init( device_t *dev, + + return root; + } ++#endif + + static int firegl_proc_cleanup( int minor, + struct proc_dir_entry *root, +@@ -6135,59 +6332,4 @@ void ATI_API_CALL KCL_fpu_end(void) + kernel_fpu_end(); + } + +-/** Create new directory entry under "/proc/ati/...." +- * Where +- * root_dir - Root directory. If NULL then we should use "/proc/ati" root. +- * name - Pointer to the name of directory +- * access - Access attribute. We could use it to disable access to the directory for everybody accept owner. +- * By default owner is root. +- * Return NULL if failure. Pointer to proc_dir_entry otherwise +- */ +-void * KCL_create_proc_dir(void *root_dir, const char *name, unsigned int access) +-{ +- struct proc_dir_entry *dir = NULL; +- +- if (root_dir == NULL) +- dir = create_proc_entry(name, S_IFDIR | access, firegl_stub_root); +- else +- dir = create_proc_entry(name, S_IFDIR | access, (struct proc_dir_entry *)root_dir); +- +- return dir; +-} +- +-/* Remove proc directory entry +- * root - Pointer to directory proc entry or NULL if for "/proc/ati" +- * name - Name to delete +- */ +-void KCL_remove_proc_dir_entry(void *root, const char *name) +-{ +- if (root == NULL) +- remove_proc_entry(name, firegl_stub_root); +- else +- remove_proc_entry(name, (struct proc_dir_entry *)root); +-} +- +- +-/* Create proc_entry under "root_dir" +- * read_fn - Function which will be called on read request +- * write_fn - Function which will be called on write request +- * private_data - Pointer to private data which will be passed +- */ +-void KCL_create_proc_entry(void *root_dir, const char *name, unsigned int access_mode, void *read_fn, void *write_fn, void *private_data) +-{ +- struct proc_dir_entry *ent = NULL; +- +- if (root_dir == NULL || name == NULL) +- return; +- +- ent = create_proc_entry(name, access_mode, (struct proc_dir_entry *)root_dir); +- +- if (ent) +- { +- ent->read_proc = (read_proc_t *)read_fn; +- ent->write_proc = (write_proc_t *)write_fn; +- ent->data = private_data; +- } +-} +- + #endif /* __KERNEL__ */ +-- +1.7.9.5 + From 966c69b052a651550e29a10094b638e8d6c96548 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Mon, 1 Jul 2013 23:18:48 +0300 Subject: [PATCH 10/61] xf86-video-nvidia: add support for kernel 3.10 --- .../patches.upstream/kernel-3.10-fix.patch | 605 ++++++++++++++++++ 1 file changed, 605 insertions(+) create mode 100644 packages/x11/driver/xf86-video-nvidia/patches.upstream/kernel-3.10-fix.patch diff --git a/packages/x11/driver/xf86-video-nvidia/patches.upstream/kernel-3.10-fix.patch b/packages/x11/driver/xf86-video-nvidia/patches.upstream/kernel-3.10-fix.patch new file mode 100644 index 0000000000..1f075f7121 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia/patches.upstream/kernel-3.10-fix.patch @@ -0,0 +1,605 @@ +# https://devtalk.nvidia.com/default/topic/543728/linux/building-nvidia-driver-on-kernel-3-9-0/post/3814531/#3814531 + +diff -ur -X - a/kernel/nv-i2c.c b/kernel/nv-i2c.c +--- a/kernel/nv-i2c.c 2013-04-26 00:22:30.000000000 -0400 ++++ b/kernel/nv-i2c.c 2013-05-13 05:20:55.571981365 -0400 +@@ -311,8 +311,6 @@ + BOOL NV_API_CALL nv_i2c_del_adapter(nv_state_t *nv, void *data) + { + struct i2c_adapter *pI2cAdapter = (struct i2c_adapter *)data; +- int osstatus = 0; +- BOOL wasReleased = FALSE; + + #if defined(KERNEL_2_4) + if (!NV_WEAK_SYMBOL_PRESENT(i2c_add_adapter)) +@@ -324,15 +322,10 @@ + if (!pI2cAdapter) return FALSE; + + // attempt release with the OS +- osstatus = i2c_del_adapter(pI2cAdapter); ++ i2c_del_adapter(pI2cAdapter); ++ os_free_mem(pI2cAdapter); + +- if (!osstatus) +- { +- os_free_mem(pI2cAdapter); +- wasReleased = TRUE; +- } +- +- return wasReleased; ++ return TRUE; + } + + #else // (defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)) +diff -ur -X - a/kernel/nv-procfs.c b/kernel/nv-procfs.c +--- a/kernel/nv-procfs.c 2013-04-26 00:22:30.000000000 -0400 ++++ b/kernel/nv-procfs.c 2013-05-22 04:52:45.229495748 -0400 +@@ -60,60 +60,41 @@ + __entry; \ + }) + +-#define NV_CREATE_PROC_FILE(name,parent,__read_proc, \ +- __write_proc,__fops,__data) \ +- ({ \ +- struct proc_dir_entry *__entry; \ +- int __mode = (S_IFREG | S_IRUGO); \ +- if ((NvUPtr)(__write_proc) != 0) \ +- __mode |= S_IWUSR; \ +- __entry = NV_CREATE_PROC_ENTRY(name, __mode, parent); \ +- if (__entry != NULL) \ +- { \ +- if ((NvUPtr)(__read_proc) != 0) \ +- __entry->read_proc = (__read_proc); \ +- if ((NvUPtr)(__write_proc) != 0) \ +- { \ +- __entry->write_proc = (__write_proc); \ +- __entry->proc_fops = (__fops); \ +- } \ +- __entry->data = (__data); \ +- } \ +- __entry; \ +- }) ++#define NV_PROC_RW (S_IFREG|S_IRUGO|S_IWUSR) ++#define NV_PROC_RO (S_IFREG|S_IRUGO) + + #define NV_CREATE_PROC_DIR(name,parent) \ + ({ \ + struct proc_dir_entry *__entry; \ + int __mode = (S_IFDIR | S_IRUGO | S_IXUGO); \ +- __entry = NV_CREATE_PROC_ENTRY(name, __mode, parent); \ ++ __entry = proc_mkdir_mode(name, __mode, parent); \ + __entry; \ + }) + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,9,255) ++static inline void *PDE_DATA(const struct inode *inode) { ++ return PDE(inode)->data; ++} ++#endif ++ + #define NV_PROC_WRITE_BUFFER_SIZE (64 * RM_PAGE_SIZE) + + static int +-nv_procfs_read_gpu_info( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data ++nv_procfs_show_gpu_info( ++ struct seq_file *m, ++ void *v + ) + { +- nv_state_t *nv = data; ++ nv_state_t *nv = m->private; + nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv); + struct pci_dev *dev = nvl->dev; + char *type, *fmt, tmpstr[NV_DEVICE_NAME_LENGTH]; +- int len = 0, status; ++ int status; + NvU8 *uuid; + NvU32 vbios_rev1, vbios_rev2, vbios_rev3, vbios_rev4, vbios_rev5; + NvU32 fpga_rev1, fpga_rev2, fpga_rev3; + nv_stack_t *sp = NULL; + +- *eof = 1; +- + NV_KMEM_CACHE_ALLOC_STACK(sp); + if (sp == NULL) + { +@@ -134,31 +115,31 @@ + if (rm_get_device_name(sp, nv, dev->device, dev->subsystem_vendor, + dev->subsystem_device, NV_DEVICE_NAME_LENGTH, + tmpstr) != RM_OK) +- { ++ { + strcpy (tmpstr, "Unknown"); + } + } + +- len += sprintf(page+len, "Model: \t\t %s\n", tmpstr); +- len += sprintf(page+len, "IRQ: \t\t %d\n", nv->interrupt_line); ++ seq_printf(m, "Model: \t\t %s\n", tmpstr); ++ seq_printf(m, "IRQ: \t\t %d\n", nv->interrupt_line); + + if (NV_IS_GVI_DEVICE(nv)) + { + status = rm_gvi_get_firmware_version(sp, nv, &fpga_rev1, &fpga_rev2, + &fpga_rev3); + if (status != RM_OK) +- len += sprintf(page+len, "Firmware: \t ????.??.??\n"); ++ seq_printf(m, "Firmware: \t ????.??.??\n"); + else + { + fmt = "Firmware: \t %x.%x.%x\n"; +- len += sprintf(page+len, fmt, fpga_rev1, fpga_rev2, fpga_rev3); ++ seq_printf(m, fmt, fpga_rev1, fpga_rev2, fpga_rev3); + } + } + else + { + if (rm_get_gpu_uuid(sp, nv, &uuid, NULL) == RM_OK) + { +- len += sprintf(page+len, "GPU UUID: \t %s\n", (char *)uuid); ++ seq_printf(m, "GPU UUID: \t %s\n", (char *)uuid); + os_free_mem(uuid); + } + +@@ -166,12 +147,12 @@ + &vbios_rev3, &vbios_rev4, + &vbios_rev5) != RM_OK) + { +- len += sprintf(page+len, "Video BIOS: \t ??.??.??.??.??\n"); ++ seq_printf(m, "Video BIOS: \t ??.??.??.??.??\n"); + } + else + { + fmt = "Video BIOS: \t %02x.%02x.%02x.%02x.%02x\n"; +- len += sprintf(page+len, fmt, vbios_rev1, vbios_rev2, vbios_rev3, ++ seq_printf(m, fmt, vbios_rev1, vbios_rev2, vbios_rev3, + vbios_rev4, vbios_rev5); + } + } +@@ -180,12 +161,12 @@ + type = "PCIe"; + else + type = "PCI"; +- len += sprintf(page+len, "Bus Type: \t %s\n", type); ++ seq_printf(m, "Bus Type: \t %s\n", type); + +- len += sprintf(page+len, "DMA Size: \t %d bits\n", ++ seq_printf(m, "DMA Size: \t %d bits\n", + nv_count_bits(dev->dma_mask)); +- len += sprintf(page+len, "DMA Mask: \t 0x%llx\n", dev->dma_mask); +- len += sprintf(page+len, "Bus Location: \t %04x:%02x.%02x.%x\n", ++ seq_printf(m, "DMA Mask: \t 0x%llx\n", dev->dma_mask); ++ seq_printf(m, "Bus Location: \t %04x:%02x.%02x.%x\n", + nv->domain, nv->bus, nv->slot, PCI_FUNC(dev->devfn)); + #if defined(DEBUG) + do +@@ -193,7 +174,7 @@ + int j; + for (j = 0; j < NV_GPU_NUM_BARS; j++) + { +- len += sprintf(page+len, "BAR%u: \t\t 0x%llx (%lluMB)\n", ++ seq_printf(m, "BAR%u: \t\t 0x%llx (%lluMB)\n", + j, nv->bars[j].address, (nv->bars[j].size >> 20)); + } + } while (0); +@@ -201,26 +182,120 @@ + + NV_KMEM_CACHE_FREE_STACK(sp); + +- return len; ++ return 0; + } + + static int +-nv_procfs_read_version( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data ++nv_procfs_open_gpu_info( ++ struct inode *inode, ++ struct file *file ++) ++{ ++ return single_open(file, nv_procfs_show_gpu_info, PDE_DATA(inode)); ++} ++ ++static const struct file_operations nv_procfs_gpu_info_fops = { ++ .owner = THIS_MODULE, ++ .open = nv_procfs_open_gpu_info, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int ++nv_procfs_show_version( ++ struct seq_file *m, ++ void *v ++) ++{ ++ seq_printf(m, "NVRM version: %s\n", pNVRM_ID); ++ seq_printf(m, "GCC version: %s\n", NV_COMPILER); ++ ++ return 0; ++} ++ ++static int ++nv_procfs_open_version( ++ struct inode *inode, ++ struct file *file ++) ++{ ++ return single_open(file, nv_procfs_show_version, NULL); ++} ++ ++static const struct file_operations nv_procfs_version_fops = { ++ .owner = THIS_MODULE, ++ .open = nv_procfs_open_version, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int ++nv_procfs_show_registry( ++ struct seq_file *m, ++ void *v ++) ++{ ++ nv_state_t *nv = m->private; ++ nv_linux_state_t *nvl = NULL; ++ char *registry_keys; ++ ++ if (nv != NULL) ++ nvl = NV_GET_NVL_FROM_NV_STATE(nv); ++ registry_keys = ((nvl != NULL) ? ++ nvl->registry_keys : nv_registry_keys); ++ ++ seq_printf(m, "Binary: \"%s\"\n", registry_keys); ++ ++ return 0; ++} ++ ++static ssize_t ++nv_procfs_write_registry( ++ struct file *file, ++ const char __user *buffer, ++ size_t count, ++ loff_t *pos + ) + { +- int len = 0; +- *eof = 1; ++ int status = 0; ++ nv_file_private_t *nvfp = NV_GET_FILE_PRIVATE(file); ++ char *proc_buffer; ++ unsigned long bytes_left; ++ ++ down(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_PROCFS]); ++ ++ bytes_left = (NV_PROC_WRITE_BUFFER_SIZE - nvfp->off - 1); ++ ++ if (count == 0) ++ { ++ status = -EINVAL; ++ goto done; ++ } ++ else if ((bytes_left == 0) || (count > bytes_left)) ++ { ++ status = -ENOSPC; ++ goto done; ++ } ++ ++ proc_buffer = &((char *)nvfp->data)[nvfp->off]; ++ ++ if (copy_from_user(proc_buffer, buffer, count)) ++ { ++ nv_printf(NV_DBG_ERRORS, "NVRM: failed to copy in proc data!\n"); ++ status = -EFAULT; ++ } ++ else ++ { ++ nvfp->proc_data = PDE_DATA(file->f_inode); ++ nvfp->off += count; ++ } + +- len += sprintf(page+len, "NVRM version: %s\n", pNVRM_ID); +- len += sprintf(page+len, "GCC version: %s\n", NV_COMPILER); ++done: ++ up(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_PROCFS]); + +- return len; ++ return ((status < 0) ? status : count); + } + + static int +@@ -233,7 +308,7 @@ + nv_stack_t *sp = NULL; + + if (0 == (file->f_mode & FMODE_WRITE)) +- return 0; ++ return single_open(file, nv_procfs_show_registry, PDE_DATA(inode)); + + nvfp = nv_alloc_file_private(); + if (nvfp == NULL) +@@ -282,6 +357,9 @@ + RM_STATUS rm_status; + int rc = 0; + ++ if (0 == (file->f_mode & FMODE_WRITE)) ++ return single_release(inode, file); ++ + nvfp = NV_GET_FILE_PRIVATE(file); + if (nvfp == NULL) + return 0; +@@ -346,122 +424,81 @@ + return rc; + } + +-static struct file_operations nv_procfs_registry_fops = { ++static const struct file_operations nv_procfs_registry_fops = { + .open = nv_procfs_open_registry, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = nv_procfs_write_registry, + .release = nv_procfs_close_registry, + }; + + static int +-nv_procfs_read_params( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data ++nv_procfs_show_params( ++ struct seq_file *m, ++ void *v + ) + { + unsigned int i; +- int len = 0; + nv_parm_t *entry; + +- *eof = 1; + + for (i = 0; (entry = &nv_parms[i])->name != NULL; i++) +- len += sprintf(page+len, "%s: %u\n", entry->name, *entry->data); ++ seq_printf(m, "%s: %u\n", entry->name, *entry->data); + +- len += sprintf(page+len, "RegistryDwords: \"%s\"\n", ++ seq_printf(m, "RegistryDwords: \"%s\"\n", + (NVreg_RegistryDwords != NULL) ? NVreg_RegistryDwords : ""); +- len += sprintf(page+len, "RmMsg: \"%s\"\n", ++ seq_printf(m, "RmMsg: \"%s\"\n", + (NVreg_RmMsg != NULL) ? NVreg_RmMsg : ""); + +- return len; ++ return 0; + } + + static int +-nv_procfs_read_registry( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data +-) ++nv_procfs_open_params( ++ struct inode *inode, ++ struct file *file ++) + { +- nv_state_t *nv = data; +- nv_linux_state_t *nvl = NULL; +- char *registry_keys; ++ return single_open(file, nv_procfs_show_params, NULL); ++} + +- if (nv != NULL) +- nvl = NV_GET_NVL_FROM_NV_STATE(nv); +- registry_keys = ((nvl != NULL) ? +- nvl->registry_keys : nv_registry_keys); ++static const struct file_operations nv_procfs_params_fops = { ++ .owner = THIS_MODULE, ++ .open = nv_procfs_open_params, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; + +- *eof = 1; +- return sprintf(page, "Binary: \"%s\"\n", registry_keys); +-} + + static int +-nv_procfs_write_registry( +- struct file *file, +- const char *buffer, +- unsigned long count, +- void *data ++nv_procfs_show_text_file( ++ struct seq_file *m, ++ void *v + ) + { +- int status = 0; +- nv_file_private_t *nvfp = NV_GET_FILE_PRIVATE(file); +- char *proc_buffer; +- unsigned long bytes_left; +- +- down(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_PROCFS]); +- +- bytes_left = (NV_PROC_WRITE_BUFFER_SIZE - nvfp->off - 1); ++ seq_printf(m, "%s", (char *)m->private); + +- if (count == 0) +- { +- status = -EINVAL; +- goto done; +- } +- else if ((bytes_left == 0) || (count > bytes_left)) +- { +- status = -ENOSPC; +- goto done; +- } +- +- proc_buffer = &((char *)nvfp->data)[nvfp->off]; +- +- if (copy_from_user(proc_buffer, buffer, count)) +- { +- nv_printf(NV_DBG_ERRORS, "NVRM: failed to copy in proc data!\n"); +- status = -EFAULT; +- } +- else +- { +- nvfp->proc_data = data; +- nvfp->off += count; +- } +- +-done: +- up(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_PROCFS]); +- +- return ((status < 0) ? status : (int)count); ++ return 0; + } + + static int +-nv_procfs_read_text_file( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data ++nv_procfs_open_text_file( ++ struct inode *inode, ++ struct file *file + ) + { +- *eof = 1; +- return sprintf(page, "%s", (char *)data); ++ return single_open(file, nv_procfs_show_text_file, PDE_DATA(inode)); + } + ++static const struct file_operations nv_procfs_text_fops = { ++ .owner = THIS_MODULE, ++ .open = nv_procfs_open_text_file, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ + static void + nv_procfs_add_text_file( + struct proc_dir_entry *parent, +@@ -469,22 +506,7 @@ + const char *text + ) + { +- NV_CREATE_PROC_FILE(filename, parent, +- nv_procfs_read_text_file, NULL, NULL, (void *)text); +-} +- +-static void nv_procfs_unregister_all(struct proc_dir_entry *entry) +-{ +- while (entry) +- { +- struct proc_dir_entry *next = entry->next; +- if (entry->subdir) +- nv_procfs_unregister_all(entry->subdir); +- remove_proc_entry(entry->name, entry->parent); +- if (entry == proc_nvidia) +- break; +- entry = next; +- } ++ proc_create_data(filename, NV_PROC_RO, parent, &nv_procfs_text_fops, (void *)text); + } + #endif + +@@ -513,26 +535,11 @@ + if (!proc_nvidia) + goto failed; + +- entry = NV_CREATE_PROC_FILE("params", proc_nvidia, +- nv_procfs_read_params, NULL, NULL, NULL); ++ entry = proc_create("params", NV_PROC_RO, proc_nvidia, &nv_procfs_params_fops); + if (!entry) + goto failed; + +- /* +- * entry->proc_fops originally points to a constant +- * structure, so to add more methods for the +- * binary registry write path, we need to replace the +- * said entry->proc_fops with a new fops structure. +- * However, in preparation for this, we need to preserve +- * the procfs read() and write() operations. +- */ +- nv_procfs_registry_fops.read = entry->proc_fops->read; +- nv_procfs_registry_fops.write = entry->proc_fops->write; +- +- entry = NV_CREATE_PROC_FILE("registry", proc_nvidia, +- nv_procfs_read_registry, +- nv_procfs_write_registry, +- &nv_procfs_registry_fops, NULL); ++ entry = proc_create("registry", NV_PROC_RW, proc_nvidia, &nv_procfs_registry_fops); + if (!entry) + goto failed; + +@@ -553,8 +560,7 @@ + + nv_procfs_add_text_file(proc_nvidia_patches, "README", __README_patches); + +- entry = NV_CREATE_PROC_FILE("version", proc_nvidia, +- nv_procfs_read_version, NULL, NULL, NULL); ++ entry = proc_create("version", NV_PROC_RO, proc_nvidia, &nv_procfs_version_fops); + if (!entry) + goto failed; + +@@ -571,15 +577,11 @@ + if (!proc_nvidia_gpu) + goto failed; + +- entry = NV_CREATE_PROC_FILE("information", proc_nvidia_gpu, +- nv_procfs_read_gpu_info, NULL, NULL, nv); ++ entry = proc_create_data("information", NV_PROC_RO, proc_nvidia_gpu, &nv_procfs_gpu_info_fops, nv); + if (!entry) + goto failed; + +- entry = NV_CREATE_PROC_FILE("registry", proc_nvidia_gpu, +- nv_procfs_read_registry, +- nv_procfs_write_registry, +- &nv_procfs_registry_fops, nv); ++ entry = proc_create_data("registry", NV_PROC_RW, proc_nvidia_gpu, &nv_procfs_registry_fops, nv); + if (!entry) + goto failed; + } +@@ -587,7 +589,7 @@ + return 0; + #if defined(CONFIG_PROC_FS) + failed: +- nv_procfs_unregister_all(proc_nvidia); ++ remove_proc_subtree("nvidia", proc_nvidia); + return -1; + #endif + } +@@ -595,6 +597,6 @@ + void nv_unregister_procfs(void) + { + #if defined(CONFIG_PROC_FS) +- nv_procfs_unregister_all(proc_nvidia); ++ remove_proc_subtree("nvidia", proc_nvidia); + #endif + } From 882061d0f4fdc6b1df10940d28949f668cac8baa Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 2 Jul 2013 15:09:28 +0200 Subject: [PATCH 11/61] RTL8188EU: use driver from https://github.com/lwfinger/rtl8188eu Signed-off-by: Stephan Raue --- packages/linux-drivers/RTL8188EU/meta | 6 +- .../RTL8188EU-use_kthread_run_v2.patch | 142 ------------------ 2 files changed, 4 insertions(+), 144 deletions(-) delete mode 100644 packages/linux-drivers/RTL8188EU/patches/RTL8188EU-use_kthread_run_v2.patch diff --git a/packages/linux-drivers/RTL8188EU/meta b/packages/linux-drivers/RTL8188EU/meta index 32c9be4eaf..52ae5e0011 100644 --- a/packages/linux-drivers/RTL8188EU/meta +++ b/packages/linux-drivers/RTL8188EU/meta @@ -19,11 +19,13 @@ ################################################################################ PKG_NAME="RTL8188EU" -PKG_VERSION="20130425" +# realtek: PKG_VERSION="20130425" +PKG_VERSION="fb786d0" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" -PKG_SITE="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PFid=48&Level=5&Conn=4&ProdID=274&DownTypeID=3&GetDown=false&Downloads=true" +# realtek: PKG_SITE="http://www.realtek.com.tw/downloads/downloadsView.aspx?Langid=1&PFid=48&Level=5&Conn=4&ProdID=274&DownTypeID=3&GetDown=false&Downloads=true" +PKG_SITE="https://github.com/lwfinger/rtl8188eu" PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_DEPENDS="" PKG_BUILD_DEPENDS="toolchain linux" diff --git a/packages/linux-drivers/RTL8188EU/patches/RTL8188EU-use_kthread_run_v2.patch b/packages/linux-drivers/RTL8188EU/patches/RTL8188EU-use_kthread_run_v2.patch deleted file mode 100644 index 5f71e1e10d..0000000000 --- a/packages/linux-drivers/RTL8188EU/patches/RTL8188EU-use_kthread_run_v2.patch +++ /dev/null @@ -1,142 +0,0 @@ -diff -Naur RTL8188EU-20130425/core/rtw_mp.c RTL8188EU-20130425.patch/core/rtw_mp.c ---- RTL8188EU-20130425/core/rtw_mp.c 2013-04-27 07:20:29.000000000 +0200 -+++ RTL8188EU-20130425.patch/core/rtw_mp.c 2013-04-27 15:46:36.416055469 +0200 -@@ -1219,7 +1219,8 @@ - - //3 6. start thread - #ifdef PLATFORM_LINUX -- pmp_priv->tx.PktTxThread = kernel_thread(mp_xmit_packet_thread, pmp_priv, CLONE_FS|CLONE_FILES); -+ if(!start_kthread(&pmp_priv->tx.PktTxThread, mp_xmit_packet_thread, pmp_priv, "8188eu-mp-xmit")) -+ DBG_871X("Create PktTx Thread Fail !!!!!\n"); - #endif - #ifdef PLATFORM_FREEBSD - { -@@ -1228,9 +1229,9 @@ - pmp_priv->tx.PktTxThread = kproc_kthread_add(mp_xmit_packet_thread, pmp_priv, - &p, &td, RFHIGHPID, 0, "MPXmitThread", "MPXmitThread"); - } -+if (pmp_priv->tx.PktTxThread < 0) -+ DBG_871X("Create PktTx Thread Fail !!!!!\n"); - #endif -- if (pmp_priv->tx.PktTxThread < 0) -- DBG_871X("Create PktTx Thread Fail !!!!!\n"); - - } - -diff -Naur RTL8188EU-20130425/include/osdep_service.h RTL8188EU-20130425.patch/include/osdep_service.h ---- RTL8188EU-20130425/include/osdep_service.h 2013-04-27 07:20:29.000000000 +0200 -+++ RTL8188EU-20130425.patch/include/osdep_service.h 2013-04-27 15:59:42.647641402 +0200 -@@ -813,6 +813,9 @@ - #include - #endif - -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)) -+ #include -+#endif - - #ifdef CONFIG_USB_HCI - typedef struct urb * PURB; -@@ -846,8 +849,12 @@ - //typedef u32 _irqL; - typedef unsigned long _irqL; - typedef struct net_device * _nic_hdl; -- -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) - typedef pid_t _thread_hdl_; -+#else -+ typedef struct task_struct * _thread_hdl_; -+#endif - typedef int thread_return; - typedef void* thread_context; - -@@ -1394,7 +1401,7 @@ - static __inline void thread_enter(char *name) - { - #ifdef PLATFORM_LINUX -- daemonize("%s", name); -+ //daemonize("%s", name); - allow_signal(SIGTERM); - #endif - #ifdef PLATFORM_FREEBSD -@@ -1677,4 +1684,8 @@ - - #endif - -+#ifdef PLATFORM_LINUX -+extern int start_kthread(_thread_hdl_ *t_hdl, int (*threadfn)(void *data), -+ void *data, const char *name); -+#endif - -diff -Naur RTL8188EU-20130425/include/rtw_recv.h RTL8188EU-20130425.patch/include/rtw_recv.h ---- RTL8188EU-20130425/include/rtw_recv.h 2013-04-27 07:20:29.000000000 +0200 -+++ RTL8188EU-20130425.patch/include/rtw_recv.h 2013-04-27 16:01:59.026051453 +0200 -@@ -658,7 +658,9 @@ - //from any given member of recv_frame. - // rxmem indicates the any member/address in recv_frame - -- return (union recv_frame*)(((SIZE_PTR)rxmem >> RXFRAME_ALIGN) << RXFRAME_ALIGN); -+ //return (union recv_frame*)(((uint)rxmem>>RXFRAME_ALIGN) <> RXFRAME_ALIGN) << RXFRAME_ALIGN); -+ return (union recv_frame*)(((ulong)rxmem>>RXFRAME_ALIGN) <xmitThread = kernel_thread(rtw_xmit_thread, padapter, CLONE_FS|CLONE_FILES); -- if(padapter->xmitThread < 0) -+ if(!start_kthread(&padapter->xmitThread, rtw_xmit_thread, padapter, "8188eu-xmit")) - _status = _FAIL; - #endif - - #ifdef CONFIG_RECV_THREAD_MODE -- padapter->recvThread = kernel_thread(rtw_recv_thread, padapter, CLONE_FS|CLONE_FILES); -- if(padapter->recvThread < 0) -+ if(!start_kthread(&padapter->recvThread, recv_thread, padapter, "8188eu-recv")) - _status = _FAIL; - #endif - -- padapter->cmdThread = kernel_thread(rtw_cmd_thread, padapter, CLONE_FS|CLONE_FILES); -- if(padapter->cmdThread < 0) -+ if(!start_kthread(&padapter->cmdThread, rtw_cmd_thread, padapter, "8188eu-cmd")) - _status = _FAIL; - else - _rtw_down_sema(&padapter->cmdpriv.terminate_cmdthread_sema); //wait for cmd_thread to run - - - #ifdef CONFIG_EVENT_THREAD_MODE -- padapter->evtThread = kernel_thread(event_thread, padapter, CLONE_FS|CLONE_FILES); -- if(padapter->evtThread < 0) -+ if(!start_kthread(&padapter->evtThread, event_thread, padapter, "8188eu-evt")) - _status = _FAIL; - #endif - -diff -Naur RTL8188EU-20130425/os_dep/osdep_service.c RTL8188EU-20130425.patch/os_dep/osdep_service.c ---- RTL8188EU-20130425/os_dep/osdep_service.c 2013-04-27 07:20:29.000000000 +0200 -+++ RTL8188EU-20130425.patch/os_dep/osdep_service.c 2013-04-27 15:38:15.965258008 +0200 -@@ -1920,3 +1920,19 @@ - #endif - } - -+#ifdef PLATFORM_LINUX -+int start_kthread(_thread_hdl_ *t_hdl, int (*threadfn)(void *data), -+ void *data, const char *name) -+{ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)) -+ *t_hdl = kernel_thread(threadfn, data, CLONE_FS|CLONE_FILES); -+ if(*t_hdl < 0) -+#else -+ *t_hdl = kthread_run(threadfn, data, name); -+ if(IS_ERR(*t_hdl)) -+#endif -+ return 0; -+ return -1; -+} -+#endif -+ From 2b5df6664ab527206859391d7ff73ecd82354de2 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 2 Jul 2013 17:20:51 +0200 Subject: [PATCH 12/61] projects/*/linux: update kernel config for linux-3.10 Signed-off-by: Stephan Raue --- projects/ARCTIC_MC/linux/linux.x86_64.conf | 817 ++++++++++++++++----- projects/ATV/linux/linux.i386.conf | 174 +++-- projects/Fusion/linux/linux.i386.conf | 181 +++-- projects/Fusion/linux/linux.x86_64.conf | 198 +++-- projects/Generic/linux/linux.i386.conf | 183 +++-- projects/Generic/linux/linux.x86_64.conf | 200 +++-- projects/Generic_OSS/linux/linux.i386.conf | 183 +++-- projects/ION/linux/linux.i386.conf | 179 +++-- projects/ION/linux/linux.x86_64.conf | 194 +++-- projects/Intel/linux/linux.i386.conf | 180 +++-- projects/Intel/linux/linux.x86_64.conf | 195 +++-- projects/Ultra/linux/linux.x86_64.conf | 191 +++-- projects/Virtual/linux/linux.i386.conf | 183 +++-- projects/Virtual/linux/linux.x86_64.conf | 200 +++-- 14 files changed, 2070 insertions(+), 1188 deletions(-) diff --git a/projects/ARCTIC_MC/linux/linux.x86_64.conf b/projects/ARCTIC_MC/linux/linux.x86_64.conf index 534fdde772..25de06c3ef 100644 --- a/projects/ARCTIC_MC/linux/linux.x86_64.conf +++ b/projects/ARCTIC_MC/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 3.9.8 Kernel Configuration +# Linux/x86_64 3.10.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -14,13 +14,14 @@ CONFIG_HAVE_LATENCYTOP_SUPPORT=y CONFIG_MMU=y CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_GENERIC_ISA_DMA=y CONFIG_GENERIC_BUG=y CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -92,14 +93,20 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # # CPU/Task time and stats accounting # -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y # CONFIG_IRQ_TIME_ACCOUNTING is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set @@ -111,19 +118,25 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_TREE_RCU=y # CONFIG_PREEMPT_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_RCU_USER_QS is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_RCU_USER_QS=y +CONFIG_CONTEXT_TRACKING_FORCE=y CONFIG_RCU_FANOUT=32 CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_NOCB_CPU is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y CONFIG_ARCH_WANTS_PROT_NUMA_PROT_NONE=y +CONFIG_ARCH_USES_NUMA_PROT_NONE=y +CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y +CONFIG_NUMA_BALANCING=y # CONFIG_CGROUPS is not set # CONFIG_CHECKPOINT_RESTORE is not set # CONFIG_NAMESPACES is not set @@ -144,16 +157,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y -# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_HAVE_UID16=y CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y +# CONFIG_UID16 is not set +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -162,6 +177,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -171,7 +187,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -206,12 +221,16 @@ CONFIG_HAVE_ARCH_JUMP_LABEL=y CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y CONFIG_HAVE_CMPXCHG_LOCAL=y CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y CONFIG_HAVE_ARCH_SECCOMP_FILTER=y CONFIG_SECCOMP_FILTER=y CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y # # GCOV-based kernel profiling @@ -256,6 +275,7 @@ CONFIG_LDM_PARTITION=y # CONFIG_KARMA_PARTITION is not set CONFIG_EFI_PARTITION=y # CONFIG_SYSV68_PARTITION is not set +CONFIG_BLOCK_COMPAT=y # # IO Schedulers @@ -283,29 +303,29 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_EXTENDED_PLATFORM is not set CONFIG_X86_INTEL_LPSS=y CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_MK8 is not set # CONFIG_MPSC is not set # CONFIG_MCORE2 is not set -CONFIG_MATOM=y -# CONFIG_GENERIC_CPU is not set +# CONFIG_MATOM is not set +CONFIG_GENERIC_CPU=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 CONFIG_X86_L1_CACHE_SHIFT=6 -CONFIG_X86_USE_PPRO_CHECKSUM=y CONFIG_X86_TSC=y CONFIG_X86_CMPXCHG64=y CONFIG_X86_CMOV=y CONFIG_X86_MINIMUM_CPU_FAMILY=64 CONFIG_X86_DEBUGCTLMSR=y -CONFIG_PROCESSOR_SELECT=y +# CONFIG_PROCESSOR_SELECT is not set CONFIG_CPU_SUP_INTEL=y -# CONFIG_CPU_SUP_AMD is not set -# CONFIG_CPU_SUP_CENTAUR is not set +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_CENTAUR=y CONFIG_HPET_TIMER=y CONFIG_HPET_EMULATE_RTC=y CONFIG_DMI=y +CONFIG_GART_IOMMU=y # CONFIG_CALGARY_IOMMU is not set CONFIG_SWIOTLB=y CONFIG_IOMMU_HELPER=y @@ -323,7 +343,7 @@ CONFIG_X86_IO_APIC=y # CONFIG_I8K is not set CONFIG_MICROCODE=y CONFIG_MICROCODE_INTEL=y -# CONFIG_MICROCODE_AMD is not set +CONFIG_MICROCODE_AMD=y CONFIG_MICROCODE_OLD_INTERFACE=y CONFIG_MICROCODE_INTEL_LIB=y CONFIG_MICROCODE_INTEL_EARLY=y @@ -333,7 +353,12 @@ CONFIG_X86_CPUID=y CONFIG_ARCH_PHYS_ADDR_T_64BIT=y CONFIG_ARCH_DMA_ADDR_T_64BIT=y CONFIG_DIRECT_GBPAGES=y -# CONFIG_NUMA is not set +CONFIG_NUMA=y +CONFIG_AMD_NUMA=y +CONFIG_X86_64_ACPI_NUMA=y +CONFIG_NODES_SPAN_OTHER_NODES=y +# CONFIG_NUMA_EMU is not set +CONFIG_NODES_SHIFT=6 CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y @@ -342,6 +367,7 @@ CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_SELECT_MEMORY_MODEL=y CONFIG_SPARSEMEM_MANUAL=y CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y @@ -350,6 +376,7 @@ CONFIG_SPARSEMEM_VMEMMAP=y CONFIG_HAVE_MEMBLOCK=y CONFIG_HAVE_MEMBLOCK_NODE_MAP=y CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_MOVABLE_NODE=y # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set # CONFIG_MEMORY_HOTPLUG is not set CONFIG_PAGEFLAGS_EXTENDED=y @@ -376,7 +403,7 @@ CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 CONFIG_X86_PAT=y CONFIG_ARCH_USES_PG_UNCACHED=y -# CONFIG_ARCH_RANDOM is not set +CONFIG_ARCH_RANDOM=y # CONFIG_X86_SMAP is not set CONFIG_EFI=y # CONFIG_EFI_STUB is not set @@ -396,10 +423,12 @@ CONFIG_PHYSICAL_ALIGN=0x1000000 CONFIG_HOTPLUG_CPU=y # CONFIG_BOOTPARAM_HOTPLUG_CPU0 is not set # CONFIG_DEBUG_HOTPLUG_CPU0 is not set +# CONFIG_COMPAT_VDSO is not set CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="root=/dev/ram0 rdinit=/init" +CONFIG_CMDLINE="root=/dev/ram0 rdinit=/init i915.i915_enable_rc6=0" # CONFIG_CMDLINE_OVERRIDE is not set CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_USE_PERCPU_NUMA_NODE_ID=y # # Power management and ACPI options @@ -424,6 +453,7 @@ CONFIG_ACPI_SLEEP=y # CONFIG_ACPI_AC is not set CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_VIDEO=y CONFIG_ACPI_FAN=y # CONFIG_ACPI_DOCK is not set CONFIG_ACPI_I2C=y @@ -431,6 +461,7 @@ CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_PROCESSOR_AGGREGATOR=y CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_NUMA=y # CONFIG_ACPI_CUSTOM_DSDT is not set # CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set CONFIG_ACPI_BLACKLIST_YEAR=0 @@ -466,10 +497,12 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y # # x86 CPU frequency scaling drivers # -# CONFIG_X86_INTEL_PSTATE is not set +CONFIG_X86_INTEL_PSTATE=y # CONFIG_X86_PCC_CPUFREQ is not set CONFIG_X86_ACPI_CPUFREQ=y -# CONFIG_X86_POWERNOW_K8 is not set +CONFIG_X86_ACPI_CPUFREQ_CPB=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set CONFIG_X86_P4_CLOCKMOD=m @@ -518,7 +551,8 @@ CONFIG_HT_IRQ=y # CONFIG_PCI_PASID is not set CONFIG_PCI_IOAPIC=y CONFIG_PCI_LABEL=y -# CONFIG_ISA_DMA_API is not set +CONFIG_ISA_DMA_API=y +CONFIG_AMD_NB=y # CONFIG_PCCARD is not set # CONFIG_HOTPLUG_PCI is not set # CONFIG_RAPIDIO is not set @@ -527,14 +561,23 @@ CONFIG_PCI_LABEL=y # Executable file formats / Emulations # CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y # CONFIG_COREDUMP is not set -# CONFIG_IA32_EMULATION is not set +CONFIG_IA32_EMULATION=y +# CONFIG_IA32_AOUT is not set +# CONFIG_X86_X32 is not set +CONFIG_COMPAT=y +CONFIG_COMPAT_FOR_U64_ALIGNMENT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_KEYS_COMPAT=y CONFIG_HAVE_TEXT_POKE_SMP=y CONFIG_X86_DEV_DMA_OPS=y CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y # # Networking options @@ -554,6 +597,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -703,6 +747,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -793,7 +839,7 @@ CONFIG_STANDALONE=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="rtl_nic/rtl8105e-1.fw rtl_nic/rtl8106e-1.fw rtl_nic/rtl8168d-1.fw rtl_nic/rtl8168d-2.fw rtl_nic/rtl8168e-1.fw rtl_nic/rtl8168e-2.fw rtl_nic/rtl8168e-3.fw rtl_nic/rtl8168f-1.fw rtl_nic/rtl8168f-2.fw rtl_nic/rtl8168g-1.fw rtl_nic/rtl8402-1.fw rtl_nic/rtl8411-1.fw" +CONFIG_EXTRA_FIRMWARE="bnx2/bnx2-mips-06-6.2.1.fw bnx2/bnx2-mips-09-6.2.1a.fw bnx2/bnx2-rv2p-06-6.0.15.fw bnx2/bnx2-rv2p-09-6.0.17.fw bnx2/bnx2-rv2p-09ax-6.0.17.fw tigon/tg3.bin tigon/tg3_tso5.bin tigon/tg3_tso.bin rtl_nic/rtl8105e-1.fw rtl_nic/rtl8106e-1.fw rtl_nic/rtl8168d-1.fw rtl_nic/rtl8168d-2.fw rtl_nic/rtl8168e-1.fw rtl_nic/rtl8168e-2.fw rtl_nic/rtl8168e-3.fw rtl_nic/rtl8168f-1.fw rtl_nic/rtl8168f-2.fw rtl_nic/rtl8168g-1.fw rtl_nic/rtl8402-1.fw rtl_nic/rtl8411-1.fw" CONFIG_EXTRA_FIRMWARE_DIR="firmware" CONFIG_FW_LOADER_USER_HELPER=y # CONFIG_DEBUG_DRIVER is not set @@ -817,6 +863,7 @@ CONFIG_PNP=y # CONFIG_PNPACPI=y CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set @@ -843,9 +890,10 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # # Misc devices # -# CONFIG_SENSORS_LIS3LV02D is not set +CONFIG_SENSORS_LIS3LV02D=m # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -864,10 +912,10 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -889,6 +937,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -948,7 +997,9 @@ CONFIG_ISCSI_BOOT_SYSFS=y # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC94XX is not set -# CONFIG_SCSI_MVSAS is not set +CONFIG_SCSI_MVSAS=y +# CONFIG_SCSI_MVSAS_DEBUG is not set +# CONFIG_SCSI_MVSAS_TASKLET is not set # CONFIG_SCSI_MVUMI is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set @@ -960,13 +1011,16 @@ CONFIG_ISCSI_BOOT_SYSFS=y # CONFIG_SCSI_MPT3SAS is not set # CONFIG_SCSI_UFSHCD is not set # CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set # CONFIG_VMWARE_PVSCSI is not set # CONFIG_LIBFC is not set # CONFIG_LIBFCOE is not set # CONFIG_FCOE is not set # CONFIG_FCOE_FNIC is not set # CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_ISCI is not set # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set @@ -1021,20 +1075,20 @@ CONFIG_ATA_PIIX=y # CONFIG_SATA_MV is not set CONFIG_SATA_NV=y # CONFIG_SATA_PROMISE is not set -# CONFIG_SATA_SIL is not set -# CONFIG_SATA_SIS is not set +CONFIG_SATA_SIL=y +CONFIG_SATA_SIS=y # CONFIG_SATA_SVW is not set -# CONFIG_SATA_ULI is not set -# CONFIG_SATA_VIA is not set +CONFIG_SATA_ULI=y +CONFIG_SATA_VIA=y # CONFIG_SATA_VITESSE is not set # # PATA SFF controllers with BMDMA # -# CONFIG_PATA_ALI is not set -# CONFIG_PATA_AMD is not set +CONFIG_PATA_ALI=y +CONFIG_PATA_AMD=y # CONFIG_PATA_ARTOP is not set -# CONFIG_PATA_ATIIXP is not set +CONFIG_PATA_ATIIXP=y # CONFIG_PATA_ATP867X is not set # CONFIG_PATA_CMD64X is not set # CONFIG_PATA_CS5520 is not set @@ -1063,7 +1117,7 @@ CONFIG_PATA_JMICRON=y # CONFIG_PATA_SCH is not set # CONFIG_PATA_SERVERWORKS is not set # CONFIG_PATA_SIL680 is not set -# CONFIG_PATA_SIS is not set +CONFIG_PATA_SIS=y # CONFIG_PATA_TOSHIBA is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_VIA is not set @@ -1092,7 +1146,10 @@ CONFIG_ATA_GENERIC=y # # IEEE 1394 (FireWire) support # -# CONFIG_FIREWIRE is not set +CONFIG_FIREWIRE=m +CONFIG_FIREWIRE_OHCI=m +CONFIG_FIREWIRE_SBP2=m +# CONFIG_FIREWIRE_NET is not set # CONFIG_FIREWIRE_NOSY is not set # CONFIG_I2O is not set # CONFIG_MACINTOSH_DRIVERS is not set @@ -1126,52 +1183,108 @@ CONFIG_TUN=m # CONFIG_NET_DSA_MV88E6131 is not set # CONFIG_NET_DSA_MV88E6123_61_65 is not set CONFIG_ETHERNET=y -# CONFIG_NET_VENDOR_3COM is not set +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=y +# CONFIG_TYPHOON is not set # CONFIG_NET_VENDOR_ADAPTEC is not set # CONFIG_NET_VENDOR_ALTEON is not set -# CONFIG_NET_VENDOR_AMD is not set -# CONFIG_NET_VENDOR_ATHEROS is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +CONFIG_PCNET32=y +CONFIG_NET_VENDOR_ATHEROS=y +CONFIG_ATL2=y +CONFIG_ATL1=y +CONFIG_ATL1E=y +CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set -# CONFIG_NET_VENDOR_BROADCOM is not set +CONFIG_NET_VENDOR_BROADCOM=y +CONFIG_B44=y +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI=y +CONFIG_BNX2=y +CONFIG_CNIC=y +CONFIG_TIGON3=y +# CONFIG_BNX2X is not set # CONFIG_NET_VENDOR_BROCADE is not set # CONFIG_NET_CALXEDA_XGMAC is not set # CONFIG_NET_VENDOR_CHELSIO is not set # CONFIG_NET_VENDOR_CISCO is not set # CONFIG_DNET is not set -# CONFIG_NET_VENDOR_DEC is not set +CONFIG_NET_VENDOR_DEC=y +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +# CONFIG_TULIP is not set +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +CONFIG_ULI526X=y # CONFIG_NET_VENDOR_DLINK is not set # CONFIG_NET_VENDOR_EMULEX is not set # CONFIG_NET_VENDOR_EXAR is not set # CONFIG_NET_VENDOR_HP is not set -# CONFIG_NET_VENDOR_INTEL is not set -# CONFIG_IP1000 is not set -# CONFIG_JME is not set -# CONFIG_NET_VENDOR_MARVELL is not set -# CONFIG_NET_VENDOR_MELLANOX is not set +CONFIG_NET_VENDOR_INTEL=y +CONFIG_E100=y +CONFIG_E1000=y +CONFIG_E1000E=y +CONFIG_IGB=y +CONFIG_IGB_HWMON=y +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +CONFIG_NET_VENDOR_I825XX=y +CONFIG_IP1000=y +CONFIG_JME=y +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +CONFIG_SKGE=y +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKGE_GENESIS=y +CONFIG_SKY2=y +# CONFIG_SKY2_DEBUG is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set # CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MYRI is not set # CONFIG_FEALNX is not set # CONFIG_NET_VENDOR_NATSEMI is not set -# CONFIG_NET_VENDOR_NVIDIA is not set +CONFIG_NET_VENDOR_NVIDIA=y +CONFIG_FORCEDETH=y # CONFIG_NET_VENDOR_OKI is not set # CONFIG_ETHOC is not set # CONFIG_NET_PACKET_ENGINE is not set -# CONFIG_NET_VENDOR_QLOGIC is not set +CONFIG_NET_VENDOR_QLOGIC=y +CONFIG_QLA3XXX=y +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set CONFIG_NET_VENDOR_REALTEK=y # CONFIG_8139CP is not set -# CONFIG_8139TOO is not set +CONFIG_8139TOO=y +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set CONFIG_R8169=y # CONFIG_NET_VENDOR_RDC is not set # CONFIG_NET_VENDOR_SEEQ is not set # CONFIG_NET_VENDOR_SILAN is not set -# CONFIG_NET_VENDOR_SIS is not set +CONFIG_NET_VENDOR_SIS=y +CONFIG_SIS900=y +CONFIG_SIS190=y # CONFIG_SFC is not set # CONFIG_NET_VENDOR_SMSC is not set # CONFIG_NET_VENDOR_STMICRO is not set # CONFIG_NET_VENDOR_SUN is not set # CONFIG_NET_VENDOR_TEHUTI is not set # CONFIG_NET_VENDOR_TI is not set -# CONFIG_NET_VENDOR_VIA is not set +CONFIG_NET_VENDOR_VIA=y +CONFIG_VIA_RHINE=y +# CONFIG_VIA_RHINE_MMIO is not set +CONFIG_VIA_VELOCITY=y # CONFIG_NET_VENDOR_WIZNET is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -1181,19 +1294,19 @@ CONFIG_PHYLIB=y # # MII PHY device drivers # -# CONFIG_AT803X_PHY is not set -# CONFIG_AMD_PHY is not set -# CONFIG_MARVELL_PHY is not set +CONFIG_AT803X_PHY=y +CONFIG_AMD_PHY=y +CONFIG_MARVELL_PHY=y # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set # CONFIG_LXT_PHY is not set # CONFIG_CICADA_PHY is not set # CONFIG_VITESSE_PHY is not set # CONFIG_SMSC_PHY is not set -# CONFIG_BROADCOM_PHY is not set +CONFIG_BROADCOM_PHY=y # CONFIG_BCM87XX_PHY is not set # CONFIG_ICPLUS_PHY is not set -# CONFIG_REALTEK_PHY is not set +CONFIG_REALTEK_PHY=y # CONFIG_NATIONAL_PHY is not set # CONFIG_STE10XP is not set # CONFIG_LSI_ET1011C_PHY is not set @@ -1219,6 +1332,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1245,8 +1359,12 @@ CONFIG_USB_NET_RNDIS_HOST=m # CONFIG_USB_SIERRA_NET is not set # CONFIG_USB_VL600 is not set CONFIG_WLAN=y -# CONFIG_LIBERTAS_THINFIRM is not set -# CONFIG_ATMEL is not set +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +# CONFIG_AIRO is not set +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m # CONFIG_AT76C50X_USB is not set # CONFIG_PRISM54 is not set CONFIG_USB_ZD1201=m @@ -1260,48 +1378,117 @@ CONFIG_RTL8187_LEDS=y CONFIG_ATH_COMMON=m CONFIG_ATH_CARDS=m # CONFIG_ATH_DEBUG is not set -# CONFIG_ATH5K is not set -# CONFIG_ATH5K_PCI is not set -# CONFIG_ATH9K is not set -# CONFIG_ATH9K_HTC is not set +CONFIG_ATH5K=m +# CONFIG_ATH5K_DEBUG is not set +CONFIG_ATH5K_PCI=y +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_BTCOEX_SUPPORT=y +CONFIG_ATH9K=m +CONFIG_ATH9K_PCI=y +CONFIG_ATH9K_AHB=y +# CONFIG_ATH9K_DEBUGFS is not set +# CONFIG_ATH9K_LEGACY_RATE_CONTROL is not set +CONFIG_ATH9K_HTC=m +# CONFIG_ATH9K_HTC_DEBUGFS is not set CONFIG_CARL9170=m CONFIG_CARL9170_LEDS=y CONFIG_CARL9170_WPC=y -# CONFIG_ATH6KL is not set +CONFIG_ATH6KL=m +# CONFIG_ATH6KL_SDIO is not set +CONFIG_ATH6KL_USB=m +# CONFIG_ATH6KL_DEBUG is not set CONFIG_AR5523=m # CONFIG_WIL6210 is not set -# CONFIG_B43 is not set -# CONFIG_B43LEGACY is not set -# CONFIG_BRCMFMAC is not set +CONFIG_B43=m +CONFIG_B43_SSB=y +CONFIG_B43_PCI_AUTOSELECT=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_N=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_LEDS=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_LEDS=y +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y +CONFIG_BRCMFMAC_USB=y +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set CONFIG_HOSTAP=m CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y # CONFIG_HOSTAP_PLX is not set # CONFIG_HOSTAP_PCI is not set -# CONFIG_IPW2100 is not set -# CONFIG_IPW2200 is not set -# CONFIG_IWLWIFI is not set -# CONFIG_IWL4965 is not set -# CONFIG_IWL3945 is not set -# CONFIG_LIBERTAS is not set +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_LIBIPW=m +# CONFIG_LIBIPW_DEBUG is not set +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y + +# +# Debugging Options +# +# CONFIG_IWLWIFI_DEBUG is not set +# CONFIG_IWLWIFI_P2P is not set +CONFIG_IWLEGACY=m +CONFIG_IWL4965=m +CONFIG_IWL3945=m + +# +# iwl3945 / iwl4965 Debugging Options +# +# CONFIG_IWLEGACY_DEBUG is not set +CONFIG_LIBERTAS=m +# CONFIG_LIBERTAS_USB is not set +# CONFIG_LIBERTAS_SDIO is not set +# CONFIG_LIBERTAS_DEBUG is not set +# CONFIG_LIBERTAS_MESH is not set # CONFIG_HERMES is not set CONFIG_P54_COMMON=m CONFIG_P54_USB=m -# CONFIG_P54_PCI is not set +CONFIG_P54_PCI=m CONFIG_P54_LEDS=y CONFIG_RT2X00=m -# CONFIG_RT2400PCI is not set -# CONFIG_RT2500PCI is not set -# CONFIG_RT61PCI is not set -# CONFIG_RT2800PCI is not set +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT61PCI=m +CONFIG_RT2800PCI=m +CONFIG_RT2800PCI_RT33XX=y +CONFIG_RT2800PCI_RT35XX=y +CONFIG_RT2800PCI_RT53XX=y +CONFIG_RT2800PCI_RT3290=y CONFIG_RT2500USB=m CONFIG_RT73USB=m CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m +CONFIG_RT2X00_LIB_MMIO=m +CONFIG_RT2X00_LIB_PCI=m CONFIG_RT2X00_LIB_USB=m CONFIG_RT2X00_LIB=m CONFIG_RT2X00_LIB_FIRMWARE=y @@ -1310,11 +1497,13 @@ CONFIG_RT2X00_LIB_LEDS=y # CONFIG_RT2X00_DEBUG is not set CONFIG_RTLWIFI=m # CONFIG_RTLWIFI_DEBUG is not set -# CONFIG_RTL8192CE is not set -# CONFIG_RTL8192SE is not set -# CONFIG_RTL8192DE is not set +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set +CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set @@ -1332,8 +1521,8 @@ CONFIG_ZD1211RW=m # CONFIG_INPUT=y CONFIG_INPUT_FF_MEMLESS=y -# CONFIG_INPUT_POLLDEV is not set -# CONFIG_INPUT_SPARSEKMAP is not set +CONFIG_INPUT_POLLDEV=y +CONFIG_INPUT_SPARSEKMAP=y # CONFIG_INPUT_MATRIXKMAP is not set # @@ -1431,6 +1620,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1513,7 +1703,7 @@ CONFIG_I2C_BOARDINFO=y CONFIG_I2C_CHARDEV=y # CONFIG_I2C_MUX is not set CONFIG_I2C_HELPER_AUTO=y -CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOBIT=y # # I2C Hardware Bus support @@ -1530,14 +1720,14 @@ CONFIG_I2C_ALGOBIT=m CONFIG_I2C_I801=y CONFIG_I2C_ISCH=y # CONFIG_I2C_ISMT is not set -# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_PIIX4=y CONFIG_I2C_NFORCE2=y # CONFIG_I2C_NFORCE2_S4985 is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_VIA is not set -# CONFIG_I2C_VIAPRO is not set +CONFIG_I2C_VIA=y +CONFIG_I2C_VIAPRO=y # # ACPI drivers @@ -1573,12 +1763,25 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # # PPS support # -# CONFIG_PPS is not set +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set # # PPS generators support @@ -1587,7 +1790,7 @@ CONFIG_I2C_INTEL_MID=y # # PTP clock support # -# CONFIG_PTP_1588_CLOCK is not set +CONFIG_PTP_1588_CLOCK=y # # Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. @@ -1638,9 +1841,9 @@ CONFIG_HWMON_VID=y # CONFIG_SENSORS_ADT7470 is not set # CONFIG_SENSORS_ADT7475 is not set # CONFIG_SENSORS_ASC7621 is not set -# CONFIG_SENSORS_K8TEMP is not set -# CONFIG_SENSORS_K10TEMP is not set -# CONFIG_SENSORS_FAM15H_POWER is not set +CONFIG_SENSORS_K8TEMP=m +CONFIG_SENSORS_K10TEMP=m +CONFIG_SENSORS_FAM15H_POWER=m # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS620 is not set @@ -1655,7 +1858,7 @@ CONFIG_HWMON_VID=y # CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_HIH6130 is not set CONFIG_SENSORS_CORETEMP=m -# CONFIG_SENSORS_IT87 is not set +CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_JC42 is not set # CONFIG_SENSORS_LINEAGE is not set # CONFIG_SENSORS_LM63 is not set @@ -1674,6 +1877,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1685,6 +1889,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1742,7 +1947,7 @@ CONFIG_THERMAL_GOV_STEP_WISE=y # CONFIG_THERMAL_GOV_USER_SPACE is not set CONFIG_CPU_THERMAL=y # CONFIG_THERMAL_EMULATION is not set -# CONFIG_INTEL_POWERCLAMP is not set +CONFIG_INTEL_POWERCLAMP=m CONFIG_WATCHDOG=y CONFIG_WATCHDOG_CORE=y CONFIG_WATCHDOG_NOWAYOUT=y @@ -1801,13 +2006,12 @@ CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # -CONFIG_SSB=m +CONFIG_SSB=y CONFIG_SSB_SPROM=y +CONFIG_SSB_BLOCKIO=y CONFIG_SSB_PCIHOST_POSSIBLE=y CONFIG_SSB_PCIHOST=y -# CONFIG_SSB_B43_PCI_BRIDGE is not set -CONFIG_SSB_SDIOHOST_POSSIBLE=y -# CONFIG_SSB_SDIOHOST is not set +CONFIG_SSB_B43_PCI_BRIDGE=y # CONFIG_SSB_SILENT is not set # CONFIG_SSB_DEBUG is not set CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y @@ -1823,58 +2027,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_RTSX_PCI is not set -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -1892,7 +2099,9 @@ CONFIG_VIDEO_V4L2=m # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set CONFIG_VIDEO_TUNER=m CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_DMA_SG=m CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DVB=m CONFIG_VIDEOBUF2_CORE=m CONFIG_VIDEOBUF2_MEMOPS=m CONFIG_VIDEOBUF2_VMALLOC=m @@ -1921,15 +2130,15 @@ CONFIG_IR_SANYO_DECODER=m CONFIG_IR_MCE_KBD_DECODER=m CONFIG_RC_DEVICES=y CONFIG_RC_ATI_REMOTE=m -# CONFIG_IR_ENE is not set -# CONFIG_IR_IMON is not set +CONFIG_IR_ENE=m +CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m CONFIG_IR_ITE_CIR=m -# CONFIG_IR_FINTEK is not set -# CONFIG_IR_NUVOTON is not set +CONFIG_IR_FINTEK=m +CONFIG_IR_NUVOTON=m CONFIG_IR_REDRAT3=m CONFIG_IR_STREAMZAP=m -# CONFIG_IR_WINBOND_CIR is not set +CONFIG_IR_WINBOND_CIR=m CONFIG_IR_IGUANA=m CONFIG_IR_TTUSBIR=m # CONFIG_RC_LOOPBACK is not set @@ -1989,7 +2198,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2016,43 +2224,111 @@ CONFIG_VIDEO_EM28XX=m CONFIG_VIDEO_EM28XX_ALSA=m CONFIG_VIDEO_EM28XX_DVB=m CONFIG_VIDEO_EM28XX_RC=m -# CONFIG_MEDIA_PCI_SUPPORT is not set +CONFIG_MEDIA_PCI_SUPPORT=y + +# +# Media capture/analog TV support +# +# CONFIG_VIDEO_IVTV is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_MXB is not set + +# +# Media capture/analog/hybrid TV support +# +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_CX18_ALSA=m +CONFIG_VIDEO_CX23885=m +CONFIG_MEDIA_ALTERA_CI=m +# CONFIG_VIDEO_CX25821 is not set +CONFIG_VIDEO_CX88=m +# CONFIG_VIDEO_CX88_ALSA is not set +# CONFIG_VIDEO_CX88_BLACKBIRD is not set +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88_MPEG=m +CONFIG_VIDEO_BT848=m +CONFIG_DVB_BT8XX=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_RC=y +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7164=m + +# +# Media digital TV PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET_CORE=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +# CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG is not set +# CONFIG_DVB_PLUTO2 is not set +CONFIG_DVB_DM1105=m +# CONFIG_DVB_PT1 is not set +CONFIG_MANTIS_CORE=m +CONFIG_DVB_MANTIS=m +# CONFIG_DVB_HOPPER is not set +CONFIG_DVB_NGENE=m +CONFIG_DVB_DDBRIDGE=m # # Supported MMC/SDIO adapters # CONFIG_SMS_SDIO_DRV=m + +# +# Supported FireWire (IEEE 1394) Adapters +# +CONFIG_DVB_FIREDTV=m +CONFIG_DVB_FIREDTV_INPUT=y CONFIG_MEDIA_COMMON_OPTIONS=y # # common driver options # CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m CONFIG_SAA716X_SUPPORT=y CONFIG_SAA716X_CORE=m CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # # Audio decoders, processors and mixers # +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TDA7432=m CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS5345=m CONFIG_VIDEO_CS53L32A=m CONFIG_VIDEO_WM8775=m # # RDS decoders # +CONFIG_VIDEO_SAA6588=m # # Video decoders @@ -2089,7 +2365,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2100,6 +2375,7 @@ CONFIG_MEDIA_TUNER_MT20XX=m CONFIG_MEDIA_TUNER_MT2060=m CONFIG_MEDIA_TUNER_MT2063=m CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MT2131=m CONFIG_MEDIA_TUNER_QT1010=m CONFIG_MEDIA_TUNER_XC2028=m CONFIG_MEDIA_TUNER_XC5000=m @@ -2116,13 +2392,15 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends # CONFIG_DVB_CX24120=m CONFIG_DVB_STB0899=m -# CONFIG_DVB_CXD2099 is not set +CONFIG_DVB_CXD2099=m CONFIG_DVB_STB6100=m CONFIG_DVB_STV090x=m CONFIG_DVB_STV6110x=m @@ -2132,12 +2410,16 @@ CONFIG_DVB_STV6110x=m # CONFIG_DVB_DRXK=m CONFIG_DVB_TDA18271C2DD=m +CONFIG_DVB_STV0367DD=m +CONFIG_DVB_TDA18212DD=m # # DVB-S (satellite) frontends # +CONFIG_DVB_CX24110=m CONFIG_DVB_CX24123=m CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10036=m CONFIG_DVB_ZL10039=m CONFIG_DVB_S5H1420=m CONFIG_DVB_STV0288=m @@ -2145,22 +2427,33 @@ CONFIG_DVB_STB6000=m CONFIG_DVB_STV0299=m CONFIG_DVB_STV6110=m CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA8083=m CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_VES1X93=m CONFIG_DVB_TUNER_ITD1000=m CONFIG_DVB_TUNER_CX24113=m CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m CONFIG_DVB_CX24116=m CONFIG_DVB_M88DS3103=m +CONFIG_DVB_M88DC2800=m CONFIG_DVB_SI21XX=m CONFIG_DVB_TS2020=m CONFIG_DVB_DS3000=m +CONFIG_DVB_MB86A16=m CONFIG_DVB_TDA10071=m # # DVB-T (terrestrial) frontends # +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m CONFIG_DVB_CX22702=m CONFIG_DVB_DRXD=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m CONFIG_DVB_MT352=m CONFIG_DVB_ZL10353=m CONFIG_DVB_DIB3000MB=m @@ -2170,6 +2463,7 @@ CONFIG_DVB_DIB7000P=m CONFIG_DVB_TDA10048=m CONFIG_DVB_AF9013=m CONFIG_DVB_EC100=m +CONFIG_DVB_STV0367=m CONFIG_DVB_CXD2820R=m CONFIG_DVB_RTL2830=m CONFIG_DVB_RTL2832=m @@ -2177,6 +2471,8 @@ CONFIG_DVB_RTL2832=m # # DVB-C (cable) frontends # +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m CONFIG_DVB_TDA10023=m CONFIG_DVB_STV0297=m @@ -2184,6 +2480,8 @@ CONFIG_DVB_STV0297=m # ATSC (North American/Korean Terrestrial/Cable DTV) frontends # CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m CONFIG_DVB_BCM3510=m CONFIG_DVB_LGDT330X=m CONFIG_DVB_LGDT3305=m @@ -2198,6 +2496,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2211,11 +2510,13 @@ CONFIG_DVB_TUNER_DIB0090=m # CONFIG_DVB_LNBP21=m CONFIG_DVB_LNBP22=m +CONFIG_DVB_ISL6405=m CONFIG_DVB_ISL6421=m CONFIG_DVB_ISL6423=m CONFIG_DVB_A8293=m CONFIG_DVB_LGS8GXX=m CONFIG_DVB_ATBM8830=m +CONFIG_DVB_TDA665x=m CONFIG_DVB_IX2505V=m CONFIG_DVB_IT913X_FE=m CONFIG_DVB_M88RS2000=m @@ -2230,15 +2531,46 @@ CONFIG_DVB_AF9033=m # Graphics support # CONFIG_AGP=y +# CONFIG_AGP_AMD64 is not set CONFIG_AGP_INTEL=y # CONFIG_AGP_SIS is not set -# CONFIG_AGP_VIA is not set +CONFIG_AGP_VIA=y CONFIG_VGA_ARB=y CONFIG_VGA_ARB_MAX_GPUS=16 -# CONFIG_VGA_SWITCHEROO is not set -# CONFIG_DRM is not set +CONFIG_VGA_SWITCHEROO=y +CONFIG_DRM=y +CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_TTM=m + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_R128 is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_I810 is not set +CONFIG_DRM_I915=y +CONFIG_DRM_I915_KMS=y +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_SIS is not set +# CONFIG_DRM_VIA is not set +# CONFIG_DRM_SAVAGE is not set +CONFIG_DRM_VMWGFX=m +# CONFIG_DRM_VMWGFX_FBCON is not set +# CONFIG_DRM_GMA500 is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y +CONFIG_HDMI=y CONFIG_FB=y # CONFIG_FIRMWARE_EDID is not set # CONFIG_FB_DDC is not set @@ -2252,7 +2584,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set +CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2279,7 +2611,6 @@ CONFIG_FB_EFI=y # CONFIG_FB_RIVA is not set # CONFIG_FB_I740 is not set # CONFIG_FB_LE80578 is not set -# CONFIG_FB_INTEL is not set # CONFIG_FB_MATROX is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set @@ -2308,7 +2639,17 @@ CONFIG_FB_EFI=y # CONFIG_FB_BROADSHEET is not set # CONFIG_FB_AUO_K190X is not set # CONFIG_EXYNOS_VIDEO is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_LCD_CLASS_DEVICE is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_BACKLIGHT_APPLE is not set +# CONFIG_BACKLIGHT_SAHARA is not set +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630 is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set # # Console display driver support @@ -2328,8 +2669,8 @@ CONFIG_SOUND=y # CONFIG_SOUND_OSS_CORE is not set CONFIG_SND=y CONFIG_SND_TIMER=y -CONFIG_SND_PCM=y -CONFIG_SND_HWDEP=y +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m CONFIG_SND_RAWMIDI=m CONFIG_SND_JACK=y # CONFIG_SND_SEQUENCER is not set @@ -2349,13 +2690,17 @@ CONFIG_SND_DMA_SGBUF=y # CONFIG_SND_OPL4_LIB_SEQ is not set # CONFIG_SND_SBAWE_SEQ is not set # CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_AC97_CODEC=m # CONFIG_SND_DRIVERS is not set CONFIG_SND_PCI=y # CONFIG_SND_AD1889 is not set # CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALS4000 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ASIHPI is not set -# CONFIG_SND_ATIIXP is not set +CONFIG_SND_ATIIXP=m # CONFIG_SND_ATIIXP_MODEM is not set # CONFIG_SND_AU8810 is not set # CONFIG_SND_AU8820 is not set @@ -2363,13 +2708,15 @@ CONFIG_SND_PCI=y # CONFIG_SND_AW2 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_OXYGEN is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_OXYGEN=m # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS5530 is not set # CONFIG_SND_CS5535AUDIO is not set -# CONFIG_SND_CTXFI is not set +CONFIG_SND_CTXFI=m # CONFIG_SND_DARLA20 is not set # CONFIG_SND_GINA20 is not set # CONFIG_SND_LAYLA20 is not set @@ -2384,14 +2731,15 @@ CONFIG_SND_PCI=y # CONFIG_SND_INDIGODJ is not set # CONFIG_SND_INDIGOIOX is not set # CONFIG_SND_INDIGODJX is not set -# CONFIG_SND_EMU10K1 is not set -# CONFIG_SND_EMU10K1X is not set +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m # CONFIG_SND_ENS1370 is not set # CONFIG_SND_ENS1371 is not set # CONFIG_SND_ES1938 is not set # CONFIG_SND_ES1968 is not set # CONFIG_SND_FM801 is not set -CONFIG_SND_HDA_INTEL=y +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDA_DSP_LOADER=y CONFIG_SND_HDA_PREALLOC_SIZE=64 CONFIG_SND_HDA_HWDEP=y CONFIG_SND_HDA_RECONFIG=y @@ -2400,23 +2748,24 @@ CONFIG_SND_HDA_INPUT_BEEP_MODE=1 CONFIG_SND_HDA_INPUT_JACK=y CONFIG_SND_HDA_PATCH_LOADER=y CONFIG_SND_HDA_CODEC_REALTEK=y -# CONFIG_SND_HDA_CODEC_ANALOG is not set -# CONFIG_SND_HDA_CODEC_SIGMATEL is not set -# CONFIG_SND_HDA_CODEC_VIA is not set +CONFIG_SND_HDA_CODEC_ANALOG=y +CONFIG_SND_HDA_CODEC_SIGMATEL=y +CONFIG_SND_HDA_CODEC_VIA=y CONFIG_SND_HDA_CODEC_HDMI=y -# CONFIG_SND_HDA_CODEC_CIRRUS is not set -# CONFIG_SND_HDA_CODEC_CONEXANT is not set -# CONFIG_SND_HDA_CODEC_CA0110 is not set -# CONFIG_SND_HDA_CODEC_CA0132 is not set -# CONFIG_SND_HDA_CODEC_CMEDIA is not set -# CONFIG_SND_HDA_CODEC_SI3054 is not set +CONFIG_SND_HDA_CODEC_CIRRUS=y +CONFIG_SND_HDA_CODEC_CONEXANT=y +CONFIG_SND_HDA_CODEC_CA0110=y +CONFIG_SND_HDA_CODEC_CA0132=y +CONFIG_SND_HDA_CODEC_CA0132_DSP=y +CONFIG_SND_HDA_CODEC_CMEDIA=y +CONFIG_SND_HDA_CODEC_SI3054=y CONFIG_SND_HDA_GENERIC=y CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 # CONFIG_SND_HDSP is not set # CONFIG_SND_HDSPM is not set # CONFIG_SND_ICE1712 is not set -# CONFIG_SND_ICE1724 is not set -# CONFIG_SND_INTEL8X0 is not set +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m # CONFIG_SND_INTEL8X0M is not set # CONFIG_SND_KORG1212 is not set # CONFIG_SND_LOLA is not set @@ -2433,7 +2782,7 @@ CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 # CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set -# CONFIG_SND_VIRTUOSO is not set +CONFIG_SND_VIRTUOSO=m # CONFIG_SND_VX222 is not set # CONFIG_SND_YMFPCI is not set CONFIG_SND_USB=y @@ -2443,8 +2792,13 @@ CONFIG_SND_USB_AUDIO=m # CONFIG_SND_USB_CAIAQ is not set # CONFIG_SND_USB_US122L is not set # CONFIG_SND_USB_6FIRE is not set +CONFIG_SND_FIREWIRE=y +# CONFIG_SND_FIREWIRE_SPEAKERS is not set +# CONFIG_SND_ISIGHT is not set +# CONFIG_SND_SCS1X is not set # CONFIG_SND_SOC is not set # CONFIG_SOUND_PRIME is not set +CONFIG_AC97_BUS=m # # HID support @@ -2461,6 +2815,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2543,12 +2898,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2562,13 +2916,14 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_HCD_SSB is not set # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2576,7 +2931,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2614,6 +2968,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2669,6 +3025,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2699,20 +3056,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -2738,11 +3083,13 @@ CONFIG_MMC_SDHCI_PCI=m # CONFIG_MMC_SDHCI_PLTFM is not set # CONFIG_MMC_SDHCI_PXAV3 is not set # CONFIG_MMC_SDHCI_PXAV2 is not set +# CONFIG_MMC_WBSD is not set # CONFIG_MMC_TIFM_SD is not set # CONFIG_MMC_CB710 is not set # CONFIG_MMC_VIA_SDMMC is not set # CONFIG_MMC_VUB300 is not set # CONFIG_MMC_USHC is not set +CONFIG_MMC_REALTEK_PCI=m CONFIG_MEMSTICK=m # CONFIG_MEMSTICK_DEBUG is not set @@ -2758,6 +3105,7 @@ CONFIG_MEMSTICK=m # CONFIG_MEMSTICK_TIFM_MS is not set CONFIG_MEMSTICK_JMICRON_38X=m # CONFIG_MEMSTICK_R592 is not set +CONFIG_MEMSTICK_REALTEK_PCI=m CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y @@ -2770,20 +3118,22 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set # CONFIG_LEDS_BD2802 is not set # CONFIG_LEDS_INTEL_SS4200 is not set +# CONFIG_LEDS_DELL_NETBOOKS is not set # CONFIG_LEDS_TCA6507 is not set # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -2795,6 +3145,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -2870,7 +3221,16 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_RTC_DRV_HID_SENSOR_TIME is not set # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set +CONFIG_UIO=y +# CONFIG_UIO_CIF is not set +# CONFIG_UIO_PDRV is not set +# CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_DMEM_GENIRQ is not set +# CONFIG_UIO_AEC is not set +# CONFIG_UIO_SERCOS3 is not set +# CONFIG_UIO_PCI_GENERIC is not set +# CONFIG_UIO_NETX is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -2881,7 +3241,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -2891,7 +3250,7 @@ CONFIG_STAGING=y # CONFIG_ECHO is not set # CONFIG_COMEDI is not set # CONFIG_ASUS_OLED is not set -# CONFIG_R8187SE is not set +CONFIG_R8187SE=m CONFIG_RTL8192U=m # CONFIG_RTLLIB is not set CONFIG_R8712U=m @@ -2904,9 +3263,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -2924,13 +3283,13 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m # CONFIG_LIRC_IMON is not set # CONFIG_LIRC_SASEM is not set -# CONFIG_LIRC_SERIAL is not set +CONFIG_LIRC_SERIAL=m +CONFIG_LIRC_SERIAL_TRANSMITTER=y # CONFIG_LIRC_SIR is not set CONFIG_LIRC_XBOX=m # CONFIG_LIRC_ZILOG is not set @@ -2947,7 +3306,43 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_BPCTL is not set # CONFIG_CED1401 is not set # CONFIG_DGRP is not set -# CONFIG_X86_PLATFORM_DEVICES is not set +# CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set +CONFIG_X86_PLATFORM_DEVICES=y +# CONFIG_ACER_WMI is not set +# CONFIG_ACERHDF is not set +# CONFIG_ASUS_LAPTOP is not set +# CONFIG_CHROMEOS_LAPTOP is not set +# CONFIG_DELL_WMI is not set +# CONFIG_DELL_WMI_AIO is not set +# CONFIG_FUJITSU_LAPTOP is not set +# CONFIG_FUJITSU_TABLET is not set +# CONFIG_AMILO_RFKILL is not set +CONFIG_HP_ACCEL=m +CONFIG_HP_WMI=m +# CONFIG_MSI_LAPTOP is not set +# CONFIG_PANASONIC_LAPTOP is not set +# CONFIG_COMPAL_LAPTOP is not set +# CONFIG_SONY_LAPTOP is not set +# CONFIG_IDEAPAD_LAPTOP is not set +# CONFIG_THINKPAD_ACPI is not set +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_INTEL_MENLOW is not set +CONFIG_ACPI_WMI=m +# CONFIG_MSI_WMI is not set +# CONFIG_TOPSTAR_LAPTOP is not set +# CONFIG_ACPI_TOSHIBA is not set +# CONFIG_TOSHIBA_BT_RFKILL is not set +# CONFIG_ACPI_CMPC is not set +# CONFIG_INTEL_IPS is not set +# CONFIG_IBM_RTL is not set +# CONFIG_XO15_EBOOK is not set +# CONFIG_SAMSUNG_LAPTOP is not set +# CONFIG_MXM_WMI is not set +# CONFIG_INTEL_OAKTRAIL is not set +# CONFIG_SAMSUNG_Q10 is not set +# CONFIG_APPLE_GMUX is not set +# CONFIG_PVPANIC is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -2973,7 +3368,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -2982,13 +3376,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -2997,6 +3391,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3024,11 +3423,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3111,6 +3513,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3269,6 +3672,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3286,6 +3691,7 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_RBTREE_TEST is not set # CONFIG_INTERVAL_TREE_TEST is not set # CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set +# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set # CONFIG_DYNAMIC_DEBUG is not set # CONFIG_DMA_API_DEBUG is not set # CONFIG_ATOMIC64_SELFTEST is not set @@ -3293,6 +3699,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3305,6 +3712,7 @@ CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_DEBUG_NX_TEST is not set # CONFIG_DEBUG_TLBFLUSH is not set +# CONFIG_IOMMU_DEBUG is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -3319,7 +3727,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3381,6 +3788,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3402,6 +3810,8 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y # CONFIG_CRYPTO_SHA1_SSSE3 is not set +# CONFIG_CRYPTO_SHA256_SSSE3 is not set +# CONFIG_CRYPTO_SHA512_SSSE3 is not set CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3421,6 +3831,7 @@ CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAMELLIA_X86_64 is not set # CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set # CONFIG_CRYPTO_CAST6 is not set @@ -3434,6 +3845,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set # CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_TWOFISH_X86_64 is not set @@ -3508,4 +3920,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/ATV/linux/linux.i386.conf b/projects/ATV/linux/linux.i386.conf index 4b8ac6697b..fbcee0ff3c 100644 --- a/projects/ATV/linux/linux.i386.conf +++ b/projects/ATV/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/i386 3.9.8 Kernel Configuration +# Linux/i386 3.10.0 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -20,7 +20,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -87,6 +86,9 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -132,18 +134,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -152,6 +154,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -161,7 +164,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -277,7 +279,7 @@ CONFIG_ZONE_DMA=y CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y # CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_M486 is not set @@ -557,6 +559,7 @@ CONFIG_ISA_DMA_API=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set @@ -583,6 +586,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -732,6 +736,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_BQL=y # @@ -869,6 +875,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -887,10 +894,10 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -912,6 +919,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1251,6 +1259,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1342,6 +1351,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_USB=m @@ -1356,6 +1366,7 @@ CONFIG_RTLWIFI=m # CONFIG_RTL8192SE is not set # CONFIG_RTL8192DE is not set # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set # CONFIG_WL_TI is not set CONFIG_ZD1211RW=m @@ -1456,6 +1467,7 @@ CONFIG_INPUT_MISC=y CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1599,6 +1611,11 @@ CONFIG_I2C_I801=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1731,58 +1748,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_RTSX_PCI is not set -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -# CONFIG_LPC_SCH is not set -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -1897,7 +1917,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -1936,15 +1955,18 @@ CONFIG_MEDIA_COMMON_OPTIONS=y # CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m # CONFIG_SAA716X_SUPPORT is not set CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -1993,7 +2015,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2020,6 +2041,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2102,6 +2125,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2162,7 +2186,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2382,6 +2405,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2464,10 +2488,10 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2480,17 +2504,16 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set # CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2528,6 +2551,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2583,6 +2608,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2613,20 +2639,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set @@ -2642,6 +2656,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -2651,11 +2666,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -2667,6 +2682,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -2743,6 +2759,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -2753,7 +2770,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -2776,9 +2792,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set # CONFIG_VT6656 is not set # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -2796,7 +2812,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -2819,6 +2834,8 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set CONFIG_ZCACHE=y +# CONFIG_ZCACHE_DEBUG is not set +# CONFIG_USB_DWC2 is not set # CONFIG_X86_PLATFORM_DEVICES is not set # @@ -2838,7 +2855,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -2846,13 +2862,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -2861,6 +2877,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -2888,11 +2909,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -2975,6 +2999,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3130,6 +3155,8 @@ CONFIG_ARCH_WANT_FRAME_POINTERS=y # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3154,6 +3181,7 @@ CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y # CONFIG_KMEMCHECK is not set +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3166,6 +3194,7 @@ CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_DEBUG_NX_TEST is not set CONFIG_DOUBLEFAULT=y +# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -3180,7 +3209,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3241,6 +3269,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3357,4 +3386,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Fusion/linux/linux.i386.conf b/projects/Fusion/linux/linux.i386.conf index f00687ecf1..9b016d15fc 100644 --- a/projects/Fusion/linux/linux.i386.conf +++ b/projects/Fusion/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/i386 3.9.8 Kernel Configuration +# Linux/i386 3.10.0 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -20,7 +20,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -91,6 +90,9 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -141,18 +143,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -161,6 +163,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -170,7 +173,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -289,7 +291,7 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_INTEL_LPSS is not set # CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_M486 is not set @@ -503,6 +505,7 @@ CONFIG_X86_ACPI_CPUFREQ_CPB=y # CONFIG_X86_POWERNOW_K6 is not set # CONFIG_X86_POWERNOW_K7 is not set # CONFIG_X86_POWERNOW_K8 is not set +CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_GX_SUSPMOD is not set # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_SPEEDSTEP_ICH is not set @@ -574,6 +577,7 @@ CONFIG_AMD_NB=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y @@ -600,6 +604,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -749,6 +754,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -890,6 +897,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_LIS3LV02D=m # CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -908,10 +916,10 @@ CONFIG_SENSORS_LIS3LV02D=m # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -933,6 +941,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1189,6 +1198,7 @@ CONFIG_NET_VENDOR_ATHEROS=y # CONFIG_ATL1 is not set # CONFIG_ATL1E is not set CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y # CONFIG_B44 is not set @@ -1286,6 +1296,7 @@ CONFIG_SLHC=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1354,7 +1365,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set CONFIG_B43LEGACY=m @@ -1378,6 +1388,7 @@ CONFIG_HOSTAP_FIRMWARE_NVRAM=y CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1413,6 +1424,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1429,6 +1441,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1547,6 +1560,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1691,6 +1705,11 @@ CONFIG_I2C_PIIX4=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1800,6 +1819,7 @@ CONFIG_SENSORS_FAM15H_POWER=y # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1811,6 +1831,7 @@ CONFIG_SENSORS_FAM15H_POWER=y # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1948,58 +1969,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=m -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -# CONFIG_LPC_SCH is not set -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2116,7 +2140,6 @@ CONFIG_DVB_USB_CINERGY_T2=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2214,6 +2237,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2223,11 +2247,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2280,7 +2306,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2308,6 +2333,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2410,6 +2437,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2473,7 +2501,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2692,6 +2719,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2774,12 +2802,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2793,13 +2820,13 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2807,7 +2834,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2845,6 +2871,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2900,6 +2928,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2930,20 +2959,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set @@ -2959,6 +2976,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -2969,11 +2987,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -2985,6 +3003,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3061,6 +3080,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3071,7 +3091,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3094,9 +3113,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3114,7 +3133,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3138,6 +3156,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACERHDF is not set # CONFIG_ASUS_LAPTOP is not set @@ -3162,6 +3181,7 @@ CONFIG_ACPI_WMI=m # CONFIG_XO15_EBOOK is not set # CONFIG_MXM_WMI is not set # CONFIG_SAMSUNG_Q10 is not set +# CONFIG_PVPANIC is not set # # Hardware Spinlock drivers @@ -3180,7 +3200,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3188,13 +3207,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3203,6 +3222,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3230,11 +3254,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3317,6 +3344,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3476,6 +3504,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3500,6 +3530,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3512,6 +3543,7 @@ CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_DEBUG_NX_TEST is not set CONFIG_DOUBLEFAULT=y +# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -3526,7 +3558,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3588,6 +3619,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3704,4 +3736,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Fusion/linux/linux.x86_64.conf b/projects/Fusion/linux/linux.x86_64.conf index 73eaffd180..4a52821d5e 100644 --- a/projects/Fusion/linux/linux.x86_64.conf +++ b/projects/Fusion/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 3.9.8 Kernel Configuration +# Linux/x86_64 3.10.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -20,7 +20,6 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -92,15 +91,19 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # # CPU/Task time and stats accounting # -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set -# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set # CONFIG_TASKSTATS is not set @@ -111,13 +114,16 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_TREE_RCU=y # CONFIG_PREEMPT_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_RCU_USER_QS is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_RCU_USER_QS=y +CONFIG_CONTEXT_TRACKING_FORCE=y CONFIG_RCU_FANOUT=32 CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_NOCB_CPU is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 @@ -144,18 +150,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -164,6 +170,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -173,7 +180,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -289,7 +295,7 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_EXTENDED_PLATFORM is not set # CONFIG_X86_INTEL_LPSS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set CONFIG_MK8=y @@ -476,6 +482,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_X86_ACPI_CPUFREQ=y CONFIG_X86_ACPI_CPUFREQ_CPB=y # CONFIG_X86_POWERNOW_K8 is not set +CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_P4_CLOCKMOD is not set @@ -535,6 +542,7 @@ CONFIG_AMD_NB=y CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y # CONFIG_COREDUMP is not set @@ -568,6 +576,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -717,6 +726,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -858,6 +869,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_LIS3LV02D=m # CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -876,10 +888,10 @@ CONFIG_SENSORS_LIS3LV02D=m # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -901,6 +913,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1152,6 +1165,7 @@ CONFIG_NET_VENDOR_ATHEROS=y # CONFIG_ATL1 is not set # CONFIG_ATL1E is not set CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y # CONFIG_B44 is not set @@ -1249,6 +1263,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1316,7 +1331,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set CONFIG_B43LEGACY=m @@ -1340,6 +1354,7 @@ CONFIG_HOSTAP_FIRMWARE_NVRAM=y CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1375,6 +1390,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1391,6 +1407,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1508,6 +1525,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1648,6 +1666,11 @@ CONFIG_I2C_PIIX4=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1757,6 +1780,7 @@ CONFIG_SENSORS_FAM15H_POWER=y # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1768,6 +1792,7 @@ CONFIG_SENSORS_FAM15H_POWER=y # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1904,58 +1929,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=m -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -# CONFIG_LPC_SCH is not set -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2072,7 +2100,6 @@ CONFIG_DVB_USB_CINERGY_T2=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2170,6 +2197,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2179,11 +2207,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2236,7 +2266,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2264,6 +2293,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2366,6 +2397,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2423,7 +2455,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2639,6 +2670,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2721,12 +2753,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2740,13 +2771,13 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2754,7 +2785,6 @@ CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2792,6 +2822,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2847,6 +2879,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2877,20 +2910,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set @@ -2906,6 +2927,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -2916,11 +2938,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -2932,6 +2954,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3008,6 +3031,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3018,7 +3042,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3041,9 +3064,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3061,7 +3084,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3085,6 +3107,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACERHDF is not set # CONFIG_ASUS_LAPTOP is not set @@ -3108,6 +3131,7 @@ CONFIG_ACPI_WMI=m # CONFIG_XO15_EBOOK is not set # CONFIG_MXM_WMI is not set # CONFIG_SAMSUNG_Q10 is not set +# CONFIG_PVPANIC is not set # # Hardware Spinlock drivers @@ -3125,7 +3149,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3134,13 +3157,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3149,6 +3172,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3176,11 +3204,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3263,6 +3294,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3421,6 +3453,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3446,6 +3480,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3473,7 +3508,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3535,6 +3569,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3556,6 +3591,8 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y # CONFIG_CRYPTO_SHA1_SSSE3 is not set +# CONFIG_CRYPTO_SHA256_SSSE3 is not set +# CONFIG_CRYPTO_SHA512_SSSE3 is not set CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3575,6 +3612,7 @@ CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAMELLIA_X86_64 is not set # CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set # CONFIG_CRYPTO_CAST6 is not set @@ -3588,6 +3626,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set # CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_TWOFISH_X86_64 is not set @@ -3661,4 +3700,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Generic/linux/linux.i386.conf b/projects/Generic/linux/linux.i386.conf index 2b494b6b6c..dac4626cee 100644 --- a/projects/Generic/linux/linux.i386.conf +++ b/projects/Generic/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/i386 3.9.8 Kernel Configuration +# Linux/i386 3.10.0 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -20,7 +20,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -91,6 +90,9 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -141,18 +143,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -161,6 +163,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -170,7 +173,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -290,7 +292,7 @@ CONFIG_X86_MPPARSE=y CONFIG_X86_INTEL_LPSS=y # CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_M486 is not set @@ -511,6 +513,7 @@ CONFIG_X86_ACPI_CPUFREQ_CPB=y # CONFIG_X86_POWERNOW_K6 is not set # CONFIG_X86_POWERNOW_K7 is not set CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_GX_SUSPMOD is not set # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_SPEEDSTEP_ICH is not set @@ -583,6 +586,7 @@ CONFIG_AMD_NB=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y @@ -609,6 +613,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -758,6 +763,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -901,6 +908,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_SENSORS_LIS3LV02D=m # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -919,10 +927,10 @@ CONFIG_SENSORS_LIS3LV02D=m # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -944,6 +952,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1204,6 +1213,7 @@ CONFIG_ATL2=y CONFIG_ATL1=y CONFIG_ATL1E=y CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y CONFIG_B44=y @@ -1339,6 +1349,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1413,7 +1424,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set CONFIG_B43LEGACY=m @@ -1429,7 +1439,6 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y CONFIG_BRCMUTIL=m CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y -# CONFIG_BRCMFMAC_SDIO_OOB is not set CONFIG_BRCMFMAC_USB=y # CONFIG_BRCM_TRACING is not set # CONFIG_BRCMDBG is not set @@ -1452,6 +1461,7 @@ CONFIG_LIBIPW=m CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1491,6 +1501,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1507,6 +1518,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1626,6 +1638,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1772,6 +1785,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1881,6 +1899,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1892,6 +1911,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -2030,58 +2050,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2198,7 +2221,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2297,6 +2319,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2306,11 +2329,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2363,7 +2388,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2391,6 +2415,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2493,6 +2519,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2567,6 +2594,7 @@ CONFIG_DRM_I915_KMS=y # CONFIG_DRM_AST is not set # CONFIG_DRM_MGAG200 is not set # CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_HDMI=y @@ -2583,7 +2611,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2816,6 +2843,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2898,12 +2926,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2917,6 +2944,7 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -2924,7 +2952,6 @@ CONFIG_USB_EHCI_PCI=y CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_SSB is not set # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2932,7 +2959,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2970,6 +2996,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -3025,6 +3053,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -3055,20 +3084,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -3129,6 +3146,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -3139,11 +3157,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -3155,6 +3173,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3239,6 +3258,7 @@ CONFIG_UIO=y # CONFIG_UIO_SERCOS3 is not set # CONFIG_UIO_PCI_GENERIC is not set # CONFIG_UIO_NETX is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3249,7 +3269,6 @@ CONFIG_UIO=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3272,9 +3291,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3292,7 +3311,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3317,6 +3335,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACER_WMI is not set # CONFIG_ACERHDF is not set @@ -3352,6 +3371,7 @@ CONFIG_ACPI_WMI=m # CONFIG_INTEL_OAKTRAIL is not set # CONFIG_SAMSUNG_Q10 is not set # CONFIG_APPLE_GMUX is not set +# CONFIG_PVPANIC is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -3378,7 +3398,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3386,13 +3405,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3401,6 +3420,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3428,11 +3452,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3515,6 +3542,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3674,6 +3702,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3698,6 +3728,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3710,6 +3741,7 @@ CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_DEBUG_NX_TEST is not set CONFIG_DOUBLEFAULT=y +# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -3724,7 +3756,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3786,6 +3817,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3903,4 +3935,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Generic/linux/linux.x86_64.conf b/projects/Generic/linux/linux.x86_64.conf index bf8e9135c7..0dad6d5621 100644 --- a/projects/Generic/linux/linux.x86_64.conf +++ b/projects/Generic/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 3.9.8 Kernel Configuration +# Linux/x86_64 3.10.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -22,7 +22,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -94,14 +93,20 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # # CPU/Task time and stats accounting # -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y # CONFIG_IRQ_TIME_ACCOUNTING is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set @@ -113,13 +118,16 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_TREE_RCU=y # CONFIG_PREEMPT_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_RCU_USER_QS is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_RCU_USER_QS=y +CONFIG_CONTEXT_TRACKING_FORCE=y CONFIG_RCU_FANOUT=32 CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_NOCB_CPU is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 @@ -149,18 +157,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -169,6 +177,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -178,7 +187,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -295,7 +303,7 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_EXTENDED_PLATFORM is not set CONFIG_X86_INTEL_LPSS=y CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_MK8 is not set @@ -494,6 +502,7 @@ CONFIG_X86_INTEL_PSTATE=y CONFIG_X86_ACPI_CPUFREQ=y CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set CONFIG_X86_P4_CLOCKMOD=m @@ -554,6 +563,7 @@ CONFIG_AMD_NB=y CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y # CONFIG_COREDUMP is not set @@ -587,6 +597,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -736,6 +747,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -880,6 +893,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_SENSORS_LIS3LV02D=m # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -898,10 +912,10 @@ CONFIG_SENSORS_LIS3LV02D=m # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -923,6 +937,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1181,6 +1196,7 @@ CONFIG_ATL2=y CONFIG_ATL1=y CONFIG_ATL1E=y CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y CONFIG_B44=y @@ -1316,6 +1332,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1390,7 +1407,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set CONFIG_B43LEGACY=m @@ -1406,7 +1422,6 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y CONFIG_BRCMUTIL=m CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y -# CONFIG_BRCMFMAC_SDIO_OOB is not set CONFIG_BRCMFMAC_USB=y # CONFIG_BRCM_TRACING is not set # CONFIG_BRCMDBG is not set @@ -1429,6 +1444,7 @@ CONFIG_LIBIPW=m CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1468,6 +1484,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1484,6 +1501,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1602,6 +1620,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1744,6 +1763,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1853,6 +1877,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1864,6 +1889,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -2001,58 +2027,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2169,7 +2198,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2268,6 +2296,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2277,11 +2306,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2334,7 +2365,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2362,6 +2392,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2464,6 +2496,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2532,6 +2565,7 @@ CONFIG_DRM_I915_KMS=y # CONFIG_DRM_AST is not set # CONFIG_DRM_MGAG200 is not set # CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_HDMI=y @@ -2548,7 +2582,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2779,6 +2812,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2861,12 +2895,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2880,6 +2913,7 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -2887,7 +2921,6 @@ CONFIG_USB_EHCI_PCI=y CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_SSB is not set # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2895,7 +2928,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2933,6 +2965,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2988,6 +3022,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -3018,20 +3053,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -3092,6 +3115,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -3102,11 +3126,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -3118,6 +3142,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3202,6 +3227,7 @@ CONFIG_UIO=y # CONFIG_UIO_SERCOS3 is not set # CONFIG_UIO_PCI_GENERIC is not set # CONFIG_UIO_NETX is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3212,7 +3238,6 @@ CONFIG_UIO=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3235,9 +3260,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3255,7 +3280,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3280,6 +3304,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACER_WMI is not set # CONFIG_ACERHDF is not set @@ -3314,6 +3339,7 @@ CONFIG_ACPI_WMI=m # CONFIG_INTEL_OAKTRAIL is not set # CONFIG_SAMSUNG_Q10 is not set # CONFIG_APPLE_GMUX is not set +# CONFIG_PVPANIC is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -3339,7 +3365,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3348,13 +3373,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3363,6 +3388,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3390,11 +3420,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3477,6 +3510,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3635,6 +3669,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3660,6 +3696,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3687,7 +3724,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3749,6 +3785,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3770,6 +3807,8 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y # CONFIG_CRYPTO_SHA1_SSSE3 is not set +# CONFIG_CRYPTO_SHA256_SSSE3 is not set +# CONFIG_CRYPTO_SHA512_SSSE3 is not set CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3789,6 +3828,7 @@ CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAMELLIA_X86_64 is not set # CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set # CONFIG_CRYPTO_CAST6 is not set @@ -3802,6 +3842,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set # CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_TWOFISH_X86_64 is not set @@ -3876,4 +3917,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Generic_OSS/linux/linux.i386.conf b/projects/Generic_OSS/linux/linux.i386.conf index 2dd0514994..13f8a913a2 100644 --- a/projects/Generic_OSS/linux/linux.i386.conf +++ b/projects/Generic_OSS/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/i386 3.9.8 Kernel Configuration +# Linux/i386 3.10.0 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -20,7 +20,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -91,6 +90,9 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -141,18 +143,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -161,6 +163,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -170,7 +173,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -290,7 +292,7 @@ CONFIG_X86_MPPARSE=y CONFIG_X86_INTEL_LPSS=y # CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_M486 is not set @@ -511,6 +513,7 @@ CONFIG_X86_ACPI_CPUFREQ_CPB=y # CONFIG_X86_POWERNOW_K6 is not set # CONFIG_X86_POWERNOW_K7 is not set CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_GX_SUSPMOD is not set # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_SPEEDSTEP_ICH is not set @@ -583,6 +586,7 @@ CONFIG_AMD_NB=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y @@ -609,6 +613,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -758,6 +763,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -901,6 +908,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_SENSORS_LIS3LV02D=m # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -919,10 +927,10 @@ CONFIG_SENSORS_LIS3LV02D=m # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -944,6 +952,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1204,6 +1213,7 @@ CONFIG_ATL2=y CONFIG_ATL1=y CONFIG_ATL1E=y CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y CONFIG_B44=y @@ -1337,6 +1347,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1411,7 +1422,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set CONFIG_B43LEGACY=m @@ -1427,7 +1437,6 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y CONFIG_BRCMUTIL=m CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y -# CONFIG_BRCMFMAC_SDIO_OOB is not set CONFIG_BRCMFMAC_USB=y # CONFIG_BRCM_TRACING is not set # CONFIG_BRCMDBG is not set @@ -1450,6 +1459,7 @@ CONFIG_LIBIPW=m CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1489,6 +1499,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1505,6 +1516,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1624,6 +1636,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1770,6 +1783,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1879,6 +1897,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1890,6 +1909,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -2028,58 +2048,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2196,7 +2219,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2295,6 +2317,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2304,11 +2327,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2361,7 +2386,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2389,6 +2413,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2491,6 +2517,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2570,6 +2597,7 @@ CONFIG_DRM_I915_KMS=y # CONFIG_DRM_AST is not set # CONFIG_DRM_MGAG200 is not set # CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_HDMI=y @@ -2586,7 +2614,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2819,6 +2846,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2901,12 +2929,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2920,6 +2947,7 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -2927,7 +2955,6 @@ CONFIG_USB_EHCI_PCI=y CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_SSB is not set # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2935,7 +2962,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2973,6 +2999,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -3028,6 +3056,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -3058,20 +3087,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -3132,6 +3149,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -3142,11 +3160,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -3158,6 +3176,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3242,6 +3261,7 @@ CONFIG_UIO=y # CONFIG_UIO_SERCOS3 is not set # CONFIG_UIO_PCI_GENERIC is not set # CONFIG_UIO_NETX is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3252,7 +3272,6 @@ CONFIG_UIO=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3275,9 +3294,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3295,7 +3314,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3320,6 +3338,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACER_WMI is not set # CONFIG_ACERHDF is not set @@ -3355,6 +3374,7 @@ CONFIG_MXM_WMI=y # CONFIG_INTEL_OAKTRAIL is not set # CONFIG_SAMSUNG_Q10 is not set # CONFIG_APPLE_GMUX is not set +# CONFIG_PVPANIC is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -3381,7 +3401,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3389,13 +3408,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3404,6 +3423,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3431,11 +3455,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3518,6 +3545,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3677,6 +3705,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3701,6 +3731,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3713,6 +3744,7 @@ CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_DEBUG_NX_TEST is not set CONFIG_DOUBLEFAULT=y +# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -3727,7 +3759,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3789,6 +3820,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3906,4 +3938,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/ION/linux/linux.i386.conf b/projects/ION/linux/linux.i386.conf index 3b2defaafa..4c9466d575 100644 --- a/projects/ION/linux/linux.i386.conf +++ b/projects/ION/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/i386 3.9.8 Kernel Configuration +# Linux/i386 3.10.0 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -20,7 +20,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -91,6 +90,9 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -141,18 +143,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -161,6 +163,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -170,7 +173,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -290,7 +292,7 @@ CONFIG_X86_MPPARSE=y CONFIG_X86_INTEL_LPSS=y # CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_M486 is not set @@ -578,6 +580,7 @@ CONFIG_ISA_DMA_API=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y @@ -604,6 +607,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -753,6 +757,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -896,6 +902,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -914,10 +921,10 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -939,6 +946,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1195,6 +1203,7 @@ CONFIG_NET_VENDOR_ATHEROS=y # CONFIG_ATL1 is not set # CONFIG_ATL1E is not set CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_BROCADE is not set @@ -1293,6 +1302,7 @@ CONFIG_SLHC=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1365,7 +1375,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set # CONFIG_B43LEGACY is not set @@ -1380,6 +1389,7 @@ CONFIG_HOSTAP_FIRMWARE_NVRAM=y CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1415,6 +1425,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1431,6 +1442,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1550,6 +1562,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1696,6 +1709,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1805,6 +1823,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1816,6 +1835,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1956,58 +1976,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2124,7 +2147,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2223,6 +2245,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2232,11 +2255,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2289,7 +2314,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2317,6 +2341,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2419,6 +2445,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2481,7 +2508,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2702,6 +2728,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2784,12 +2811,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2803,13 +2829,13 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2817,7 +2843,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2855,6 +2880,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2910,6 +2937,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2940,20 +2968,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -3014,6 +3030,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -3023,11 +3040,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -3039,6 +3056,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3115,6 +3133,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3125,7 +3144,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3148,9 +3166,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3168,7 +3186,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3193,6 +3210,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set # CONFIG_X86_PLATFORM_DEVICES is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y @@ -3220,7 +3238,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3228,13 +3245,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3243,6 +3260,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3270,11 +3292,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3357,6 +3382,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3516,6 +3542,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3540,6 +3568,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3552,6 +3581,7 @@ CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_DEBUG_NX_TEST is not set CONFIG_DOUBLEFAULT=y +# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -3566,7 +3596,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3628,6 +3657,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3745,4 +3775,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/ION/linux/linux.x86_64.conf b/projects/ION/linux/linux.x86_64.conf index 57ab5c5aca..9120e10278 100644 --- a/projects/ION/linux/linux.x86_64.conf +++ b/projects/ION/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 3.9.8 Kernel Configuration +# Linux/x86_64 3.10.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -20,7 +20,6 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -92,14 +91,20 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # # CPU/Task time and stats accounting # -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y # CONFIG_IRQ_TIME_ACCOUNTING is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set @@ -111,13 +116,16 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_TREE_RCU=y # CONFIG_PREEMPT_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_RCU_USER_QS is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_RCU_USER_QS=y +CONFIG_CONTEXT_TRACKING_FORCE=y CONFIG_RCU_FANOUT=32 CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_NOCB_CPU is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 @@ -144,16 +152,16 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_EXPERT=y # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -162,6 +170,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -171,7 +180,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -283,7 +291,7 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_EXTENDED_PLATFORM is not set CONFIG_X86_INTEL_LPSS=y CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_MK8 is not set @@ -528,6 +536,7 @@ CONFIG_PCI_LABEL=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y # CONFIG_COREDUMP is not set @@ -554,6 +563,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -703,6 +713,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -846,6 +858,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -864,10 +877,10 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -889,6 +902,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1140,6 +1154,7 @@ CONFIG_NET_VENDOR_ATHEROS=y # CONFIG_ATL1 is not set # CONFIG_ATL1E is not set CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set # CONFIG_NET_VENDOR_BROADCOM is not set # CONFIG_NET_VENDOR_BROCADE is not set @@ -1238,6 +1253,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1309,7 +1325,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set # CONFIG_B43LEGACY is not set @@ -1324,6 +1339,7 @@ CONFIG_HOSTAP_FIRMWARE_NVRAM=y CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1359,6 +1375,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1375,6 +1392,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1493,6 +1511,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1635,6 +1654,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1744,6 +1768,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1755,6 +1780,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1894,58 +1920,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2062,7 +2091,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2161,6 +2189,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2170,11 +2199,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2227,7 +2258,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2255,6 +2285,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2357,6 +2389,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2413,7 +2446,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2630,6 +2662,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2712,12 +2745,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2731,13 +2763,13 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2745,7 +2777,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2783,6 +2814,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2838,6 +2871,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2868,20 +2902,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -2941,6 +2963,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -2950,11 +2973,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -2966,6 +2989,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3042,6 +3066,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3052,7 +3077,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3075,9 +3099,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3095,7 +3119,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3120,6 +3143,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set # CONFIG_X86_PLATFORM_DEVICES is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y @@ -3146,7 +3170,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3155,13 +3178,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3170,6 +3193,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3197,11 +3225,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3284,6 +3315,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3442,6 +3474,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3467,6 +3501,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3493,7 +3528,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3555,6 +3589,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3576,6 +3611,8 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y # CONFIG_CRYPTO_SHA1_SSSE3 is not set +# CONFIG_CRYPTO_SHA256_SSSE3 is not set +# CONFIG_CRYPTO_SHA512_SSSE3 is not set CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3595,6 +3632,7 @@ CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAMELLIA_X86_64 is not set # CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set # CONFIG_CRYPTO_CAST6 is not set @@ -3608,6 +3646,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set # CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_TWOFISH_X86_64 is not set @@ -3682,4 +3721,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Intel/linux/linux.i386.conf b/projects/Intel/linux/linux.i386.conf index 9d4f298e04..b78e6335d2 100644 --- a/projects/Intel/linux/linux.i386.conf +++ b/projects/Intel/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/i386 3.9.8 Kernel Configuration +# Linux/i386 3.10.0 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -20,7 +20,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -91,6 +90,9 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -141,18 +143,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y CONFIG_UID16=y # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -161,6 +163,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -170,7 +173,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -290,7 +292,7 @@ CONFIG_X86_MPPARSE=y CONFIG_X86_INTEL_LPSS=y # CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_M486 is not set @@ -580,6 +582,7 @@ CONFIG_ISA_DMA_API=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y @@ -606,6 +609,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -755,6 +759,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -898,6 +904,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -916,10 +923,10 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -941,6 +948,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1197,6 +1205,7 @@ CONFIG_NET_VENDOR_ATHEROS=y # CONFIG_ATL1 is not set CONFIG_ATL1E=y CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y # CONFIG_B44 is not set @@ -1303,6 +1312,7 @@ CONFIG_SLHC=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1375,7 +1385,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set # CONFIG_B43LEGACY is not set @@ -1399,6 +1408,7 @@ CONFIG_LIBIPW=m CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1434,6 +1444,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1450,6 +1461,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1569,6 +1581,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1714,6 +1727,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1823,6 +1841,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1834,6 +1853,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1974,58 +1994,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2142,7 +2165,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2241,6 +2263,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2250,11 +2273,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2307,7 +2332,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2335,6 +2359,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2437,6 +2463,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2510,6 +2537,7 @@ CONFIG_DRM_I915_KMS=y # CONFIG_DRM_AST is not set # CONFIG_DRM_MGAG200 is not set # CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_HDMI=y @@ -2526,7 +2554,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2758,6 +2785,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2840,12 +2868,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2859,17 +2886,16 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set # CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2907,6 +2933,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2962,6 +2990,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2992,20 +3021,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -3066,6 +3083,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -3075,11 +3093,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -3091,6 +3109,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3167,6 +3186,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3177,7 +3197,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3200,9 +3219,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3220,7 +3239,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3245,6 +3263,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set # CONFIG_X86_PLATFORM_DEVICES is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y @@ -3272,7 +3291,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3280,13 +3298,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3295,6 +3313,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3322,11 +3345,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3409,6 +3435,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3568,6 +3595,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3592,6 +3621,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3604,6 +3634,7 @@ CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_DEBUG_NX_TEST is not set CONFIG_DOUBLEFAULT=y +# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -3618,7 +3649,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3680,6 +3710,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3797,4 +3828,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Intel/linux/linux.x86_64.conf b/projects/Intel/linux/linux.x86_64.conf index fb3a65046e..a0182f570b 100644 --- a/projects/Intel/linux/linux.x86_64.conf +++ b/projects/Intel/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 3.9.8 Kernel Configuration +# Linux/x86_64 3.10.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -20,7 +20,6 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -92,14 +91,20 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # # CPU/Task time and stats accounting # -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y # CONFIG_IRQ_TIME_ACCOUNTING is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set @@ -111,13 +116,16 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_TREE_RCU=y # CONFIG_PREEMPT_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_RCU_USER_QS is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_RCU_USER_QS=y +CONFIG_CONTEXT_TRACKING_FORCE=y CONFIG_RCU_FANOUT=32 CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_NOCB_CPU is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 @@ -147,16 +155,16 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_EXPERT=y # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -165,6 +173,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -174,7 +183,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -286,7 +294,7 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_EXTENDED_PLATFORM is not set CONFIG_X86_INTEL_LPSS=y CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_MK8 is not set @@ -543,6 +551,7 @@ CONFIG_PCI_LABEL=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y # CONFIG_COREDUMP is not set @@ -569,6 +578,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -718,6 +728,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -861,6 +873,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -879,10 +892,10 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -904,6 +917,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1155,6 +1169,7 @@ CONFIG_NET_VENDOR_ATHEROS=y # CONFIG_ATL1 is not set CONFIG_ATL1E=y CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y # CONFIG_B44 is not set @@ -1261,6 +1276,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1332,7 +1348,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set # CONFIG_B43LEGACY is not set @@ -1356,6 +1371,7 @@ CONFIG_LIBIPW=m CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1391,6 +1407,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1407,6 +1424,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1525,6 +1543,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1666,6 +1685,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1775,6 +1799,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1786,6 +1811,7 @@ CONFIG_SENSORS_CORETEMP=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1925,58 +1951,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2093,7 +2122,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2192,6 +2220,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2201,11 +2230,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2258,7 +2289,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2286,6 +2316,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2388,6 +2420,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2455,6 +2488,7 @@ CONFIG_DRM_I915_KMS=y # CONFIG_DRM_AST is not set # CONFIG_DRM_MGAG200 is not set # CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_HDMI=y @@ -2471,7 +2505,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2699,6 +2732,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2781,12 +2815,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2800,17 +2833,16 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set # CONFIG_USB_OHCI_HCD is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2848,6 +2880,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2903,6 +2937,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2933,20 +2968,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -3006,6 +3029,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -3015,11 +3039,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -3031,6 +3055,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3107,6 +3132,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3117,7 +3143,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3140,9 +3165,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3160,7 +3185,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3185,6 +3209,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set # CONFIG_X86_PLATFORM_DEVICES is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y @@ -3211,7 +3236,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3220,13 +3244,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3235,6 +3259,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3262,11 +3291,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3349,6 +3381,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3507,6 +3540,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3532,6 +3567,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3558,7 +3594,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3620,6 +3655,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3641,6 +3677,8 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y # CONFIG_CRYPTO_SHA1_SSSE3 is not set +# CONFIG_CRYPTO_SHA256_SSSE3 is not set +# CONFIG_CRYPTO_SHA512_SSSE3 is not set CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3660,6 +3698,7 @@ CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAMELLIA_X86_64 is not set # CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set # CONFIG_CRYPTO_CAST6 is not set @@ -3673,6 +3712,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set # CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_TWOFISH_X86_64 is not set @@ -3747,4 +3787,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Ultra/linux/linux.x86_64.conf b/projects/Ultra/linux/linux.x86_64.conf index dc2453d7bb..54b81b3eb9 100644 --- a/projects/Ultra/linux/linux.x86_64.conf +++ b/projects/Ultra/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 3.9.8 Kernel Configuration +# Linux/x86_64 3.10.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -20,7 +20,6 @@ CONFIG_GENERIC_HWEIGHT=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -92,14 +91,20 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # # CPU/Task time and stats accounting # -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y # CONFIG_IRQ_TIME_ACCOUNTING is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set @@ -111,13 +116,16 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_TREE_RCU=y # CONFIG_PREEMPT_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_RCU_USER_QS is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_RCU_USER_QS=y +CONFIG_CONTEXT_TRACKING_FORCE=y CONFIG_RCU_FANOUT=32 CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_NOCB_CPU is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 @@ -144,16 +152,16 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_EXPERT=y # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -162,6 +170,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -171,7 +180,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -283,7 +291,7 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_EXTENDED_PLATFORM is not set CONFIG_X86_INTEL_LPSS=y CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_MK8 is not set @@ -528,6 +536,7 @@ CONFIG_PCI_LABEL=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y # CONFIG_COREDUMP is not set @@ -554,6 +563,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -703,6 +713,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -845,6 +857,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -863,10 +876,10 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -888,6 +901,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1216,6 +1230,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1305,6 +1320,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_USB=m @@ -1319,6 +1335,7 @@ CONFIG_RTLWIFI=m # CONFIG_RTL8192SE is not set # CONFIG_RTL8192DE is not set # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set # CONFIG_WL_TI is not set CONFIG_ZD1211RW=m @@ -1419,6 +1436,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1561,6 +1579,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1662,6 +1685,7 @@ CONFIG_SENSORS_CORETEMP=y # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1673,6 +1697,7 @@ CONFIG_SENSORS_CORETEMP=y # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1809,58 +1834,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_MFD_RTSX_PCI is not set -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -1975,7 +2003,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2014,15 +2041,18 @@ CONFIG_MEDIA_COMMON_OPTIONS=y # CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m # CONFIG_SAA716X_SUPPORT is not set CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2071,7 +2101,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2098,6 +2127,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2180,6 +2211,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2234,7 +2266,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -2443,6 +2474,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2525,12 +2557,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2544,13 +2575,13 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2558,7 +2589,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2596,6 +2626,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2651,6 +2683,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2681,20 +2714,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set # CONFIG_MMC is not set # CONFIG_MEMSTICK is not set @@ -2710,6 +2731,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -2719,11 +2741,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -2735,6 +2757,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -2811,6 +2834,7 @@ CONFIG_RTC_DRV_CMOS=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -2821,7 +2845,6 @@ CONFIG_RTC_DRV_CMOS=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -2844,9 +2867,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set # CONFIG_VT6656 is not set # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -2864,7 +2887,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -2886,6 +2908,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_BPCTL is not set # CONFIG_CED1401 is not set # CONFIG_DGRP is not set +# CONFIG_USB_DWC2 is not set # CONFIG_X86_PLATFORM_DEVICES is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y @@ -2912,7 +2935,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -2921,13 +2943,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -2936,6 +2958,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -2963,11 +2990,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3050,6 +3080,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3208,6 +3239,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3232,6 +3265,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3258,7 +3292,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3320,6 +3353,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3341,6 +3375,8 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y # CONFIG_CRYPTO_SHA1_SSSE3 is not set +# CONFIG_CRYPTO_SHA256_SSSE3 is not set +# CONFIG_CRYPTO_SHA512_SSSE3 is not set CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3360,6 +3396,7 @@ CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAMELLIA_X86_64 is not set # CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set # CONFIG_CRYPTO_CAST6 is not set @@ -3373,6 +3410,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set # CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_TWOFISH_X86_64 is not set @@ -3447,4 +3485,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Virtual/linux/linux.i386.conf b/projects/Virtual/linux/linux.i386.conf index 847574a866..488935e5fa 100644 --- a/projects/Virtual/linux/linux.i386.conf +++ b/projects/Virtual/linux/linux.i386.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/i386 3.9.8 Kernel Configuration +# Linux/i386 3.10.0 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -20,7 +20,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -91,6 +90,9 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -141,18 +143,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -161,6 +163,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -170,7 +173,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -290,7 +292,7 @@ CONFIG_X86_MPPARSE=y CONFIG_X86_INTEL_LPSS=y # CONFIG_X86_32_IRIS is not set CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_M486 is not set @@ -511,6 +513,7 @@ CONFIG_X86_ACPI_CPUFREQ_CPB=y # CONFIG_X86_POWERNOW_K6 is not set # CONFIG_X86_POWERNOW_K7 is not set CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_GX_SUSPMOD is not set # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_SPEEDSTEP_ICH is not set @@ -583,6 +586,7 @@ CONFIG_AMD_NB=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_MISC=y @@ -609,6 +613,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -758,6 +763,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -901,6 +908,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_SENSORS_LIS3LV02D=m # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -919,10 +927,10 @@ CONFIG_SENSORS_LIS3LV02D=m # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -944,6 +952,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1204,6 +1213,7 @@ CONFIG_ATL2=y CONFIG_ATL1=y CONFIG_ATL1E=y CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y CONFIG_B44=y @@ -1339,6 +1349,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1413,7 +1424,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set CONFIG_B43LEGACY=m @@ -1429,7 +1439,6 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y CONFIG_BRCMUTIL=m CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y -# CONFIG_BRCMFMAC_SDIO_OOB is not set CONFIG_BRCMFMAC_USB=y # CONFIG_BRCM_TRACING is not set # CONFIG_BRCMDBG is not set @@ -1452,6 +1461,7 @@ CONFIG_LIBIPW=m CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1491,6 +1501,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1507,6 +1518,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1626,6 +1638,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1772,6 +1785,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1881,6 +1899,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1892,6 +1911,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -2030,58 +2050,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2198,7 +2221,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2297,6 +2319,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2306,11 +2329,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2363,7 +2388,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2391,6 +2415,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2493,6 +2519,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2569,6 +2596,7 @@ CONFIG_DRM_VMWGFX_FBCON=y # CONFIG_DRM_AST is not set # CONFIG_DRM_MGAG200 is not set # CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_HDMI=y @@ -2585,7 +2613,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set @@ -2819,6 +2846,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2901,12 +2929,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2920,6 +2947,7 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -2927,7 +2955,6 @@ CONFIG_USB_EHCI_PCI=y CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_SSB is not set # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2935,7 +2962,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2973,6 +2999,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -3028,6 +3056,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -3058,20 +3087,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -3132,6 +3149,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -3142,11 +3160,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -3158,6 +3176,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3242,6 +3261,7 @@ CONFIG_UIO=y # CONFIG_UIO_SERCOS3 is not set # CONFIG_UIO_PCI_GENERIC is not set # CONFIG_UIO_NETX is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3252,7 +3272,6 @@ CONFIG_UIO=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3275,9 +3294,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3295,7 +3314,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3320,6 +3338,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACER_WMI is not set # CONFIG_ACERHDF is not set @@ -3355,6 +3374,7 @@ CONFIG_ACPI_WMI=m # CONFIG_INTEL_OAKTRAIL is not set # CONFIG_SAMSUNG_Q10 is not set # CONFIG_APPLE_GMUX is not set +# CONFIG_PVPANIC is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -3381,7 +3401,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3389,13 +3408,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3404,6 +3423,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3431,11 +3455,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3518,6 +3545,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3677,6 +3705,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3701,6 +3731,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3713,6 +3744,7 @@ CONFIG_DEBUG_RODATA=y # CONFIG_DEBUG_SET_MODULE_RONX is not set # CONFIG_DEBUG_NX_TEST is not set CONFIG_DOUBLEFAULT=y +# CONFIG_DEBUG_TLBFLUSH is not set # CONFIG_IOMMU_STRESS is not set CONFIG_HAVE_MMIOTRACE_SUPPORT=y CONFIG_IO_DELAY_TYPE_0X80=0 @@ -3727,7 +3759,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3789,6 +3820,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3906,4 +3938,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y diff --git a/projects/Virtual/linux/linux.x86_64.conf b/projects/Virtual/linux/linux.x86_64.conf index 51ebca936a..25de06c3ef 100644 --- a/projects/Virtual/linux/linux.x86_64.conf +++ b/projects/Virtual/linux/linux.x86_64.conf @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86_64 3.9.8 Kernel Configuration +# Linux/x86_64 3.10.0 Kernel Configuration # CONFIG_64BIT=y CONFIG_X86_64=y @@ -22,7 +22,6 @@ CONFIG_ARCH_MAY_HAVE_PC_FDC=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y CONFIG_ARCH_HAS_CPU_AUTOPROBE=y CONFIG_HAVE_SETUP_PER_CPU_AREA=y @@ -94,14 +93,20 @@ CONFIG_GENERIC_CMOS_UPDATE=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +# CONFIG_NO_HZ_IDLE is not set +CONFIG_NO_HZ_FULL=y +CONFIG_NO_HZ_FULL_ALL=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y # # CPU/Task time and stats accounting # -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_VIRT_CPU_ACCOUNTING=y +# CONFIG_TICK_CPU_ACCOUNTING is not set +CONFIG_VIRT_CPU_ACCOUNTING_GEN=y # CONFIG_IRQ_TIME_ACCOUNTING is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set @@ -113,13 +118,16 @@ CONFIG_BSD_PROCESS_ACCT=y CONFIG_TREE_RCU=y # CONFIG_PREEMPT_RCU is not set CONFIG_RCU_STALL_COMMON=y -# CONFIG_RCU_USER_QS is not set +CONFIG_CONTEXT_TRACKING=y +CONFIG_RCU_USER_QS=y +CONFIG_CONTEXT_TRACKING_FORCE=y CONFIG_RCU_FANOUT=32 CONFIG_RCU_FANOUT_LEAF=16 # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_NOCB_CPU is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=m CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 @@ -149,18 +157,18 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_HOTPLUG=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set # CONFIG_SYSCTL_SYSCALL is not set -CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_PCSPKR_PLATFORM is not set -CONFIG_HAVE_PCSPKR_PLATFORM=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y @@ -169,6 +177,7 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y # CONFIG_AIO is not set +CONFIG_PCI_QUIRKS=y # CONFIG_EMBEDDED is not set CONFIG_HAVE_PERF_EVENTS=y @@ -178,7 +187,6 @@ CONFIG_HAVE_PERF_EVENTS=y CONFIG_PERF_EVENTS=y # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y -CONFIG_PCI_QUIRKS=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB=y # CONFIG_SLUB is not set @@ -295,7 +303,7 @@ CONFIG_X86_MPPARSE=y # CONFIG_X86_EXTENDED_PLATFORM is not set CONFIG_X86_INTEL_LPSS=y CONFIG_SCHED_OMIT_FRAME_POINTER=y -# CONFIG_PARAVIRT_GUEST is not set +# CONFIG_HYPERVISOR_GUEST is not set CONFIG_NO_BOOTMEM=y # CONFIG_MEMTEST is not set # CONFIG_MK8 is not set @@ -494,6 +502,7 @@ CONFIG_X86_INTEL_PSTATE=y CONFIG_X86_ACPI_CPUFREQ=y CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set CONFIG_X86_P4_CLOCKMOD=m @@ -554,6 +563,7 @@ CONFIG_AMD_NB=y CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y # CONFIG_COREDUMP is not set @@ -587,6 +597,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -736,6 +747,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_RPS=y CONFIG_RFS_ACCEL=y CONFIG_XPS=y @@ -880,6 +893,7 @@ CONFIG_BLK_DEV_RAM_SIZE=16384 CONFIG_SENSORS_LIS3LV02D=m # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_IBM_ASM is not set # CONFIG_PHANTOM is not set # CONFIG_INTEL_MID_PTI is not set @@ -898,10 +912,10 @@ CONFIG_SENSORS_LIS3LV02D=m # CONFIG_SENSORS_APDS990X is not set # CONFIG_HMC6352 is not set # CONFIG_DS1682 is not set -# CONFIG_VMWARE_BALLOON is not set # CONFIG_BMP085_I2C is not set # CONFIG_PCH_PHUB is not set # CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -923,6 +937,7 @@ CONFIG_EEPROM_93CX6=m # CONFIG_ALTERA_STAPL=m # CONFIG_INTEL_MEI is not set +# CONFIG_INTEL_MEI_ME is not set # CONFIG_VMWARE_VMCI is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set @@ -1181,6 +1196,7 @@ CONFIG_ATL2=y CONFIG_ATL1=y CONFIG_ATL1E=y CONFIG_ATL1C=y +# CONFIG_ALX is not set # CONFIG_NET_CADENCE is not set CONFIG_NET_VENDOR_BROADCOM=y CONFIG_B44=y @@ -1316,6 +1332,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=m CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -1390,7 +1407,6 @@ CONFIG_B43_PCICORE_AUTOSELECT=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -CONFIG_B43_PHY_HT=y CONFIG_B43_LEDS=y # CONFIG_B43_DEBUG is not set CONFIG_B43LEGACY=m @@ -1406,7 +1422,6 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y CONFIG_BRCMUTIL=m CONFIG_BRCMFMAC=m CONFIG_BRCMFMAC_SDIO=y -# CONFIG_BRCMFMAC_SDIO_OOB is not set CONFIG_BRCMFMAC_USB=y # CONFIG_BRCM_TRACING is not set # CONFIG_BRCMDBG is not set @@ -1429,6 +1444,7 @@ CONFIG_LIBIPW=m CONFIG_IWLWIFI=m CONFIG_IWLDVM=m CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y # # Debugging Options @@ -1468,6 +1484,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_MMIO=m @@ -1484,6 +1501,7 @@ CONFIG_RTL8192CE=m CONFIG_RTL8192SE=m CONFIG_RTL8192DE=m # CONFIG_RTL8723AE is not set +CONFIG_RTL8188EE=m # CONFIG_RTL8192CU is not set CONFIG_RTL8192C_COMMON=m # CONFIG_WL_TI is not set @@ -1602,6 +1620,7 @@ CONFIG_INPUT_ATI_REMOTE2=m CONFIG_INPUT_UINPUT=y # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1744,6 +1763,11 @@ CONFIG_I2C_INTEL_MID=y # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_SPI is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1853,6 +1877,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX16065 is not set @@ -1864,6 +1889,7 @@ CONFIG_SENSORS_IT87=m # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -2001,58 +2027,61 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set -CONFIG_MFD_RTSX_PCI=m -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_LPC_ICH is not set +CONFIG_LPC_SCH=y +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RDC321X is not set +CONFIG_MFD_RTSX_PCI=m +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_VX855 is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X_I2C is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_CS5535 is not set -CONFIG_LPC_SCH=y -# CONFIG_LPC_ICH is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -2169,7 +2198,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -2268,6 +2296,7 @@ CONFIG_MEDIA_COMMON_OPTIONS=y CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_BTCX=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_VIDEO_SAA7146=m CONFIG_VIDEO_SAA7146_VV=m @@ -2277,11 +2306,13 @@ CONFIG_DVB_SAA716X_BUDGET=m CONFIG_DVB_SAA716X_HYBRID=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -2334,7 +2365,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -2362,6 +2392,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -2464,6 +2496,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -2534,6 +2567,7 @@ CONFIG_DRM_VMWGFX=m # CONFIG_DRM_AST is not set # CONFIG_DRM_MGAG200 is not set # CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_QXL is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y CONFIG_HDMI=y @@ -2550,7 +2584,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set CONFIG_FB_DEFERRED_IO=y # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set @@ -2782,6 +2815,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -2864,12 +2898,11 @@ CONFIG_USB=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set -CONFIG_USB_SUSPEND=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB_CBAF is not set @@ -2883,6 +2916,7 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_ROOT_HUB_TT=y CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_PCI=y +# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set @@ -2890,7 +2924,6 @@ CONFIG_USB_EHCI_PCI=y CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_HCD_SSB is not set # CONFIG_USB_OHCI_HCD_PLATFORM is not set -# CONFIG_USB_EHCI_HCD_PLATFORM is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y @@ -2898,7 +2931,6 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2936,6 +2968,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2991,6 +3025,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -3021,20 +3056,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_NOP_USB_XCEIV is not set # CONFIG_UWB is not set CONFIG_MMC=m # CONFIG_MMC_DEBUG is not set @@ -3095,6 +3118,7 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_CLEVO_MAIL is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set @@ -3105,11 +3129,11 @@ CONFIG_LEDS_CLASS=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_ONESHOT is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set @@ -3121,6 +3145,7 @@ CONFIG_LEDS_TRIGGERS=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set # CONFIG_EDAC is not set @@ -3205,6 +3230,7 @@ CONFIG_UIO=y # CONFIG_UIO_SERCOS3 is not set # CONFIG_UIO_PCI_GENERIC is not set # CONFIG_UIO_NETX is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -3215,7 +3241,6 @@ CONFIG_UIO=y # # Microsoft Hyper-V guest support # -# CONFIG_HYPERV is not set CONFIG_STAGING=y # CONFIG_ET131X is not set # CONFIG_SLICOSS is not set @@ -3238,9 +3263,9 @@ CONFIG_RTS5139=m # CONFIG_VT6655 is not set CONFIG_VT6656=m # CONFIG_DX_SEP is not set +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -3258,7 +3283,6 @@ CONFIG_STAGING_MEDIA=y CONFIG_DVB_AS102=m # CONFIG_VIDEO_DT3155 is not set # CONFIG_VIDEO_GO7007 is not set -# CONFIG_SOLO6X10 is not set CONFIG_LIRC_STAGING=y # CONFIG_LIRC_BT829 is not set CONFIG_LIRC_IGORPLUGUSB=m @@ -3283,6 +3307,7 @@ CONFIG_NET_VENDOR_SILICOM=y # CONFIG_CED1401 is not set # CONFIG_DGRP is not set # CONFIG_FIREWIRE_SERIAL is not set +# CONFIG_USB_DWC2 is not set CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_ACER_WMI is not set # CONFIG_ACERHDF is not set @@ -3317,6 +3342,7 @@ CONFIG_ACPI_WMI=m # CONFIG_INTEL_OAKTRAIL is not set # CONFIG_SAMSUNG_Q10 is not set # CONFIG_APPLE_GMUX is not set +# CONFIG_PVPANIC is not set CONFIG_CLKDEV_LOOKUP=y CONFIG_HAVE_CLK_PREPARE=y CONFIG_COMMON_CLK=y @@ -3342,7 +3368,6 @@ CONFIG_CLKBLD_I8253=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set @@ -3351,13 +3376,13 @@ CONFIG_CLKBLD_I8253=y # CONFIG_VME_BUS is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # Firmware Drivers # # CONFIG_EDD is not set CONFIG_FIRMWARE_MEMMAP=y -CONFIG_EFI_VARS=y # CONFIG_DELL_RBU is not set # CONFIG_DCDBAS is not set CONFIG_DMIID=y @@ -3366,6 +3391,11 @@ CONFIG_ISCSI_IBFT_FIND=y CONFIG_ISCSI_IBFT=y # CONFIG_GOOGLE_FIRMWARE is not set +# +# EFI (Extensible Firmware Interface) Support +# +CONFIG_EFI_VARS=y + # # File systems # @@ -3393,11 +3423,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -3480,6 +3513,7 @@ CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_F2FS_FS is not set +# CONFIG_EFIVAR_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y @@ -3638,6 +3672,8 @@ CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_NOTIFIER_ERROR_INJECTION is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set +CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_PAGEALLOC is not set CONFIG_USER_STACKTRACE_SUPPORT=y CONFIG_HAVE_FUNCTION_TRACER=y @@ -3663,6 +3699,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set CONFIG_STRICT_DEVMEM=y # CONFIG_X86_VERBOSE_BOOTUP is not set @@ -3690,7 +3727,6 @@ CONFIG_DEFAULT_IO_DELAY_TYPE=0 # CONFIG_DEBUG_BOOT_PARAMS is not set # CONFIG_CPA_DEBUG is not set CONFIG_OPTIMIZE_INLINING=y -# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set # CONFIG_DEBUG_NMI_SELFTEST is not set # @@ -3752,6 +3788,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -3773,6 +3810,8 @@ CONFIG_CRYPTO_MICHAEL_MIC=m # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y # CONFIG_CRYPTO_SHA1_SSSE3 is not set +# CONFIG_CRYPTO_SHA256_SSSE3 is not set +# CONFIG_CRYPTO_SHA512_SSSE3 is not set CONFIG_CRYPTO_SHA256=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set @@ -3792,6 +3831,7 @@ CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAMELLIA_X86_64 is not set # CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set +# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set # CONFIG_CRYPTO_CAST6 is not set @@ -3805,6 +3845,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set # CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set +# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_TWOFISH_X86_64 is not set @@ -3879,4 +3920,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y CONFIG_UCS2_STRING=y From f5378d8fc580712f4510f876ba2bc8eaa570ebe1 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 00:34:11 +0200 Subject: [PATCH 13/61] xf86-video-fglrx-legacy: fix kernel 3.10 patch Signed-off-by: Stephan Raue --- ...lrx-legacy-replace_old_procfs_calls.patch} | 105 +++--------------- 1 file changed, 14 insertions(+), 91 deletions(-) rename packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/{replace_old_procfs_calls.patch => xf86-video-fglrx-legacy-replace_old_procfs_calls.patch} (72%) diff --git a/packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/replace_old_procfs_calls.patch b/packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/xf86-video-fglrx-legacy-replace_old_procfs_calls.patch similarity index 72% rename from packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/replace_old_procfs_calls.patch rename to packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/xf86-video-fglrx-legacy-replace_old_procfs_calls.patch index a1f3a6ab73..ace2461268 100644 --- a/packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/replace_old_procfs_calls.patch +++ b/packages/x11/driver/xf86-video-fglrx-legacy/patches.upstream/xf86-video-fglrx-legacy-replace_old_procfs_calls.patch @@ -1,20 +1,7 @@ -From 455d3759e6d732a4e382dbdeca35afaedaf3f52e Mon Sep 17 00:00:00 2001 -From: Alberto Milone -Date: Thu, 20 Jun 2013 16:02:12 +0200 -Subject: [PATCH 1/1] Add support for Linux 3.10 - -source: http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/x11-drivers/ati-drivers/files/ati-drivers-13.6-linux-3.10-proc.diff ---- - drmP.h | 4 - - drm_proc.h | 55 ------------ - firegl_public.c | 252 +++++++++++++++++++++++++++++++++++++++++++------------ - 3 files changed, 197 insertions(+), 114 deletions(-) - -diff --git a/drmP.h b/drmP.h -index 81546b2..4e74526 100755 ---- a/common/lib/modules/fglrx/build_mod/drmP.h -+++ b/common/lib/modules/fglrx/build_mod//drmP.h -@@ -901,10 +901,6 @@ int DRM(stub_register)(const char *name, +diff -Naur xf86-video-fglrx-legacy/common/lib/modules/fglrx/build_mod/drmP.h xf86-video-fglrx-legacy.patch/common/lib/modules/fglrx/build_mod/drmP.h +--- xf86-video-fglrx-legacy/common/lib/modules/fglrx/build_mod/drmP.h 2012-07-18 17:58:01.000000000 +0200 ++++ xf86-video-fglrx-legacy.patch/common/lib/modules/fglrx/build_mod/drmP.h 2013-07-02 23:22:27.700054231 +0200 +@@ -901,10 +901,6 @@ int DRM(stub_unregister)(int minor); /* Proc support (drm_proc.h) */ @@ -25,11 +12,10 @@ index 81546b2..4e74526 100755 extern int DRM(proc_cleanup)(int minor, struct proc_dir_entry *root, struct proc_dir_entry *dev_root); -diff --git a/drm_proc.h b/drm_proc.h -index 1e3ab4a..c52ad7e 100755 ---- a/common/lib/modules/fglrx/build_mod/drm_proc.h -+++ b/common/lib/modules/fglrx/build_mod//drm_proc.h -@@ -75,61 +75,6 @@ struct drm_proc_list { +diff -Naur xf86-video-fglrx-legacy/common/lib/modules/fglrx/build_mod/drm_proc.h xf86-video-fglrx-legacy.patch/common/lib/modules/fglrx/build_mod/drm_proc.h +--- xf86-video-fglrx-legacy/common/lib/modules/fglrx/build_mod/drm_proc.h 2012-07-18 17:58:01.000000000 +0200 ++++ xf86-video-fglrx-legacy.patch/common/lib/modules/fglrx/build_mod/drm_proc.h 2013-07-02 23:22:27.701054202 +0200 +@@ -75,61 +75,6 @@ #define DRM_PROC_ENTRIES (sizeof(DRM(proc_list))/sizeof(DRM(proc_list)[0])) /** @@ -91,11 +77,10 @@ index 1e3ab4a..c52ad7e 100755 * Cleanup the proc filesystem resources. * * \param minor device minor number. -diff --git a/firegl_public.c b/firegl_public.c -index d3ad3ce..890a0aa 100755 ---- a/common/lib/modules/fglrx/build_mod/firegl_public.c -+++ b/common/lib/modules/fglrx/build_mod//firegl_public.c -@@ -583,6 +583,202 @@ kcl_proc_list_t KCL_PROC_FileList[] = +diff -Naur xf86-video-fglrx-legacy/common/lib/modules/fglrx/build_mod/firegl_public.c xf86-video-fglrx-legacy.patch/common/lib/modules/fglrx/build_mod/firegl_public.c +--- xf86-video-fglrx-legacy/common/lib/modules/fglrx/build_mod/firegl_public.c 2013-07-02 23:33:05.566156261 +0200 ++++ xf86-video-fglrx-legacy.patch/common/lib/modules/fglrx/build_mod/firegl_public.c 2013-07-02 23:22:27.705054121 +0200 +@@ -571,6 +571,202 @@ { "NULL", NULL, NULL} // Terminate List!!! }; @@ -298,7 +283,7 @@ index d3ad3ce..890a0aa 100755 static struct proc_dir_entry *firegl_proc_init( device_t *dev, int minor, struct proc_dir_entry *root, -@@ -677,6 +873,7 @@ static struct proc_dir_entry *firegl_proc_init( device_t *dev, +@@ -665,6 +861,7 @@ return root; } @@ -306,66 +291,4 @@ index d3ad3ce..890a0aa 100755 static int firegl_proc_cleanup( int minor, struct proc_dir_entry *root, -@@ -6135,59 +6332,4 @@ void ATI_API_CALL KCL_fpu_end(void) - kernel_fpu_end(); - } - --/** Create new directory entry under "/proc/ati/...." -- * Where -- * root_dir - Root directory. If NULL then we should use "/proc/ati" root. -- * name - Pointer to the name of directory -- * access - Access attribute. We could use it to disable access to the directory for everybody accept owner. -- * By default owner is root. -- * Return NULL if failure. Pointer to proc_dir_entry otherwise -- */ --void * KCL_create_proc_dir(void *root_dir, const char *name, unsigned int access) --{ -- struct proc_dir_entry *dir = NULL; -- -- if (root_dir == NULL) -- dir = create_proc_entry(name, S_IFDIR | access, firegl_stub_root); -- else -- dir = create_proc_entry(name, S_IFDIR | access, (struct proc_dir_entry *)root_dir); -- -- return dir; --} -- --/* Remove proc directory entry -- * root - Pointer to directory proc entry or NULL if for "/proc/ati" -- * name - Name to delete -- */ --void KCL_remove_proc_dir_entry(void *root, const char *name) --{ -- if (root == NULL) -- remove_proc_entry(name, firegl_stub_root); -- else -- remove_proc_entry(name, (struct proc_dir_entry *)root); --} -- -- --/* Create proc_entry under "root_dir" -- * read_fn - Function which will be called on read request -- * write_fn - Function which will be called on write request -- * private_data - Pointer to private data which will be passed -- */ --void KCL_create_proc_entry(void *root_dir, const char *name, unsigned int access_mode, void *read_fn, void *write_fn, void *private_data) --{ -- struct proc_dir_entry *ent = NULL; -- -- if (root_dir == NULL || name == NULL) -- return; -- -- ent = create_proc_entry(name, access_mode, (struct proc_dir_entry *)root_dir); -- -- if (ent) -- { -- ent->read_proc = (read_proc_t *)read_fn; -- ent->write_proc = (write_proc_t *)write_fn; -- ent->data = private_data; -- } --} -- - #endif /* __KERNEL__ */ --- -1.7.9.5 - +diff -Naur xf86-video-fglrx-legacy/common/lib/modules/fglrx/build_mod/firegl_public.c.orig xf86-video-fglrx-legacy.patch/common/lib/modules/fglrx/build_mod/firegl_public.c.orig From 3ce9c98c3d57988f99e83c747b31a79d2934b27e Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 02:00:04 +0200 Subject: [PATCH 14/61] projects/*/linux: build p4-clockmod driver statically in kernel, wakeup after suspend should work again Signed-off-by: Stephan Raue --- projects/ARCTIC_MC/linux/linux.x86_64.conf | 2 +- projects/Generic/linux/linux.i386.conf | 2 +- projects/Generic/linux/linux.x86_64.conf | 2 +- projects/Generic_OSS/linux/linux.i386.conf | 2 +- projects/ION/linux/linux.i386.conf | 2 +- projects/ION/linux/linux.x86_64.conf | 2 +- projects/Ultra/linux/linux.x86_64.conf | 2 +- projects/Virtual/linux/linux.i386.conf | 2 +- projects/Virtual/linux/linux.x86_64.conf | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/projects/ARCTIC_MC/linux/linux.x86_64.conf b/projects/ARCTIC_MC/linux/linux.x86_64.conf index 25de06c3ef..4d6727f309 100644 --- a/projects/ARCTIC_MC/linux/linux.x86_64.conf +++ b/projects/ARCTIC_MC/linux/linux.x86_64.conf @@ -504,7 +504,7 @@ CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_POWERNOW_K8=y CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_P4_CLOCKMOD=y # # shared options diff --git a/projects/Generic/linux/linux.i386.conf b/projects/Generic/linux/linux.i386.conf index dac4626cee..6ebe4b26ab 100644 --- a/projects/Generic/linux/linux.i386.conf +++ b/projects/Generic/linux/linux.i386.conf @@ -518,7 +518,7 @@ CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_SPEEDSTEP_ICH is not set # CONFIG_X86_SPEEDSTEP_SMI is not set -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_P4_CLOCKMOD=y # CONFIG_X86_CPUFREQ_NFORCE2 is not set # CONFIG_X86_LONGRUN is not set # CONFIG_X86_LONGHAUL is not set diff --git a/projects/Generic/linux/linux.x86_64.conf b/projects/Generic/linux/linux.x86_64.conf index 0dad6d5621..a1137a9d95 100644 --- a/projects/Generic/linux/linux.x86_64.conf +++ b/projects/Generic/linux/linux.x86_64.conf @@ -504,7 +504,7 @@ CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_POWERNOW_K8=y CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_P4_CLOCKMOD=y # # shared options diff --git a/projects/Generic_OSS/linux/linux.i386.conf b/projects/Generic_OSS/linux/linux.i386.conf index 13f8a913a2..7d56b79cea 100644 --- a/projects/Generic_OSS/linux/linux.i386.conf +++ b/projects/Generic_OSS/linux/linux.i386.conf @@ -518,7 +518,7 @@ CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_SPEEDSTEP_ICH is not set # CONFIG_X86_SPEEDSTEP_SMI is not set -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_P4_CLOCKMOD=y # CONFIG_X86_CPUFREQ_NFORCE2 is not set # CONFIG_X86_LONGRUN is not set # CONFIG_X86_LONGHAUL is not set diff --git a/projects/ION/linux/linux.i386.conf b/projects/ION/linux/linux.i386.conf index 4c9466d575..754c42aa7f 100644 --- a/projects/ION/linux/linux.i386.conf +++ b/projects/ION/linux/linux.i386.conf @@ -513,7 +513,7 @@ CONFIG_X86_ACPI_CPUFREQ=y # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_SPEEDSTEP_ICH is not set # CONFIG_X86_SPEEDSTEP_SMI is not set -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_P4_CLOCKMOD=y # CONFIG_X86_CPUFREQ_NFORCE2 is not set # CONFIG_X86_LONGRUN is not set # CONFIG_X86_LONGHAUL is not set diff --git a/projects/ION/linux/linux.x86_64.conf b/projects/ION/linux/linux.x86_64.conf index 9120e10278..a70bf0d627 100644 --- a/projects/ION/linux/linux.x86_64.conf +++ b/projects/ION/linux/linux.x86_64.conf @@ -479,7 +479,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_X86_ACPI_CPUFREQ=y # CONFIG_X86_POWERNOW_K8 is not set # CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_P4_CLOCKMOD=y # # shared options diff --git a/projects/Ultra/linux/linux.x86_64.conf b/projects/Ultra/linux/linux.x86_64.conf index 54b81b3eb9..fac877af21 100644 --- a/projects/Ultra/linux/linux.x86_64.conf +++ b/projects/Ultra/linux/linux.x86_64.conf @@ -479,7 +479,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_X86_ACPI_CPUFREQ=y # CONFIG_X86_POWERNOW_K8 is not set # CONFIG_X86_SPEEDSTEP_CENTRINO is not set -# CONFIG_X86_P4_CLOCKMOD is not set +CONFIG_X86_P4_CLOCKMOD=y # # shared options diff --git a/projects/Virtual/linux/linux.i386.conf b/projects/Virtual/linux/linux.i386.conf index 488935e5fa..c4a0a39c15 100644 --- a/projects/Virtual/linux/linux.i386.conf +++ b/projects/Virtual/linux/linux.i386.conf @@ -518,7 +518,7 @@ CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set # CONFIG_X86_SPEEDSTEP_ICH is not set # CONFIG_X86_SPEEDSTEP_SMI is not set -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_P4_CLOCKMOD=y # CONFIG_X86_CPUFREQ_NFORCE2 is not set # CONFIG_X86_LONGRUN is not set # CONFIG_X86_LONGHAUL is not set diff --git a/projects/Virtual/linux/linux.x86_64.conf b/projects/Virtual/linux/linux.x86_64.conf index 25de06c3ef..4d6727f309 100644 --- a/projects/Virtual/linux/linux.x86_64.conf +++ b/projects/Virtual/linux/linux.x86_64.conf @@ -504,7 +504,7 @@ CONFIG_X86_ACPI_CPUFREQ_CPB=y CONFIG_X86_POWERNOW_K8=y CONFIG_X86_AMD_FREQ_SENSITIVITY=m # CONFIG_X86_SPEEDSTEP_CENTRINO is not set -CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_P4_CLOCKMOD=y # # shared options From 49ebf023a0d305ee423dd838a5d104076275ce77 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Wed, 3 Jul 2013 13:14:59 +0300 Subject: [PATCH 15/61] open-vm-tools: remove vmhgfs & cleanup --- .../open-vm-tools/init.d/92_open-vm-tools | 1 - packages/sysutils/open-vm-tools/install | 19 ------------------- .../open-vm-tools-disable-vmhgfs.patch | 13 +++++++++++++ 3 files changed, 13 insertions(+), 20 deletions(-) create mode 100644 packages/sysutils/open-vm-tools/patches/open-vm-tools-disable-vmhgfs.patch diff --git a/packages/sysutils/open-vm-tools/init.d/92_open-vm-tools b/packages/sysutils/open-vm-tools/init.d/92_open-vm-tools index fa1690e70e..3ebce7d72c 100644 --- a/packages/sysutils/open-vm-tools/init.d/92_open-vm-tools +++ b/packages/sysutils/open-vm-tools/init.d/92_open-vm-tools @@ -31,7 +31,6 @@ wait_for_xorg # load modules - modprobe vmhgfs modprobe vmxnet /usr/bin/vmtoolsd --background /var/run/vmtoolsd.pid diff --git a/packages/sysutils/open-vm-tools/install b/packages/sysutils/open-vm-tools/install index e3b9ddd57b..2f273b4a10 100755 --- a/packages/sysutils/open-vm-tools/install +++ b/packages/sysutils/open-vm-tools/install @@ -27,28 +27,9 @@ VER=`ls $BUILD/linux*/modules/lib/modules` mkdir -p $INSTALL/lib/modules/$VER/open-vm-tools find $PKG_BUILD/ -name \*.ko -exec cp {} $INSTALL/lib/modules/$VER/open-vm-tools \; -mkdir -p $INSTALL/sbin - cp -PR $PKG_BUILD/hgfsmounter/mount.vmhgfs $INSTALL/sbin - mkdir -p $INSTALL/usr/lib - cp -PR $PKG_BUILD/libguestlib/.libs/libguestlib.so* $INSTALL/usr/lib - cp -PR $PKG_BUILD/libhgfs/.libs/libhgfs.so* $INSTALL/usr/lib cp -PR $PKG_BUILD/libvmtools/.libs/libvmtools.so* $INSTALL/usr/lib -mkdir -p $INSTALL/usr/lib/open-vm-tools/plugins/common - cp -PR $PKG_BUILD/services/plugins/*/.libs/libhgfsServer.so $INSTALL/usr/lib/open-vm-tools/plugins/common - cp -PR $PKG_BUILD/services/plugins/*/.libs/libvix.so $INSTALL/usr/lib/open-vm-tools/plugins/common - -mkdir -p $INSTALL/usr/lib/open-vm-tools/plugins/vmsvc - cp -PR $PKG_BUILD/services/plugins/*/.libs/libguestInfo.so $INSTALL/usr/lib/open-vm-tools/plugins/vmsvc - cp -PR $PKG_BUILD/services/plugins/*/.libs/libpowerOps.so $INSTALL/usr/lib/open-vm-tools/plugins/vmsvc - cp -PR $PKG_BUILD/services/plugins/*/.libs/libtimeSync.so $INSTALL/usr/lib/open-vm-tools/plugins/vmsvc - cp -PR $PKG_BUILD/services/plugins/*/.libs/libvmbackup.so $INSTALL/usr/lib/open-vm-tools/plugins/vmsvc - mkdir -p $INSTALL/usr/bin cp -PR $PKG_BUILD/services/vmtoolsd/.libs/vmtoolsd $INSTALL/usr/bin cp -PR $PKG_BUILD/checkvm/.libs/vmware-checkvm $INSTALL/usr/bin - cp -PR $PKG_BUILD/hgfsclient/.libs/vmware-hgfsclient $INSTALL/usr/bin - cp -PR $PKG_BUILD/rpctool/vmware-rpctool $INSTALL/usr/bin - cp -PR $PKG_BUILD/toolbox/.libs/vmware-toolbox-cmd $INSTALL/usr/bin - cp -PR $PKG_BUILD/xferlogs/.libs/vmware-xferlogs $INSTALL/usr/bin diff --git a/packages/sysutils/open-vm-tools/patches/open-vm-tools-disable-vmhgfs.patch b/packages/sysutils/open-vm-tools/patches/open-vm-tools-disable-vmhgfs.patch new file mode 100644 index 0000000000..d157944217 --- /dev/null +++ b/packages/sysutils/open-vm-tools/patches/open-vm-tools-disable-vmhgfs.patch @@ -0,0 +1,13 @@ +diff --git a/configure.ac b/configure.ac +index b79026d..ac73873 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -947,7 +947,7 @@ if test "$os" = "linux"; then + + LIBVMTOOLS_LIBADD="$LIBVMTOOLS_LIBADD -lrt" + +- MODULES="$MODULES vmxnet vmhgfs" ++ MODULES="$MODULES vmxnet" + # See if we need vmci and vsock modules. Starting with 3.9 they made + # their way into mainline kernel. + if test "$osVersion" -lt 309000; then From 772ccfb22922af2197ec999712873dec902ef3ec Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 12:40:25 +0200 Subject: [PATCH 16/61] RTL8192CU: rename patch Signed-off-by: Stephan Raue --- ...thread_run_v2.patch => RTL8192CU-001-use_kthread_run_v2.patch} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/linux-drivers/RTL8192CU/patches/{RTL8192CU-use_kthread_run_v2.patch => RTL8192CU-001-use_kthread_run_v2.patch} (100%) diff --git a/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-use_kthread_run_v2.patch b/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-001-use_kthread_run_v2.patch similarity index 100% rename from packages/linux-drivers/RTL8192CU/patches/RTL8192CU-use_kthread_run_v2.patch rename to packages/linux-drivers/RTL8192CU/patches/RTL8192CU-001-use_kthread_run_v2.patch From f3e1aa0b8f79bf4e25effab47dba45fcce2087bf Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 12:41:04 +0200 Subject: [PATCH 17/61] RTL8192CU: add kernel 3.10 patches Signed-off-by: Stephan Raue --- ...L8192CU-002-linux-3.10-proc_create-1.patch | 285 ++++ ...L8192CU-003-linux-3.10-proc_create-2.patch | 92 ++ ...L8192CU-004-linux-3.10-proc_create-3.patch | 1427 +++++++++++++++++ 3 files changed, 1804 insertions(+) create mode 100644 packages/linux-drivers/RTL8192CU/patches/RTL8192CU-002-linux-3.10-proc_create-1.patch create mode 100644 packages/linux-drivers/RTL8192CU/patches/RTL8192CU-003-linux-3.10-proc_create-2.patch create mode 100644 packages/linux-drivers/RTL8192CU/patches/RTL8192CU-004-linux-3.10-proc_create-3.patch diff --git a/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-002-linux-3.10-proc_create-1.patch b/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-002-linux-3.10-proc_create-1.patch new file mode 100644 index 0000000000..74a47c8652 --- /dev/null +++ b/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-002-linux-3.10-proc_create-1.patch @@ -0,0 +1,285 @@ +From 0bb2e327dd12e44fbd67ff169217fa1f7f0c609b Mon Sep 17 00:00:00 2001 +From: kolasa +Date: Sun, 12 May 2013 21:21:46 +0200 +Subject: [PATCH] switching to proc_create ( /proc for read/write is not yet + usable ) + +--- + .../os_dep/linux/os_intfs.c | 105 ++++++++++++++++++++- + 1 file changed, 100 insertions(+), 5 deletions(-) + +diff --git a/os_dep/linux/os_intfs.c b/os_dep/linux/os_intfs.c +index 4d057a6..17f46f6 100644 +--- a/os_dep/linux/os_intfs.c ++++ b/os_dep/linux/os_intfs.c +@@ -275,14 +275,22 @@ void rtw_proc_init_one(struct net_device *dev) + #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + rtw_proc=create_proc_entry(rtw_proc_name, S_IFDIR, proc_net); + #else ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + rtw_proc=create_proc_entry(rtw_proc_name, S_IFDIR, init_net.proc_net); ++#else ++ rtw_proc=proc_mkdir(rtw_proc_name, init_net.proc_net); ++#endif + #endif + if (rtw_proc == NULL) { + DBG_8192C(KERN_ERR "Unable to create rtw_proc directory\n"); + return; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("ver_info", S_IFREG | S_IRUGO, rtw_proc, proc_get_drv_version, dev); ++#else ++ entry = proc_create_data("ver_info", S_IFREG | S_IRUGO, rtw_proc, proc_get_drv_version, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; +@@ -293,10 +301,13 @@ void rtw_proc_init_one(struct net_device *dev) + + if(padapter->dir_dev == NULL) + { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + padapter->dir_dev = create_proc_entry(dev->name, + S_IFDIR | S_IRUGO | S_IXUGO, + rtw_proc); +- ++#else ++ padapter->dir_dev = proc_mkdir(dev->name,rtw_proc); ++#endif + dir_dev = padapter->dir_dev; + + if(dir_dev==NULL) +@@ -324,84 +335,136 @@ void rtw_proc_init_one(struct net_device *dev) + + rtw_proc_cnt++; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("write_reg", S_IFREG | S_IRUGO, + dir_dev, proc_get_write_reg, dev); ++#else ++ entry = proc_create_data("write_reg", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_write_reg, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry->write_proc = proc_set_write_reg; + + entry = create_proc_read_entry("read_reg", S_IFREG | S_IRUGO, + dir_dev, proc_get_read_reg, dev); ++#else ++ entry = proc_create_data("read_reg", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_read_reg, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry->write_proc = proc_set_read_reg; + +- + entry = create_proc_read_entry("fwstate", S_IFREG | S_IRUGO, + dir_dev, proc_get_fwstate, dev); ++#else ++ entry = proc_create_data("fwstate", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_fwstate, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + +- ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("sec_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_sec_info, dev); ++#else ++ entry = proc_create_data("sec_info", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_sec_info, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("mlmext_state", S_IFREG | S_IRUGO, + dir_dev, proc_get_mlmext_state, dev); ++#else ++ entry = proc_create_data("mlmext_state", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_mlmext_state, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + +- ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("qos_option", S_IFREG | S_IRUGO, + dir_dev, proc_get_qos_option, dev); ++#else ++ entry = proc_create_data("qos_option", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_qos_option, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("ht_option", S_IFREG | S_IRUGO, + dir_dev, proc_get_ht_option, dev); ++#else ++ entry = proc_create_data("ht_option", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_ht_option, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("rf_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_rf_info, dev); ++#else ++ entry = proc_create_data("rf_info", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_rf_info, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("ap_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_ap_info, dev); ++#else ++ entry = proc_create_data("ap_info", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_ap_info, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("adapter_state", S_IFREG | S_IRUGO, + dir_dev, proc_get_adapter_state, dev); ++#else ++ entry = proc_create_data("adapter_state", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_adapter_state, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("trx_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_trx_info, dev); ++#else ++ entry = proc_create_data("trx_info", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_trx_info, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; +@@ -409,8 +472,13 @@ void rtw_proc_init_one(struct net_device *dev) + + #ifdef CONFIG_AP_MODE + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("all_sta_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_all_sta_info, dev); ++#else ++ entry = proc_create_data("all_sta_info", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_all_sta_info, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; +@@ -418,8 +486,13 @@ void rtw_proc_init_one(struct net_device *dev) + #endif + + #ifdef DBG_MEMORY_LEAK ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("_malloc_cnt", S_IFREG | S_IRUGO, + dir_dev, proc_get_malloc_cnt, dev); ++#else ++ entry = proc_create_data("_malloc_cnt", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_malloc_cnt, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; +@@ -427,38 +500,60 @@ void rtw_proc_init_one(struct net_device *dev) + #endif + + #ifdef CONFIG_FIND_BEST_CHANNEL ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("best_channel", S_IFREG | S_IRUGO, + dir_dev, proc_get_best_channel, dev); ++#else ++ entry = proc_create_data("best_channel", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_best_channel, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } + #endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("rx_signal", S_IFREG | S_IRUGO, + dir_dev, proc_get_rx_signal, dev); ++#else ++ entry = proc_create_data("rx_signal", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_rx_signal, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry->write_proc = proc_set_rx_signal; + + entry = create_proc_read_entry("ampdu_enable", S_IFREG | S_IRUGO, + dir_dev, proc_get_ampdu_enable, dev); ++#else ++ entry = proc_create_data("ampdu_enable", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_ampdu_enable, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry->write_proc = proc_set_ampdu_enable; + + entry = create_proc_read_entry("rssi_disp", S_IFREG | S_IRUGO, + dir_dev, proc_get_rssi_disp, dev); ++#else ++ entry = proc_create_data("rssi_disp", S_IFREG | S_IRUGO, ++ dir_dev, proc_get_rssi_disp, dev); ++#endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry->write_proc = proc_set_rssi_disp; +- ++#endif + } + + void rtw_proc_remove_one(struct net_device *dev) +-- +1.8.1.6 + diff --git a/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-003-linux-3.10-proc_create-2.patch b/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-003-linux-3.10-proc_create-2.patch new file mode 100644 index 0000000000..882e28ce6f --- /dev/null +++ b/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-003-linux-3.10-proc_create-2.patch @@ -0,0 +1,92 @@ +From e30a6db935752679770b31668e899a7b77e1fec4 Mon Sep 17 00:00:00 2001 +From: kolasa +Date: Mon, 13 May 2013 11:43:03 +0200 +Subject: [PATCH] Usable /proc/net/rtl819xC/ver_info + +--- + .../core/rtw_debug.c | 9 +++++++++ + .../include/rtw_debug.h | 5 ++++- + .../os_dep/linux/os_intfs.c | 14 +++++++++++++- + 3 files changed, 26 insertions(+), 2 deletions(-) + +diff --git a/core/rtw_debug.c b/core/rtw_debug.c +index 04e472d..018fe48 100644 +--- a/core/rtw_debug.c ++++ b/core/rtw_debug.c +@@ -62,6 +62,7 @@ + #ifdef CONFIG_PROC_DEBUG + #include + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_drv_version(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -75,6 +76,14 @@ int proc_get_drv_version(char *page, char **start, + *eof = 1; + return len; + } ++#else ++int proc_get_drv_version(struct seq_file *m, void* data) ++{ ++ struct net_device *dev = data; ++ ++ return seq_printf(m, "%s\n", DRIVERVERSION); ++} ++#endif + + int proc_get_write_reg(char *page, char **start, + off_t offset, int count, +diff --git a/include/rtw_debug.h b/include/rtw_debug.h +index eca6692..5b3e5cc 100644 +--- a/include/rtw_debug.h ++++ b/include/rtw_debug.h +@@ -285,10 +285,13 @@ + + #ifdef CONFIG_PROC_DEBUG + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_drv_version(char *page, char **start, + off_t offset, int count, + int *eof, void *data); +- ++#else ++ int proc_get_drv_version(struct seq_file *m, void *data); ++#endif + int proc_get_write_reg(char *page, char **start, + off_t offset, int count, + int *eof, void *data); +diff --git a/os_dep/linux/os_intfs.c b/os_dep/linux/os_intfs.c +index 99a5a1c..0e61bf9 100644 +--- a/os_dep/linux/os_intfs.c ++++ b/os_dep/linux/os_intfs.c +@@ -255,6 +255,18 @@ + static struct proc_dir_entry *rtw_proc = NULL; + static int rtw_proc_cnt = 0; + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) ++static int drv_version_proc_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_drv_version, NULL); ++} ++ ++static const struct file_operations drv_version_fops = { ++ .open = drv_version_proc_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++}; ++#endif ++ + void rtw_proc_init_one(struct net_device *dev) + { + struct proc_dir_entry *dir_dev = NULL; +@@ -289,7 +301,7 @@ void rtw_proc_init_one(struct net_device *dev) + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("ver_info", S_IFREG | S_IRUGO, rtw_proc, proc_get_drv_version, dev); + #else +- entry = proc_create_data("ver_info", S_IFREG | S_IRUGO, rtw_proc, proc_get_drv_version, dev); ++ entry = proc_create_data("ver_info", S_IFREG | S_IRUGO, rtw_proc, &drv_version_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); +-- +1.8.1.6 + diff --git a/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-004-linux-3.10-proc_create-3.patch b/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-004-linux-3.10-proc_create-3.patch new file mode 100644 index 0000000000..5099ccb4a5 --- /dev/null +++ b/packages/linux-drivers/RTL8192CU/patches/RTL8192CU-004-linux-3.10-proc_create-3.patch @@ -0,0 +1,1427 @@ +From 02ead960e8818cc580e7a94218860d1a49abc759 Mon Sep 17 00:00:00 2001 +From: kolasa +Date: Sat, 18 May 2013 21:27:43 +0200 +Subject: [PATCH] Full switch to proc_create for kernel >= 3.10 Fix error + return code in start_kthread() + +--- + .../core/rtw_debug.c | 548 ++++++++++++++++++++- + .../include/rtw_debug.h | 80 ++- + .../os_dep/linux/os_intfs.c | 314 ++++++++++-- + .../os_dep/osdep_service.c | 3 +- + 4 files changed, 875 insertions(+), 70 deletions(-) + +diff --git a/core/rtw_debug.c b/core/rtw_debug.c +index 018fe48..d4f6e7d 100644 +--- a/core/rtw_debug.c ++++ b/core/rtw_debug.c +@@ -79,12 +79,12 @@ int proc_get_drv_version(char *page, char **start, + #else + int proc_get_drv_version(struct seq_file *m, void* data) + { +- struct net_device *dev = data; +- +- return seq_printf(m, "%s\n", DRIVERVERSION); ++ seq_printf(m, "%s\n", DRIVERVERSION); ++ return 0; + } + #endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_write_reg(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -92,7 +92,14 @@ int proc_get_write_reg(char *page, char **start, + *eof = 1; + return 0; + } ++#else ++int proc_get_write_reg(struct seq_file *m, void* data) ++{ ++ return 0; ++} ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_set_write_reg(struct file *file, const char *buffer, + unsigned long count, void *data) + { +@@ -137,10 +144,59 @@ int proc_set_write_reg(struct file *file, const char *buffer, + return count; + + } ++#else ++int proc_set_write_reg_open(struct seq_file *m, void* data) ++{ ++ return 0; ++} ++ ++ssize_t proc_set_write_reg(struct file *file, const char *buffer, size_t count, loff_t *pos) ++{ ++ struct net_device *dev = (struct net_device *)pos; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ char tmp[32]; ++ u32 addr, val, len; ++ ++ if (count < 3) ++ { ++ DBG_8192C("argument size is less than 3\n"); ++ return -EFAULT; ++ } ++ len = min(count, sizeof(tmp)-1); ++ if (buffer && !copy_from_user(tmp, buffer, len)) { ++ tmp[len] = '\0'; ++ ++ if(sscanf(tmp, "%x %x %x", &addr, &val, &len)!=3) { ++ DBG_8192C("invalid write_reg parameter!\n"); ++ return -EFAULT; ++ } ++ ++ switch(len) ++ { ++ case 1: ++ rtw_write8(padapter, addr, (u8)val); ++ break; ++ case 2: ++ rtw_write16(padapter, addr, (u16)val); ++ break; ++ case 4: ++ rtw_write32(padapter, addr, val); ++ break; ++ default: ++ DBG_8192C("error write length=%d", len); ++ break; ++ } ++ ++ } ++ ++ return count; ++} ++#endif + + static u32 proc_get_read_addr=0xeeeeeeee; + static u32 proc_get_read_len=0x4; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_read_reg(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -208,7 +264,77 @@ int proc_set_read_reg(struct file *file, const char *buffer, + return count; + + } ++#else ++int proc_get_read_reg(struct seq_file *m, void* data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ ++ if(proc_get_read_addr==0xeeeeeeee) ++ { ++ return 0; ++ } ++ ++ switch(proc_get_read_len) ++ { ++ case 1: ++ seq_printf(m, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr)); ++ break; ++ case 2: ++ seq_printf(m, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr)); ++ break; ++ case 4: ++ seq_printf(m, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr)); ++ break; ++ default: ++ seq_printf(m, "error read length=%d\n", proc_get_read_len); ++ break; ++ } ++ return 0; ++} ++ ++ssize_t proc_set_read_reg(struct file *file, const char *buf, ++ size_t count, loff_t *pos) ++{ ++ struct net_device *dev = (struct net_device *)pos; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ ++ char *cmd, *buffer; ++ ++ u32 addr, len, num; ++ ++ if (count < 2) ++ { ++ DBG_8192C("argument size is less than 2\n"); ++ return -EFAULT; ++ } ++ cmd = kmalloc(count+1, GFP_KERNEL); ++ if(!cmd) ++ return -ENOMEM; ++ if(!copy_from_user(cmd, buf, count)) { ++ ++ cmd[count]='\0'; ++ buffer = cmd; ++ ++ num = sscanf(buffer, "%x %x", &addr, &len); ++ ++ if (num != 2) { ++ DBG_8192C("invalid read_reg parameter!\n"); ++ return count; ++ } ++ ++ proc_get_read_addr = addr; ++ proc_get_read_len = len; ++ }else{ ++ kfree(cmd); ++ return -EFAULT; ++ } ++ kfree(cmd); ++ return count; ++} ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_fwstate(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -224,7 +350,18 @@ int proc_get_fwstate(char *page, char **start, + *eof = 1; + return len; + } ++#else ++int proc_get_fwstate(struct seq_file *m, void* data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); ++ seq_printf(m, "fwstate=0x%x\n",get_fwstate(pmlmepriv)); ++ return 0; ++} ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_sec_info(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -242,7 +379,20 @@ int proc_get_sec_info(char *page, char **start, + *eof = 1; + return len; + } ++#else ++int proc_get_sec_info(struct seq_file *m, void* data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct security_priv *psecuritypriv = &padapter->securitypriv; ++ seq_printf(m, "auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n", ++ psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm, ++ psecuritypriv->ndisauthtype, psecuritypriv->ndisencryptstatus); ++ return 0; ++} ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_mlmext_state(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -259,7 +409,19 @@ int proc_get_mlmext_state(char *page, char **start, + *eof = 1; + return len; + } ++#else ++int proc_get_mlmext_state(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; ++ struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); ++ seq_printf(m, "pmlmeinfo->state=0x%x\n", pmlmeinfo->state); ++ return 0; ++} ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_qos_option(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -276,7 +438,18 @@ int proc_get_qos_option(char *page, char **start, + return len; + + } ++#else ++int proc_get_qos_option(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); ++ seq_printf(m, "qos_option=%d\n", pmlmepriv->qospriv.qos_option); ++ return 0; ++} ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_ht_option(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -292,7 +465,18 @@ int proc_get_ht_option(char *page, char **start, + *eof = 1; + return len; + } ++#else ++int proc_get_ht_option(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); ++ seq_printf(m, "ht_option=%d\n", pmlmepriv->htpriv.ht_option); ++ return 0; ++} ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_rf_info(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -310,7 +494,19 @@ int proc_get_rf_info(char *page, char **start, + return len; + + } ++#else ++int proc_get_rf_info(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; ++ seq_printf(m, "cur_ch=%d, cur_bw=%d, cur_ch_offet=%d\n", ++ pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); ++ return 0; ++} ++#endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_ap_info(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -359,7 +555,53 @@ int proc_get_ap_info(char *page, char **start, + return len; + + } ++#else ++int proc_get_ap_info(struct seq_file *m, void *data) ++{ ++ struct sta_info *psta; ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); ++ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; ++ struct wlan_network *cur_network = &(pmlmepriv->cur_network); ++ struct sta_priv *pstapriv = &padapter->stapriv; ++ int len = 0; + ++ psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress); ++ if(psta) ++ { ++ int i; ++ struct recv_reorder_ctrl *preorder_ctrl; ++ ++ seq_printf(m, "SSID=%s\n", cur_network->network.Ssid.Ssid); ++ seq_printf(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); ++ seq_printf(m, "cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset); ++ seq_printf(m, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self); ++ seq_printf(m, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); ++ seq_printf(m, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); ++ seq_printf(m, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); ++ seq_printf(m, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); ++ seq_printf(m, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); ++ ++ for(i=0;i<16;i++) ++ { ++ preorder_ctrl = &psta->recvreorder_ctrl[i]; ++ if(preorder_ctrl->enable) ++ { ++ seq_printf(m, "tid=%d, indicate_seq=%d\n", i, preorder_ctrl->indicate_seq); ++ } ++ } ++ ++ } ++ else ++ { ++ seq_printf(m, "can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress)); ++ } ++ return 0; ++} ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_adapter_state(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -375,7 +617,18 @@ int proc_get_adapter_state(char *page, char **start, + return len; + + } +- ++#else ++int proc_get_adapter_state(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ seq_printf(m, "bSurpriseRemoved=%d, bDriverStopped=%d\n", ++ padapter->bSurpriseRemoved, padapter->bDriverStopped); ++ return 0; ++} ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_trx_info(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -396,8 +649,23 @@ int proc_get_trx_info(char *page, char **start, + return len; + + } +- +- ++#else ++int proc_get_trx_info(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct xmit_priv *pxmitpriv = &padapter->xmitpriv; ++ struct recv_priv *precvpriv = &padapter->recvpriv; ++ seq_printf(m, "free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d, free_ext_xmitbuf_cnt=%d, free_recvframe_cnt=%d\n", ++ pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt,pxmitpriv->free_xmit_extbuf_cnt, precvpriv->free_recvframe_cnt); ++#ifdef CONFIG_USB_HCI ++ seq_printf(m, "rx_urb_pending_cn=%d\n", precvpriv->rx_pending_cnt); ++#endif ++ return 0; ++} ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_rx_signal(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -426,7 +694,7 @@ int proc_get_rx_signal(char *page, char **start, + } + + int proc_set_rx_signal(struct file *file, const char *buffer, +- unsigned long count, void *data) ++ unsigned long count, void *data); + { + struct net_device *dev = (struct net_device *)data; + _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); +@@ -461,7 +729,62 @@ int proc_set_rx_signal(struct file *file, const char *buffer, + return count; + + } ++#else ++int proc_get_rx_signal(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); ++ seq_printf(m, ++ "rssi:%d\n" ++ "rxpwdb:%d\n" ++ "signal_strength:%u\n" ++ "signal_qual:%u\n" ++ "noise:%u\n", ++ padapter->recvpriv.rssi, ++ padapter->recvpriv.rxpwdb, ++ padapter->recvpriv.signal_strength, ++ padapter->recvpriv.signal_qual, ++ padapter->recvpriv.noise ++ ); ++ return 0; ++} ++ ++ssize_t proc_set_rx_signal(struct file *file, const char *buffer, size_t count, loff_t *pos) ++{ ++ struct net_device *dev = (struct net_device *)pos; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ char tmp[32]; ++ u32 is_signal_dbg, signal_strength; ++ ++ if (count < 1) ++ return -EFAULT; ++ ++ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { ++ ++ int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength); ++ ++ is_signal_dbg = is_signal_dbg==0?0:1; ++ ++ if(is_signal_dbg && num!=2) ++ return count; ++ ++ signal_strength = signal_strength>100?100:signal_strength; ++ signal_strength = signal_strength<0?0:signal_strength; ++ ++ padapter->recvpriv.is_signal_dbg = is_signal_dbg; ++ padapter->recvpriv.signal_strength_dbg=signal_strength; + ++ if(is_signal_dbg) ++ DBG_871X("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength); ++ else ++ DBG_871X("set %s\n", "HW_SIGNAL_STRENGTH"); ++ } ++ return count; ++} ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_ampdu_enable(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -508,7 +831,46 @@ int proc_set_ampdu_enable(struct file *file, const char *buffer, + return count; + + } ++#else ++int proc_get_ampdu_enable(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct registry_priv *pregpriv = &padapter->registrypriv; ++ if(pregpriv) ++ seq_printf(m, ++ "%d\n", ++ pregpriv->ampdu_enable ++ ); ++ return 0; ++} + ++ssize_t proc_set_ampdu_enable(struct file *file, const char *buffer, size_t count, loff_t *pos) ++{ ++ struct net_device *dev = (struct net_device *)pos; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct registry_priv *pregpriv = &padapter->registrypriv; ++ char tmp[32]; ++ u32 mode; ++ ++ if (count < 1) ++ return -EFAULT; ++ ++ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { ++ ++ int num = sscanf(tmp, "%d ", &mode); ++ ++ if( pregpriv && mode >= 0 && mode < 3 ) ++ { ++ pregpriv->ampdu_enable= mode; ++ printk("ampdu_enable=%d\n", mode); ++ } ++ } ++ return count; ++} ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_rssi_disp(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -556,10 +918,52 @@ int proc_set_rssi_disp(struct file *file, const char *buffer, + return count; + + } ++#else ++int proc_get_rssi_disp(struct seq_file *m, void *data) ++{ ++ return 0; ++} + ++ssize_t proc_set_rssi_disp(struct file *file, const char *buffer, size_t count, loff_t *pos) ++{ ++ struct net_device *dev = (struct net_device *)pos; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ char tmp[32]; ++ u32 enable=0; ++ ++ if (count < 1) ++ { ++ DBG_8192C("argument size is less than 1\n"); ++ return -EFAULT; ++ } ++ ++ if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) { ++ ++ int num = sscanf(tmp, "%x", &enable); ++ ++ if (num != 1) { ++ DBG_8192C("invalid set_rssi_disp parameter!\n"); ++ return count; ++ } + ++ if(enable) ++ { ++ DBG_8192C("Turn On Rx RSSI Display Function\n"); ++ padapter->bRxRSSIDisplay = enable ; ++ } ++ else ++ { ++ DBG_8192C("Turn Off Rx RSSI Display Function\n"); ++ padapter->bRxRSSIDisplay = 0 ; ++ } ++ } ++ return count; ++} ++#endif ++ + #ifdef CONFIG_AP_MODE + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_all_sta_info(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -629,14 +1033,74 @@ int proc_get_all_sta_info(char *page, char **start, + return len; + + } +- +-#endif ++#else ++int proc_get_all_sta_info(struct seq_file *m, void *data) ++{ ++ _irqL irqL; ++ struct sta_info *psta; ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct sta_priv *pstapriv = &padapter->stapriv; ++ int i, j; ++ _list *plist, *phead; ++ struct recv_reorder_ctrl *preorder_ctrl; ++ seq_printf(m, "sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap); ++ ++ _enter_critical_bh(&pstapriv->sta_hash_lock, &irqL); ++ ++ for(i=0; i< NUM_STA; i++) ++ { ++ phead = &(pstapriv->sta_hash[i]); ++ plist = get_next(phead); ++ ++ while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) ++ { ++ psta = LIST_CONTAINOR(plist, struct sta_info, hash_list); ++ ++ plist = get_next(plist); ++ ++ //if(extra_arg == psta->aid) ++ { ++ seq_printf(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr)); ++ seq_printf(m, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self); ++ seq_printf(m, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate); ++ seq_printf(m, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid); ++ seq_printf(m, "bwmode=%d, ch_offset=%d, sgi=%d\n", psta->htpriv.bwmode, psta->htpriv.ch_offset, psta->htpriv.sgi); ++ seq_printf(m, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable); ++ seq_printf(m, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap); ++ seq_printf(m, "sleepq_len=%d\n", psta->sleepq_len); ++ seq_printf(m, "capability=0x%x\n", psta->capability); ++ seq_printf(m, "flags=0x%x\n", psta->flags); ++ seq_printf(m, "wpa_psk=0x%x\n", psta->wpa_psk); ++ seq_printf(m, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher); ++ seq_printf(m, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher); ++ seq_printf(m, "qos_info=0x%x\n", psta->qos_info); ++ seq_printf(m, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy); ++ ++ for(j=0;j<16;j++) ++ { ++ preorder_ctrl = &psta->recvreorder_ctrl[j]; ++ if(preorder_ctrl->enable) ++ { ++ seq_printf(m, "tid=%d, indicate_seq=%d\n", j, preorder_ctrl->indicate_seq); ++ } ++ } ++ } ++ } ++ } ++ _exit_critical_bh(&pstapriv->sta_hash_lock, &irqL); ++ return 0; ++} ++#endif ++ ++#endif + + #ifdef DBG_MEMORY_LEAK + #include + extern atomic_t _malloc_cnt;; + extern atomic_t _malloc_size;; + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_malloc_cnt(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -650,9 +1114,20 @@ int proc_get_malloc_cnt(char *page, char **start, + *eof = 1; + return len; + } ++#else ++int proc_get_malloc_cnt(struct seq_file *m, void *data) ++{ ++ seq_printf(m, "_malloc_cnt=%d\n", atomic_read(&_malloc_cnt)); ++ seq_printf(m, "_malloc_size=%d\n", atomic_read(&_malloc_size)); ++ return 0; ++} ++#endif ++ + #endif /* DBG_MEMORY_LEAK */ + + #ifdef CONFIG_FIND_BEST_CHANNEL ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_best_channel(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +@@ -712,6 +1187,61 @@ int proc_get_best_channel(char *page, char **start, + return len; + + } ++#else ++int proc_get_best_channel(struct seq_file *m, void *data) ++{ ++ struct net_device *dev = m->private; ++ _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); ++ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; ++ u32 i, best_channel_24G = 1, best_channel_5G = 36, index_24G = 0, index_5G = 0; ++ ++ for (i=0; pmlmeext->channel_set[i].ChannelNum !=0; i++) { ++ if ( pmlmeext->channel_set[i].ChannelNum == 1) ++ index_24G = i; ++ if ( pmlmeext->channel_set[i].ChannelNum == 36) ++ index_5G = i; ++ } ++ ++ for (i=0; pmlmeext->channel_set[i].ChannelNum !=0; i++) { ++ // 2.4G ++ if ( pmlmeext->channel_set[i].ChannelNum == 6 ) { ++ if ( pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_24G].rx_count ) { ++ index_24G = i; ++ best_channel_24G = pmlmeext->channel_set[i].ChannelNum; ++ } ++ } ++ ++ // 5G ++ if ( pmlmeext->channel_set[i].ChannelNum >= 36 ++ && pmlmeext->channel_set[i].ChannelNum < 140 ) { ++ // Find primary channel ++ if ( (( pmlmeext->channel_set[i].ChannelNum - 36) % 8 == 0) ++ && (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count) ) { ++ index_5G = i; ++ best_channel_5G = pmlmeext->channel_set[i].ChannelNum; ++ } ++ } ++ ++ if ( pmlmeext->channel_set[i].ChannelNum >= 149 ++ && pmlmeext->channel_set[i].ChannelNum < 165) { ++ // find primary channel ++ if ( (( pmlmeext->channel_set[i].ChannelNum - 149) % 8 == 0) ++ && (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count) ) { ++ index_5G = i; ++ best_channel_5G = pmlmeext->channel_set[i].ChannelNum; ++ } ++ } ++#if 1 // debug ++ seq_printf(m, "The rx cnt of channel %3d = %d\n", ++ pmlmeext->channel_set[i].ChannelNum, pmlmeext->channel_set[i].rx_count); ++#endif ++ } ++ seq_printf(m, "best_channel_5G = %d\n", best_channel_5G); ++ seq_printf(m, "best_channel_24G = %d\n", best_channel_24G); ++ return 0; ++} ++#endif ++ + #endif /* CONFIG_FIND_BEST_CHANNEL */ + + #endif +diff --git a/include/rtw_debug.h b/include/rtw_debug.h +index 5b3e5cc..624add6 100644 +--- a/include/rtw_debug.h ++++ b/include/rtw_debug.h +@@ -24,7 +24,6 @@ + #include + #include + +- + #define _drv_emerg_ 1 + #define _drv_alert_ 2 + #define _drv_crit_ 3 +@@ -35,7 +34,6 @@ + #define _drv_dump_ 8 + #define _drv_debug_ 9 + +- + #define _module_rtl871x_xmit_c_ BIT(0) + #define _module_xmit_osdep_c_ BIT(1) + #define _module_rtl871x_recv_c_ BIT(2) +@@ -179,7 +177,6 @@ + + #endif /* CONFIG_DEBUG_RTL871X */ + +- + #if defined (_dbgdump) && defined (_MODULE_DEFINE_) + + #undef RT_TRACE +@@ -193,7 +190,6 @@ + + #endif + +- + #if defined (_dbgdump) + + #undef _func_enter_ +@@ -231,7 +227,6 @@ + } + #endif + +- + #ifdef CONFIG_DEBUG_RTL819X + #ifdef PLATFORM_WINDOWS + +@@ -281,23 +276,19 @@ + #define ERR_8192C _dbgdump + #endif + +- +- + #ifdef CONFIG_PROC_DEBUG + + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_drv_version(char *page, char **start, + off_t offset, int count, + int *eof, void *data); +-#else +- int proc_get_drv_version(struct seq_file *m, void *data); +-#endif ++ + int proc_get_write_reg(char *page, char **start, + off_t offset, int count, + int *eof, void *data); + +- int proc_set_write_reg(struct file *file, const char *buffer, +- unsigned long count, void *data); ++ int proc_set_write_reg(struct file *file, const char *buffer, ++ unsigned long count, void *data); + + int proc_get_read_reg(char *page, char **start, + off_t offset, int count, +@@ -306,7 +297,6 @@ + int proc_set_read_reg(struct file *file, const char *buffer, + unsigned long count, void *data); + +- + int proc_get_fwstate(char *page, char **start, + off_t offset, int count, + int *eof, void *data); +@@ -342,28 +332,75 @@ + int proc_get_trx_info(char *page, char **start, + off_t offset, int count, + int *eof, void *data); ++#else ++ int proc_get_drv_version(struct seq_file *m, void *data); ++ ++ int proc_get_write_reg(struct seq_file *m, void *data); ++ ++ ssize_t proc_set_write_reg(struct file *file, const char *buffer, ++ size_t count, loff_t *pos); ++ ++ int proc_get_read_reg(struct seq_file *m, void *data); ++ ++ ssize_t proc_set_read_reg(struct file *file, const char *buffer, ++ size_t count, loff_t *pos); ++ ++ int proc_get_fwstate(struct seq_file *m, void *data); + ++ int proc_get_sec_info(struct seq_file *m, void *data); ++ ++ int proc_get_mlmext_state(struct seq_file *m, void *data); ++ ++ int proc_get_qos_option(struct seq_file *m, void *data); ++ ++ int proc_get_ht_option(struct seq_file *m, void *data); ++ ++ int proc_get_rf_info(struct seq_file *m, void *data); ++ ++ int proc_get_ap_info(struct seq_file *m, void *data); ++ ++ int proc_get_adapter_state(struct seq_file *m, void *data); ++ ++ int proc_get_trx_info(struct seq_file *m, void *data); ++#endif + + #ifdef CONFIG_AP_MODE + ++# if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_all_sta_info(char *page, char **start, + off_t offset, int count, + int *eof, void *data); ++# else ++ int proc_get_all_sta_info(struct seq_file *m, void *data); ++# endif + + #endif + + #ifdef DBG_MEMORY_LEAK ++ ++# if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_malloc_cnt(char *page, char **start, + off_t offset, int count, + int *eof, void *data); ++# else ++ int proc_get_malloc_cnt(struct seq_file *m, void *data); ++# endif ++ + #endif + + #ifdef CONFIG_FIND_BEST_CHANNEL ++ ++# if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_best_channel(char *page, char **start, + off_t offset, int count, + int *eof, void *data); ++# else ++ int proc_get_best_channel(struct seq_file *m, void *data); ++# endif ++ + #endif + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + int proc_get_rx_signal(char *page, char **start, + off_t offset, int count, + int *eof, void *data); +@@ -384,7 +421,22 @@ + + int proc_set_rssi_disp(struct file *file, const char *buffer, + unsigned long count, void *data); +- ++#else ++ int proc_get_rx_signal(struct seq_file *m, void *data); ++ ++ ssize_t proc_set_rx_signal(struct file *file, const char *buffer, ++ size_t count, loff_t *pos); ++ ++ int proc_get_ampdu_enable(struct seq_file *m, void *data); ++ ++ ssize_t proc_set_ampdu_enable(struct file *file, const char *buffer, ++ size_t count, loff_t *pos); ++ ++ int proc_get_rssi_disp(struct seq_file *m, void *data); ++ ++ ssize_t proc_set_rssi_disp(struct file *file, const char *buffer, ++ size_t count, loff_t *pos); ++#endif + + #endif //CONFIG_PROC_DEBUG + +diff --git a/os_dep/linux/os_intfs.c b/os_dep/linux/os_intfs.c +index 0e61bf9..05f0b59 100644 +--- a/os_dep/linux/os_intfs.c ++++ b/os_dep/linux/os_intfs.c +@@ -255,16 +255,244 @@ + static struct proc_dir_entry *rtw_proc = NULL; + static int rtw_proc_cnt = 0; + ++/* ++ * seq_file wrappers for procfile show routines, kernel >= 3.10 ++ */ + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +-static int drv_version_proc_open(struct inode *inode, struct file *file){ +- return single_open(file, proc_get_drv_version, NULL); ++ ++static int proc_get_drv_version_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_drv_version, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_drv_version_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_drv_version_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int proc_get_write_reg_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_write_reg, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_write_reg_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_write_reg_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = proc_set_write_reg, ++ .release = seq_release, ++}; ++ ++static int proc_get_read_reg_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_read_reg, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_read_reg_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_read_reg_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = proc_set_read_reg, ++ .release = seq_release, ++}; ++ ++static int proc_get_rssi_disp_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_rssi_disp, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_rssi_disp_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_rssi_disp_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = proc_set_rssi_disp, ++ .release = seq_release, ++}; ++ ++static int proc_get_ampdu_enable_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_ampdu_enable, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_ampdu_enable_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_ampdu_enable_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = proc_set_ampdu_enable, ++ .release = seq_release, ++}; ++ ++static int proc_get_rx_signal_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_rx_signal, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_rx_signal_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_rx_signal_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = proc_set_rx_signal, ++ .release = seq_release, ++}; ++ ++static int proc_get_fwstate_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_fwstate, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_fwstate_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_fwstate_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int proc_get_mlmext_state_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_mlmext_state, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_mlmext_state_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_mlmext_state_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int proc_get_qos_option_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_qos_option, PDE_DATA(inode)); + } + +-static const struct file_operations drv_version_fops = { +- .open = drv_version_proc_open, ++static const struct file_operations proc_get_qos_option_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_qos_option_open, + .read = seq_read, + .llseek = seq_lseek, ++ .release = single_release, + }; ++ ++static int proc_get_ht_option_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_ht_option, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_ht_option_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_ht_option_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int proc_get_rf_info_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_rf_info, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_rf_info_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_rf_info_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int proc_get_ap_info_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_ap_info, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_ap_info_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_ap_info_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int proc_get_adapter_state_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_adapter_state, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_adapter_state_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_adapter_state_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int proc_get_trx_info_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_trx_info, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_trx_info_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_trx_info_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int proc_get_sec_info_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_sec_info, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_sec_info_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_sec_info_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++# ifdef CONFIG_AP_MODE ++ ++static int proc_get_all_sta_info_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_all_sta_info, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_all_sta_info_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_all_sta_info_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++# endif ++ ++# ifdef DBG_MEMORY_LEAK ++ ++static int proc_get_malloc_cnt_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_malloc_cnt, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_malloc_cnt_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_malloc_cnt_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++# endif ++ ++# ifdef CONFIG_FIND_BEST_CHANNEL ++ ++static int proc_get_best_channel_open(struct inode *inode, struct file *file){ ++ return single_open(file, proc_get_best_channel, PDE_DATA(inode)); ++} ++ ++static const struct file_operations proc_get_best_channel_fops = { ++ .owner = THIS_MODULE, ++ .open = proc_get_best_channel_open, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++# endif ++ + #endif + + void rtw_proc_init_one(struct net_device *dev) +@@ -287,11 +515,11 @@ void rtw_proc_init_one(struct net_device *dev) + #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + rtw_proc=create_proc_entry(rtw_proc_name, S_IFDIR, proc_net); + #else +-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ++# if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + rtw_proc=create_proc_entry(rtw_proc_name, S_IFDIR, init_net.proc_net); +-#else ++# else + rtw_proc=proc_mkdir(rtw_proc_name, init_net.proc_net); +-#endif ++# endif + #endif + if (rtw_proc == NULL) { + DBG_8192C(KERN_ERR "Unable to create rtw_proc directory\n"); +@@ -301,7 +529,7 @@ void rtw_proc_init_one(struct net_device *dev) + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("ver_info", S_IFREG | S_IRUGO, rtw_proc, proc_get_drv_version, dev); + #else +- entry = proc_create_data("ver_info", S_IFREG | S_IRUGO, rtw_proc, &drv_version_fops, dev); ++ entry = proc_create_data("ver_info", S_IFREG | S_IRUGO, rtw_proc, &proc_get_drv_version_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); +@@ -309,8 +537,6 @@ void rtw_proc_init_one(struct net_device *dev) + } + } + +- +- + if(padapter->dir_dev == NULL) + { + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) +@@ -352,7 +578,7 @@ void rtw_proc_init_one(struct net_device *dev) + dir_dev, proc_get_write_reg, dev); + #else + entry = proc_create_data("write_reg", S_IFREG | S_IRUGO, +- dir_dev, proc_get_write_reg, dev); ++ dir_dev, &proc_get_write_reg_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); +@@ -365,7 +591,7 @@ void rtw_proc_init_one(struct net_device *dev) + dir_dev, proc_get_read_reg, dev); + #else + entry = proc_create_data("read_reg", S_IFREG | S_IRUGO, +- dir_dev, proc_get_read_reg, dev); ++ dir_dev, &proc_get_read_reg_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); +@@ -378,104 +604,95 @@ void rtw_proc_init_one(struct net_device *dev) + dir_dev, proc_get_fwstate, dev); + #else + entry = proc_create_data("fwstate", S_IFREG | S_IRUGO, +- dir_dev, proc_get_fwstate, dev); ++ dir_dev, &proc_get_fwstate_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("sec_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_sec_info, dev); + #else + entry = proc_create_data("sec_info", S_IFREG | S_IRUGO, +- dir_dev, proc_get_sec_info, dev); ++ dir_dev, &proc_get_sec_info_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } +- +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("mlmext_state", S_IFREG | S_IRUGO, + dir_dev, proc_get_mlmext_state, dev); + #else + entry = proc_create_data("mlmext_state", S_IFREG | S_IRUGO, +- dir_dev, proc_get_mlmext_state, dev); ++ dir_dev, &proc_get_mlmext_state_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("qos_option", S_IFREG | S_IRUGO, + dir_dev, proc_get_qos_option, dev); + #else + entry = proc_create_data("qos_option", S_IFREG | S_IRUGO, +- dir_dev, proc_get_qos_option, dev); ++ dir_dev, &proc_get_qos_option_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("ht_option", S_IFREG | S_IRUGO, + dir_dev, proc_get_ht_option, dev); + #else + entry = proc_create_data("ht_option", S_IFREG | S_IRUGO, +- dir_dev, proc_get_ht_option, dev); ++ dir_dev, &proc_get_ht_option_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("rf_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_rf_info, dev); + #else + entry = proc_create_data("rf_info", S_IFREG | S_IRUGO, +- dir_dev, proc_get_rf_info, dev); ++ dir_dev, &proc_get_rf_info_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("ap_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_ap_info, dev); + #else + entry = proc_create_data("ap_info", S_IFREG | S_IRUGO, +- dir_dev, proc_get_ap_info, dev); ++ dir_dev, &proc_get_ap_info_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("adapter_state", S_IFREG | S_IRUGO, + dir_dev, proc_get_adapter_state, dev); + #else + entry = proc_create_data("adapter_state", S_IFREG | S_IRUGO, +- dir_dev, proc_get_adapter_state, dev); ++ dir_dev, &proc_get_adapter_state_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("trx_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_trx_info, dev); + #else + entry = proc_create_data("trx_info", S_IFREG | S_IRUGO, +- dir_dev, proc_get_trx_info, dev); ++ dir_dev, &proc_get_trx_info_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); +@@ -484,45 +701,50 @@ void rtw_proc_init_one(struct net_device *dev) + + #ifdef CONFIG_AP_MODE + +-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ++# if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("all_sta_info", S_IFREG | S_IRUGO, + dir_dev, proc_get_all_sta_info, dev); +-#else ++# else + entry = proc_create_data("all_sta_info", S_IFREG | S_IRUGO, +- dir_dev, proc_get_all_sta_info, dev); +-#endif ++ dir_dev, &proc_get_all_sta_info_fops, dev); ++# endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } ++ + #endif + + #ifdef DBG_MEMORY_LEAK +-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ++ ++# if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("_malloc_cnt", S_IFREG | S_IRUGO, + dir_dev, proc_get_malloc_cnt, dev); +-#else ++# else + entry = proc_create_data("_malloc_cnt", S_IFREG | S_IRUGO, +- dir_dev, proc_get_malloc_cnt, dev); +-#endif ++ dir_dev, &proc_get_malloc_cnt_fops, dev); ++# endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } ++ + #endif + + #ifdef CONFIG_FIND_BEST_CHANNEL +-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) ++ ++# if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) + entry = create_proc_read_entry("best_channel", S_IFREG | S_IRUGO, + dir_dev, proc_get_best_channel, dev); +-#else ++# else + entry = proc_create_data("best_channel", S_IFREG | S_IRUGO, +- dir_dev, proc_get_best_channel, dev); +-#endif ++ dir_dev, &proc_get_best_channel_fops, dev); ++# endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + return; + } ++ + #endif + + #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) +@@ -530,7 +752,7 @@ void rtw_proc_init_one(struct net_device *dev) + dir_dev, proc_get_rx_signal, dev); + #else + entry = proc_create_data("rx_signal", S_IFREG | S_IRUGO, +- dir_dev, proc_get_rx_signal, dev); ++ dir_dev, &proc_get_rx_signal_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); +@@ -543,7 +765,7 @@ void rtw_proc_init_one(struct net_device *dev) + dir_dev, proc_get_ampdu_enable, dev); + #else + entry = proc_create_data("ampdu_enable", S_IFREG | S_IRUGO, +- dir_dev, proc_get_ampdu_enable, dev); ++ dir_dev, &proc_get_ampdu_enable_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); +@@ -557,7 +779,7 @@ void rtw_proc_init_one(struct net_device *dev) + dir_dev, proc_get_rssi_disp, dev); + #else + entry = proc_create_data("rssi_disp", S_IFREG | S_IRUGO, +- dir_dev, proc_get_rssi_disp, dev); ++ dir_dev, &proc_get_rssi_disp_fops, dev); + #endif + if (!entry) { + DBG_871X("Unable to create_proc_read_entry!\n"); + +-- +1.8.1.6 + From b314d3e73de31e5e1e893235fc064a14afe767a6 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 12:41:41 +0200 Subject: [PATCH 18/61] dbus: update to dbus-1.6.12 Signed-off-by: Stephan Raue --- packages/sysutils/dbus/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sysutils/dbus/meta b/packages/sysutils/dbus/meta index c4b2d6c672..8a3feb1ef2 100644 --- a/packages/sysutils/dbus/meta +++ b/packages/sysutils/dbus/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="dbus" -PKG_VERSION="1.6.10" +PKG_VERSION="1.6.12" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From 45f6173ce098f656afac0af15fcbe31c793278f4 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 14:22:08 +0200 Subject: [PATCH 19/61] projects/RPi: update RPi patch for kernel 3.10 support, enable kernel 3.10 support, update kernel config for kernel 3.10 Signed-off-by: Stephan Raue --- projects/RPi/linux/linux.arm.conf | 180 +- projects/RPi/options | 2 +- ...tch => linux-01-RPi_support-1fdd347.patch} | 144916 ++++++--------- 3 files changed, 59131 insertions(+), 85967 deletions(-) rename projects/RPi/patches/linux/{linux-01-RPi_support-5eb73fa.patch => linux-01-RPi_support-1fdd347.patch} (76%) diff --git a/projects/RPi/linux/linux.arm.conf b/projects/RPi/linux/linux.arm.conf index 0b9ad34695..aacb71061a 100644 --- a/projects/RPi/linux/linux.arm.conf +++ b/projects/RPi/linux/linux.arm.conf @@ -1,10 +1,9 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.9.8 Kernel Configuration +# Linux/arm 3.10.0 Kernel Configuration # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y -CONFIG_GENERIC_GPIO=y CONFIG_HAVE_PROC_CPU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y @@ -66,6 +65,9 @@ CONFIG_GENERIC_CLOCKEVENTS_BUILD=y # Timers subsystem # CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y @@ -73,6 +75,7 @@ CONFIG_HIGH_RES_TIMERS=y # CPU/Task time and stats accounting # CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_IRQ_TIME_ACCOUNTING is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set @@ -110,13 +113,13 @@ CONFIG_INITRAMFS_COMPRESSION_NONE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y -CONFIG_EXPERT=y CONFIG_HAVE_UID16=y +CONFIG_HOTPLUG=y +CONFIG_EXPERT=y # CONFIG_UID16 is not set CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_BASE_FULL=y @@ -151,12 +154,15 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_ARCH_JUMP_LABEL=y CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y CONFIG_MODULES_USE_ELF_REL=y CONFIG_CLONE_BACKWARDS=y CONFIG_OLD_SIGSUSPEND3=y @@ -229,17 +235,12 @@ CONFIG_MMU=y # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set CONFIG_ARCH_BCM2708=y -# CONFIG_ARCH_BCM2835 is not set -# CONFIG_ARCH_CNS3XXX is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_GEMINI is not set -# CONFIG_ARCH_SIRF is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set -# CONFIG_ARCH_MXS is not set # CONFIG_ARCH_NETX is not set -# CONFIG_ARCH_H720X is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set @@ -252,7 +253,6 @@ CONFIG_ARCH_BCM2708=y # CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_LPC32XX is not set -# CONFIG_ARCH_TEGRA is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_MSM is not set # CONFIG_ARCH_SHMOBILE is not set @@ -266,12 +266,10 @@ CONFIG_ARCH_BCM2708=y # CONFIG_ARCH_EXYNOS is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_U300 is not set -# CONFIG_ARCH_U8500 is not set -# CONFIG_ARCH_NOMADIK is not set -# CONFIG_PLAT_SPEAR is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP1 is not set # CONFIG_GPIO_PCA953X is not set +# CONFIG_PLAT_SPEAR is not set # # Broadcom BCM2708 Implementations @@ -430,6 +428,7 @@ CONFIG_VFP=y # CONFIG_BINFMT_ELF=y CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +CONFIG_BINFMT_SCRIPT=y CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set @@ -463,6 +462,7 @@ CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE_DEMUX is not set +CONFIG_NET_IP_TUNNEL=m CONFIG_IP_MROUTE=y CONFIG_IP_PIMSM_V1=y CONFIG_IP_PIMSM_V2=y @@ -612,6 +612,8 @@ CONFIG_DNS_RESOLVER=y # CONFIG_BATMAN_ADV is not set # CONFIG_OPENVSWITCH is not set # CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_MMAP is not set +# CONFIG_NETLINK_DIAG is not set CONFIG_BQL=y # CONFIG_BPF_JIT is not set @@ -727,6 +729,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_SENSORS_LIS3LV02D is not set # CONFIG_AD525X_DPOT is not set # CONFIG_ATMEL_PWM is not set +# CONFIG_DUMMY_IRQ is not set # CONFIG_ICS932S401 is not set # CONFIG_ATMEL_SSC is not set # CONFIG_ENCLOSURE_SERVICES is not set @@ -744,6 +747,7 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BMP085_SPI is not set # CONFIG_USB_SWITCH_FSA9480 is not set # CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set # CONFIG_C2PORT is not set # @@ -888,6 +892,7 @@ CONFIG_SLHC=m # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=m CONFIG_USB_USBNET=y CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_AX88179_178A=m @@ -947,7 +952,6 @@ CONFIG_B43_SSB=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y CONFIG_B43_PHY_LP=y -# CONFIG_B43_PHY_HT is not set CONFIG_B43_LEDS=y CONFIG_B43_HWRNG=y # CONFIG_B43_DEBUG is not set @@ -966,6 +970,7 @@ CONFIG_RT2800USB=m CONFIG_RT2800USB_RT33XX=y CONFIG_RT2800USB_RT35XX=y CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y CONFIG_RT2800USB_UNKNOWN=y CONFIG_RT2800_LIB=m CONFIG_RT2X00_LIB_USB=m @@ -1057,6 +1062,7 @@ CONFIG_INPUT_UINPUT=m # CONFIG_INPUT_PCF8574 is not set # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set # CONFIG_INPUT_CMA3000 is not set # @@ -1181,6 +1187,11 @@ CONFIG_SPI_BCM2708=m # CONFIG_SPI_SPIDEV=m # CONFIG_SPI_TLE62X0 is not set + +# +# Qualcomm MSM SSBI bus support +# +# CONFIG_SSBI is not set # CONFIG_HSI is not set # @@ -1214,6 +1225,7 @@ CONFIG_GPIO_SYSFS=y # CONFIG_GPIO_GENERIC_PLATFORM is not set # CONFIG_GPIO_EM is not set # CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_RCAR is not set # CONFIG_GPIO_TS5500 is not set # @@ -1286,6 +1298,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set # CONFIG_SENSORS_ADT7410 is not set # CONFIG_SENSORS_ADT7411 is not set # CONFIG_SENSORS_ADT7462 is not set @@ -1323,6 +1336,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LTC4215 is not set # CONFIG_SENSORS_LTC4245 is not set # CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95234 is not set # CONFIG_SENSORS_LM95241 is not set # CONFIG_SENSORS_LM95245 is not set # CONFIG_SENSORS_MAX1111 is not set @@ -1335,6 +1349,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NCT6775 is not set # CONFIG_SENSORS_NTC_THERMISTOR is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -1406,47 +1421,64 @@ CONFIG_BCMA_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set -# CONFIG_MFD_88PM860X is not set -# CONFIG_MFD_88PM800 is not set -# CONFIG_MFD_88PM805 is not set -# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_CROS_EC is not set # CONFIG_MFD_ASIC3 is not set -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_HTC_EGPIO is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_HTC_I2CPLD is not set -# CONFIG_MFD_LM3533 is not set -# CONFIG_TPS6105X is not set -# CONFIG_TPS65010 is not set -# CONFIG_TPS6507X is not set -# CONFIG_MFD_TPS65217 is not set -# CONFIG_MFD_TPS6586X is not set -# CONFIG_MFD_TPS65910 is not set -# CONFIG_MFD_TPS65912_I2C is not set -# CONFIG_MFD_TPS65912_SPI is not set -# CONFIG_MFD_TPS80031 is not set -# CONFIG_TWL4030_CORE is not set -# CONFIG_TWL6040_CORE is not set -# CONFIG_MFD_STMPE is not set -# CONFIG_MFD_TC3589X is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_T7L66XB is not set -# CONFIG_MFD_SMSC is not set -# CONFIG_MFD_TC6387XB is not set -# CONFIG_MFD_TC6393XB is not set # CONFIG_PMIC_DA903X is not set # CONFIG_MFD_DA9052_SPI is not set # CONFIG_MFD_DA9052_I2C is not set # CONFIG_MFD_DA9055 is not set -# CONFIG_PMIC_ADP5520 is not set -# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_MAX77686 is not set # CONFIG_MFD_MAX77693 is not set # CONFIG_MFD_MAX8907 is not set # CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_MAX8997 is not set # CONFIG_MFD_MAX8998 is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_RC5T583 is not set # CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_SYSCON is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set # CONFIG_MFD_ARIZONA_I2C is not set # CONFIG_MFD_ARIZONA_SPI is not set # CONFIG_MFD_WM8400 is not set @@ -1454,19 +1486,6 @@ CONFIG_BCMA_POSSIBLE=y # CONFIG_MFD_WM831X_SPI is not set # CONFIG_MFD_WM8350_I2C is not set # CONFIG_MFD_WM8994 is not set -# CONFIG_MFD_PCF50633 is not set -# CONFIG_MFD_MC13XXX_SPI is not set -# CONFIG_MFD_MC13XXX_I2C is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_EZX_PCAP is not set -# CONFIG_MFD_WL1273_CORE is not set -# CONFIG_MFD_TPS65090 is not set -# CONFIG_MFD_AAT2870_CORE is not set -# CONFIG_MFD_RC5T583 is not set -# CONFIG_MFD_PALMAS is not set -# CONFIG_MFD_VIPERBOARD is not set -# CONFIG_MFD_RETU is not set -# CONFIG_MFD_AS3711 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=m @@ -1574,7 +1593,6 @@ CONFIG_DVB_USB_DTV5100=m CONFIG_DVB_USB_AZ6027=m CONFIG_DVB_USB_TECHNISAT_USB2=m CONFIG_DVB_USB_V2=m -CONFIG_DVB_USB_CYPRESS_FIRMWARE=m CONFIG_DVB_USB_AF9015=m CONFIG_DVB_USB_AF9035=m CONFIG_DVB_USB_ANYSEE=m @@ -1611,14 +1629,17 @@ CONFIG_MEDIA_COMMON_OPTIONS=y # CONFIG_VIDEO_CX2341X=m CONFIG_VIDEO_TVEEPROM=m +CONFIG_CYPRESS_FIRMWARE=m CONFIG_DVB_B2C2_FLEXCOP=m CONFIG_SMS_SIANO_MDTV=m CONFIG_SMS_SIANO_RC=y +# CONFIG_SMS_SIANO_DEBUGFS is not set # # Media ancillary drivers (tuners, sensors, i2c, frontends) # CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y CONFIG_VIDEO_IR_I2C=m # @@ -1667,7 +1688,6 @@ CONFIG_VIDEO_MT9V011=m # # Sensors used on soc_camera driver # -CONFIG_MEDIA_ATTACH=y CONFIG_MEDIA_TUNER=m CONFIG_MEDIA_TUNER_SIMPLE=m CONFIG_MEDIA_TUNER_TDA8290=m @@ -1696,6 +1716,8 @@ CONFIG_MEDIA_TUNER_TDA18212=m CONFIG_MEDIA_TUNER_E4000=m CONFIG_MEDIA_TUNER_FC2580=m CONFIG_MEDIA_TUNER_TUA9001=m +CONFIG_MEDIA_TUNER_IT913X=m +CONFIG_MEDIA_TUNER_R820T=m # # Multistandard (satellite) frontends @@ -1777,6 +1799,7 @@ CONFIG_DVB_S5H1411=m # CONFIG_DVB_S921=m CONFIG_DVB_DIB8000=m +CONFIG_DVB_MB86A20S=m # # Digital terrestrial only tuners/PLL @@ -1824,7 +1847,6 @@ CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_SYS_IMAGEBLIT is not set # CONFIG_FB_FOREIGN_ENDIAN is not set # CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_WMT_GE_ROPS is not set # CONFIG_FB_SVGALIB is not set # CONFIG_FB_MACMODES is not set # CONFIG_FB_BACKLIGHT is not set @@ -1875,6 +1897,7 @@ CONFIG_HID_GENERIC=y CONFIG_HID_A4TECH=y # CONFIG_HID_ACRUX is not set CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set CONFIG_HID_AUREAL=y CONFIG_HID_BELKIN=y CONFIG_HID_CHERRY=y @@ -1956,10 +1979,10 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # # Miscellaneous USB options # +CONFIG_USB_DEFAULT_PERSIST=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set -# CONFIG_USB_DWC3 is not set CONFIG_USB_MON=m # CONFIG_USB_WUSB_CBAF is not set @@ -1975,7 +1998,6 @@ CONFIG_USB_MON=m # CONFIG_USB_R8A66597_HCD is not set CONFIG_USB_DWCOTG=y # CONFIG_USB_HCD_SSB is not set -# CONFIG_USB_CHIPIDEA is not set # # USB Device Class drivers @@ -2013,6 +2035,8 @@ CONFIG_USB_STORAGE=y # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_CHIPIDEA is not set # # USB port drivers @@ -2068,6 +2092,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_XSENS_MT is not set # CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_WISHBONE is not set # CONFIG_USB_SERIAL_ZTE is not set # CONFIG_USB_SERIAL_SSU100 is not set # CONFIG_USB_SERIAL_QT2 is not set @@ -2097,22 +2122,8 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_YUREX is not set # CONFIG_USB_EZUSB_FX2 is not set # CONFIG_USB_HSIC_USB3503 is not set - -# -# USB Physical Layer drivers -# -# CONFIG_OMAP_USB3 is not set -# CONFIG_OMAP_CONTROL_USB is not set -# CONFIG_USB_ISP1301 is not set -# CONFIG_USB_RCAR_PHY is not set +# CONFIG_USB_PHY is not set # CONFIG_USB_GADGET is not set - -# -# OTG and related infrastructure -# -# CONFIG_USB_GPIO_VBUS is not set -# CONFIG_USB_ULPI is not set -# CONFIG_NOP_USB_XCEIV is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set @@ -2156,6 +2167,7 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LP3944 is not set # CONFIG_LEDS_LP5521 is not set # CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set # CONFIG_LEDS_PCA955X is not set # CONFIG_LEDS_PCA9633 is not set # CONFIG_LEDS_DAC124S085 is not set @@ -2166,11 +2178,11 @@ CONFIG_LEDS_GPIO=y # CONFIG_LEDS_LM355x is not set # CONFIG_LEDS_OT200 is not set # CONFIG_LEDS_BLINKM is not set -CONFIG_LEDS_TRIGGERS=y # # LED Triggers # +CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y # CONFIG_LEDS_TRIGGER_ONESHOT is not set CONFIG_LEDS_TRIGGER_HEARTBEAT=y @@ -2183,6 +2195,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y # iptables trigger is under Netfilter config (LED target) # # CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_EDAC is not set CONFIG_RTC_LIB=y @@ -2190,6 +2203,7 @@ CONFIG_RTC_LIB=y # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set +# CONFIG_VIRT_DRIVERS is not set # # Virtio drivers @@ -2213,9 +2227,9 @@ CONFIG_RTS5139=m # CONFIG_TRANZPORT is not set # CONFIG_USB_SERIAL_QUATECH2 is not set CONFIG_VT6656=m +CONFIG_ZSMALLOC=y CONFIG_ZRAM=y # CONFIG_ZRAM_DEBUG is not set -CONFIG_ZSMALLOC=y # CONFIG_USB_ENESTORAGE is not set # CONFIG_BCM_WIMAX is not set # CONFIG_FT1000 is not set @@ -2248,6 +2262,7 @@ CONFIG_LIRC_XBOX=m # CONFIG_CED1401 is not set # CONFIG_DGRP is not set CONFIG_ZCACHE=y +# CONFIG_ZCACHE_DEBUG is not set CONFIG_CLKDEV_LOOKUP=y # @@ -2264,13 +2279,13 @@ CONFIG_CLKDEV_LOOKUP=y # # Rpmsg drivers # -# CONFIG_VIRT_DRIVERS is not set # CONFIG_PM_DEVFREQ is not set # CONFIG_EXTCON is not set # CONFIG_MEMORY is not set # CONFIG_IIO is not set # CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set +# CONFIG_RESET_CONTROLLER is not set # # File systems @@ -2299,11 +2314,14 @@ CONFIG_XFS_FS=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_POSIX_ACL is not set # CONFIG_XFS_RT is not set +# CONFIG_XFS_WARN is not set # CONFIG_XFS_DEBUG is not set # CONFIG_GFS2_FS is not set CONFIG_BTRFS_FS=y # CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set +# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set +# CONFIG_BTRFS_DEBUG is not set # CONFIG_NILFS2_FS is not set # CONFIG_FS_POSIX_ACL is not set CONFIG_EXPORTFS=y @@ -2555,12 +2573,14 @@ CONFIG_TRACING_SUPPORT=y # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set +# CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_STRICT_DEVMEM is not set # CONFIG_ARM_UNWIND is not set # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_LL is not set CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S" +CONFIG_UNCOMPRESS_INCLUDE="mach/uncompress.h" # CONFIG_OC_ETM is not set # CONFIG_PID_IN_CONTEXTIDR is not set @@ -2622,6 +2642,7 @@ CONFIG_CRYPTO_ECB=y # # Hash modes # +# CONFIG_CRYPTO_CMAC is not set CONFIG_CRYPTO_HMAC=y # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set @@ -2729,4 +2750,5 @@ CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y CONFIG_AVERAGE=y # CONFIG_CORDIC is not set # CONFIG_DDR is not set +CONFIG_OID_REGISTRY=y # CONFIG_VIRTUALIZATION is not set diff --git a/projects/RPi/options b/projects/RPi/options index cc3a150a2e..c77db212d2 100755 --- a/projects/RPi/options +++ b/projects/RPi/options @@ -109,7 +109,7 @@ # Kernel to use. values can be: # default: default mainline kernel # ti-omap4: Ti's OMAP4 kernel - LINUX="3.9" + LINUX="default" # use linux-next (latest rc) instead latest released version LINUX_NEXT="no" diff --git a/projects/RPi/patches/linux/linux-01-RPi_support-5eb73fa.patch b/projects/RPi/patches/linux/linux-01-RPi_support-1fdd347.patch similarity index 76% rename from projects/RPi/patches/linux/linux-01-RPi_support-5eb73fa.patch rename to projects/RPi/patches/linux/linux-01-RPi_support-1fdd347.patch index 61c026b557..064e5031c7 100644 --- a/projects/RPi/patches/linux/linux-01-RPi_support-5eb73fa.patch +++ b/projects/RPi/patches/linux/linux-01-RPi_support-1fdd347.patch @@ -1,45187 +1,7 @@ -From f2bc7f5b52625b24363d97d778a9f519ae72d199 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 001/102] Add dwc_otg driver - -Signed-off-by: popcornmix ---- - drivers/usb/Makefile | 1 + - drivers/usb/core/generic.c | 1 + - drivers/usb/core/message.c | 79 + - drivers/usb/core/otg_whitelist.h | 172 +- - drivers/usb/gadget/file_storage.c | 3676 +++++++++++++ - drivers/usb/host/Kconfig | 13 + - drivers/usb/host/Makefile | 2 + - drivers/usb/host/dwc_common_port/Makefile | 46 + - drivers/usb/host/dwc_common_port/Makefile.linux | 36 + - drivers/usb/host/dwc_common_port/doc/doxygen.cfg | 270 + - drivers/usb/host/dwc_common_port/dwc_cc.c | 506 ++ - drivers/usb/host/dwc_common_port/dwc_cc.h | 209 + - .../usb/host/dwc_common_port/dwc_common_linux.c | 1138 ++++ - drivers/usb/host/dwc_common_port/dwc_list.h | 616 +++ - drivers/usb/host/dwc_common_port/dwc_mem.c | 172 + - drivers/usb/host/dwc_common_port/dwc_notifier.c | 256 + - drivers/usb/host/dwc_common_port/dwc_notifier.h | 112 + - drivers/usb/host/dwc_common_port/dwc_os.h | 925 ++++ - drivers/usb/host/dwc_common_port/usb.h | 850 +++ - drivers/usb/host/dwc_otg/Makefile | 80 + - drivers/usb/host/dwc_otg/doc/doxygen.cfg | 224 + - drivers/usb/host/dwc_otg/dummy_audio.c | 1575 ++++++ - drivers/usb/host/dwc_otg/dwc_cfi_common.h | 142 + - drivers/usb/host/dwc_otg/dwc_otg_attr.c | 1316 +++++ - drivers/usb/host/dwc_otg/dwc_otg_attr.h | 88 + - drivers/usb/host/dwc_otg/dwc_otg_cfi.c | 1876 +++++++ - drivers/usb/host/dwc_otg/dwc_otg_cfi.h | 319 ++ - drivers/usb/host/dwc_otg/dwc_otg_cil.c | 5410 ++++++++++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_cil.h | 1143 +++++ - drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 846 +++ - drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 641 +++ - drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 113 + - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 1577 ++++++ - drivers/usb/host/dwc_otg/dwc_otg_driver.h | 101 + - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 3330 ++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 804 +++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1106 ++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 393 ++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2065 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 840 +++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 732 +++ - drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2067 ++++++++ - drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 216 + - drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 333 ++ - drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 4077 +++++++++++++++ - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1288 +++++ - drivers/usb/host/dwc_otg/dwc_otg_regs.h | 2237 ++++++++ - drivers/usb/host/dwc_otg/test/Makefile | 16 + - drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 ++ - drivers/usb/host/dwc_otg/test/test_mod_param.pl | 133 + - drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 + - 51 files changed, 44649 insertions(+), 49 deletions(-) - create mode 100644 drivers/usb/gadget/file_storage.c - create mode 100644 drivers/usb/host/dwc_common_port/Makefile - create mode 100644 drivers/usb/host/dwc_common_port/Makefile.linux - create mode 100644 drivers/usb/host/dwc_common_port/doc/doxygen.cfg - create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.h - create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_linux.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_list.h - create mode 100644 drivers/usb/host/dwc_common_port/dwc_mem.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.h - create mode 100644 drivers/usb/host/dwc_common_port/dwc_os.h - create mode 100644 drivers/usb/host/dwc_common_port/usb.h - create mode 100644 drivers/usb/host/dwc_otg/Makefile - create mode 100644 drivers/usb/host/dwc_otg/doc/doxygen.cfg - create mode 100644 drivers/usb/host/dwc_otg/dummy_audio.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_cfi_common.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_core_if.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_dbg.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h - create mode 100644 drivers/usb/host/dwc_otg/test/Makefile - create mode 100644 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm - create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl - create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl - -diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile -index 8f5ebce..3c435e3 100644 ---- a/drivers/usb/Makefile -+++ b/drivers/usb/Makefile -@@ -25,6 +25,7 @@ obj-$(CONFIG_USB_U132_HCD) += host/ - obj-$(CONFIG_USB_R8A66597_HCD) += host/ - obj-$(CONFIG_USB_HWA_HCD) += host/ - obj-$(CONFIG_USB_ISP1760_HCD) += host/ -+obj-$(CONFIG_USB_DWCOTG) += host/ - obj-$(CONFIG_USB_IMX21_HCD) += host/ - obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ - -diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c -index 271e761..3144db8 100644 ---- a/drivers/usb/core/generic.c -+++ b/drivers/usb/core/generic.c -@@ -152,6 +152,7 @@ int usb_choose_configuration(struct usb_device *udev) - dev_warn(&udev->dev, - "no configuration chosen from %d choice%s\n", - num_configs, plural(num_configs)); -+ dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA); - } - return i; - } -diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c -index 444d30e..3ff77fa 100644 ---- a/drivers/usb/core/message.c -+++ b/drivers/usb/core/message.c -@@ -1875,6 +1875,85 @@ int usb_set_configuration(struct usb_device *dev, int configuration) - if (cp->string == NULL && - !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) - cp->string = usb_cache_string(dev, cp->desc.iConfiguration); -+/* Uncomment this define to enable the HS Electrical Test support */ -+#define DWC_HS_ELECT_TST 1 -+#ifdef DWC_HS_ELECT_TST -+ /* Here we implement the HS Electrical Test support. The -+ * tester uses a vendor ID of 0x1A0A to indicate we should -+ * run a special test sequence. The product ID tells us -+ * which sequence to run. We invoke the test sequence by -+ * sending a non-standard SetFeature command to our root -+ * hub port. Our dwc_otg_hcd_hub_control() routine will -+ * recognize the command and perform the desired test -+ * sequence. -+ */ -+ if (dev->descriptor.idVendor == 0x1A0A) { -+ /* HSOTG Electrical Test */ -+ dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n"); -+ -+ if (dev->bus && dev->bus->root_hub) { -+ struct usb_device *hdev = dev->bus->root_hub; -+ dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct); -+ -+ switch (dev->descriptor.idProduct) { -+ case 0x0101: /* TEST_SE0_NAK */ -+ dev_warn(&dev->dev, "TEST_SE0_NAK\n"); -+ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), -+ USB_REQ_SET_FEATURE, USB_RT_PORT, -+ USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ); -+ break; -+ -+ case 0x0102: /* TEST_J */ -+ dev_warn(&dev->dev, "TEST_J\n"); -+ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), -+ USB_REQ_SET_FEATURE, USB_RT_PORT, -+ USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ); -+ break; -+ -+ case 0x0103: /* TEST_K */ -+ dev_warn(&dev->dev, "TEST_K\n"); -+ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), -+ USB_REQ_SET_FEATURE, USB_RT_PORT, -+ USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ); -+ break; -+ -+ case 0x0104: /* TEST_PACKET */ -+ dev_warn(&dev->dev, "TEST_PACKET\n"); -+ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), -+ USB_REQ_SET_FEATURE, USB_RT_PORT, -+ USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ); -+ break; -+ -+ case 0x0105: /* TEST_FORCE_ENABLE */ -+ dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n"); -+ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), -+ USB_REQ_SET_FEATURE, USB_RT_PORT, -+ USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ); -+ break; -+ -+ case 0x0106: /* HS_HOST_PORT_SUSPEND_RESUME */ -+ dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n"); -+ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), -+ USB_REQ_SET_FEATURE, USB_RT_PORT, -+ USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ); -+ break; -+ -+ case 0x0107: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ -+ dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n"); -+ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), -+ USB_REQ_SET_FEATURE, USB_RT_PORT, -+ USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ); -+ break; -+ -+ case 0x0108: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ -+ dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n"); -+ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), -+ USB_REQ_SET_FEATURE, USB_RT_PORT, -+ USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ); -+ } -+ } -+ } -+#endif /* DWC_HS_ELECT_TST */ - - /* Now that the interfaces are installed, re-enable LPM. */ - usb_unlocked_enable_lpm(dev); -diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h -index e8cdce5..3a0da17 100644 ---- a/drivers/usb/core/otg_whitelist.h -+++ b/drivers/usb/core/otg_whitelist.h -@@ -19,33 +19,82 @@ - static struct usb_device_id whitelist_table [] = { - - /* hubs are optional in OTG, but very handy ... */ -+#define CERT_WITHOUT_HUBS -+#if defined(CERT_WITHOUT_HUBS) -+{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/ -+#else - { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), }, - { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), }, -+{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), }, -+#endif - - #ifdef CONFIG_USB_PRINTER /* ignoring nonstatic linkage! */ - /* FIXME actually, printers are NOT supposed to use device classes; - * they're supposed to use interface classes... - */ --{ USB_DEVICE_INFO(7, 1, 1) }, --{ USB_DEVICE_INFO(7, 1, 2) }, --{ USB_DEVICE_INFO(7, 1, 3) }, -+//{ USB_DEVICE_INFO(7, 1, 1) }, -+//{ USB_DEVICE_INFO(7, 1, 2) }, -+//{ USB_DEVICE_INFO(7, 1, 3) }, - #endif - - #ifdef CONFIG_USB_NET_CDCETHER - /* Linux-USB CDC Ethernet gadget */ --{ USB_DEVICE(0x0525, 0xa4a1), }, -+//{ USB_DEVICE(0x0525, 0xa4a1), }, - /* Linux-USB CDC Ethernet + RNDIS gadget */ --{ USB_DEVICE(0x0525, 0xa4a2), }, -+//{ USB_DEVICE(0x0525, 0xa4a2), }, - #endif - - #if defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE) - /* gadget zero, for testing */ --{ USB_DEVICE(0x0525, 0xa4a0), }, -+//{ USB_DEVICE(0x0525, 0xa4a0), }, - #endif -+ -+/* OPT Tester */ -+{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */ -+{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */ -+{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */ -+{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */ -+{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */ -+{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME */ -+{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */ -+{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */ -+ -+/* Sony cameras */ -+{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), }, -+ -+/* Memory Devices */ -+//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */ -+//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */ -+//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */ -+//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD */ -+{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/ -+//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */ -+ -+/* HP Printers */ -+//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */ -+//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */ -+ -+/* Speakers */ -+//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */ -+//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */ - - { } /* Terminating entry */ - }; - -+static inline void report_errors(struct usb_device *dev) -+{ -+ /* OTG MESSAGE: report errors here, customize to match your product */ -+ dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n", -+ le16_to_cpu(dev->descriptor.idVendor), -+ le16_to_cpu(dev->descriptor.idProduct)); -+ if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){ -+ dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n"); -+ } else { -+ dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n"); -+ } -+} -+ -+ - static int is_targeted(struct usb_device *dev) - { - struct usb_device_id *id = whitelist_table; -@@ -55,58 +104,83 @@ static int is_targeted(struct usb_device *dev) - return 1; - - /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */ -- if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a && -- le16_to_cpu(dev->descriptor.idProduct) == 0xbadd)) -- return 0; -- -- /* NOTE: can't use usb_match_id() since interface caches -- * aren't set up yet. this is cut/paste from that code. -- */ -- for (id = whitelist_table; id->match_flags; id++) { -- if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && -- id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) -- continue; -- -- if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && -- id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) -- continue; -- -- /* No need to test id->bcdDevice_lo != 0, since 0 is never -- greater than any unsigned number. */ -- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && -- (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) -- continue; -- -- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && -- (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) -- continue; -- -- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && -- (id->bDeviceClass != dev->descriptor.bDeviceClass)) -- continue; -- -- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && -- (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass)) -- continue; -- -- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && -- (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) -- continue; -+ if (dev->descriptor.idVendor == 0x1a0a && -+ dev->descriptor.idProduct == 0xbadd) { -+ return 0; -+ } else if (!enable_whitelist) { -+ return 1; -+ } else { -+ -+#ifdef DEBUG -+ dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n", -+ dev->descriptor.idVendor, -+ dev->descriptor.idProduct, -+ dev->descriptor.bDeviceClass, -+ dev->descriptor.bDeviceSubClass, -+ dev->descriptor.bDeviceProtocol); -+#endif - - return 1; -+ /* NOTE: can't use usb_match_id() since interface caches -+ * aren't set up yet. this is cut/paste from that code. -+ */ -+ for (id = whitelist_table; id->match_flags; id++) { -+#ifdef DEBUG -+ dev_dbg(&dev->dev, -+ "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n", -+ id->idVendor, -+ id->idProduct, -+ id->bDeviceClass, -+ id->bDeviceSubClass, -+ id->bDeviceProtocol); -+#endif -+ -+ if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && -+ id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) -+ continue; -+ -+ if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && -+ id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) -+ continue; -+ -+ /* No need to test id->bcdDevice_lo != 0, since 0 is never -+ greater than any unsigned number. */ -+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && -+ (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) -+ continue; -+ -+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && -+ (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) -+ continue; -+ -+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && -+ (id->bDeviceClass != dev->descriptor.bDeviceClass)) -+ continue; -+ -+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && -+ (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass)) -+ continue; -+ -+ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && -+ (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) -+ continue; -+ -+ return 1; -+ } - } - - /* add other match criteria here ... */ - -- -- /* OTG MESSAGE: report errors here, customize to match your product */ -- dev_err(&dev->dev, "device v%04x p%04x is not supported\n", -- le16_to_cpu(dev->descriptor.idVendor), -- le16_to_cpu(dev->descriptor.idProduct)); - #ifdef CONFIG_USB_OTG_WHITELIST -+ report_errors(dev); - return 0; - #else -- return 1; -+ if (enable_whitelist) { -+ report_errors(dev); -+ return 0; -+ } else { -+ return 1; -+ } - #endif - } - -diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c -new file mode 100644 -index 0000000..a896d73 ---- /dev/null -+++ b/drivers/usb/gadget/file_storage.c -@@ -0,0 +1,3676 @@ -+/* -+ * file_storage.c -- File-backed USB Storage Gadget, for USB development -+ * -+ * Copyright (C) 2003-2008 Alan Stern -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS 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. -+ */ -+ -+ -+/* -+ * The File-backed Storage Gadget acts as a USB Mass Storage device, -+ * appearing to the host as a disk drive or as a CD-ROM drive. In addition -+ * to providing an example of a genuinely useful gadget driver for a USB -+ * device, it also illustrates a technique of double-buffering for increased -+ * throughput. Last but not least, it gives an easy way to probe the -+ * behavior of the Mass Storage drivers in a USB host. -+ * -+ * Backing storage is provided by a regular file or a block device, specified -+ * by the "file" module parameter. Access can be limited to read-only by -+ * setting the optional "ro" module parameter. (For CD-ROM emulation, -+ * access is always read-only.) The gadget will indicate that it has -+ * removable media if the optional "removable" module parameter is set. -+ * -+ * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), -+ * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected -+ * by the optional "transport" module parameter. It also supports the -+ * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), -+ * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by -+ * the optional "protocol" module parameter. In addition, the default -+ * Vendor ID, Product ID, release number and serial number can be overridden. -+ * -+ * There is support for multiple logical units (LUNs), each of which has -+ * its own backing file. The number of LUNs can be set using the optional -+ * "luns" module parameter (anywhere from 1 to 8), and the corresponding -+ * files are specified using comma-separated lists for "file" and "ro". -+ * The default number of LUNs is taken from the number of "file" elements; -+ * it is 1 if "file" is not given. If "removable" is not set then a backing -+ * file must be specified for each LUN. If it is set, then an unspecified -+ * or empty backing filename means the LUN's medium is not loaded. Ideally -+ * each LUN would be settable independently as a disk drive or a CD-ROM -+ * drive, but currently all LUNs have to be the same type. The CD-ROM -+ * emulation includes a single data track and no audio tracks; hence there -+ * need be only one backing file per LUN. -+ * -+ * Requirements are modest; only a bulk-in and a bulk-out endpoint are -+ * needed (an interrupt-out endpoint is also needed for CBI). The memory -+ * requirement amounts to two 16K buffers, size configurable by a parameter. -+ * Support is included for both full-speed and high-speed operation. -+ * -+ * Note that the driver is slightly non-portable in that it assumes a -+ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and -+ * interrupt-in endpoints. With most device controllers this isn't an -+ * issue, but there may be some with hardware restrictions that prevent -+ * a buffer from being used by more than one endpoint. -+ * -+ * Module options: -+ * -+ * file=filename[,filename...] -+ * Required if "removable" is not set, names of -+ * the files or block devices used for -+ * backing storage -+ * serial=HHHH... Required serial number (string of hex chars) -+ * ro=b[,b...] Default false, booleans for read-only access -+ * removable Default false, boolean for removable media -+ * luns=N Default N = number of filenames, number of -+ * LUNs to support -+ * nofua=b[,b...] Default false, booleans for ignore FUA flag -+ * in SCSI WRITE(10,12) commands -+ * stall Default determined according to the type of -+ * USB device controller (usually true), -+ * boolean to permit the driver to halt -+ * bulk endpoints -+ * cdrom Default false, boolean for whether to emulate -+ * a CD-ROM drive -+ * transport=XXX Default BBB, transport name (CB, CBI, or BBB) -+ * protocol=YYY Default SCSI, protocol name (RBC, 8020 or -+ * ATAPI, QIC, UFI, 8070, or SCSI; -+ * also 1 - 6) -+ * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID -+ * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID -+ * release=0xRRRR Override the USB release number (bcdDevice) -+ * buflen=N Default N=16384, buffer size used (will be -+ * rounded down to a multiple of -+ * PAGE_CACHE_SIZE) -+ * -+ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro", -+ * "removable", "luns", "nofua", "stall", and "cdrom" options are available; -+ * default values are used for everything else. -+ * -+ * The pathnames of the backing files and the ro settings are available in -+ * the attribute files "file", "nofua", and "ro" in the lun subdirectory of -+ * the gadget's sysfs directory. If the "removable" option is set, writing to -+ * these files will simulate ejecting/loading the medium (writing an empty -+ * line means eject) and adjusting a write-enable tab. Changes to the ro -+ * setting are not allowed when the medium is loaded or if CD-ROM emulation -+ * is being used. -+ * -+ * This gadget driver is heavily based on "Gadget Zero" by David Brownell. -+ * The driver's SCSI command interface was based on the "Information -+ * technology - Small Computer System Interface - 2" document from -+ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at -+ * . The single exception -+ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the -+ * "Universal Serial Bus Mass Storage Class UFI Command Specification" -+ * document, Revision 1.0, December 14, 1998, available at -+ * . -+ */ -+ -+ -+/* -+ * Driver Design -+ * -+ * The FSG driver is fairly straightforward. There is a main kernel -+ * thread that handles most of the work. Interrupt routines field -+ * callbacks from the controller driver: bulk- and interrupt-request -+ * completion notifications, endpoint-0 events, and disconnect events. -+ * Completion events are passed to the main thread by wakeup calls. Many -+ * ep0 requests are handled at interrupt time, but SetInterface, -+ * SetConfiguration, and device reset requests are forwarded to the -+ * thread in the form of "exceptions" using SIGUSR1 signals (since they -+ * should interrupt any ongoing file I/O operations). -+ * -+ * The thread's main routine implements the standard command/data/status -+ * parts of a SCSI interaction. It and its subroutines are full of tests -+ * for pending signals/exceptions -- all this polling is necessary since -+ * the kernel has no setjmp/longjmp equivalents. (Maybe this is an -+ * indication that the driver really wants to be running in userspace.) -+ * An important point is that so long as the thread is alive it keeps an -+ * open reference to the backing file. This will prevent unmounting -+ * the backing file's underlying filesystem and could cause problems -+ * during system shutdown, for example. To prevent such problems, the -+ * thread catches INT, TERM, and KILL signals and converts them into -+ * an EXIT exception. -+ * -+ * In normal operation the main thread is started during the gadget's -+ * fsg_bind() callback and stopped during fsg_unbind(). But it can also -+ * exit when it receives a signal, and there's no point leaving the -+ * gadget running when the thread is dead. So just before the thread -+ * exits, it deregisters the gadget driver. This makes things a little -+ * tricky: The driver is deregistered at two places, and the exiting -+ * thread can indirectly call fsg_unbind() which in turn can tell the -+ * thread to exit. The first problem is resolved through the use of the -+ * REGISTERED atomic bitflag; the driver will only be deregistered once. -+ * The second problem is resolved by having fsg_unbind() check -+ * fsg->state; it won't try to stop the thread if the state is already -+ * FSG_STATE_TERMINATED. -+ * -+ * To provide maximum throughput, the driver uses a circular pipeline of -+ * buffer heads (struct fsg_buffhd). In principle the pipeline can be -+ * arbitrarily long; in practice the benefits don't justify having more -+ * than 2 stages (i.e., double buffering). But it helps to think of the -+ * pipeline as being a long one. Each buffer head contains a bulk-in and -+ * a bulk-out request pointer (since the buffer can be used for both -+ * output and input -- directions always are given from the host's -+ * point of view) as well as a pointer to the buffer and various state -+ * variables. -+ * -+ * Use of the pipeline follows a simple protocol. There is a variable -+ * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. -+ * At any time that buffer head may still be in use from an earlier -+ * request, so each buffer head has a state variable indicating whether -+ * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the -+ * buffer head to be EMPTY, filling the buffer either by file I/O or by -+ * USB I/O (during which the buffer head is BUSY), and marking the buffer -+ * head FULL when the I/O is complete. Then the buffer will be emptied -+ * (again possibly by USB I/O, during which it is marked BUSY) and -+ * finally marked EMPTY again (possibly by a completion routine). -+ * -+ * A module parameter tells the driver to avoid stalling the bulk -+ * endpoints wherever the transport specification allows. This is -+ * necessary for some UDCs like the SuperH, which cannot reliably clear a -+ * halt on a bulk endpoint. However, under certain circumstances the -+ * Bulk-only specification requires a stall. In such cases the driver -+ * will halt the endpoint and set a flag indicating that it should clear -+ * the halt in software during the next device reset. Hopefully this -+ * will permit everything to work correctly. Furthermore, although the -+ * specification allows the bulk-out endpoint to halt when the host sends -+ * too much data, implementing this would cause an unavoidable race. -+ * The driver will always use the "no-stall" approach for OUT transfers. -+ * -+ * One subtle point concerns sending status-stage responses for ep0 -+ * requests. Some of these requests, such as device reset, can involve -+ * interrupting an ongoing file I/O operation, which might take an -+ * arbitrarily long time. During that delay the host might give up on -+ * the original ep0 request and issue a new one. When that happens the -+ * driver should not notify the host about completion of the original -+ * request, as the host will no longer be waiting for it. So the driver -+ * assigns to each ep0 request a unique tag, and it keeps track of the -+ * tag value of the request associated with a long-running exception -+ * (device-reset, interface-change, or configuration-change). When the -+ * exception handler is finished, the status-stage response is submitted -+ * only if the current ep0 request tag is equal to the exception request -+ * tag. Thus only the most recently received ep0 request will get a -+ * status-stage response. -+ * -+ * Warning: This driver source file is too long. It ought to be split up -+ * into a header file plus about 3 separate .c files, to handle the details -+ * of the Gadget, USB Mass Storage, and SCSI protocols. -+ */ -+ -+ -+/* #define VERBOSE_DEBUG */ -+/* #define DUMP_MSGS */ -+ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "gadget_chips.h" -+ -+ -+ -+/* -+ * Kbuild is not very cooperative with respect to linking separately -+ * compiled library objects into one module. So for now we won't use -+ * separate compilation ... ensuring init/exit sections work to shrink -+ * the runtime footprint, and giving us at least some parts of what -+ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. -+ */ -+#include "usbstring.c" -+#include "config.c" -+#include "epautoconf.c" -+ -+/*-------------------------------------------------------------------------*/ -+ -+#define DRIVER_DESC "File-backed Storage Gadget" -+#define DRIVER_NAME "g_file_storage" -+#define DRIVER_VERSION "1 September 2010" -+ -+static char fsg_string_manufacturer[64]; -+static const char fsg_string_product[] = DRIVER_DESC; -+static const char fsg_string_config[] = "Self-powered"; -+static const char fsg_string_interface[] = "Mass Storage"; -+ -+ -+#include "storage_common.c" -+ -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_AUTHOR("Alan Stern"); -+MODULE_LICENSE("Dual BSD/GPL"); -+ -+/* -+ * This driver assumes self-powered hardware and has no way for users to -+ * trigger remote wakeup. It uses autoconfiguration to select endpoints -+ * and endpoint addresses. -+ */ -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+ -+/* Encapsulate the module parameter settings */ -+ -+static struct { -+ char *file[FSG_MAX_LUNS]; -+ char *serial; -+ bool ro[FSG_MAX_LUNS]; -+ bool nofua[FSG_MAX_LUNS]; -+ unsigned int num_filenames; -+ unsigned int num_ros; -+ unsigned int num_nofuas; -+ unsigned int nluns; -+ -+ bool removable; -+ bool can_stall; -+ bool cdrom; -+ -+ char *transport_parm; -+ char *protocol_parm; -+ unsigned short vendor; -+ unsigned short product; -+ unsigned short release; -+ unsigned int buflen; -+ -+ int transport_type; -+ char *transport_name; -+ int protocol_type; -+ char *protocol_name; -+ -+} mod_data = { // Default values -+ .transport_parm = "BBB", -+ .protocol_parm = "SCSI", -+ .removable = 0, -+ .can_stall = 1, -+ .cdrom = 0, -+ .vendor = FSG_VENDOR_ID, -+ .product = FSG_PRODUCT_ID, -+ .release = 0xffff, // Use controller chip type -+ .buflen = 16384, -+ }; -+ -+ -+module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames, -+ S_IRUGO); -+MODULE_PARM_DESC(file, "names of backing files or devices"); -+ -+module_param_named(serial, mod_data.serial, charp, S_IRUGO); -+MODULE_PARM_DESC(serial, "USB serial number"); -+ -+module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); -+MODULE_PARM_DESC(ro, "true to force read-only"); -+ -+module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas, -+ S_IRUGO); -+MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit"); -+ -+module_param_named(luns, mod_data.nluns, uint, S_IRUGO); -+MODULE_PARM_DESC(luns, "number of LUNs"); -+ -+module_param_named(removable, mod_data.removable, bool, S_IRUGO); -+MODULE_PARM_DESC(removable, "true to simulate removable media"); -+ -+module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); -+MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); -+ -+module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); -+MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); -+ -+/* In the non-TEST version, only the module parameters listed above -+ * are available. */ -+#ifdef CONFIG_USB_FILE_STORAGE_TEST -+ -+module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO); -+MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)"); -+ -+module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO); -+MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, " -+ "8070, or SCSI)"); -+ -+module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO); -+MODULE_PARM_DESC(vendor, "USB Vendor ID"); -+ -+module_param_named(product, mod_data.product, ushort, S_IRUGO); -+MODULE_PARM_DESC(product, "USB Product ID"); -+ -+module_param_named(release, mod_data.release, ushort, S_IRUGO); -+MODULE_PARM_DESC(release, "USB release number"); -+ -+module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); -+MODULE_PARM_DESC(buflen, "I/O buffer size"); -+ -+#endif /* CONFIG_USB_FILE_STORAGE_TEST */ -+ -+ -+/* -+ * These definitions will permit the compiler to avoid generating code for -+ * parts of the driver that aren't used in the non-TEST version. Even gcc -+ * can recognize when a test of a constant expression yields a dead code -+ * path. -+ */ -+ -+#ifdef CONFIG_USB_FILE_STORAGE_TEST -+ -+#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK) -+#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI) -+#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI) -+ -+#else -+ -+#define transport_is_bbb() 1 -+#define transport_is_cbi() 0 -+#define protocol_is_scsi() 1 -+ -+#endif /* CONFIG_USB_FILE_STORAGE_TEST */ -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+ -+struct fsg_dev { -+ /* lock protects: state, all the req_busy's, and cbbuf_cmnd */ -+ spinlock_t lock; -+ struct usb_gadget *gadget; -+ -+ /* filesem protects: backing files in use */ -+ struct rw_semaphore filesem; -+ -+ /* reference counting: wait until all LUNs are released */ -+ struct kref ref; -+ -+ struct usb_ep *ep0; // Handy copy of gadget->ep0 -+ struct usb_request *ep0req; // For control responses -+ unsigned int ep0_req_tag; -+ const char *ep0req_name; -+ -+ struct usb_request *intreq; // For interrupt responses -+ int intreq_busy; -+ struct fsg_buffhd *intr_buffhd; -+ -+ unsigned int bulk_out_maxpacket; -+ enum fsg_state state; // For exception handling -+ unsigned int exception_req_tag; -+ -+ u8 config, new_config; -+ -+ unsigned int running : 1; -+ unsigned int bulk_in_enabled : 1; -+ unsigned int bulk_out_enabled : 1; -+ unsigned int intr_in_enabled : 1; -+ unsigned int phase_error : 1; -+ unsigned int short_packet_received : 1; -+ unsigned int bad_lun_okay : 1; -+ -+ unsigned long atomic_bitflags; -+#define REGISTERED 0 -+#define IGNORE_BULK_OUT 1 -+#define SUSPENDED 2 -+ -+ struct usb_ep *bulk_in; -+ struct usb_ep *bulk_out; -+ struct usb_ep *intr_in; -+ -+ struct fsg_buffhd *next_buffhd_to_fill; -+ struct fsg_buffhd *next_buffhd_to_drain; -+ -+ int thread_wakeup_needed; -+ struct completion thread_notifier; -+ struct task_struct *thread_task; -+ -+ int cmnd_size; -+ u8 cmnd[MAX_COMMAND_SIZE]; -+ enum data_direction data_dir; -+ u32 data_size; -+ u32 data_size_from_cmnd; -+ u32 tag; -+ unsigned int lun; -+ u32 residue; -+ u32 usb_amount_left; -+ -+ /* The CB protocol offers no way for a host to know when a command -+ * has completed. As a result the next command may arrive early, -+ * and we will still have to handle it. For that reason we need -+ * a buffer to store new commands when using CB (or CBI, which -+ * does not oblige a host to wait for command completion either). */ -+ int cbbuf_cmnd_size; -+ u8 cbbuf_cmnd[MAX_COMMAND_SIZE]; -+ -+ unsigned int nluns; -+ struct fsg_lun *luns; -+ struct fsg_lun *curlun; -+ /* Must be the last entry */ -+ struct fsg_buffhd buffhds[]; -+}; -+ -+typedef void (*fsg_routine_t)(struct fsg_dev *); -+ -+static int exception_in_progress(struct fsg_dev *fsg) -+{ -+ return (fsg->state > FSG_STATE_IDLE); -+} -+ -+/* Make bulk-out requests be divisible by the maxpacket size */ -+static void set_bulk_out_req_length(struct fsg_dev *fsg, -+ struct fsg_buffhd *bh, unsigned int length) -+{ -+ unsigned int rem; -+ -+ bh->bulk_out_intended_length = length; -+ rem = length % fsg->bulk_out_maxpacket; -+ if (rem > 0) -+ length += fsg->bulk_out_maxpacket - rem; -+ bh->outreq->length = length; -+} -+ -+static struct fsg_dev *the_fsg; -+static struct usb_gadget_driver fsg_driver; -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) -+{ -+ const char *name; -+ -+ if (ep == fsg->bulk_in) -+ name = "bulk-in"; -+ else if (ep == fsg->bulk_out) -+ name = "bulk-out"; -+ else -+ name = ep->name; -+ DBG(fsg, "%s set halt\n", name); -+ return usb_ep_set_halt(ep); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* -+ * DESCRIPTORS ... most are static, but strings and (full) configuration -+ * descriptors are built on demand. Also the (static) config and interface -+ * descriptors are adjusted during fsg_bind(). -+ */ -+ -+/* There is only one configuration. */ -+#define CONFIG_VALUE 1 -+ -+static struct usb_device_descriptor -+device_desc = { -+ .bLength = sizeof device_desc, -+ .bDescriptorType = USB_DT_DEVICE, -+ -+ .bcdUSB = cpu_to_le16(0x0200), -+ .bDeviceClass = USB_CLASS_PER_INTERFACE, -+ -+ /* The next three values can be overridden by module parameters */ -+ .idVendor = cpu_to_le16(FSG_VENDOR_ID), -+ .idProduct = cpu_to_le16(FSG_PRODUCT_ID), -+ .bcdDevice = cpu_to_le16(0xffff), -+ -+ .iManufacturer = FSG_STRING_MANUFACTURER, -+ .iProduct = FSG_STRING_PRODUCT, -+ .iSerialNumber = FSG_STRING_SERIAL, -+ .bNumConfigurations = 1, -+}; -+ -+static struct usb_config_descriptor -+config_desc = { -+ .bLength = sizeof config_desc, -+ .bDescriptorType = USB_DT_CONFIG, -+ -+ /* wTotalLength computed by usb_gadget_config_buf() */ -+ .bNumInterfaces = 1, -+ .bConfigurationValue = CONFIG_VALUE, -+ .iConfiguration = FSG_STRING_CONFIG, -+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, -+ .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, -+}; -+ -+ -+static struct usb_qualifier_descriptor -+dev_qualifier = { -+ .bLength = sizeof dev_qualifier, -+ .bDescriptorType = USB_DT_DEVICE_QUALIFIER, -+ -+ .bcdUSB = cpu_to_le16(0x0200), -+ .bDeviceClass = USB_CLASS_PER_INTERFACE, -+ -+ .bNumConfigurations = 1, -+}; -+ -+static int populate_bos(struct fsg_dev *fsg, u8 *buf) -+{ -+ memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE); -+ buf += USB_DT_BOS_SIZE; -+ -+ memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE); -+ buf += USB_DT_USB_EXT_CAP_SIZE; -+ -+ memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE); -+ -+ return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE -+ + USB_DT_USB_EXT_CAP_SIZE; -+} -+ -+/* -+ * Config descriptors must agree with the code that sets configurations -+ * and with code managing interfaces and their altsettings. They must -+ * also handle different speeds and other-speed requests. -+ */ -+static int populate_config_buf(struct usb_gadget *gadget, -+ u8 *buf, u8 type, unsigned index) -+{ -+ enum usb_device_speed speed = gadget->speed; -+ int len; -+ const struct usb_descriptor_header **function; -+ -+ if (index > 0) -+ return -EINVAL; -+ -+ if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG) -+ speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed; -+ function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH -+ ? (const struct usb_descriptor_header **)fsg_hs_function -+ : (const struct usb_descriptor_header **)fsg_fs_function; -+ -+ /* for now, don't advertise srp-only devices */ -+ if (!gadget_is_otg(gadget)) -+ function++; -+ -+ len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function); -+ ((struct usb_config_descriptor *) buf)->bDescriptorType = type; -+ return len; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* These routines may be called in process context or in_irq */ -+ -+/* Caller must hold fsg->lock */ -+static void wakeup_thread(struct fsg_dev *fsg) -+{ -+ /* Tell the main thread that something has happened */ -+ fsg->thread_wakeup_needed = 1; -+ if (fsg->thread_task) -+ wake_up_process(fsg->thread_task); -+} -+ -+ -+static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) -+{ -+ unsigned long flags; -+ -+ /* Do nothing if a higher-priority exception is already in progress. -+ * If a lower-or-equal priority exception is in progress, preempt it -+ * and notify the main thread by sending it a signal. */ -+ spin_lock_irqsave(&fsg->lock, flags); -+ if (fsg->state <= new_state) { -+ fsg->exception_req_tag = fsg->ep0_req_tag; -+ fsg->state = new_state; -+ if (fsg->thread_task) -+ send_sig_info(SIGUSR1, SEND_SIG_FORCED, -+ fsg->thread_task); -+ } -+ spin_unlock_irqrestore(&fsg->lock, flags); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* The disconnect callback and ep0 routines. These always run in_irq, -+ * except that ep0_queue() is called in the main thread to acknowledge -+ * completion of various requests: set config, set interface, and -+ * Bulk-only device reset. */ -+ -+static void fsg_disconnect(struct usb_gadget *gadget) -+{ -+ struct fsg_dev *fsg = get_gadget_data(gadget); -+ -+ DBG(fsg, "disconnect or port reset\n"); -+ raise_exception(fsg, FSG_STATE_DISCONNECT); -+} -+ -+ -+static int ep0_queue(struct fsg_dev *fsg) -+{ -+ int rc; -+ -+ rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC); -+ if (rc != 0 && rc != -ESHUTDOWN) { -+ -+ /* We can't do much more than wait for a reset */ -+ WARNING(fsg, "error in submission: %s --> %d\n", -+ fsg->ep0->name, rc); -+ } -+ return rc; -+} -+ -+static void ep0_complete(struct usb_ep *ep, struct usb_request *req) -+{ -+ struct fsg_dev *fsg = ep->driver_data; -+ -+ if (req->actual > 0) -+ dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual); -+ if (req->status || req->actual != req->length) -+ DBG(fsg, "%s --> %d, %u/%u\n", __func__, -+ req->status, req->actual, req->length); -+ if (req->status == -ECONNRESET) // Request was cancelled -+ usb_ep_fifo_flush(ep); -+ -+ if (req->status == 0 && req->context) -+ ((fsg_routine_t) (req->context))(fsg); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Bulk and interrupt endpoint completion handlers. -+ * These always run in_irq. */ -+ -+static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) -+{ -+ struct fsg_dev *fsg = ep->driver_data; -+ struct fsg_buffhd *bh = req->context; -+ -+ if (req->status || req->actual != req->length) -+ DBG(fsg, "%s --> %d, %u/%u\n", __func__, -+ req->status, req->actual, req->length); -+ if (req->status == -ECONNRESET) // Request was cancelled -+ usb_ep_fifo_flush(ep); -+ -+ /* Hold the lock while we update the request and buffer states */ -+ smp_wmb(); -+ spin_lock(&fsg->lock); -+ bh->inreq_busy = 0; -+ bh->state = BUF_STATE_EMPTY; -+ wakeup_thread(fsg); -+ spin_unlock(&fsg->lock); -+} -+ -+static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) -+{ -+ struct fsg_dev *fsg = ep->driver_data; -+ struct fsg_buffhd *bh = req->context; -+ -+ dump_msg(fsg, "bulk-out", req->buf, req->actual); -+ if (req->status || req->actual != bh->bulk_out_intended_length) -+ DBG(fsg, "%s --> %d, %u/%u\n", __func__, -+ req->status, req->actual, -+ bh->bulk_out_intended_length); -+ if (req->status == -ECONNRESET) // Request was cancelled -+ usb_ep_fifo_flush(ep); -+ -+ /* Hold the lock while we update the request and buffer states */ -+ smp_wmb(); -+ spin_lock(&fsg->lock); -+ bh->outreq_busy = 0; -+ bh->state = BUF_STATE_FULL; -+ wakeup_thread(fsg); -+ spin_unlock(&fsg->lock); -+} -+ -+ -+#ifdef CONFIG_USB_FILE_STORAGE_TEST -+static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) -+{ -+ struct fsg_dev *fsg = ep->driver_data; -+ struct fsg_buffhd *bh = req->context; -+ -+ if (req->status || req->actual != req->length) -+ DBG(fsg, "%s --> %d, %u/%u\n", __func__, -+ req->status, req->actual, req->length); -+ if (req->status == -ECONNRESET) // Request was cancelled -+ usb_ep_fifo_flush(ep); -+ -+ /* Hold the lock while we update the request and buffer states */ -+ smp_wmb(); -+ spin_lock(&fsg->lock); -+ fsg->intreq_busy = 0; -+ bh->state = BUF_STATE_EMPTY; -+ wakeup_thread(fsg); -+ spin_unlock(&fsg->lock); -+} -+ -+#else -+static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) -+{} -+#endif /* CONFIG_USB_FILE_STORAGE_TEST */ -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Ep0 class-specific handlers. These always run in_irq. */ -+ -+#ifdef CONFIG_USB_FILE_STORAGE_TEST -+static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ struct usb_request *req = fsg->ep0req; -+ static u8 cbi_reset_cmnd[6] = { -+ SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff}; -+ -+ /* Error in command transfer? */ -+ if (req->status || req->length != req->actual || -+ req->actual < 6 || req->actual > MAX_COMMAND_SIZE) { -+ -+ /* Not all controllers allow a protocol stall after -+ * receiving control-out data, but we'll try anyway. */ -+ fsg_set_halt(fsg, fsg->ep0); -+ return; // Wait for reset -+ } -+ -+ /* Is it the special reset command? */ -+ if (req->actual >= sizeof cbi_reset_cmnd && -+ memcmp(req->buf, cbi_reset_cmnd, -+ sizeof cbi_reset_cmnd) == 0) { -+ -+ /* Raise an exception to stop the current operation -+ * and reinitialize our state. */ -+ DBG(fsg, "cbi reset request\n"); -+ raise_exception(fsg, FSG_STATE_RESET); -+ return; -+ } -+ -+ VDBG(fsg, "CB[I] accept device-specific command\n"); -+ spin_lock(&fsg->lock); -+ -+ /* Save the command for later */ -+ if (fsg->cbbuf_cmnd_size) -+ WARNING(fsg, "CB[I] overwriting previous command\n"); -+ fsg->cbbuf_cmnd_size = req->actual; -+ memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size); -+ -+ wakeup_thread(fsg); -+ spin_unlock(&fsg->lock); -+} -+ -+#else -+static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{} -+#endif /* CONFIG_USB_FILE_STORAGE_TEST */ -+ -+ -+static int class_setup_req(struct fsg_dev *fsg, -+ const struct usb_ctrlrequest *ctrl) -+{ -+ struct usb_request *req = fsg->ep0req; -+ int value = -EOPNOTSUPP; -+ u16 w_index = le16_to_cpu(ctrl->wIndex); -+ u16 w_value = le16_to_cpu(ctrl->wValue); -+ u16 w_length = le16_to_cpu(ctrl->wLength); -+ -+ if (!fsg->config) -+ return value; -+ -+ /* Handle Bulk-only class-specific requests */ -+ if (transport_is_bbb()) { -+ switch (ctrl->bRequest) { -+ -+ case US_BULK_RESET_REQUEST: -+ if (ctrl->bRequestType != (USB_DIR_OUT | -+ USB_TYPE_CLASS | USB_RECIP_INTERFACE)) -+ break; -+ if (w_index != 0 || w_value != 0 || w_length != 0) { -+ value = -EDOM; -+ break; -+ } -+ -+ /* Raise an exception to stop the current operation -+ * and reinitialize our state. */ -+ DBG(fsg, "bulk reset request\n"); -+ raise_exception(fsg, FSG_STATE_RESET); -+ value = DELAYED_STATUS; -+ break; -+ -+ case US_BULK_GET_MAX_LUN: -+ if (ctrl->bRequestType != (USB_DIR_IN | -+ USB_TYPE_CLASS | USB_RECIP_INTERFACE)) -+ break; -+ if (w_index != 0 || w_value != 0 || w_length != 1) { -+ value = -EDOM; -+ break; -+ } -+ VDBG(fsg, "get max LUN\n"); -+ *(u8 *) req->buf = fsg->nluns - 1; -+ value = 1; -+ break; -+ } -+ } -+ -+ /* Handle CBI class-specific requests */ -+ else { -+ switch (ctrl->bRequest) { -+ -+ case USB_CBI_ADSC_REQUEST: -+ if (ctrl->bRequestType != (USB_DIR_OUT | -+ USB_TYPE_CLASS | USB_RECIP_INTERFACE)) -+ break; -+ if (w_index != 0 || w_value != 0) { -+ value = -EDOM; -+ break; -+ } -+ if (w_length > MAX_COMMAND_SIZE) { -+ value = -EOVERFLOW; -+ break; -+ } -+ value = w_length; -+ fsg->ep0req->context = received_cbi_adsc; -+ break; -+ } -+ } -+ -+ if (value == -EOPNOTSUPP) -+ VDBG(fsg, -+ "unknown class-specific control req " -+ "%02x.%02x v%04x i%04x l%u\n", -+ ctrl->bRequestType, ctrl->bRequest, -+ le16_to_cpu(ctrl->wValue), w_index, w_length); -+ return value; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Ep0 standard request handlers. These always run in_irq. */ -+ -+static int standard_setup_req(struct fsg_dev *fsg, -+ const struct usb_ctrlrequest *ctrl) -+{ -+ struct usb_request *req = fsg->ep0req; -+ int value = -EOPNOTSUPP; -+ u16 w_index = le16_to_cpu(ctrl->wIndex); -+ u16 w_value = le16_to_cpu(ctrl->wValue); -+ -+ /* Usually this just stores reply data in the pre-allocated ep0 buffer, -+ * but config change events will also reconfigure hardware. */ -+ switch (ctrl->bRequest) { -+ -+ case USB_REQ_GET_DESCRIPTOR: -+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | -+ USB_RECIP_DEVICE)) -+ break; -+ switch (w_value >> 8) { -+ -+ case USB_DT_DEVICE: -+ VDBG(fsg, "get device descriptor\n"); -+ device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket; -+ value = sizeof device_desc; -+ memcpy(req->buf, &device_desc, value); -+ break; -+ case USB_DT_DEVICE_QUALIFIER: -+ VDBG(fsg, "get device qualifier\n"); -+ if (!gadget_is_dualspeed(fsg->gadget) || -+ fsg->gadget->speed == USB_SPEED_SUPER) -+ break; -+ /* -+ * Assume ep0 uses the same maxpacket value for both -+ * speeds -+ */ -+ dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; -+ value = sizeof dev_qualifier; -+ memcpy(req->buf, &dev_qualifier, value); -+ break; -+ -+ case USB_DT_OTHER_SPEED_CONFIG: -+ VDBG(fsg, "get other-speed config descriptor\n"); -+ if (!gadget_is_dualspeed(fsg->gadget) || -+ fsg->gadget->speed == USB_SPEED_SUPER) -+ break; -+ goto get_config; -+ case USB_DT_CONFIG: -+ VDBG(fsg, "get configuration descriptor\n"); -+get_config: -+ value = populate_config_buf(fsg->gadget, -+ req->buf, -+ w_value >> 8, -+ w_value & 0xff); -+ break; -+ -+ case USB_DT_STRING: -+ VDBG(fsg, "get string descriptor\n"); -+ -+ /* wIndex == language code */ -+ value = usb_gadget_get_string(&fsg_stringtab, -+ w_value & 0xff, req->buf); -+ break; -+ -+ case USB_DT_BOS: -+ VDBG(fsg, "get bos descriptor\n"); -+ -+ if (gadget_is_superspeed(fsg->gadget)) -+ value = populate_bos(fsg, req->buf); -+ break; -+ } -+ -+ break; -+ -+ /* One config, two speeds */ -+ case USB_REQ_SET_CONFIGURATION: -+ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | -+ USB_RECIP_DEVICE)) -+ break; -+ VDBG(fsg, "set configuration\n"); -+ if (w_value == CONFIG_VALUE || w_value == 0) { -+ fsg->new_config = w_value; -+ -+ /* Raise an exception to wipe out previous transaction -+ * state (queued bufs, etc) and set the new config. */ -+ raise_exception(fsg, FSG_STATE_CONFIG_CHANGE); -+ value = DELAYED_STATUS; -+ } -+ break; -+ case USB_REQ_GET_CONFIGURATION: -+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | -+ USB_RECIP_DEVICE)) -+ break; -+ VDBG(fsg, "get configuration\n"); -+ *(u8 *) req->buf = fsg->config; -+ value = 1; -+ break; -+ -+ case USB_REQ_SET_INTERFACE: -+ if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD | -+ USB_RECIP_INTERFACE)) -+ break; -+ if (fsg->config && w_index == 0) { -+ -+ /* Raise an exception to wipe out previous transaction -+ * state (queued bufs, etc) and install the new -+ * interface altsetting. */ -+ raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE); -+ value = DELAYED_STATUS; -+ } -+ break; -+ case USB_REQ_GET_INTERFACE: -+ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | -+ USB_RECIP_INTERFACE)) -+ break; -+ if (!fsg->config) -+ break; -+ if (w_index != 0) { -+ value = -EDOM; -+ break; -+ } -+ VDBG(fsg, "get interface\n"); -+ *(u8 *) req->buf = 0; -+ value = 1; -+ break; -+ -+ default: -+ VDBG(fsg, -+ "unknown control req %02x.%02x v%04x i%04x l%u\n", -+ ctrl->bRequestType, ctrl->bRequest, -+ w_value, w_index, le16_to_cpu(ctrl->wLength)); -+ } -+ -+ return value; -+} -+ -+ -+static int fsg_setup(struct usb_gadget *gadget, -+ const struct usb_ctrlrequest *ctrl) -+{ -+ struct fsg_dev *fsg = get_gadget_data(gadget); -+ int rc; -+ int w_length = le16_to_cpu(ctrl->wLength); -+ -+ ++fsg->ep0_req_tag; // Record arrival of a new request -+ fsg->ep0req->context = NULL; -+ fsg->ep0req->length = 0; -+ dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); -+ -+ if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) -+ rc = class_setup_req(fsg, ctrl); -+ else -+ rc = standard_setup_req(fsg, ctrl); -+ -+ /* Respond with data/status or defer until later? */ -+ if (rc >= 0 && rc != DELAYED_STATUS) { -+ rc = min(rc, w_length); -+ fsg->ep0req->length = rc; -+ fsg->ep0req->zero = rc < w_length; -+ fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? -+ "ep0-in" : "ep0-out"); -+ rc = ep0_queue(fsg); -+ } -+ -+ /* Device either stalls (rc < 0) or reports success */ -+ return rc; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* All the following routines run in process context */ -+ -+ -+/* Use this for bulk or interrupt transfers, not ep0 */ -+static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, -+ struct usb_request *req, int *pbusy, -+ enum fsg_buffer_state *state) -+{ -+ int rc; -+ -+ if (ep == fsg->bulk_in) -+ dump_msg(fsg, "bulk-in", req->buf, req->length); -+ else if (ep == fsg->intr_in) -+ dump_msg(fsg, "intr-in", req->buf, req->length); -+ -+ spin_lock_irq(&fsg->lock); -+ *pbusy = 1; -+ *state = BUF_STATE_BUSY; -+ spin_unlock_irq(&fsg->lock); -+ rc = usb_ep_queue(ep, req, GFP_KERNEL); -+ if (rc != 0) { -+ *pbusy = 0; -+ *state = BUF_STATE_EMPTY; -+ -+ /* We can't do much more than wait for a reset */ -+ -+ /* Note: currently the net2280 driver fails zero-length -+ * submissions if DMA is enabled. */ -+ if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && -+ req->length == 0)) -+ WARNING(fsg, "error in submission: %s --> %d\n", -+ ep->name, rc); -+ } -+} -+ -+ -+static int sleep_thread(struct fsg_dev *fsg) -+{ -+ int rc = 0; -+ -+ /* Wait until a signal arrives or we are woken up */ -+ for (;;) { -+ try_to_freeze(); -+ set_current_state(TASK_INTERRUPTIBLE); -+ if (signal_pending(current)) { -+ rc = -EINTR; -+ break; -+ } -+ if (fsg->thread_wakeup_needed) -+ break; -+ schedule(); -+ } -+ __set_current_state(TASK_RUNNING); -+ fsg->thread_wakeup_needed = 0; -+ return rc; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int do_read(struct fsg_dev *fsg) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ u32 lba; -+ struct fsg_buffhd *bh; -+ int rc; -+ u32 amount_left; -+ loff_t file_offset, file_offset_tmp; -+ unsigned int amount; -+ ssize_t nread; -+ -+ /* Get the starting Logical Block Address and check that it's -+ * not too big */ -+ if (fsg->cmnd[0] == READ_6) -+ lba = get_unaligned_be24(&fsg->cmnd[1]); -+ else { -+ lba = get_unaligned_be32(&fsg->cmnd[2]); -+ -+ /* We allow DPO (Disable Page Out = don't save data in the -+ * cache) and FUA (Force Unit Access = don't read from the -+ * cache), but we don't implement them. */ -+ if ((fsg->cmnd[1] & ~0x18) != 0) { -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ } -+ if (lba >= curlun->num_sectors) { -+ curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -+ return -EINVAL; -+ } -+ file_offset = ((loff_t) lba) << curlun->blkbits; -+ -+ /* Carry out the file reads */ -+ amount_left = fsg->data_size_from_cmnd; -+ if (unlikely(amount_left == 0)) -+ return -EIO; // No default reply -+ -+ for (;;) { -+ -+ /* Figure out how much we need to read: -+ * Try to read the remaining amount. -+ * But don't read more than the buffer size. -+ * And don't try to read past the end of the file. -+ */ -+ amount = min((unsigned int) amount_left, mod_data.buflen); -+ amount = min((loff_t) amount, -+ curlun->file_length - file_offset); -+ -+ /* Wait for the next buffer to become available */ -+ bh = fsg->next_buffhd_to_fill; -+ while (bh->state != BUF_STATE_EMPTY) { -+ rc = sleep_thread(fsg); -+ if (rc) -+ return rc; -+ } -+ -+ /* If we were asked to read past the end of file, -+ * end with an empty buffer. */ -+ if (amount == 0) { -+ curlun->sense_data = -+ SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -+ curlun->sense_data_info = file_offset >> curlun->blkbits; -+ curlun->info_valid = 1; -+ bh->inreq->length = 0; -+ bh->state = BUF_STATE_FULL; -+ break; -+ } -+ -+ /* Perform the read */ -+ file_offset_tmp = file_offset; -+ nread = vfs_read(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -+ VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, -+ (unsigned long long) file_offset, -+ (int) nread); -+ if (signal_pending(current)) -+ return -EINTR; -+ -+ if (nread < 0) { -+ LDBG(curlun, "error in file read: %d\n", -+ (int) nread); -+ nread = 0; -+ } else if (nread < amount) { -+ LDBG(curlun, "partial file read: %d/%u\n", -+ (int) nread, amount); -+ nread = round_down(nread, curlun->blksize); -+ } -+ file_offset += nread; -+ amount_left -= nread; -+ fsg->residue -= nread; -+ -+ /* Except at the end of the transfer, nread will be -+ * equal to the buffer size, which is divisible by the -+ * bulk-in maxpacket size. -+ */ -+ bh->inreq->length = nread; -+ bh->state = BUF_STATE_FULL; -+ -+ /* If an error occurred, report it and its position */ -+ if (nread < amount) { -+ curlun->sense_data = SS_UNRECOVERED_READ_ERROR; -+ curlun->sense_data_info = file_offset >> curlun->blkbits; -+ curlun->info_valid = 1; -+ break; -+ } -+ -+ if (amount_left == 0) -+ break; // No more left to read -+ -+ /* Send this buffer and go read some more */ -+ bh->inreq->zero = 0; -+ start_transfer(fsg, fsg->bulk_in, bh->inreq, -+ &bh->inreq_busy, &bh->state); -+ fsg->next_buffhd_to_fill = bh->next; -+ } -+ -+ return -EIO; // No default reply -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int do_write(struct fsg_dev *fsg) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ u32 lba; -+ struct fsg_buffhd *bh; -+ int get_some_more; -+ u32 amount_left_to_req, amount_left_to_write; -+ loff_t usb_offset, file_offset, file_offset_tmp; -+ unsigned int amount; -+ ssize_t nwritten; -+ int rc; -+ -+ if (curlun->ro) { -+ curlun->sense_data = SS_WRITE_PROTECTED; -+ return -EINVAL; -+ } -+ spin_lock(&curlun->filp->f_lock); -+ curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait -+ spin_unlock(&curlun->filp->f_lock); -+ -+ /* Get the starting Logical Block Address and check that it's -+ * not too big */ -+ if (fsg->cmnd[0] == WRITE_6) -+ lba = get_unaligned_be24(&fsg->cmnd[1]); -+ else { -+ lba = get_unaligned_be32(&fsg->cmnd[2]); -+ -+ /* We allow DPO (Disable Page Out = don't save data in the -+ * cache) and FUA (Force Unit Access = write directly to the -+ * medium). We don't implement DPO; we implement FUA by -+ * performing synchronous output. */ -+ if ((fsg->cmnd[1] & ~0x18) != 0) { -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ /* FUA */ -+ if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) { -+ spin_lock(&curlun->filp->f_lock); -+ curlun->filp->f_flags |= O_DSYNC; -+ spin_unlock(&curlun->filp->f_lock); -+ } -+ } -+ if (lba >= curlun->num_sectors) { -+ curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -+ return -EINVAL; -+ } -+ -+ /* Carry out the file writes */ -+ get_some_more = 1; -+ file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits; -+ amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd; -+ -+ while (amount_left_to_write > 0) { -+ -+ /* Queue a request for more data from the host */ -+ bh = fsg->next_buffhd_to_fill; -+ if (bh->state == BUF_STATE_EMPTY && get_some_more) { -+ -+ /* Figure out how much we want to get: -+ * Try to get the remaining amount, -+ * but not more than the buffer size. -+ */ -+ amount = min(amount_left_to_req, mod_data.buflen); -+ -+ /* Beyond the end of the backing file? */ -+ if (usb_offset >= curlun->file_length) { -+ get_some_more = 0; -+ curlun->sense_data = -+ SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -+ curlun->sense_data_info = usb_offset >> curlun->blkbits; -+ curlun->info_valid = 1; -+ continue; -+ } -+ -+ /* Get the next buffer */ -+ usb_offset += amount; -+ fsg->usb_amount_left -= amount; -+ amount_left_to_req -= amount; -+ if (amount_left_to_req == 0) -+ get_some_more = 0; -+ -+ /* Except at the end of the transfer, amount will be -+ * equal to the buffer size, which is divisible by -+ * the bulk-out maxpacket size. -+ */ -+ set_bulk_out_req_length(fsg, bh, amount); -+ start_transfer(fsg, fsg->bulk_out, bh->outreq, -+ &bh->outreq_busy, &bh->state); -+ fsg->next_buffhd_to_fill = bh->next; -+ continue; -+ } -+ -+ /* Write the received data to the backing file */ -+ bh = fsg->next_buffhd_to_drain; -+ if (bh->state == BUF_STATE_EMPTY && !get_some_more) -+ break; // We stopped early -+ if (bh->state == BUF_STATE_FULL) { -+ smp_rmb(); -+ fsg->next_buffhd_to_drain = bh->next; -+ bh->state = BUF_STATE_EMPTY; -+ -+ /* Did something go wrong with the transfer? */ -+ if (bh->outreq->status != 0) { -+ curlun->sense_data = SS_COMMUNICATION_FAILURE; -+ curlun->sense_data_info = file_offset >> curlun->blkbits; -+ curlun->info_valid = 1; -+ break; -+ } -+ -+ amount = bh->outreq->actual; -+ if (curlun->file_length - file_offset < amount) { -+ LERROR(curlun, -+ "write %u @ %llu beyond end %llu\n", -+ amount, (unsigned long long) file_offset, -+ (unsigned long long) curlun->file_length); -+ amount = curlun->file_length - file_offset; -+ } -+ -+ /* Don't accept excess data. The spec doesn't say -+ * what to do in this case. We'll ignore the error. -+ */ -+ amount = min(amount, bh->bulk_out_intended_length); -+ -+ /* Don't write a partial block */ -+ amount = round_down(amount, curlun->blksize); -+ if (amount == 0) -+ goto empty_write; -+ -+ /* Perform the write */ -+ file_offset_tmp = file_offset; -+ nwritten = vfs_write(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -+ VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, -+ (unsigned long long) file_offset, -+ (int) nwritten); -+ if (signal_pending(current)) -+ return -EINTR; // Interrupted! -+ -+ if (nwritten < 0) { -+ LDBG(curlun, "error in file write: %d\n", -+ (int) nwritten); -+ nwritten = 0; -+ } else if (nwritten < amount) { -+ LDBG(curlun, "partial file write: %d/%u\n", -+ (int) nwritten, amount); -+ nwritten = round_down(nwritten, curlun->blksize); -+ } -+ file_offset += nwritten; -+ amount_left_to_write -= nwritten; -+ fsg->residue -= nwritten; -+ -+ /* If an error occurred, report it and its position */ -+ if (nwritten < amount) { -+ curlun->sense_data = SS_WRITE_ERROR; -+ curlun->sense_data_info = file_offset >> curlun->blkbits; -+ curlun->info_valid = 1; -+ break; -+ } -+ -+ empty_write: -+ /* Did the host decide to stop early? */ -+ if (bh->outreq->actual < bh->bulk_out_intended_length) { -+ fsg->short_packet_received = 1; -+ break; -+ } -+ continue; -+ } -+ -+ /* Wait for something to happen */ -+ rc = sleep_thread(fsg); -+ if (rc) -+ return rc; -+ } -+ -+ return -EIO; // No default reply -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int do_synchronize_cache(struct fsg_dev *fsg) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ int rc; -+ -+ /* We ignore the requested LBA and write out all file's -+ * dirty data buffers. */ -+ rc = fsg_lun_fsync_sub(curlun); -+ if (rc) -+ curlun->sense_data = SS_WRITE_ERROR; -+ return 0; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void invalidate_sub(struct fsg_lun *curlun) -+{ -+ struct file *filp = curlun->filp; -+ struct inode *inode = filp->f_path.dentry->d_inode; -+ unsigned long rc; -+ -+ rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); -+ VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc); -+} -+ -+static int do_verify(struct fsg_dev *fsg) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ u32 lba; -+ u32 verification_length; -+ struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; -+ loff_t file_offset, file_offset_tmp; -+ u32 amount_left; -+ unsigned int amount; -+ ssize_t nread; -+ -+ /* Get the starting Logical Block Address and check that it's -+ * not too big */ -+ lba = get_unaligned_be32(&fsg->cmnd[2]); -+ if (lba >= curlun->num_sectors) { -+ curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -+ return -EINVAL; -+ } -+ -+ /* We allow DPO (Disable Page Out = don't save data in the -+ * cache) but we don't implement it. */ -+ if ((fsg->cmnd[1] & ~0x10) != 0) { -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ -+ verification_length = get_unaligned_be16(&fsg->cmnd[7]); -+ if (unlikely(verification_length == 0)) -+ return -EIO; // No default reply -+ -+ /* Prepare to carry out the file verify */ -+ amount_left = verification_length << curlun->blkbits; -+ file_offset = ((loff_t) lba) << curlun->blkbits; -+ -+ /* Write out all the dirty buffers before invalidating them */ -+ fsg_lun_fsync_sub(curlun); -+ if (signal_pending(current)) -+ return -EINTR; -+ -+ invalidate_sub(curlun); -+ if (signal_pending(current)) -+ return -EINTR; -+ -+ /* Just try to read the requested blocks */ -+ while (amount_left > 0) { -+ -+ /* Figure out how much we need to read: -+ * Try to read the remaining amount, but not more than -+ * the buffer size. -+ * And don't try to read past the end of the file. -+ */ -+ amount = min((unsigned int) amount_left, mod_data.buflen); -+ amount = min((loff_t) amount, -+ curlun->file_length - file_offset); -+ if (amount == 0) { -+ curlun->sense_data = -+ SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -+ curlun->sense_data_info = file_offset >> curlun->blkbits; -+ curlun->info_valid = 1; -+ break; -+ } -+ -+ /* Perform the read */ -+ file_offset_tmp = file_offset; -+ nread = vfs_read(curlun->filp, -+ (char __user *) bh->buf, -+ amount, &file_offset_tmp); -+ VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, -+ (unsigned long long) file_offset, -+ (int) nread); -+ if (signal_pending(current)) -+ return -EINTR; -+ -+ if (nread < 0) { -+ LDBG(curlun, "error in file verify: %d\n", -+ (int) nread); -+ nread = 0; -+ } else if (nread < amount) { -+ LDBG(curlun, "partial file verify: %d/%u\n", -+ (int) nread, amount); -+ nread = round_down(nread, curlun->blksize); -+ } -+ if (nread == 0) { -+ curlun->sense_data = SS_UNRECOVERED_READ_ERROR; -+ curlun->sense_data_info = file_offset >> curlun->blkbits; -+ curlun->info_valid = 1; -+ break; -+ } -+ file_offset += nread; -+ amount_left -= nread; -+ } -+ return 0; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ u8 *buf = (u8 *) bh->buf; -+ -+ static char vendor_id[] = "Linux "; -+ static char product_disk_id[] = "File-Stor Gadget"; -+ static char product_cdrom_id[] = "File-CD Gadget "; -+ -+ if (!fsg->curlun) { // Unsupported LUNs are okay -+ fsg->bad_lun_okay = 1; -+ memset(buf, 0, 36); -+ buf[0] = 0x7f; // Unsupported, no device-type -+ buf[4] = 31; // Additional length -+ return 36; -+ } -+ -+ memset(buf, 0, 8); -+ buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK); -+ if (mod_data.removable) -+ buf[1] = 0x80; -+ buf[2] = 2; // ANSI SCSI level 2 -+ buf[3] = 2; // SCSI-2 INQUIRY data format -+ buf[4] = 31; // Additional length -+ // No special options -+ sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, -+ (mod_data.cdrom ? product_cdrom_id : -+ product_disk_id), -+ mod_data.release); -+ return 36; -+} -+ -+ -+static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ u8 *buf = (u8 *) bh->buf; -+ u32 sd, sdinfo; -+ int valid; -+ -+ /* -+ * From the SCSI-2 spec., section 7.9 (Unit attention condition): -+ * -+ * If a REQUEST SENSE command is received from an initiator -+ * with a pending unit attention condition (before the target -+ * generates the contingent allegiance condition), then the -+ * target shall either: -+ * a) report any pending sense data and preserve the unit -+ * attention condition on the logical unit, or, -+ * b) report the unit attention condition, may discard any -+ * pending sense data, and clear the unit attention -+ * condition on the logical unit for that initiator. -+ * -+ * FSG normally uses option a); enable this code to use option b). -+ */ -+#if 0 -+ if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { -+ curlun->sense_data = curlun->unit_attention_data; -+ curlun->unit_attention_data = SS_NO_SENSE; -+ } -+#endif -+ -+ if (!curlun) { // Unsupported LUNs are okay -+ fsg->bad_lun_okay = 1; -+ sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; -+ sdinfo = 0; -+ valid = 0; -+ } else { -+ sd = curlun->sense_data; -+ sdinfo = curlun->sense_data_info; -+ valid = curlun->info_valid << 7; -+ curlun->sense_data = SS_NO_SENSE; -+ curlun->sense_data_info = 0; -+ curlun->info_valid = 0; -+ } -+ -+ memset(buf, 0, 18); -+ buf[0] = valid | 0x70; // Valid, current error -+ buf[2] = SK(sd); -+ put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ -+ buf[7] = 18 - 8; // Additional sense length -+ buf[12] = ASC(sd); -+ buf[13] = ASCQ(sd); -+ return 18; -+} -+ -+ -+static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ u32 lba = get_unaligned_be32(&fsg->cmnd[2]); -+ int pmi = fsg->cmnd[8]; -+ u8 *buf = (u8 *) bh->buf; -+ -+ /* Check the PMI and LBA fields */ -+ if (pmi > 1 || (pmi == 0 && lba != 0)) { -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ -+ put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); -+ /* Max logical block */ -+ put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */ -+ return 8; -+} -+ -+ -+static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ int msf = fsg->cmnd[1] & 0x02; -+ u32 lba = get_unaligned_be32(&fsg->cmnd[2]); -+ u8 *buf = (u8 *) bh->buf; -+ -+ if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */ -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ if (lba >= curlun->num_sectors) { -+ curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; -+ return -EINVAL; -+ } -+ -+ memset(buf, 0, 8); -+ buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ -+ store_cdrom_address(&buf[4], msf, lba); -+ return 8; -+} -+ -+ -+static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ int msf = fsg->cmnd[1] & 0x02; -+ int start_track = fsg->cmnd[6]; -+ u8 *buf = (u8 *) bh->buf; -+ -+ if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ -+ start_track > 1) { -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ -+ memset(buf, 0, 20); -+ buf[1] = (20-2); /* TOC data length */ -+ buf[2] = 1; /* First track number */ -+ buf[3] = 1; /* Last track number */ -+ buf[5] = 0x16; /* Data track, copying allowed */ -+ buf[6] = 0x01; /* Only track is number 1 */ -+ store_cdrom_address(&buf[8], msf, 0); -+ -+ buf[13] = 0x16; /* Lead-out track is data */ -+ buf[14] = 0xAA; /* Lead-out track number */ -+ store_cdrom_address(&buf[16], msf, curlun->num_sectors); -+ return 20; -+} -+ -+ -+static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ int mscmnd = fsg->cmnd[0]; -+ u8 *buf = (u8 *) bh->buf; -+ u8 *buf0 = buf; -+ int pc, page_code; -+ int changeable_values, all_pages; -+ int valid_page = 0; -+ int len, limit; -+ -+ if ((fsg->cmnd[1] & ~0x08) != 0) { // Mask away DBD -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ pc = fsg->cmnd[2] >> 6; -+ page_code = fsg->cmnd[2] & 0x3f; -+ if (pc == 3) { -+ curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; -+ return -EINVAL; -+ } -+ changeable_values = (pc == 1); -+ all_pages = (page_code == 0x3f); -+ -+ /* Write the mode parameter header. Fixed values are: default -+ * medium type, no cache control (DPOFUA), and no block descriptors. -+ * The only variable value is the WriteProtect bit. We will fill in -+ * the mode data length later. */ -+ memset(buf, 0, 8); -+ if (mscmnd == MODE_SENSE) { -+ buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA -+ buf += 4; -+ limit = 255; -+ } else { // MODE_SENSE_10 -+ buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA -+ buf += 8; -+ limit = 65535; // Should really be mod_data.buflen -+ } -+ -+ /* No block descriptors */ -+ -+ /* The mode pages, in numerical order. The only page we support -+ * is the Caching page. */ -+ if (page_code == 0x08 || all_pages) { -+ valid_page = 1; -+ buf[0] = 0x08; // Page code -+ buf[1] = 10; // Page length -+ memset(buf+2, 0, 10); // None of the fields are changeable -+ -+ if (!changeable_values) { -+ buf[2] = 0x04; // Write cache enable, -+ // Read cache not disabled -+ // No cache retention priorities -+ put_unaligned_be16(0xffff, &buf[4]); -+ /* Don't disable prefetch */ -+ /* Minimum prefetch = 0 */ -+ put_unaligned_be16(0xffff, &buf[8]); -+ /* Maximum prefetch */ -+ put_unaligned_be16(0xffff, &buf[10]); -+ /* Maximum prefetch ceiling */ -+ } -+ buf += 12; -+ } -+ -+ /* Check that a valid page was requested and the mode data length -+ * isn't too long. */ -+ len = buf - buf0; -+ if (!valid_page || len > limit) { -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ -+ /* Store the mode data length */ -+ if (mscmnd == MODE_SENSE) -+ buf0[0] = len - 1; -+ else -+ put_unaligned_be16(len - 2, buf0); -+ return len; -+} -+ -+ -+static int do_start_stop(struct fsg_dev *fsg) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ int loej, start; -+ -+ if (!mod_data.removable) { -+ curlun->sense_data = SS_INVALID_COMMAND; -+ return -EINVAL; -+ } -+ -+ // int immed = fsg->cmnd[1] & 0x01; -+ loej = fsg->cmnd[4] & 0x02; -+ start = fsg->cmnd[4] & 0x01; -+ -+#ifdef CONFIG_USB_FILE_STORAGE_TEST -+ if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed -+ (fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ -+ if (!start) { -+ -+ /* Are we allowed to unload the media? */ -+ if (curlun->prevent_medium_removal) { -+ LDBG(curlun, "unload attempt prevented\n"); -+ curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; -+ return -EINVAL; -+ } -+ if (loej) { // Simulate an unload/eject -+ up_read(&fsg->filesem); -+ down_write(&fsg->filesem); -+ fsg_lun_close(curlun); -+ up_write(&fsg->filesem); -+ down_read(&fsg->filesem); -+ } -+ } else { -+ -+ /* Our emulation doesn't support mounting; the medium is -+ * available for use as soon as it is loaded. */ -+ if (!fsg_lun_is_open(curlun)) { -+ curlun->sense_data = SS_MEDIUM_NOT_PRESENT; -+ return -EINVAL; -+ } -+ } -+#endif -+ return 0; -+} -+ -+ -+static int do_prevent_allow(struct fsg_dev *fsg) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ int prevent; -+ -+ if (!mod_data.removable) { -+ curlun->sense_data = SS_INVALID_COMMAND; -+ return -EINVAL; -+ } -+ -+ prevent = fsg->cmnd[4] & 0x01; -+ if ((fsg->cmnd[4] & ~0x01) != 0) { // Mask away Prevent -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ -+ if (curlun->prevent_medium_removal && !prevent) -+ fsg_lun_fsync_sub(curlun); -+ curlun->prevent_medium_removal = prevent; -+ return 0; -+} -+ -+ -+static int do_read_format_capacities(struct fsg_dev *fsg, -+ struct fsg_buffhd *bh) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ u8 *buf = (u8 *) bh->buf; -+ -+ buf[0] = buf[1] = buf[2] = 0; -+ buf[3] = 8; // Only the Current/Maximum Capacity Descriptor -+ buf += 4; -+ -+ put_unaligned_be32(curlun->num_sectors, &buf[0]); -+ /* Number of blocks */ -+ put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */ -+ buf[4] = 0x02; /* Current capacity */ -+ return 12; -+} -+ -+ -+static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ -+ /* We don't support MODE SELECT */ -+ curlun->sense_data = SS_INVALID_COMMAND; -+ return -EINVAL; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int halt_bulk_in_endpoint(struct fsg_dev *fsg) -+{ -+ int rc; -+ -+ rc = fsg_set_halt(fsg, fsg->bulk_in); -+ if (rc == -EAGAIN) -+ VDBG(fsg, "delayed bulk-in endpoint halt\n"); -+ while (rc != 0) { -+ if (rc != -EAGAIN) { -+ WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); -+ rc = 0; -+ break; -+ } -+ -+ /* Wait for a short time and then try again */ -+ if (msleep_interruptible(100) != 0) -+ return -EINTR; -+ rc = usb_ep_set_halt(fsg->bulk_in); -+ } -+ return rc; -+} -+ -+static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) -+{ -+ int rc; -+ -+ DBG(fsg, "bulk-in set wedge\n"); -+ rc = usb_ep_set_wedge(fsg->bulk_in); -+ if (rc == -EAGAIN) -+ VDBG(fsg, "delayed bulk-in endpoint wedge\n"); -+ while (rc != 0) { -+ if (rc != -EAGAIN) { -+ WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); -+ rc = 0; -+ break; -+ } -+ -+ /* Wait for a short time and then try again */ -+ if (msleep_interruptible(100) != 0) -+ return -EINTR; -+ rc = usb_ep_set_wedge(fsg->bulk_in); -+ } -+ return rc; -+} -+ -+static int throw_away_data(struct fsg_dev *fsg) -+{ -+ struct fsg_buffhd *bh; -+ u32 amount; -+ int rc; -+ -+ while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY || -+ fsg->usb_amount_left > 0) { -+ -+ /* Throw away the data in a filled buffer */ -+ if (bh->state == BUF_STATE_FULL) { -+ smp_rmb(); -+ bh->state = BUF_STATE_EMPTY; -+ fsg->next_buffhd_to_drain = bh->next; -+ -+ /* A short packet or an error ends everything */ -+ if (bh->outreq->actual < bh->bulk_out_intended_length || -+ bh->outreq->status != 0) { -+ raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); -+ return -EINTR; -+ } -+ continue; -+ } -+ -+ /* Try to submit another request if we need one */ -+ bh = fsg->next_buffhd_to_fill; -+ if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) { -+ amount = min(fsg->usb_amount_left, -+ (u32) mod_data.buflen); -+ -+ /* Except at the end of the transfer, amount will be -+ * equal to the buffer size, which is divisible by -+ * the bulk-out maxpacket size. -+ */ -+ set_bulk_out_req_length(fsg, bh, amount); -+ start_transfer(fsg, fsg->bulk_out, bh->outreq, -+ &bh->outreq_busy, &bh->state); -+ fsg->next_buffhd_to_fill = bh->next; -+ fsg->usb_amount_left -= amount; -+ continue; -+ } -+ -+ /* Otherwise wait for something to happen */ -+ rc = sleep_thread(fsg); -+ if (rc) -+ return rc; -+ } -+ return 0; -+} -+ -+ -+static int finish_reply(struct fsg_dev *fsg) -+{ -+ struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; -+ int rc = 0; -+ -+ switch (fsg->data_dir) { -+ case DATA_DIR_NONE: -+ break; // Nothing to send -+ -+ /* If we don't know whether the host wants to read or write, -+ * this must be CB or CBI with an unknown command. We mustn't -+ * try to send or receive any data. So stall both bulk pipes -+ * if we can and wait for a reset. */ -+ case DATA_DIR_UNKNOWN: -+ if (mod_data.can_stall) { -+ fsg_set_halt(fsg, fsg->bulk_out); -+ rc = halt_bulk_in_endpoint(fsg); -+ } -+ break; -+ -+ /* All but the last buffer of data must have already been sent */ -+ case DATA_DIR_TO_HOST: -+ if (fsg->data_size == 0) -+ ; // Nothing to send -+ -+ /* If there's no residue, simply send the last buffer */ -+ else if (fsg->residue == 0) { -+ bh->inreq->zero = 0; -+ start_transfer(fsg, fsg->bulk_in, bh->inreq, -+ &bh->inreq_busy, &bh->state); -+ fsg->next_buffhd_to_fill = bh->next; -+ } -+ -+ /* There is a residue. For CB and CBI, simply mark the end -+ * of the data with a short packet. However, if we are -+ * allowed to stall, there was no data at all (residue == -+ * data_size), and the command failed (invalid LUN or -+ * sense data is set), then halt the bulk-in endpoint -+ * instead. */ -+ else if (!transport_is_bbb()) { -+ if (mod_data.can_stall && -+ fsg->residue == fsg->data_size && -+ (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) { -+ bh->state = BUF_STATE_EMPTY; -+ rc = halt_bulk_in_endpoint(fsg); -+ } else { -+ bh->inreq->zero = 1; -+ start_transfer(fsg, fsg->bulk_in, bh->inreq, -+ &bh->inreq_busy, &bh->state); -+ fsg->next_buffhd_to_fill = bh->next; -+ } -+ } -+ -+ /* -+ * For Bulk-only, mark the end of the data with a short -+ * packet. If we are allowed to stall, halt the bulk-in -+ * endpoint. (Note: This violates the Bulk-Only Transport -+ * specification, which requires us to pad the data if we -+ * don't halt the endpoint. Presumably nobody will mind.) -+ */ -+ else { -+ bh->inreq->zero = 1; -+ start_transfer(fsg, fsg->bulk_in, bh->inreq, -+ &bh->inreq_busy, &bh->state); -+ fsg->next_buffhd_to_fill = bh->next; -+ if (mod_data.can_stall) -+ rc = halt_bulk_in_endpoint(fsg); -+ } -+ break; -+ -+ /* We have processed all we want from the data the host has sent. -+ * There may still be outstanding bulk-out requests. */ -+ case DATA_DIR_FROM_HOST: -+ if (fsg->residue == 0) -+ ; // Nothing to receive -+ -+ /* Did the host stop sending unexpectedly early? */ -+ else if (fsg->short_packet_received) { -+ raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); -+ rc = -EINTR; -+ } -+ -+ /* We haven't processed all the incoming data. Even though -+ * we may be allowed to stall, doing so would cause a race. -+ * The controller may already have ACK'ed all the remaining -+ * bulk-out packets, in which case the host wouldn't see a -+ * STALL. Not realizing the endpoint was halted, it wouldn't -+ * clear the halt -- leading to problems later on. */ -+#if 0 -+ else if (mod_data.can_stall) { -+ fsg_set_halt(fsg, fsg->bulk_out); -+ raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); -+ rc = -EINTR; -+ } -+#endif -+ -+ /* We can't stall. Read in the excess data and throw it -+ * all away. */ -+ else -+ rc = throw_away_data(fsg); -+ break; -+ } -+ return rc; -+} -+ -+ -+static int send_status(struct fsg_dev *fsg) -+{ -+ struct fsg_lun *curlun = fsg->curlun; -+ struct fsg_buffhd *bh; -+ int rc; -+ u8 status = US_BULK_STAT_OK; -+ u32 sd, sdinfo = 0; -+ -+ /* Wait for the next buffer to become available */ -+ bh = fsg->next_buffhd_to_fill; -+ while (bh->state != BUF_STATE_EMPTY) { -+ rc = sleep_thread(fsg); -+ if (rc) -+ return rc; -+ } -+ -+ if (curlun) { -+ sd = curlun->sense_data; -+ sdinfo = curlun->sense_data_info; -+ } else if (fsg->bad_lun_okay) -+ sd = SS_NO_SENSE; -+ else -+ sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; -+ -+ if (fsg->phase_error) { -+ DBG(fsg, "sending phase-error status\n"); -+ status = US_BULK_STAT_PHASE; -+ sd = SS_INVALID_COMMAND; -+ } else if (sd != SS_NO_SENSE) { -+ DBG(fsg, "sending command-failure status\n"); -+ status = US_BULK_STAT_FAIL; -+ VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" -+ " info x%x\n", -+ SK(sd), ASC(sd), ASCQ(sd), sdinfo); -+ } -+ -+ if (transport_is_bbb()) { -+ struct bulk_cs_wrap *csw = bh->buf; -+ -+ /* Store and send the Bulk-only CSW */ -+ csw->Signature = cpu_to_le32(US_BULK_CS_SIGN); -+ csw->Tag = fsg->tag; -+ csw->Residue = cpu_to_le32(fsg->residue); -+ csw->Status = status; -+ -+ bh->inreq->length = US_BULK_CS_WRAP_LEN; -+ bh->inreq->zero = 0; -+ start_transfer(fsg, fsg->bulk_in, bh->inreq, -+ &bh->inreq_busy, &bh->state); -+ -+ } else if (mod_data.transport_type == USB_PR_CB) { -+ -+ /* Control-Bulk transport has no status phase! */ -+ return 0; -+ -+ } else { // USB_PR_CBI -+ struct interrupt_data *buf = bh->buf; -+ -+ /* Store and send the Interrupt data. UFI sends the ASC -+ * and ASCQ bytes. Everything else sends a Type (which -+ * is always 0) and the status Value. */ -+ if (mod_data.protocol_type == USB_SC_UFI) { -+ buf->bType = ASC(sd); -+ buf->bValue = ASCQ(sd); -+ } else { -+ buf->bType = 0; -+ buf->bValue = status; -+ } -+ fsg->intreq->length = CBI_INTERRUPT_DATA_LEN; -+ -+ fsg->intr_buffhd = bh; // Point to the right buffhd -+ fsg->intreq->buf = bh->inreq->buf; -+ fsg->intreq->context = bh; -+ start_transfer(fsg, fsg->intr_in, fsg->intreq, -+ &fsg->intreq_busy, &bh->state); -+ } -+ -+ fsg->next_buffhd_to_fill = bh->next; -+ return 0; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Check whether the command is properly formed and whether its data size -+ * and direction agree with the values we already have. */ -+static int check_command(struct fsg_dev *fsg, int cmnd_size, -+ enum data_direction data_dir, unsigned int mask, -+ int needs_medium, const char *name) -+{ -+ int i; -+ int lun = fsg->cmnd[1] >> 5; -+ static const char dirletter[4] = {'u', 'o', 'i', 'n'}; -+ char hdlen[20]; -+ struct fsg_lun *curlun; -+ -+ /* Adjust the expected cmnd_size for protocol encapsulation padding. -+ * Transparent SCSI doesn't pad. */ -+ if (protocol_is_scsi()) -+ ; -+ -+ /* There's some disagreement as to whether RBC pads commands or not. -+ * We'll play it safe and accept either form. */ -+ else if (mod_data.protocol_type == USB_SC_RBC) { -+ if (fsg->cmnd_size == 12) -+ cmnd_size = 12; -+ -+ /* All the other protocols pad to 12 bytes */ -+ } else -+ cmnd_size = 12; -+ -+ hdlen[0] = 0; -+ if (fsg->data_dir != DATA_DIR_UNKNOWN) -+ sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir], -+ fsg->data_size); -+ VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", -+ name, cmnd_size, dirletter[(int) data_dir], -+ fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen); -+ -+ /* We can't reply at all until we know the correct data direction -+ * and size. */ -+ if (fsg->data_size_from_cmnd == 0) -+ data_dir = DATA_DIR_NONE; -+ if (fsg->data_dir == DATA_DIR_UNKNOWN) { // CB or CBI -+ fsg->data_dir = data_dir; -+ fsg->data_size = fsg->data_size_from_cmnd; -+ -+ } else { // Bulk-only -+ if (fsg->data_size < fsg->data_size_from_cmnd) { -+ -+ /* Host data size < Device data size is a phase error. -+ * Carry out the command, but only transfer as much -+ * as we are allowed. */ -+ fsg->data_size_from_cmnd = fsg->data_size; -+ fsg->phase_error = 1; -+ } -+ } -+ fsg->residue = fsg->usb_amount_left = fsg->data_size; -+ -+ /* Conflicting data directions is a phase error */ -+ if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) { -+ fsg->phase_error = 1; -+ return -EINVAL; -+ } -+ -+ /* Verify the length of the command itself */ -+ if (cmnd_size != fsg->cmnd_size) { -+ -+ /* Special case workaround: There are plenty of buggy SCSI -+ * implementations. Many have issues with cbw->Length -+ * field passing a wrong command size. For those cases we -+ * always try to work around the problem by using the length -+ * sent by the host side provided it is at least as large -+ * as the correct command length. -+ * Examples of such cases would be MS-Windows, which issues -+ * REQUEST SENSE with cbw->Length == 12 where it should -+ * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and -+ * REQUEST SENSE with cbw->Length == 10 where it should -+ * be 6 as well. -+ */ -+ if (cmnd_size <= fsg->cmnd_size) { -+ DBG(fsg, "%s is buggy! Expected length %d " -+ "but we got %d\n", name, -+ cmnd_size, fsg->cmnd_size); -+ cmnd_size = fsg->cmnd_size; -+ } else { -+ fsg->phase_error = 1; -+ return -EINVAL; -+ } -+ } -+ -+ /* Check that the LUN values are consistent */ -+ if (transport_is_bbb()) { -+ if (fsg->lun != lun) -+ DBG(fsg, "using LUN %d from CBW, " -+ "not LUN %d from CDB\n", -+ fsg->lun, lun); -+ } -+ -+ /* Check the LUN */ -+ curlun = fsg->curlun; -+ if (curlun) { -+ if (fsg->cmnd[0] != REQUEST_SENSE) { -+ curlun->sense_data = SS_NO_SENSE; -+ curlun->sense_data_info = 0; -+ curlun->info_valid = 0; -+ } -+ } else { -+ fsg->bad_lun_okay = 0; -+ -+ /* INQUIRY and REQUEST SENSE commands are explicitly allowed -+ * to use unsupported LUNs; all others may not. */ -+ if (fsg->cmnd[0] != INQUIRY && -+ fsg->cmnd[0] != REQUEST_SENSE) { -+ DBG(fsg, "unsupported LUN %d\n", fsg->lun); -+ return -EINVAL; -+ } -+ } -+ -+ /* If a unit attention condition exists, only INQUIRY and -+ * REQUEST SENSE commands are allowed; anything else must fail. */ -+ if (curlun && curlun->unit_attention_data != SS_NO_SENSE && -+ fsg->cmnd[0] != INQUIRY && -+ fsg->cmnd[0] != REQUEST_SENSE) { -+ curlun->sense_data = curlun->unit_attention_data; -+ curlun->unit_attention_data = SS_NO_SENSE; -+ return -EINVAL; -+ } -+ -+ /* Check that only command bytes listed in the mask are non-zero */ -+ fsg->cmnd[1] &= 0x1f; // Mask away the LUN -+ for (i = 1; i < cmnd_size; ++i) { -+ if (fsg->cmnd[i] && !(mask & (1 << i))) { -+ if (curlun) -+ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; -+ return -EINVAL; -+ } -+ } -+ -+ /* If the medium isn't mounted and the command needs to access -+ * it, return an error. */ -+ if (curlun && !fsg_lun_is_open(curlun) && needs_medium) { -+ curlun->sense_data = SS_MEDIUM_NOT_PRESENT; -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* wrapper of check_command for data size in blocks handling */ -+static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size, -+ enum data_direction data_dir, unsigned int mask, -+ int needs_medium, const char *name) -+{ -+ if (fsg->curlun) -+ fsg->data_size_from_cmnd <<= fsg->curlun->blkbits; -+ return check_command(fsg, cmnd_size, data_dir, -+ mask, needs_medium, name); -+} -+ -+static int do_scsi_command(struct fsg_dev *fsg) -+{ -+ struct fsg_buffhd *bh; -+ int rc; -+ int reply = -EINVAL; -+ int i; -+ static char unknown[16]; -+ -+ dump_cdb(fsg); -+ -+ /* Wait for the next buffer to become available for data or status */ -+ bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill; -+ while (bh->state != BUF_STATE_EMPTY) { -+ rc = sleep_thread(fsg); -+ if (rc) -+ return rc; -+ } -+ fsg->phase_error = 0; -+ fsg->short_packet_received = 0; -+ -+ down_read(&fsg->filesem); // We're using the backing file -+ switch (fsg->cmnd[0]) { -+ -+ case INQUIRY: -+ fsg->data_size_from_cmnd = fsg->cmnd[4]; -+ if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, -+ (1<<4), 0, -+ "INQUIRY")) == 0) -+ reply = do_inquiry(fsg, bh); -+ break; -+ -+ case MODE_SELECT: -+ fsg->data_size_from_cmnd = fsg->cmnd[4]; -+ if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, -+ (1<<1) | (1<<4), 0, -+ "MODE SELECT(6)")) == 0) -+ reply = do_mode_select(fsg, bh); -+ break; -+ -+ case MODE_SELECT_10: -+ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -+ if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, -+ (1<<1) | (3<<7), 0, -+ "MODE SELECT(10)")) == 0) -+ reply = do_mode_select(fsg, bh); -+ break; -+ -+ case MODE_SENSE: -+ fsg->data_size_from_cmnd = fsg->cmnd[4]; -+ if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, -+ (1<<1) | (1<<2) | (1<<4), 0, -+ "MODE SENSE(6)")) == 0) -+ reply = do_mode_sense(fsg, bh); -+ break; -+ -+ case MODE_SENSE_10: -+ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -+ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -+ (1<<1) | (1<<2) | (3<<7), 0, -+ "MODE SENSE(10)")) == 0) -+ reply = do_mode_sense(fsg, bh); -+ break; -+ -+ case ALLOW_MEDIUM_REMOVAL: -+ fsg->data_size_from_cmnd = 0; -+ if ((reply = check_command(fsg, 6, DATA_DIR_NONE, -+ (1<<4), 0, -+ "PREVENT-ALLOW MEDIUM REMOVAL")) == 0) -+ reply = do_prevent_allow(fsg); -+ break; -+ -+ case READ_6: -+ i = fsg->cmnd[4]; -+ fsg->data_size_from_cmnd = (i == 0) ? 256 : i; -+ if ((reply = check_command_size_in_blocks(fsg, 6, -+ DATA_DIR_TO_HOST, -+ (7<<1) | (1<<4), 1, -+ "READ(6)")) == 0) -+ reply = do_read(fsg); -+ break; -+ -+ case READ_10: -+ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -+ if ((reply = check_command_size_in_blocks(fsg, 10, -+ DATA_DIR_TO_HOST, -+ (1<<1) | (0xf<<2) | (3<<7), 1, -+ "READ(10)")) == 0) -+ reply = do_read(fsg); -+ break; -+ -+ case READ_12: -+ fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]); -+ if ((reply = check_command_size_in_blocks(fsg, 12, -+ DATA_DIR_TO_HOST, -+ (1<<1) | (0xf<<2) | (0xf<<6), 1, -+ "READ(12)")) == 0) -+ reply = do_read(fsg); -+ break; -+ -+ case READ_CAPACITY: -+ fsg->data_size_from_cmnd = 8; -+ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -+ (0xf<<2) | (1<<8), 1, -+ "READ CAPACITY")) == 0) -+ reply = do_read_capacity(fsg, bh); -+ break; -+ -+ case READ_HEADER: -+ if (!mod_data.cdrom) -+ goto unknown_cmnd; -+ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -+ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -+ (3<<7) | (0x1f<<1), 1, -+ "READ HEADER")) == 0) -+ reply = do_read_header(fsg, bh); -+ break; -+ -+ case READ_TOC: -+ if (!mod_data.cdrom) -+ goto unknown_cmnd; -+ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -+ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -+ (7<<6) | (1<<1), 1, -+ "READ TOC")) == 0) -+ reply = do_read_toc(fsg, bh); -+ break; -+ -+ case READ_FORMAT_CAPACITIES: -+ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -+ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, -+ (3<<7), 1, -+ "READ FORMAT CAPACITIES")) == 0) -+ reply = do_read_format_capacities(fsg, bh); -+ break; -+ -+ case REQUEST_SENSE: -+ fsg->data_size_from_cmnd = fsg->cmnd[4]; -+ if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, -+ (1<<4), 0, -+ "REQUEST SENSE")) == 0) -+ reply = do_request_sense(fsg, bh); -+ break; -+ -+ case START_STOP: -+ fsg->data_size_from_cmnd = 0; -+ if ((reply = check_command(fsg, 6, DATA_DIR_NONE, -+ (1<<1) | (1<<4), 0, -+ "START-STOP UNIT")) == 0) -+ reply = do_start_stop(fsg); -+ break; -+ -+ case SYNCHRONIZE_CACHE: -+ fsg->data_size_from_cmnd = 0; -+ if ((reply = check_command(fsg, 10, DATA_DIR_NONE, -+ (0xf<<2) | (3<<7), 1, -+ "SYNCHRONIZE CACHE")) == 0) -+ reply = do_synchronize_cache(fsg); -+ break; -+ -+ case TEST_UNIT_READY: -+ fsg->data_size_from_cmnd = 0; -+ reply = check_command(fsg, 6, DATA_DIR_NONE, -+ 0, 1, -+ "TEST UNIT READY"); -+ break; -+ -+ /* Although optional, this command is used by MS-Windows. We -+ * support a minimal version: BytChk must be 0. */ -+ case VERIFY: -+ fsg->data_size_from_cmnd = 0; -+ if ((reply = check_command(fsg, 10, DATA_DIR_NONE, -+ (1<<1) | (0xf<<2) | (3<<7), 1, -+ "VERIFY")) == 0) -+ reply = do_verify(fsg); -+ break; -+ -+ case WRITE_6: -+ i = fsg->cmnd[4]; -+ fsg->data_size_from_cmnd = (i == 0) ? 256 : i; -+ if ((reply = check_command_size_in_blocks(fsg, 6, -+ DATA_DIR_FROM_HOST, -+ (7<<1) | (1<<4), 1, -+ "WRITE(6)")) == 0) -+ reply = do_write(fsg); -+ break; -+ -+ case WRITE_10: -+ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); -+ if ((reply = check_command_size_in_blocks(fsg, 10, -+ DATA_DIR_FROM_HOST, -+ (1<<1) | (0xf<<2) | (3<<7), 1, -+ "WRITE(10)")) == 0) -+ reply = do_write(fsg); -+ break; -+ -+ case WRITE_12: -+ fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]); -+ if ((reply = check_command_size_in_blocks(fsg, 12, -+ DATA_DIR_FROM_HOST, -+ (1<<1) | (0xf<<2) | (0xf<<6), 1, -+ "WRITE(12)")) == 0) -+ reply = do_write(fsg); -+ break; -+ -+ /* Some mandatory commands that we recognize but don't implement. -+ * They don't mean much in this setting. It's left as an exercise -+ * for anyone interested to implement RESERVE and RELEASE in terms -+ * of Posix locks. */ -+ case FORMAT_UNIT: -+ case RELEASE: -+ case RESERVE: -+ case SEND_DIAGNOSTIC: -+ // Fall through -+ -+ default: -+ unknown_cmnd: -+ fsg->data_size_from_cmnd = 0; -+ sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); -+ if ((reply = check_command(fsg, fsg->cmnd_size, -+ DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) { -+ fsg->curlun->sense_data = SS_INVALID_COMMAND; -+ reply = -EINVAL; -+ } -+ break; -+ } -+ up_read(&fsg->filesem); -+ -+ if (reply == -EINTR || signal_pending(current)) -+ return -EINTR; -+ -+ /* Set up the single reply buffer for finish_reply() */ -+ if (reply == -EINVAL) -+ reply = 0; // Error reply length -+ if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) { -+ reply = min((u32) reply, fsg->data_size_from_cmnd); -+ bh->inreq->length = reply; -+ bh->state = BUF_STATE_FULL; -+ fsg->residue -= reply; -+ } // Otherwise it's already set -+ -+ return 0; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) -+{ -+ struct usb_request *req = bh->outreq; -+ struct bulk_cb_wrap *cbw = req->buf; -+ -+ /* Was this a real packet? Should it be ignored? */ -+ if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) -+ return -EINVAL; -+ -+ /* Is the CBW valid? */ -+ if (req->actual != US_BULK_CB_WRAP_LEN || -+ cbw->Signature != cpu_to_le32( -+ US_BULK_CB_SIGN)) { -+ DBG(fsg, "invalid CBW: len %u sig 0x%x\n", -+ req->actual, -+ le32_to_cpu(cbw->Signature)); -+ -+ /* The Bulk-only spec says we MUST stall the IN endpoint -+ * (6.6.1), so it's unavoidable. It also says we must -+ * retain this state until the next reset, but there's -+ * no way to tell the controller driver it should ignore -+ * Clear-Feature(HALT) requests. -+ * -+ * We aren't required to halt the OUT endpoint; instead -+ * we can simply accept and discard any data received -+ * until the next reset. */ -+ wedge_bulk_in_endpoint(fsg); -+ set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); -+ return -EINVAL; -+ } -+ -+ /* Is the CBW meaningful? */ -+ if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || -+ cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { -+ DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " -+ "cmdlen %u\n", -+ cbw->Lun, cbw->Flags, cbw->Length); -+ -+ /* We can do anything we want here, so let's stall the -+ * bulk pipes if we are allowed to. */ -+ if (mod_data.can_stall) { -+ fsg_set_halt(fsg, fsg->bulk_out); -+ halt_bulk_in_endpoint(fsg); -+ } -+ return -EINVAL; -+ } -+ -+ /* Save the command for later */ -+ fsg->cmnd_size = cbw->Length; -+ memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size); -+ if (cbw->Flags & US_BULK_FLAG_IN) -+ fsg->data_dir = DATA_DIR_TO_HOST; -+ else -+ fsg->data_dir = DATA_DIR_FROM_HOST; -+ fsg->data_size = le32_to_cpu(cbw->DataTransferLength); -+ if (fsg->data_size == 0) -+ fsg->data_dir = DATA_DIR_NONE; -+ fsg->lun = cbw->Lun; -+ fsg->tag = cbw->Tag; -+ return 0; -+} -+ -+ -+static int get_next_command(struct fsg_dev *fsg) -+{ -+ struct fsg_buffhd *bh; -+ int rc = 0; -+ -+ if (transport_is_bbb()) { -+ -+ /* Wait for the next buffer to become available */ -+ bh = fsg->next_buffhd_to_fill; -+ while (bh->state != BUF_STATE_EMPTY) { -+ rc = sleep_thread(fsg); -+ if (rc) -+ return rc; -+ } -+ -+ /* Queue a request to read a Bulk-only CBW */ -+ set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN); -+ start_transfer(fsg, fsg->bulk_out, bh->outreq, -+ &bh->outreq_busy, &bh->state); -+ -+ /* We will drain the buffer in software, which means we -+ * can reuse it for the next filling. No need to advance -+ * next_buffhd_to_fill. */ -+ -+ /* Wait for the CBW to arrive */ -+ while (bh->state != BUF_STATE_FULL) { -+ rc = sleep_thread(fsg); -+ if (rc) -+ return rc; -+ } -+ smp_rmb(); -+ rc = received_cbw(fsg, bh); -+ bh->state = BUF_STATE_EMPTY; -+ -+ } else { // USB_PR_CB or USB_PR_CBI -+ -+ /* Wait for the next command to arrive */ -+ while (fsg->cbbuf_cmnd_size == 0) { -+ rc = sleep_thread(fsg); -+ if (rc) -+ return rc; -+ } -+ -+ /* Is the previous status interrupt request still busy? -+ * The host is allowed to skip reading the status, -+ * so we must cancel it. */ -+ if (fsg->intreq_busy) -+ usb_ep_dequeue(fsg->intr_in, fsg->intreq); -+ -+ /* Copy the command and mark the buffer empty */ -+ fsg->data_dir = DATA_DIR_UNKNOWN; -+ spin_lock_irq(&fsg->lock); -+ fsg->cmnd_size = fsg->cbbuf_cmnd_size; -+ memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size); -+ fsg->cbbuf_cmnd_size = 0; -+ spin_unlock_irq(&fsg->lock); -+ -+ /* Use LUN from the command */ -+ fsg->lun = fsg->cmnd[1] >> 5; -+ } -+ -+ /* Update current lun */ -+ if (fsg->lun >= 0 && fsg->lun < fsg->nluns) -+ fsg->curlun = &fsg->luns[fsg->lun]; -+ else -+ fsg->curlun = NULL; -+ -+ return rc; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep, -+ const struct usb_endpoint_descriptor *d) -+{ -+ int rc; -+ -+ ep->driver_data = fsg; -+ ep->desc = d; -+ rc = usb_ep_enable(ep); -+ if (rc) -+ ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc); -+ return rc; -+} -+ -+static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep, -+ struct usb_request **preq) -+{ -+ *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); -+ if (*preq) -+ return 0; -+ ERROR(fsg, "can't allocate request for %s\n", ep->name); -+ return -ENOMEM; -+} -+ -+/* -+ * Reset interface setting and re-init endpoint state (toggle etc). -+ * Call with altsetting < 0 to disable the interface. The only other -+ * available altsetting is 0, which enables the interface. -+ */ -+static int do_set_interface(struct fsg_dev *fsg, int altsetting) -+{ -+ int rc = 0; -+ int i; -+ const struct usb_endpoint_descriptor *d; -+ -+ if (fsg->running) -+ DBG(fsg, "reset interface\n"); -+ -+reset: -+ /* Deallocate the requests */ -+ for (i = 0; i < fsg_num_buffers; ++i) { -+ struct fsg_buffhd *bh = &fsg->buffhds[i]; -+ -+ if (bh->inreq) { -+ usb_ep_free_request(fsg->bulk_in, bh->inreq); -+ bh->inreq = NULL; -+ } -+ if (bh->outreq) { -+ usb_ep_free_request(fsg->bulk_out, bh->outreq); -+ bh->outreq = NULL; -+ } -+ } -+ if (fsg->intreq) { -+ usb_ep_free_request(fsg->intr_in, fsg->intreq); -+ fsg->intreq = NULL; -+ } -+ -+ /* Disable the endpoints */ -+ if (fsg->bulk_in_enabled) { -+ usb_ep_disable(fsg->bulk_in); -+ fsg->bulk_in_enabled = 0; -+ } -+ if (fsg->bulk_out_enabled) { -+ usb_ep_disable(fsg->bulk_out); -+ fsg->bulk_out_enabled = 0; -+ } -+ if (fsg->intr_in_enabled) { -+ usb_ep_disable(fsg->intr_in); -+ fsg->intr_in_enabled = 0; -+ } -+ -+ fsg->running = 0; -+ if (altsetting < 0 || rc != 0) -+ return rc; -+ -+ DBG(fsg, "set interface %d\n", altsetting); -+ -+ /* Enable the endpoints */ -+ d = fsg_ep_desc(fsg->gadget, -+ &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc, -+ &fsg_ss_bulk_in_desc); -+ if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) -+ goto reset; -+ fsg->bulk_in_enabled = 1; -+ -+ d = fsg_ep_desc(fsg->gadget, -+ &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc, -+ &fsg_ss_bulk_out_desc); -+ if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) -+ goto reset; -+ fsg->bulk_out_enabled = 1; -+ fsg->bulk_out_maxpacket = usb_endpoint_maxp(d); -+ clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); -+ -+ if (transport_is_cbi()) { -+ d = fsg_ep_desc(fsg->gadget, -+ &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc, -+ &fsg_ss_intr_in_desc); -+ if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) -+ goto reset; -+ fsg->intr_in_enabled = 1; -+ } -+ -+ /* Allocate the requests */ -+ for (i = 0; i < fsg_num_buffers; ++i) { -+ struct fsg_buffhd *bh = &fsg->buffhds[i]; -+ -+ if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) -+ goto reset; -+ if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0) -+ goto reset; -+ bh->inreq->buf = bh->outreq->buf = bh->buf; -+ bh->inreq->context = bh->outreq->context = bh; -+ bh->inreq->complete = bulk_in_complete; -+ bh->outreq->complete = bulk_out_complete; -+ } -+ if (transport_is_cbi()) { -+ if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0) -+ goto reset; -+ fsg->intreq->complete = intr_in_complete; -+ } -+ -+ fsg->running = 1; -+ for (i = 0; i < fsg->nluns; ++i) -+ fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; -+ return rc; -+} -+ -+ -+/* -+ * Change our operational configuration. This code must agree with the code -+ * that returns config descriptors, and with interface altsetting code. -+ * -+ * It's also responsible for power management interactions. Some -+ * configurations might not work with our current power sources. -+ * For now we just assume the gadget is always self-powered. -+ */ -+static int do_set_config(struct fsg_dev *fsg, u8 new_config) -+{ -+ int rc = 0; -+ -+ /* Disable the single interface */ -+ if (fsg->config != 0) { -+ DBG(fsg, "reset config\n"); -+ fsg->config = 0; -+ rc = do_set_interface(fsg, -1); -+ } -+ -+ /* Enable the interface */ -+ if (new_config != 0) { -+ fsg->config = new_config; -+ if ((rc = do_set_interface(fsg, 0)) != 0) -+ fsg->config = 0; // Reset on errors -+ else -+ INFO(fsg, "%s config #%d\n", -+ usb_speed_string(fsg->gadget->speed), -+ fsg->config); -+ } -+ return rc; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void handle_exception(struct fsg_dev *fsg) -+{ -+ siginfo_t info; -+ int sig; -+ int i; -+ int num_active; -+ struct fsg_buffhd *bh; -+ enum fsg_state old_state; -+ u8 new_config; -+ struct fsg_lun *curlun; -+ unsigned int exception_req_tag; -+ int rc; -+ -+ /* Clear the existing signals. Anything but SIGUSR1 is converted -+ * into a high-priority EXIT exception. */ -+ for (;;) { -+ sig = dequeue_signal_lock(current, ¤t->blocked, &info); -+ if (!sig) -+ break; -+ if (sig != SIGUSR1) { -+ if (fsg->state < FSG_STATE_EXIT) -+ DBG(fsg, "Main thread exiting on signal\n"); -+ raise_exception(fsg, FSG_STATE_EXIT); -+ } -+ } -+ -+ /* Cancel all the pending transfers */ -+ if (fsg->intreq_busy) -+ usb_ep_dequeue(fsg->intr_in, fsg->intreq); -+ for (i = 0; i < fsg_num_buffers; ++i) { -+ bh = &fsg->buffhds[i]; -+ if (bh->inreq_busy) -+ usb_ep_dequeue(fsg->bulk_in, bh->inreq); -+ if (bh->outreq_busy) -+ usb_ep_dequeue(fsg->bulk_out, bh->outreq); -+ } -+ -+ /* Wait until everything is idle */ -+ for (;;) { -+ num_active = fsg->intreq_busy; -+ for (i = 0; i < fsg_num_buffers; ++i) { -+ bh = &fsg->buffhds[i]; -+ num_active += bh->inreq_busy + bh->outreq_busy; -+ } -+ if (num_active == 0) -+ break; -+ if (sleep_thread(fsg)) -+ return; -+ } -+ -+ /* Clear out the controller's fifos */ -+ if (fsg->bulk_in_enabled) -+ usb_ep_fifo_flush(fsg->bulk_in); -+ if (fsg->bulk_out_enabled) -+ usb_ep_fifo_flush(fsg->bulk_out); -+ if (fsg->intr_in_enabled) -+ usb_ep_fifo_flush(fsg->intr_in); -+ -+ /* Reset the I/O buffer states and pointers, the SCSI -+ * state, and the exception. Then invoke the handler. */ -+ spin_lock_irq(&fsg->lock); -+ -+ for (i = 0; i < fsg_num_buffers; ++i) { -+ bh = &fsg->buffhds[i]; -+ bh->state = BUF_STATE_EMPTY; -+ } -+ fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain = -+ &fsg->buffhds[0]; -+ -+ exception_req_tag = fsg->exception_req_tag; -+ new_config = fsg->new_config; -+ old_state = fsg->state; -+ -+ if (old_state == FSG_STATE_ABORT_BULK_OUT) -+ fsg->state = FSG_STATE_STATUS_PHASE; -+ else { -+ for (i = 0; i < fsg->nluns; ++i) { -+ curlun = &fsg->luns[i]; -+ curlun->prevent_medium_removal = 0; -+ curlun->sense_data = curlun->unit_attention_data = -+ SS_NO_SENSE; -+ curlun->sense_data_info = 0; -+ curlun->info_valid = 0; -+ } -+ fsg->state = FSG_STATE_IDLE; -+ } -+ spin_unlock_irq(&fsg->lock); -+ -+ /* Carry out any extra actions required for the exception */ -+ switch (old_state) { -+ default: -+ break; -+ -+ case FSG_STATE_ABORT_BULK_OUT: -+ send_status(fsg); -+ spin_lock_irq(&fsg->lock); -+ if (fsg->state == FSG_STATE_STATUS_PHASE) -+ fsg->state = FSG_STATE_IDLE; -+ spin_unlock_irq(&fsg->lock); -+ break; -+ -+ case FSG_STATE_RESET: -+ /* In case we were forced against our will to halt a -+ * bulk endpoint, clear the halt now. (The SuperH UDC -+ * requires this.) */ -+ if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) -+ usb_ep_clear_halt(fsg->bulk_in); -+ -+ if (transport_is_bbb()) { -+ if (fsg->ep0_req_tag == exception_req_tag) -+ ep0_queue(fsg); // Complete the status stage -+ -+ } else if (transport_is_cbi()) -+ send_status(fsg); // Status by interrupt pipe -+ -+ /* Technically this should go here, but it would only be -+ * a waste of time. Ditto for the INTERFACE_CHANGE and -+ * CONFIG_CHANGE cases. */ -+ // for (i = 0; i < fsg->nluns; ++i) -+ // fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; -+ break; -+ -+ case FSG_STATE_INTERFACE_CHANGE: -+ rc = do_set_interface(fsg, 0); -+ if (fsg->ep0_req_tag != exception_req_tag) -+ break; -+ if (rc != 0) // STALL on errors -+ fsg_set_halt(fsg, fsg->ep0); -+ else // Complete the status stage -+ ep0_queue(fsg); -+ break; -+ -+ case FSG_STATE_CONFIG_CHANGE: -+ rc = do_set_config(fsg, new_config); -+ if (fsg->ep0_req_tag != exception_req_tag) -+ break; -+ if (rc != 0) // STALL on errors -+ fsg_set_halt(fsg, fsg->ep0); -+ else // Complete the status stage -+ ep0_queue(fsg); -+ break; -+ -+ case FSG_STATE_DISCONNECT: -+ for (i = 0; i < fsg->nluns; ++i) -+ fsg_lun_fsync_sub(fsg->luns + i); -+ do_set_config(fsg, 0); // Unconfigured state -+ break; -+ -+ case FSG_STATE_EXIT: -+ case FSG_STATE_TERMINATED: -+ do_set_config(fsg, 0); // Free resources -+ spin_lock_irq(&fsg->lock); -+ fsg->state = FSG_STATE_TERMINATED; // Stop the thread -+ spin_unlock_irq(&fsg->lock); -+ break; -+ } -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static int fsg_main_thread(void *fsg_) -+{ -+ struct fsg_dev *fsg = fsg_; -+ -+ /* Allow the thread to be killed by a signal, but set the signal mask -+ * to block everything but INT, TERM, KILL, and USR1. */ -+ allow_signal(SIGINT); -+ allow_signal(SIGTERM); -+ allow_signal(SIGKILL); -+ allow_signal(SIGUSR1); -+ -+ /* Allow the thread to be frozen */ -+ set_freezable(); -+ -+ /* Arrange for userspace references to be interpreted as kernel -+ * pointers. That way we can pass a kernel pointer to a routine -+ * that expects a __user pointer and it will work okay. */ -+ set_fs(get_ds()); -+ -+ /* The main loop */ -+ while (fsg->state != FSG_STATE_TERMINATED) { -+ if (exception_in_progress(fsg) || signal_pending(current)) { -+ handle_exception(fsg); -+ continue; -+ } -+ -+ if (!fsg->running) { -+ sleep_thread(fsg); -+ continue; -+ } -+ -+ if (get_next_command(fsg)) -+ continue; -+ -+ spin_lock_irq(&fsg->lock); -+ if (!exception_in_progress(fsg)) -+ fsg->state = FSG_STATE_DATA_PHASE; -+ spin_unlock_irq(&fsg->lock); -+ -+ if (do_scsi_command(fsg) || finish_reply(fsg)) -+ continue; -+ -+ spin_lock_irq(&fsg->lock); -+ if (!exception_in_progress(fsg)) -+ fsg->state = FSG_STATE_STATUS_PHASE; -+ spin_unlock_irq(&fsg->lock); -+ -+ if (send_status(fsg)) -+ continue; -+ -+ spin_lock_irq(&fsg->lock); -+ if (!exception_in_progress(fsg)) -+ fsg->state = FSG_STATE_IDLE; -+ spin_unlock_irq(&fsg->lock); -+ } -+ -+ spin_lock_irq(&fsg->lock); -+ fsg->thread_task = NULL; -+ spin_unlock_irq(&fsg->lock); -+ -+ /* If we are exiting because of a signal, unregister the -+ * gadget driver. */ -+ if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) -+ usb_gadget_unregister_driver(&fsg_driver); -+ -+ /* Let the unbind and cleanup routines know the thread has exited */ -+ complete_and_exit(&fsg->thread_notifier, 0); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+ -+/* The write permissions and store_xxx pointers are set in fsg_bind() */ -+static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); -+static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL); -+static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void fsg_release(struct kref *ref) -+{ -+ struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref); -+ -+ kfree(fsg->luns); -+ kfree(fsg); -+} -+ -+static void lun_release(struct device *dev) -+{ -+ struct rw_semaphore *filesem = dev_get_drvdata(dev); -+ struct fsg_dev *fsg = -+ container_of(filesem, struct fsg_dev, filesem); -+ -+ kref_put(&fsg->ref, fsg_release); -+} -+ -+static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) -+{ -+ struct fsg_dev *fsg = get_gadget_data(gadget); -+ int i; -+ struct fsg_lun *curlun; -+ struct usb_request *req = fsg->ep0req; -+ -+ DBG(fsg, "unbind\n"); -+ clear_bit(REGISTERED, &fsg->atomic_bitflags); -+ -+ /* If the thread isn't already dead, tell it to exit now */ -+ if (fsg->state != FSG_STATE_TERMINATED) { -+ raise_exception(fsg, FSG_STATE_EXIT); -+ wait_for_completion(&fsg->thread_notifier); -+ -+ /* The cleanup routine waits for this completion also */ -+ complete(&fsg->thread_notifier); -+ } -+ -+ /* Unregister the sysfs attribute files and the LUNs */ -+ for (i = 0; i < fsg->nluns; ++i) { -+ curlun = &fsg->luns[i]; -+ if (curlun->registered) { -+ device_remove_file(&curlun->dev, &dev_attr_nofua); -+ device_remove_file(&curlun->dev, &dev_attr_ro); -+ device_remove_file(&curlun->dev, &dev_attr_file); -+ fsg_lun_close(curlun); -+ device_unregister(&curlun->dev); -+ curlun->registered = 0; -+ } -+ } -+ -+ /* Free the data buffers */ -+ for (i = 0; i < fsg_num_buffers; ++i) -+ kfree(fsg->buffhds[i].buf); -+ -+ /* Free the request and buffer for endpoint 0 */ -+ if (req) { -+ kfree(req->buf); -+ usb_ep_free_request(fsg->ep0, req); -+ } -+ -+ set_gadget_data(gadget, NULL); -+} -+ -+ -+static int __init check_parameters(struct fsg_dev *fsg) -+{ -+ int prot; -+ int gcnum; -+ -+ /* Store the default values */ -+ mod_data.transport_type = USB_PR_BULK; -+ mod_data.transport_name = "Bulk-only"; -+ mod_data.protocol_type = USB_SC_SCSI; -+ mod_data.protocol_name = "Transparent SCSI"; -+ -+ /* Some peripheral controllers are known not to be able to -+ * halt bulk endpoints correctly. If one of them is present, -+ * disable stalls. -+ */ -+ if (gadget_is_at91(fsg->gadget)) -+ mod_data.can_stall = 0; -+ -+ if (mod_data.release == 0xffff) { // Parameter wasn't set -+ gcnum = usb_gadget_controller_number(fsg->gadget); -+ if (gcnum >= 0) -+ mod_data.release = 0x0300 + gcnum; -+ else { -+ WARNING(fsg, "controller '%s' not recognized\n", -+ fsg->gadget->name); -+ mod_data.release = 0x0399; -+ } -+ } -+ -+ prot = simple_strtol(mod_data.protocol_parm, NULL, 0); -+ -+#ifdef CONFIG_USB_FILE_STORAGE_TEST -+ if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) { -+ ; // Use default setting -+ } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) { -+ mod_data.transport_type = USB_PR_CB; -+ mod_data.transport_name = "Control-Bulk"; -+ } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) { -+ mod_data.transport_type = USB_PR_CBI; -+ mod_data.transport_name = "Control-Bulk-Interrupt"; -+ } else { -+ ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm); -+ return -EINVAL; -+ } -+ -+ if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 || -+ prot == USB_SC_SCSI) { -+ ; // Use default setting -+ } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 || -+ prot == USB_SC_RBC) { -+ mod_data.protocol_type = USB_SC_RBC; -+ mod_data.protocol_name = "RBC"; -+ } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 || -+ strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 || -+ prot == USB_SC_8020) { -+ mod_data.protocol_type = USB_SC_8020; -+ mod_data.protocol_name = "8020i (ATAPI)"; -+ } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 || -+ prot == USB_SC_QIC) { -+ mod_data.protocol_type = USB_SC_QIC; -+ mod_data.protocol_name = "QIC-157"; -+ } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 || -+ prot == USB_SC_UFI) { -+ mod_data.protocol_type = USB_SC_UFI; -+ mod_data.protocol_name = "UFI"; -+ } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 || -+ prot == USB_SC_8070) { -+ mod_data.protocol_type = USB_SC_8070; -+ mod_data.protocol_name = "8070i"; -+ } else { -+ ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm); -+ return -EINVAL; -+ } -+ -+ mod_data.buflen &= PAGE_CACHE_MASK; -+ if (mod_data.buflen <= 0) { -+ ERROR(fsg, "invalid buflen\n"); -+ return -ETOOSMALL; -+ } -+ -+#endif /* CONFIG_USB_FILE_STORAGE_TEST */ -+ -+ /* Serial string handling. -+ * On a real device, the serial string would be loaded -+ * from permanent storage. */ -+ if (mod_data.serial) { -+ const char *ch; -+ unsigned len = 0; -+ -+ /* Sanity check : -+ * The CB[I] specification limits the serial string to -+ * 12 uppercase hexadecimal characters. -+ * BBB need at least 12 uppercase hexadecimal characters, -+ * with a maximum of 126. */ -+ for (ch = mod_data.serial; *ch; ++ch) { -+ ++len; -+ if ((*ch < '0' || *ch > '9') && -+ (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */ -+ WARNING(fsg, -+ "Invalid serial string character: %c\n", -+ *ch); -+ goto no_serial; -+ } -+ } -+ if (len > 126 || -+ (mod_data.transport_type == USB_PR_BULK && len < 12) || -+ (mod_data.transport_type != USB_PR_BULK && len > 12)) { -+ WARNING(fsg, "Invalid serial string length!\n"); -+ goto no_serial; -+ } -+ fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial; -+ } else { -+ WARNING(fsg, "No serial-number string provided!\n"); -+ no_serial: -+ device_desc.iSerialNumber = 0; -+ } -+ -+ return 0; -+} -+ -+ -+static int __init fsg_bind(struct usb_gadget *gadget) -+{ -+ struct fsg_dev *fsg = the_fsg; -+ int rc; -+ int i; -+ struct fsg_lun *curlun; -+ struct usb_ep *ep; -+ struct usb_request *req; -+ char *pathbuf, *p; -+ -+ fsg->gadget = gadget; -+ set_gadget_data(gadget, fsg); -+ fsg->ep0 = gadget->ep0; -+ fsg->ep0->driver_data = fsg; -+ -+ if ((rc = check_parameters(fsg)) != 0) -+ goto out; -+ -+ if (mod_data.removable) { // Enable the store_xxx attributes -+ dev_attr_file.attr.mode = 0644; -+ dev_attr_file.store = fsg_store_file; -+ if (!mod_data.cdrom) { -+ dev_attr_ro.attr.mode = 0644; -+ dev_attr_ro.store = fsg_store_ro; -+ } -+ } -+ -+ /* Only for removable media? */ -+ dev_attr_nofua.attr.mode = 0644; -+ dev_attr_nofua.store = fsg_store_nofua; -+ -+ /* Find out how many LUNs there should be */ -+ i = mod_data.nluns; -+ if (i == 0) -+ i = max(mod_data.num_filenames, 1u); -+ if (i > FSG_MAX_LUNS) { -+ ERROR(fsg, "invalid number of LUNs: %d\n", i); -+ rc = -EINVAL; -+ goto out; -+ } -+ -+ /* Create the LUNs, open their backing files, and register the -+ * LUN devices in sysfs. */ -+ fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL); -+ if (!fsg->luns) { -+ rc = -ENOMEM; -+ goto out; -+ } -+ fsg->nluns = i; -+ -+ for (i = 0; i < fsg->nluns; ++i) { -+ curlun = &fsg->luns[i]; -+ curlun->cdrom = !!mod_data.cdrom; -+ curlun->ro = mod_data.cdrom || mod_data.ro[i]; -+ curlun->initially_ro = curlun->ro; -+ curlun->removable = mod_data.removable; -+ curlun->nofua = mod_data.nofua[i]; -+ curlun->dev.release = lun_release; -+ curlun->dev.parent = &gadget->dev; -+ curlun->dev.driver = &fsg_driver.driver; -+ dev_set_drvdata(&curlun->dev, &fsg->filesem); -+ dev_set_name(&curlun->dev,"%s-lun%d", -+ dev_name(&gadget->dev), i); -+ -+ kref_get(&fsg->ref); -+ rc = device_register(&curlun->dev); -+ if (rc) { -+ INFO(fsg, "failed to register LUN%d: %d\n", i, rc); -+ put_device(&curlun->dev); -+ goto out; -+ } -+ curlun->registered = 1; -+ -+ rc = device_create_file(&curlun->dev, &dev_attr_ro); -+ if (rc) -+ goto out; -+ rc = device_create_file(&curlun->dev, &dev_attr_nofua); -+ if (rc) -+ goto out; -+ rc = device_create_file(&curlun->dev, &dev_attr_file); -+ if (rc) -+ goto out; -+ -+ if (mod_data.file[i] && *mod_data.file[i]) { -+ rc = fsg_lun_open(curlun, mod_data.file[i]); -+ if (rc) -+ goto out; -+ } else if (!mod_data.removable) { -+ ERROR(fsg, "no file given for LUN%d\n", i); -+ rc = -EINVAL; -+ goto out; -+ } -+ } -+ -+ /* Find all the endpoints we will use */ -+ usb_ep_autoconfig_reset(gadget); -+ ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); -+ if (!ep) -+ goto autoconf_fail; -+ ep->driver_data = fsg; // claim the endpoint -+ fsg->bulk_in = ep; -+ -+ ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); -+ if (!ep) -+ goto autoconf_fail; -+ ep->driver_data = fsg; // claim the endpoint -+ fsg->bulk_out = ep; -+ -+ if (transport_is_cbi()) { -+ ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc); -+ if (!ep) -+ goto autoconf_fail; -+ ep->driver_data = fsg; // claim the endpoint -+ fsg->intr_in = ep; -+ } -+ -+ /* Fix up the descriptors */ -+ device_desc.idVendor = cpu_to_le16(mod_data.vendor); -+ device_desc.idProduct = cpu_to_le16(mod_data.product); -+ device_desc.bcdDevice = cpu_to_le16(mod_data.release); -+ -+ i = (transport_is_cbi() ? 3 : 2); // Number of endpoints -+ fsg_intf_desc.bNumEndpoints = i; -+ fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type; -+ fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type; -+ fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL; -+ -+ if (gadget_is_dualspeed(gadget)) { -+ fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL; -+ -+ /* Assume endpoint addresses are the same for both speeds */ -+ fsg_hs_bulk_in_desc.bEndpointAddress = -+ fsg_fs_bulk_in_desc.bEndpointAddress; -+ fsg_hs_bulk_out_desc.bEndpointAddress = -+ fsg_fs_bulk_out_desc.bEndpointAddress; -+ fsg_hs_intr_in_desc.bEndpointAddress = -+ fsg_fs_intr_in_desc.bEndpointAddress; -+ } -+ -+ if (gadget_is_superspeed(gadget)) { -+ unsigned max_burst; -+ -+ fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL; -+ -+ /* Calculate bMaxBurst, we know packet size is 1024 */ -+ max_burst = min_t(unsigned, mod_data.buflen / 1024, 15); -+ -+ /* Assume endpoint addresses are the same for both speeds */ -+ fsg_ss_bulk_in_desc.bEndpointAddress = -+ fsg_fs_bulk_in_desc.bEndpointAddress; -+ fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; -+ -+ fsg_ss_bulk_out_desc.bEndpointAddress = -+ fsg_fs_bulk_out_desc.bEndpointAddress; -+ fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; -+ } -+ -+ if (gadget_is_otg(gadget)) -+ fsg_otg_desc.bmAttributes |= USB_OTG_HNP; -+ -+ rc = -ENOMEM; -+ -+ /* Allocate the request and buffer for endpoint 0 */ -+ fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL); -+ if (!req) -+ goto out; -+ req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL); -+ if (!req->buf) -+ goto out; -+ req->complete = ep0_complete; -+ -+ /* Allocate the data buffers */ -+ for (i = 0; i < fsg_num_buffers; ++i) { -+ struct fsg_buffhd *bh = &fsg->buffhds[i]; -+ -+ /* Allocate for the bulk-in endpoint. We assume that -+ * the buffer will also work with the bulk-out (and -+ * interrupt-in) endpoint. */ -+ bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL); -+ if (!bh->buf) -+ goto out; -+ bh->next = bh + 1; -+ } -+ fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0]; -+ -+ /* This should reflect the actual gadget power source */ -+ usb_gadget_set_selfpowered(gadget); -+ -+ snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer, -+ "%s %s with %s", -+ init_utsname()->sysname, init_utsname()->release, -+ gadget->name); -+ -+ fsg->thread_task = kthread_create(fsg_main_thread, fsg, -+ "file-storage-gadget"); -+ if (IS_ERR(fsg->thread_task)) { -+ rc = PTR_ERR(fsg->thread_task); -+ goto out; -+ } -+ -+ INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); -+ INFO(fsg, "NOTE: This driver is deprecated. " -+ "Consider using g_mass_storage instead.\n"); -+ INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); -+ -+ pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); -+ for (i = 0; i < fsg->nluns; ++i) { -+ curlun = &fsg->luns[i]; -+ if (fsg_lun_is_open(curlun)) { -+ p = NULL; -+ if (pathbuf) { -+ p = d_path(&curlun->filp->f_path, -+ pathbuf, PATH_MAX); -+ if (IS_ERR(p)) -+ p = NULL; -+ } -+ LINFO(curlun, "ro=%d, nofua=%d, file: %s\n", -+ curlun->ro, curlun->nofua, (p ? p : "(error)")); -+ } -+ } -+ kfree(pathbuf); -+ -+ DBG(fsg, "transport=%s (x%02x)\n", -+ mod_data.transport_name, mod_data.transport_type); -+ DBG(fsg, "protocol=%s (x%02x)\n", -+ mod_data.protocol_name, mod_data.protocol_type); -+ DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", -+ mod_data.vendor, mod_data.product, mod_data.release); -+ DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n", -+ mod_data.removable, mod_data.can_stall, -+ mod_data.cdrom, mod_data.buflen); -+ DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task)); -+ -+ set_bit(REGISTERED, &fsg->atomic_bitflags); -+ -+ /* Tell the thread to start working */ -+ wake_up_process(fsg->thread_task); -+ return 0; -+ -+autoconf_fail: -+ ERROR(fsg, "unable to autoconfigure all endpoints\n"); -+ rc = -ENOTSUPP; -+ -+out: -+ fsg->state = FSG_STATE_TERMINATED; // The thread is dead -+ fsg_unbind(gadget); -+ complete(&fsg->thread_notifier); -+ return rc; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void fsg_suspend(struct usb_gadget *gadget) -+{ -+ struct fsg_dev *fsg = get_gadget_data(gadget); -+ -+ DBG(fsg, "suspend\n"); -+ set_bit(SUSPENDED, &fsg->atomic_bitflags); -+} -+ -+static void fsg_resume(struct usb_gadget *gadget) -+{ -+ struct fsg_dev *fsg = get_gadget_data(gadget); -+ -+ DBG(fsg, "resume\n"); -+ clear_bit(SUSPENDED, &fsg->atomic_bitflags); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static struct usb_gadget_driver fsg_driver = { -+ .max_speed = USB_SPEED_SUPER, -+ .function = (char *) fsg_string_product, -+ .unbind = fsg_unbind, -+ .disconnect = fsg_disconnect, -+ .setup = fsg_setup, -+ .suspend = fsg_suspend, -+ .resume = fsg_resume, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ // .release = ... -+ // .suspend = ... -+ // .resume = ... -+ }, -+}; -+ -+ -+static int __init fsg_alloc(void) -+{ -+ struct fsg_dev *fsg; -+ -+ fsg = kzalloc(sizeof *fsg + -+ fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL); -+ -+ if (!fsg) -+ return -ENOMEM; -+ spin_lock_init(&fsg->lock); -+ init_rwsem(&fsg->filesem); -+ kref_init(&fsg->ref); -+ init_completion(&fsg->thread_notifier); -+ -+ the_fsg = fsg; -+ return 0; -+} -+ -+ -+static int __init fsg_init(void) -+{ -+ int rc; -+ struct fsg_dev *fsg; -+ -+ rc = fsg_num_buffers_validate(); -+ if (rc != 0) -+ return rc; -+ -+ if ((rc = fsg_alloc()) != 0) -+ return rc; -+ fsg = the_fsg; -+ if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0) -+ kref_put(&fsg->ref, fsg_release); -+ return rc; -+} -+module_init(fsg_init); -+ -+ -+static void __exit fsg_cleanup(void) -+{ -+ struct fsg_dev *fsg = the_fsg; -+ -+ /* Unregister the driver iff the thread hasn't already done so */ -+ if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) -+ usb_gadget_unregister_driver(&fsg_driver); -+ -+ /* Wait for the thread to finish up */ -+ wait_for_completion(&fsg->thread_notifier); -+ -+ kref_put(&fsg->ref, fsg_release); -+} -+module_exit(fsg_cleanup); -diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig -index c59a112..dc69918 100644 ---- a/drivers/usb/host/Kconfig -+++ b/drivers/usb/host/Kconfig -@@ -623,6 +623,19 @@ config USB_HWA_HCD - To compile this driver a module, choose M here: the module - will be called "hwa-hc". - -+config USB_DWCOTG -+ tristate "Synopsis DWC host support" -+ depends on USB -+ help -+ The Synopsis DWC controller is a dual-role -+ host/peripheral/OTG ("On The Go") USB controllers. -+ -+ Enable this option to support this IP in host controller mode. -+ If unsure, say N. -+ -+ To compile this driver as a module, choose M here: the -+ modules built will be called dwc_otg and dwc_common_port. -+ - config USB_IMX21_HCD - tristate "i.MX21 HCD support" - depends on USB && ARM && ARCH_MXC -diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile -index 001fbff..653e258 100644 ---- a/drivers/usb/host/Makefile -+++ b/drivers/usb/host/Makefile -@@ -41,6 +41,8 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o - obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o - obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o - obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o -+ -+obj-$(CONFIG_USB_DWCOTG) += dwc_otg/ dwc_common_port/ - obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o - obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o - obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o -diff --git a/drivers/usb/host/dwc_common_port/Makefile b/drivers/usb/host/dwc_common_port/Makefile -new file mode 100644 -index 0000000..b593b08 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/Makefile -@@ -0,0 +1,46 @@ -+# -+# Makefile for DWC_common library -+# -+ -+ifneq ($(KERNELRELEASE),) -+ -+#CPPFLAGS += -DDEBUG_MEMORY -+ -+ifeq ($(CONFIG_USB_DEBUG),y) -+CPPFLAGS += -DDEBUG -+endif -+CPPFLAGS += -DDWC_LINUX -+ -+obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o -+dwc_common_port_lib-objs := dwc_cc.o \ -+ dwc_notifier.o \ -+ dwc_common_linux.o dwc_mem.o -+ -+kernrelwd := $(subst ., ,$(KERNELRELEASE)) -+kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) -+ -+ifneq ($(kernrel3),2.6.20) -+# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually -+EXTRA_CFLAGS += $(CPPFLAGS) -+endif -+ -+else -+ -+ifeq ($(DOXYGEN),) -+DOXYGEN := $(DOXYGEN) -+endif -+ -+default: -+ $(MAKE) -C$(KDIR) M=$(PWD) modules -+ -+docs: $(wildcard *.[hc]) doc/doxygen.cfg -+ $(DOXYGEN) doc/doxygen.cfg -+ -+tags: $(wildcard *.[hc]) -+ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) -+ -+endif -+ -+clean: -+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers -+ -diff --git a/drivers/usb/host/dwc_common_port/Makefile.linux b/drivers/usb/host/dwc_common_port/Makefile.linux -new file mode 100644 -index 0000000..a553a9d ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/Makefile.linux -@@ -0,0 +1,36 @@ -+# -+# Makefile for DWC_common library -+# -+ifneq ($(KERNELRELEASE),) -+ -+#CPPFLAGS += -DDEBUG_MEMORY -+ -+#CPPFLAGS += -DDEBUG -+CPPFLAGS += -DDWC_LINUX -+ -+obj-m := dwc_common_port_lib.o -+dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ -+ dwc_crypto.o dwc_notifier.o \ -+ dwc_common_linux.o dwc_mem.o -+ -+else -+ -+ -+ifeq ($(DOXYGEN),) -+DOXYGEN := $(DOXYGEN) -+endif -+ -+default: -+ $(MAKE) -C$(KDIR) M=$(PWD) modules -+ -+docs: $(wildcard *.[hc]) doc/doxygen.cfg -+ $(DOXYGEN) doc/doxygen.cfg -+ -+tags: $(wildcard *.[hc]) -+ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) -+ -+endif -+ -+clean: -+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers -+ -diff --git a/drivers/usb/host/dwc_common_port/doc/doxygen.cfg b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg -new file mode 100644 -index 0000000..605b9dab ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg -@@ -0,0 +1,270 @@ -+# Doxyfile 1.4.5 -+ -+#--------------------------------------------------------------------------- -+# Project related configuration options -+#--------------------------------------------------------------------------- -+PROJECT_NAME = "Synopsys DWC Portability and Common Library for UWB" -+PROJECT_NUMBER = -+OUTPUT_DIRECTORY = doc -+CREATE_SUBDIRS = NO -+OUTPUT_LANGUAGE = English -+BRIEF_MEMBER_DESC = YES -+REPEAT_BRIEF = YES -+ABBREVIATE_BRIEF = "The $name class" \ -+ "The $name widget" \ -+ "The $name file" \ -+ is \ -+ provides \ -+ specifies \ -+ contains \ -+ represents \ -+ a \ -+ an \ -+ the -+ALWAYS_DETAILED_SEC = YES -+INLINE_INHERITED_MEMB = NO -+FULL_PATH_NAMES = NO -+STRIP_FROM_PATH = .. -+STRIP_FROM_INC_PATH = -+SHORT_NAMES = NO -+JAVADOC_AUTOBRIEF = YES -+MULTILINE_CPP_IS_BRIEF = NO -+DETAILS_AT_TOP = YES -+INHERIT_DOCS = YES -+SEPARATE_MEMBER_PAGES = NO -+TAB_SIZE = 8 -+ALIASES = -+OPTIMIZE_OUTPUT_FOR_C = YES -+OPTIMIZE_OUTPUT_JAVA = NO -+BUILTIN_STL_SUPPORT = NO -+DISTRIBUTE_GROUP_DOC = NO -+SUBGROUPING = NO -+#--------------------------------------------------------------------------- -+# Build related configuration options -+#--------------------------------------------------------------------------- -+EXTRACT_ALL = NO -+EXTRACT_PRIVATE = NO -+EXTRACT_STATIC = YES -+EXTRACT_LOCAL_CLASSES = NO -+EXTRACT_LOCAL_METHODS = NO -+HIDE_UNDOC_MEMBERS = NO -+HIDE_UNDOC_CLASSES = NO -+HIDE_FRIEND_COMPOUNDS = NO -+HIDE_IN_BODY_DOCS = NO -+INTERNAL_DOCS = NO -+CASE_SENSE_NAMES = YES -+HIDE_SCOPE_NAMES = NO -+SHOW_INCLUDE_FILES = NO -+INLINE_INFO = YES -+SORT_MEMBER_DOCS = NO -+SORT_BRIEF_DOCS = NO -+SORT_BY_SCOPE_NAME = NO -+GENERATE_TODOLIST = YES -+GENERATE_TESTLIST = YES -+GENERATE_BUGLIST = YES -+GENERATE_DEPRECATEDLIST= YES -+ENABLED_SECTIONS = -+MAX_INITIALIZER_LINES = 30 -+SHOW_USED_FILES = YES -+SHOW_DIRECTORIES = YES -+FILE_VERSION_FILTER = -+#--------------------------------------------------------------------------- -+# configuration options related to warning and progress messages -+#--------------------------------------------------------------------------- -+QUIET = YES -+WARNINGS = YES -+WARN_IF_UNDOCUMENTED = NO -+WARN_IF_DOC_ERROR = YES -+WARN_NO_PARAMDOC = YES -+WARN_FORMAT = "$file:$line: $text" -+WARN_LOGFILE = -+#--------------------------------------------------------------------------- -+# configuration options related to the input files -+#--------------------------------------------------------------------------- -+INPUT = . -+FILE_PATTERNS = *.c \ -+ *.cc \ -+ *.cxx \ -+ *.cpp \ -+ *.c++ \ -+ *.d \ -+ *.java \ -+ *.ii \ -+ *.ixx \ -+ *.ipp \ -+ *.i++ \ -+ *.inl \ -+ *.h \ -+ *.hh \ -+ *.hxx \ -+ *.hpp \ -+ *.h++ \ -+ *.idl \ -+ *.odl \ -+ *.cs \ -+ *.php \ -+ *.php3 \ -+ *.inc \ -+ *.m \ -+ *.mm \ -+ *.dox \ -+ *.py \ -+ *.C \ -+ *.CC \ -+ *.C++ \ -+ *.II \ -+ *.I++ \ -+ *.H \ -+ *.HH \ -+ *.H++ \ -+ *.CS \ -+ *.PHP \ -+ *.PHP3 \ -+ *.M \ -+ *.MM \ -+ *.PY -+RECURSIVE = NO -+EXCLUDE = -+EXCLUDE_SYMLINKS = NO -+EXCLUDE_PATTERNS = -+EXAMPLE_PATH = -+EXAMPLE_PATTERNS = * -+EXAMPLE_RECURSIVE = NO -+IMAGE_PATH = -+INPUT_FILTER = -+FILTER_PATTERNS = -+FILTER_SOURCE_FILES = NO -+#--------------------------------------------------------------------------- -+# configuration options related to source browsing -+#--------------------------------------------------------------------------- -+SOURCE_BROWSER = NO -+INLINE_SOURCES = NO -+STRIP_CODE_COMMENTS = YES -+REFERENCED_BY_RELATION = YES -+REFERENCES_RELATION = YES -+USE_HTAGS = NO -+VERBATIM_HEADERS = NO -+#--------------------------------------------------------------------------- -+# configuration options related to the alphabetical class index -+#--------------------------------------------------------------------------- -+ALPHABETICAL_INDEX = NO -+COLS_IN_ALPHA_INDEX = 5 -+IGNORE_PREFIX = -+#--------------------------------------------------------------------------- -+# configuration options related to the HTML output -+#--------------------------------------------------------------------------- -+GENERATE_HTML = YES -+HTML_OUTPUT = html -+HTML_FILE_EXTENSION = .html -+HTML_HEADER = -+HTML_FOOTER = -+HTML_STYLESHEET = -+HTML_ALIGN_MEMBERS = YES -+GENERATE_HTMLHELP = NO -+CHM_FILE = -+HHC_LOCATION = -+GENERATE_CHI = NO -+BINARY_TOC = NO -+TOC_EXPAND = NO -+DISABLE_INDEX = NO -+ENUM_VALUES_PER_LINE = 4 -+GENERATE_TREEVIEW = YES -+TREEVIEW_WIDTH = 250 -+#--------------------------------------------------------------------------- -+# configuration options related to the LaTeX output -+#--------------------------------------------------------------------------- -+GENERATE_LATEX = NO -+LATEX_OUTPUT = latex -+LATEX_CMD_NAME = latex -+MAKEINDEX_CMD_NAME = makeindex -+COMPACT_LATEX = NO -+PAPER_TYPE = a4wide -+EXTRA_PACKAGES = -+LATEX_HEADER = -+PDF_HYPERLINKS = NO -+USE_PDFLATEX = NO -+LATEX_BATCHMODE = NO -+LATEX_HIDE_INDICES = NO -+#--------------------------------------------------------------------------- -+# configuration options related to the RTF output -+#--------------------------------------------------------------------------- -+GENERATE_RTF = NO -+RTF_OUTPUT = rtf -+COMPACT_RTF = NO -+RTF_HYPERLINKS = NO -+RTF_STYLESHEET_FILE = -+RTF_EXTENSIONS_FILE = -+#--------------------------------------------------------------------------- -+# configuration options related to the man page output -+#--------------------------------------------------------------------------- -+GENERATE_MAN = NO -+MAN_OUTPUT = man -+MAN_EXTENSION = .3 -+MAN_LINKS = NO -+#--------------------------------------------------------------------------- -+# configuration options related to the XML output -+#--------------------------------------------------------------------------- -+GENERATE_XML = NO -+XML_OUTPUT = xml -+XML_SCHEMA = -+XML_DTD = -+XML_PROGRAMLISTING = YES -+#--------------------------------------------------------------------------- -+# configuration options for the AutoGen Definitions output -+#--------------------------------------------------------------------------- -+GENERATE_AUTOGEN_DEF = NO -+#--------------------------------------------------------------------------- -+# configuration options related to the Perl module output -+#--------------------------------------------------------------------------- -+GENERATE_PERLMOD = NO -+PERLMOD_LATEX = NO -+PERLMOD_PRETTY = YES -+PERLMOD_MAKEVAR_PREFIX = -+#--------------------------------------------------------------------------- -+# Configuration options related to the preprocessor -+#--------------------------------------------------------------------------- -+ENABLE_PREPROCESSING = YES -+MACRO_EXPANSION = NO -+EXPAND_ONLY_PREDEF = NO -+SEARCH_INCLUDES = YES -+INCLUDE_PATH = -+INCLUDE_FILE_PATTERNS = -+PREDEFINED = DEBUG DEBUG_MEMORY -+EXPAND_AS_DEFINED = -+SKIP_FUNCTION_MACROS = YES -+#--------------------------------------------------------------------------- -+# Configuration::additions related to external references -+#--------------------------------------------------------------------------- -+TAGFILES = -+GENERATE_TAGFILE = -+ALLEXTERNALS = NO -+EXTERNAL_GROUPS = YES -+PERL_PATH = /usr/bin/perl -+#--------------------------------------------------------------------------- -+# Configuration options related to the dot tool -+#--------------------------------------------------------------------------- -+CLASS_DIAGRAMS = YES -+HIDE_UNDOC_RELATIONS = YES -+HAVE_DOT = NO -+CLASS_GRAPH = YES -+COLLABORATION_GRAPH = YES -+GROUP_GRAPHS = YES -+UML_LOOK = NO -+TEMPLATE_RELATIONS = NO -+INCLUDE_GRAPH = NO -+INCLUDED_BY_GRAPH = YES -+CALL_GRAPH = NO -+GRAPHICAL_HIERARCHY = YES -+DIRECTORY_GRAPH = YES -+DOT_IMAGE_FORMAT = png -+DOT_PATH = -+DOTFILE_DIRS = -+MAX_DOT_GRAPH_DEPTH = 1000 -+DOT_TRANSPARENT = NO -+DOT_MULTI_TARGETS = NO -+GENERATE_LEGEND = YES -+DOT_CLEANUP = YES -+#--------------------------------------------------------------------------- -+# Configuration::additions related to the search engine -+#--------------------------------------------------------------------------- -+SEARCHENGINE = NO -diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.c b/drivers/usb/host/dwc_common_port/dwc_cc.c -new file mode 100644 -index 0000000..3a7dd71 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_cc.c -@@ -0,0 +1,506 @@ -+/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.c $ -+ * $Revision: #1 $ -+ * $Date: 2008/12/21 $ -+ * $Change: 1156609 $ -+ * -+ * Synopsys Portability Library Software 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. -+ * ========================================================================= */ -+#include "dwc_cc.h" -+ -+typedef struct dwc_cc -+{ -+ uint32_t uid; -+ uint8_t chid[16]; -+ uint8_t cdid[16]; -+ uint8_t ck[16]; -+ uint8_t *name; -+ uint8_t length; -+ DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry; -+} dwc_cc_t; -+ -+DWC_CIRCLEQ_HEAD(context_list, dwc_cc); -+ -+/** The main structure for CC management. */ -+struct dwc_cc_if -+{ -+ dwc_mutex_t *mutex; -+ char *filename; -+ -+ unsigned is_host:1; -+ -+ dwc_notifier_t *notifier; -+ -+ struct context_list list; -+}; -+ -+#ifdef DEBUG -+static inline void dump_bytes(char *name, uint8_t *bytes, int len) -+{ -+ int i; -+ DWC_PRINTF("%s: ", name); -+ for (i=0; ilength = length; -+ cc->name = DWC_ALLOC(length); -+ DWC_MEMCPY(cc->name, name, length); -+ } -+ -+ return cc; -+} -+ -+static void free_cc(dwc_cc_t *cc) -+{ -+ if (cc->name) { -+ DWC_FREE(cc->name); -+ } -+ DWC_FREE(cc); -+} -+ -+static uint32_t next_uid(dwc_cc_if_t *cc_if) -+{ -+ uint32_t uid = 0; -+ dwc_cc_t *cc; -+ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { -+ if (cc->uid > uid) { -+ uid = cc->uid; -+ } -+ } -+ -+ if (uid == 0) { -+ uid = 255; -+ } -+ -+ return uid + 1; -+} -+ -+static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid) -+{ -+ dwc_cc_t *cc; -+ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { -+ if (cc->uid == uid) { -+ return cc; -+ } -+ } -+ return NULL; -+} -+ -+static unsigned int cc_data_size(dwc_cc_if_t *cc_if) -+{ -+ unsigned int size = 0; -+ dwc_cc_t *cc; -+ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { -+ size += (48 + 1); -+ if (cc->name) { -+ size += cc->length; -+ } -+ } -+ return size; -+} -+ -+static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid) -+{ -+ uint32_t uid = 0; -+ dwc_cc_t *cc; -+ -+ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { -+ if (DWC_MEMCMP(cc->chid, chid, 16) == 0) { -+ uid = cc->uid; -+ break; -+ } -+ } -+ return uid; -+} -+static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) -+{ -+ uint32_t uid = 0; -+ dwc_cc_t *cc; -+ -+ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { -+ if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) { -+ uid = cc->uid; -+ break; -+ } -+ } -+ return uid; -+} -+ -+/* Internal cc_add */ -+static int32_t cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) -+{ -+ dwc_cc_t *cc; -+ uint32_t uid; -+ -+ if (cc_if->is_host) { -+ uid = cc_match_cdid(cc_if, cdid); -+ } -+ else { -+ uid = cc_match_chid(cc_if, chid); -+ } -+ -+ if (uid) { -+ DWC_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); -+ cc = cc_find(cc_if, uid); -+ } -+ else { -+ cc = alloc_cc(name, length); -+ cc->uid = next_uid(cc_if); -+ DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry); -+ } -+ -+ DWC_MEMCPY(&(cc->chid[0]), chid, 16); -+ DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); -+ DWC_MEMCPY(&(cc->ck[0]), ck, 16); -+ -+ DWC_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); -+ dump_bytes("CHID", cc->chid, 16); -+ dump_bytes("CDID", cc->cdid, 16); -+ dump_bytes("CK", cc->ck, 16); -+ return cc->uid; -+} -+ -+/* Internal cc_clear */ -+static void cc_clear(dwc_cc_if_t *cc_if) -+{ -+ while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) { -+ dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list); -+ DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); -+ free_cc(cc); -+ } -+} -+ -+dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host) -+{ -+ dwc_cc_if_t *cc_if = NULL; -+ -+ /* Allocate a common_cc_if structure */ -+ cc_if = DWC_ALLOC(sizeof(dwc_cc_if_t)); -+ -+ if(!cc_if) -+ return NULL; -+ -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+ DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex); -+#else -+ cc_if->mutex = DWC_MUTEX_ALLOC(); -+#endif -+ DWC_CIRCLEQ_INIT(&cc_if->list); -+ cc_if->is_host = is_host; -+ cc_if->notifier = notifier; -+ return cc_if; -+} -+ -+void dwc_cc_if_free(dwc_cc_if_t *cc_if) -+{ -+ DWC_MUTEX_FREE(cc_if->mutex); -+ cc_clear(cc_if); -+ DWC_FREE(cc_if); -+} -+ -+static void cc_changed(dwc_cc_if_t *cc_if) -+{ -+ if (cc_if->notifier) { -+ dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if); -+ } -+} -+ -+void dwc_cc_clear(dwc_cc_if_t *cc_if) -+{ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ cc_clear(cc_if); -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ cc_changed(cc_if); -+} -+ -+int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) -+{ -+ uint32_t uid; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ uid = cc_add(cc_if, chid, cdid, ck, name, length); -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ cc_changed(cc_if); -+ -+ return uid; -+} -+ -+void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, -+ uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) -+{ -+ dwc_cc_t* cc; -+ -+ DWC_DEBUG("Change connection context %d", id); -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ cc = cc_find(cc_if, id); -+ if (!cc) { -+ DWC_ERROR("Uid %d not found in cc list", id); -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ return; -+ } -+ -+ if (chid) { -+ DWC_MEMCPY(&(cc->chid[0]), chid, 16); -+ } -+ if (cdid) { -+ DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); -+ } -+ if (ck) { -+ DWC_MEMCPY(&(cc->ck[0]), ck, 16); -+ } -+ -+ if (name) { -+ if (cc->name) { -+ DWC_FREE(cc->name); -+ } -+ cc->name = DWC_ALLOC(length); -+ cc->length = length; -+ DWC_MEMCPY(cc->name, name, length); -+ } -+ -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ -+ cc_changed(cc_if); -+ -+ DWC_DEBUG("Changed connection context id=%d\n", id); -+ dump_bytes("New CHID", cc->chid, 16); -+ dump_bytes("New CDID", cc->cdid, 16); -+ dump_bytes("New CK", cc->ck, 16); -+} -+ -+void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id) -+{ -+ dwc_cc_t *cc; -+ -+ DWC_DEBUG("Removing connection context %d", id); -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ cc = cc_find(cc_if, id); -+ if (!cc) { -+ DWC_ERROR("Uid %d not found in cc list", id); -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ return; -+ } -+ -+ DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ free_cc(cc); -+ -+ cc_changed(cc_if); -+} -+ -+uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length) -+{ -+ uint8_t *buf, *x; -+ uint8_t zero = 0; -+ dwc_cc_t *cc; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ *length = cc_data_size(cc_if); -+ if (!(*length)) { -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ return NULL; -+ } -+ -+ DWC_DEBUG("Creating data for saving (length=%d)", *length); -+ -+ buf = DWC_ALLOC(*length); -+ if (!buf) { -+ *length = 0; -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ return NULL; -+ } -+ -+ x = buf; -+ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { -+ DWC_MEMCPY(x, cc->chid, 16); -+ x += 16; -+ DWC_MEMCPY(x, cc->cdid, 16); -+ x += 16; -+ DWC_MEMCPY(x, cc->ck, 16); -+ x += 16; -+ if (cc->name) { -+ DWC_MEMCPY(x, &cc->length, 1); -+ x += 1; -+ DWC_MEMCPY(x, cc->name, cc->length); -+ x += cc->length; -+ } -+ else { -+ DWC_MEMCPY(x, &zero, 1); -+ x += 1; -+ } -+ } -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ -+ return buf; -+} -+ -+void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length) -+{ -+ uint8_t name_length; -+ uint8_t *name; -+ uint8_t *chid; -+ uint8_t *cdid; -+ uint8_t *ck; -+ uint32_t i = 0; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ cc_clear(cc_if); -+ -+ while (i < length) { -+ chid = &data[i]; -+ i += 16; -+ cdid = &data[i]; -+ i += 16; -+ ck = &data[i]; -+ i += 16; -+ -+ name_length = data[i]; -+ i ++; -+ -+ if (name_length) { -+ name = &data[i]; -+ i += name_length; -+ } -+ else { -+ name = NULL; -+ } -+ -+ /* check to see if we haven't overflown the buffer */ -+ if (i > length) { -+ DWC_ERROR("Data format error while attempting to load CCs " -+ "(nlen=%d, iter=%d, buflen=%d).", name_length, i, length); -+ break; -+ } -+ -+ cc_add(cc_if, chid, cdid, ck, name, name_length); -+ } -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ -+ cc_changed(cc_if); -+} -+ -+uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid) -+{ -+ uint32_t uid = 0; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ uid = cc_match_chid(cc_if, chid); -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ return uid; -+} -+uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) -+{ -+ uint32_t uid = 0; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ uid = cc_match_cdid(cc_if, cdid); -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ return uid; -+} -+ -+uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id) -+{ -+ uint8_t *ck = NULL; -+ dwc_cc_t *cc; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ cc = cc_find(cc_if, id); -+ if (cc) { -+ ck = cc->ck; -+ } -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ -+ return ck; -+ -+} -+ -+uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id) -+{ -+ uint8_t *retval = NULL; -+ dwc_cc_t *cc; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ cc = cc_find(cc_if, id); -+ if (cc) { -+ retval = cc->chid; -+ } -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ -+ return retval; -+} -+ -+uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id) -+{ -+ uint8_t *retval = NULL; -+ dwc_cc_t *cc; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ cc = cc_find(cc_if, id); -+ if (cc) { -+ retval = cc->cdid; -+ } -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ -+ return retval; -+} -+ -+uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length) -+{ -+ uint8_t *retval = NULL; -+ dwc_cc_t *cc; -+ -+ DWC_MUTEX_LOCK(cc_if->mutex); -+ *length = 0; -+ cc = cc_find(cc_if, id); -+ if (cc) { -+ *length = cc->length; -+ retval = cc->name; -+ } -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ -+ return retval; -+} -diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.h b/drivers/usb/host/dwc_common_port/dwc_cc.h -new file mode 100644 -index 0000000..6b464191 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_cc.h -@@ -0,0 +1,209 @@ -+/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.h $ -+ * $Revision: #1 $ -+ * $Date: 2008/12/21 $ -+ * $Change: 1156609 $ -+ * -+ * Synopsys Portability Library Software 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_CC_H_ -+#define _DWC_CC_H_ -+ -+/** @file -+ * -+ * This file defines the Context Context library. -+ * -+ * The main data structure is dwc_cc_if_t which is returned by either the -+ * dwc_cc_if_alloc function or returned by the module to the user via a provided -+ * function. The data structure is opaque and should only be manipulated via the -+ * functions provied in this API. -+ * -+ * It manages a list of connection contexts and operations can be performed to -+ * add, remove, query, search, and change, those contexts. Additionally, -+ * a dwc_notifier_t object can be requested from the manager so that -+ * the user can be notified whenever the context list has changed. -+ */ -+ -+#include "dwc_os.h" -+#include "dwc_list.h" -+#include "dwc_notifier.h" -+ -+ -+/* Notifications */ -+#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION" -+ -+struct dwc_cc_if; -+typedef struct dwc_cc_if dwc_cc_if_t; -+ -+ -+/** @name Connection Context Operations */ -+/** @{ */ -+ -+/** This function allocates memory for a dwc_cc_if_t structure, initializes -+ * fields to default values, and returns a pointer to the structure or NULL on -+ * error. */ -+extern dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host); -+ -+/** Frees the memory for the specified CC structure allocated from -+ * dwc_cc_if_alloc(). */ -+extern void dwc_cc_if_free(dwc_cc_if_t *cc_if); -+ -+/** Removes all contexts from the connection context list */ -+extern void dwc_cc_clear(dwc_cc_if_t *cc_if); -+ -+/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list. -+ * If a CHID already exists, the CK and name are overwritten. Statistics are -+ * not overwritten. -+ * -+ * @param cc_if The cc_if structure. -+ * @param chid A pointer to the 16-byte CHID. This value will be copied. -+ * @param ck A pointer to the 16-byte CK. This value will be copied. -+ * @param cdid A pointer to the 16-byte CDID. This value will be copied. -+ * @param name An optional host friendly name as defined in the association model -+ * spec. Must be a UTF16-LE unicode string. Can be NULL to indicated no name. -+ * @param length The length othe unicode string. -+ * @return A unique identifier used to refer to this context that is valid for -+ * as long as this context is still in the list. */ -+extern int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length); -+ -+/** Changes the CHID, CK, CDID, or Name values of a connection context in the -+ * list, preserving any accumulated statistics. This would typically be called -+ * if the host decideds to change the context with a SET_CONNECTION request. -+ * -+ * @param cc_if The cc_if structure. -+ * @param id The identifier of the connection context. -+ * @param chid A pointer to the 16-byte CHID. This value will be copied. NULL -+ * indicates no change. -+ * @param cdid A pointer to the 16-byte CDID. This value will be copied. NULL -+ * indicates no change. -+ * @param ck A pointer to the 16-byte CK. This value will be copied. NULL -+ * indicates no change. -+ * @param name Host friendly name UTF16-LE. NULL indicates no change. -+ * @param length Length of name. */ -+extern void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length); -+ -+/** Remove the specified connection context. -+ * @param cc_if The cc_if structure. -+ * @param id The identifier of the connection context to remove. */ -+extern void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id); -+ -+/** Get a binary block of data for the connection context list and attributes. -+ * This data can be used by the OS specific driver to save the connection -+ * context list into non-volatile memory. -+ * -+ * @param cc_if The cc_if structure. -+ * @param length Return the length of the data buffer. -+ * @return A pointer to the data buffer. The memory for this buffer should be freed with DWC_FREE() after use. */ -+extern uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length); -+ -+/** Restore the connection context list from the binary data that was previously -+ * returned from a call to dwc_cc_data_for_save. This can be used by the OS specific -+ * driver to load a connection context list from non-volatile memory. -+ * -+ * @param cc_if The cc_if structure. -+ * @param data The data bytes as returned from dwc_cc_data_for_save. -+ * @param length The length of the data. */ -+extern void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, unsigned int length); -+ -+/** Find the connection context from the specified CHID. -+ * -+ * @param cc_if The cc_if structure. -+ * @param chid A pointer to the CHID data. -+ * @return A non-zero identifier of the connection context if the CHID matches. -+ * Otherwise returns 0. */ -+extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid); -+ -+/** Find the connection context from the specified CDID. -+ * -+ * @param cc_if The cc_if structure. -+ * @param cdid A pointer to the CDID data. -+ * @return A non-zero identifier of the connection context if the CHID matches. -+ * Otherwise returns 0. */ -+extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid); -+ -+/** Retrieve the CK from the specified connection context. -+ * -+ * @param cc_if The cc_if structure. -+ * @param id The identifier of the connection context. -+ * @return A pointer to the CK data. The memory does not need to be freed. */ -+extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id); -+ -+/** Retrieve the CHID from the specified connection context. -+ * -+ * @param cc_if The cc_if structure. -+ * @param id The identifier of the connection context. -+ * @return A pointer to the CHID data. The memory does not need to be freed. */ -+extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id); -+ -+/** Retrieve the CDID from the specified connection context. -+ * -+ * @param cc_if The cc_if structure. -+ * @param id The identifier of the connection context. -+ * @return A pointer to the CDID data. The memory does not need to be freed. */ -+extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id); -+ -+extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length); -+ -+/** Checks a buffer for non-zero. -+ * @param id A pointer to a 16 byte buffer. -+ * @return true if the 16 byte value is non-zero. */ -+static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) { -+ int i; -+ for (i=0; i<16; i++) { -+ if (id[i]) return 1; -+ } -+ return 0; -+} -+ -+/** Checks a buffer for zero. -+ * @param id A pointer to a 16 byte buffer. -+ * @return true if the 16 byte value is zero. */ -+static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) { -+ return !dwc_assoc_is_not_zero_id(id); -+} -+ -+/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into -+ * buffer. */ -+static inline int dwc_print_id_string(char *buffer, uint8_t *id) { -+ char *ptr = buffer; -+ int i; -+ for (i=0; i<16; i++) { -+ ptr += DWC_SPRINTF(ptr, "%02x", id[i]); -+ if (i < 15) { -+ ptr += DWC_SPRINTF(ptr, " "); -+ } -+ } -+ return ptr - buffer; -+} -+ -+/** @} */ -+ -+#endif /* _DWC_CC_H_ */ -+ -diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -new file mode 100644 -index 0000000..fbf9dfb ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -@@ -0,0 +1,1138 @@ -+#include "dwc_cc.h" -+#include "dwc_notifier.h" -+ -+#include -+#include -+#include -+#include -+ -+MODULE_DESCRIPTION("DWC Common Library - Portable version"); -+MODULE_AUTHOR("Synopsys Inc."); -+MODULE_LICENSE ("GPL"); -+ -+static int dwc_common_port_init_module(void) -+{ -+ printk( KERN_DEBUG "Module dwc_common_port init\n" ); -+#ifdef DEBUG_MEMORY -+ dwc_memory_debug_start(); -+#endif -+ dwc_alloc_notification_manager(); -+ return 0; -+} -+ -+static void dwc_common_port_exit_module(void) -+{ -+ printk( KERN_DEBUG "Module dwc_common_port exit\n" ); -+ dwc_free_notification_manager(); -+#ifdef DEBUG_MEMORY -+ dwc_memory_debug_stop(); -+#endif -+} -+ -+module_init(dwc_common_port_init_module); -+module_exit(dwc_common_port_exit_module); -+ -+/* CC */ -+EXPORT_SYMBOL(dwc_cc_if_alloc); -+EXPORT_SYMBOL(dwc_cc_if_free); -+EXPORT_SYMBOL(dwc_cc_clear); -+EXPORT_SYMBOL(dwc_cc_add); -+EXPORT_SYMBOL(dwc_cc_remove); -+EXPORT_SYMBOL(dwc_cc_change); -+EXPORT_SYMBOL(dwc_cc_data_for_save); -+EXPORT_SYMBOL(dwc_cc_restore_from_data); -+EXPORT_SYMBOL(dwc_cc_match_chid); -+EXPORT_SYMBOL(dwc_cc_match_cdid); -+EXPORT_SYMBOL(dwc_cc_ck); -+EXPORT_SYMBOL(dwc_cc_chid); -+EXPORT_SYMBOL(dwc_cc_cdid); -+EXPORT_SYMBOL(dwc_cc_name); -+ -+/* Notification */ -+EXPORT_SYMBOL(dwc_alloc_notification_manager); -+EXPORT_SYMBOL(dwc_free_notification_manager); -+EXPORT_SYMBOL(dwc_register_notifier); -+EXPORT_SYMBOL(dwc_unregister_notifier); -+EXPORT_SYMBOL(dwc_add_observer); -+EXPORT_SYMBOL(dwc_remove_observer); -+EXPORT_SYMBOL(dwc_notify); -+ -+/* Memory Debugging Routines */ -+#ifdef DEBUG_MEMORY -+EXPORT_SYMBOL(dwc_alloc_debug); -+EXPORT_SYMBOL(dwc_alloc_atomic_debug); -+EXPORT_SYMBOL(dwc_free_debug); -+EXPORT_SYMBOL(dwc_dma_alloc_debug); -+EXPORT_SYMBOL(dwc_dma_alloc_atomic_debug); -+EXPORT_SYMBOL(dwc_dma_free_debug); -+#endif -+ -+/* OS-Level Implementations */ -+ -+/* This is the Linux kernel implementation of the DWC platform library. */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#else -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* MISC */ -+ -+void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) -+{ -+ return memset(dest, byte, size); -+} -+EXPORT_SYMBOL(DWC_MEMSET); -+ -+void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) -+{ -+ return memcpy(dest, src, size); -+} -+EXPORT_SYMBOL(DWC_MEMCPY); -+ -+void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) -+{ -+ return memmove(dest, src, size); -+} -+EXPORT_SYMBOL(DWC_MEMMOVE); -+ -+int DWC_MEMCMP(void *m1, void *m2, uint32_t size) -+{ -+ return memcmp(m1, m2, size); -+} -+EXPORT_SYMBOL(DWC_MEMCMP); -+ -+int DWC_STRNCMP(void *s1, void *s2, uint32_t size) -+{ -+ return strncmp(s1, s2, size); -+} -+EXPORT_SYMBOL(DWC_STRNCMP); -+ -+int DWC_STRCMP(void *s1, void *s2) -+{ -+ return strcmp(s1, s2); -+} -+EXPORT_SYMBOL(DWC_STRCMP); -+ -+int DWC_STRLEN(char const *str) -+{ -+ return strlen(str); -+} -+EXPORT_SYMBOL(DWC_STRLEN); -+ -+char *DWC_STRCPY(char *to, const char *from) -+{ -+ return strcpy(to, from); -+} -+EXPORT_SYMBOL(DWC_STRCPY); -+ -+char *DWC_STRDUP(char const *str) -+{ -+ int len = DWC_STRLEN(str) + 1; -+ char *new = DWC_ALLOC_ATOMIC(len); -+ if (!new) { -+ return NULL; -+ } -+ DWC_MEMCPY(new, str, len); -+ return new; -+} -+EXPORT_SYMBOL(DWC_STRDUP); -+ -+int DWC_ATOI(char *str, int32_t *value) -+{ -+ char *end = NULL; -+ *value = simple_strtol(str, &end, 0); -+ if (*end == '\0') { -+ return 0; -+ } -+ return -1; -+} -+EXPORT_SYMBOL(DWC_ATOI); -+ -+int DWC_ATOUI(char *str, uint32_t *value) -+{ -+ char *end = NULL; -+ *value = simple_strtoul(str, &end, 0); -+ if (*end == '\0') { -+ return 0; -+ } -+ return -1; -+} -+EXPORT_SYMBOL(DWC_ATOUI); -+ -+ -+/* From usbstring.c */ -+int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) -+{ -+ int count = 0; -+ u8 c; -+ u16 uchar; -+ -+ /* this insists on correct encodings, though not minimal ones. -+ * BUT it currently rejects legit 4-byte UTF-8 code points, -+ * which need surrogate pairs. (Unicode 3.1 can use them.) -+ */ -+ while (len != 0 && (c = (u8) *s++) != 0) { -+ if (unlikely(c & 0x80)) { -+ // 2-byte sequence: -+ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx -+ if ((c & 0xe0) == 0xc0) { -+ uchar = (c & 0x1f) << 6; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c; -+ -+ // 3-byte sequence (most CJKV characters): -+ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx -+ } else if ((c & 0xf0) == 0xe0) { -+ uchar = (c & 0x0f) << 12; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c << 6; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c; -+ -+ /* no bogus surrogates */ -+ if (0xd800 <= uchar && uchar <= 0xdfff) -+ goto fail; -+ -+ // 4-byte sequence (surrogate pairs, currently rare): -+ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx -+ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx -+ // (uuuuu = wwww + 1) -+ // FIXME accept the surrogate code points (only) -+ -+ } else -+ goto fail; -+ } else -+ uchar = c; -+ put_unaligned (cpu_to_le16 (uchar), cp++); -+ count++; -+ len--; -+ } -+ return count; -+fail: -+ return -1; -+} -+EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE); -+ -+/* dwc_debug.h */ -+ -+dwc_bool_t DWC_IN_IRQ(void) -+{ -+ return in_irq(); -+} -+EXPORT_SYMBOL(DWC_IN_IRQ); -+ -+int DWC_IN_BH(void) -+{ -+ return in_softirq(); -+} -+EXPORT_SYMBOL(DWC_IN_BH); -+ -+void DWC_VPRINTF(char *format, va_list args) -+{ -+ vprintk(format, args); -+} -+EXPORT_SYMBOL(DWC_VPRINTF); -+ -+int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) -+{ -+ return vsnprintf(str, size, format, args); -+} -+ -+void DWC_PRINTF(char *format, ...) -+{ -+ va_list args; -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+EXPORT_SYMBOL(DWC_PRINTF); -+ -+int DWC_SPRINTF(char *buffer, char *format, ...) -+{ -+ int retval; -+ va_list args; -+ va_start(args, format); -+ retval = vsprintf(buffer, format, args); -+ va_end(args); -+ return retval; -+} -+EXPORT_SYMBOL(DWC_SPRINTF); -+ -+int DWC_SNPRINTF(char *buffer, int size, char *format, ...) -+{ -+ int retval; -+ va_list args; -+ va_start(args, format); -+ retval = vsnprintf(buffer, size, format, args); -+ va_end(args); -+ return retval; -+} -+EXPORT_SYMBOL(DWC_SNPRINTF); -+ -+void __DWC_WARN(char *format, ...) -+{ -+ va_list args; -+ va_start(args, format); -+ DWC_PRINTF(KERN_WARNING); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+EXPORT_SYMBOL(__DWC_WARN); -+ -+void __DWC_ERROR(char *format, ...) -+{ -+ va_list args; -+ va_start(args, format); -+ DWC_PRINTF(KERN_ERR); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+EXPORT_SYMBOL(__DWC_ERROR); -+ -+void DWC_EXCEPTION(char *format, ...) -+{ -+ va_list args; -+ va_start(args, format); -+ DWC_PRINTF(KERN_ERR); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+ BUG_ON(1); -+} -+EXPORT_SYMBOL(DWC_EXCEPTION); -+ -+#ifdef DEBUG -+void __DWC_DEBUG(char *format, ...) -+{ -+ va_list args; -+ va_start(args, format); -+ DWC_PRINTF(KERN_DEBUG); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+EXPORT_SYMBOL(__DWC_DEBUG); -+#endif -+ -+ -+ -+/* dwc_mem.h */ -+ -+#if 0 -+dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, -+ uint32_t align, -+ uint32_t alloc) -+{ -+ struct dma_pool *pool = dma_pool_create("Pool", NULL, -+ size, align, alloc); -+ return (dwc_pool_t *)pool; -+} -+ -+void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) -+{ -+ dma_pool_destroy((struct dma_pool *)pool); -+} -+ -+void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, U64 *dma_addr) -+{ -+ return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); -+} -+ -+void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, U64 *dma_addr) -+{ -+ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); -+ memset(); -+} -+ -+void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) -+{ -+ dma_pool_free(pool, vaddr, daddr); -+} -+ -+#endif -+ -+void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr) -+{ -+ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_KERNEL); -+ if (!buf) { -+ return NULL; -+ } -+ memset(buf, 0, (size_t)size); -+ return buf; -+} -+EXPORT_SYMBOL(__DWC_DMA_ALLOC); -+ -+void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr) -+{ -+ dma_free_coherent(NULL, size, virt_addr, dma_addr); -+} -+EXPORT_SYMBOL(__DWC_DMA_FREE); -+ -+void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr) -+{ -+ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); -+ if (!buf) { -+ return NULL; -+ } -+ memset(buf, 0, (size_t)size); -+ return buf; -+} -+EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); -+ -+void *__DWC_ALLOC(uint32_t size) -+{ -+ return kzalloc(size, GFP_KERNEL); -+} -+EXPORT_SYMBOL(__DWC_ALLOC); -+ -+void *__DWC_ALLOC_ATOMIC(uint32_t size) -+{ -+ return kzalloc(size, GFP_ATOMIC); -+} -+EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC); -+ -+void __DWC_FREE(void *addr) -+{ -+ kfree(addr); -+} -+EXPORT_SYMBOL(__DWC_FREE); -+ -+/* Byte Ordering Conversions. */ -+uint32_t DWC_CPU_TO_LE32(void *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *((uint32_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+EXPORT_SYMBOL(DWC_CPU_TO_LE32); -+ -+uint32_t DWC_CPU_TO_BE32(void *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *((uint32_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+EXPORT_SYMBOL(DWC_CPU_TO_BE32); -+ -+uint32_t DWC_LE32_TO_CPU(void *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *((uint32_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+ -+#endif -+} -+EXPORT_SYMBOL(DWC_LE32_TO_CPU); -+ -+uint32_t DWC_BE32_TO_CPU(void *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *((uint32_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+EXPORT_SYMBOL(DWC_BE32_TO_CPU); -+ -+uint16_t DWC_CPU_TO_LE16(void *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *((uint16_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+EXPORT_SYMBOL(DWC_CPU_TO_LE16); -+ -+uint16_t DWC_CPU_TO_BE16(void *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *((uint16_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+EXPORT_SYMBOL(DWC_CPU_TO_BE16); -+ -+uint16_t DWC_LE16_TO_CPU(void *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *((uint16_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+EXPORT_SYMBOL(DWC_LE16_TO_CPU); -+ -+uint16_t DWC_BE16_TO_CPU(void *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *((uint16_t *p)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+EXPORT_SYMBOL(DWC_BE16_TO_CPU); -+ -+ -+/* Registers */ -+ -+uint32_t DWC_READ_REG32(uint32_t volatile *reg) -+{ -+ return readl(reg); -+} -+EXPORT_SYMBOL(DWC_READ_REG32); -+ -+#if 0 -+uint64_t DWC_READ_REG64(uint64_t volatile *reg) -+{ -+} -+#endif -+ -+void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value) -+{ -+ writel(value, reg); -+} -+EXPORT_SYMBOL(DWC_WRITE_REG32); -+ -+#if 0 -+void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value) -+{ -+} -+#endif -+ -+void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) -+{ -+ writel( (readl(reg) & ~clear_mask) | set_mask, reg ); -+} -+EXPORT_SYMBOL(DWC_MODIFY_REG32); -+ -+#if 0 -+void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t value) -+{ -+} -+#endif -+ -+ -+ -+/* Threading */ -+ -+typedef struct work_container -+{ -+ dwc_work_callback_t cb; -+ void *data; -+ dwc_workq_t *wq; -+ char *name; -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_ENTRY(work_container) entry; -+#endif -+ -+ struct delayed_work work; -+} work_container_t; -+ -+#ifdef DEBUG -+DWC_CIRCLEQ_HEAD(work_container_queue, work_container); -+#endif -+ -+struct dwc_workq -+{ -+ struct workqueue_struct *wq; -+ int pending; -+ dwc_spinlock_t *lock; -+ dwc_waitq_t *waitq; -+ -+#ifdef DEBUG -+ struct work_container_queue entries; -+#endif -+}; -+ -+static void do_work(struct work_struct *work) -+{ -+ int64_t flags; -+ struct delayed_work *dw = container_of(work, struct delayed_work, work); -+ work_container_t *container = container_of(dw, struct work_container, work); -+ dwc_workq_t *wq = container->wq; -+ -+ container->cb(container->data); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); -+#endif -+ -+ if (container->name) { -+ DWC_DEBUG("Work done: %s, container=%p", -+ container->name, container); //GRAYG -+ DWC_FREE(container->name); -+ } -+ DWC_FREE(container); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending --; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+} -+ -+static int work_done(void *data) -+{ -+ dwc_workq_t *workq = (dwc_workq_t *)data; -+ return workq->pending == 0; -+} -+ -+int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) -+{ -+ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); -+} -+EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE); -+ -+dwc_workq_t *DWC_WORKQ_ALLOC(char *name) -+{ -+ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ wq->wq = create_singlethread_workqueue(name); -+ wq->pending = 0; -+ wq->lock = DWC_SPINLOCK_ALLOC(); -+ wq->waitq = DWC_WAITQ_ALLOC(); -+#ifdef DEBUG -+ DWC_CIRCLEQ_INIT(&wq->entries); -+#endif -+ return wq; -+} -+EXPORT_SYMBOL(DWC_WORKQ_ALLOC); -+ -+void DWC_WORKQ_FREE(dwc_workq_t *wq) -+{ -+#ifdef DEBUG -+ if (wq->pending != 0) { -+ struct work_container *wc; -+ DWC_ERROR("Destroying work queue with pending work"); -+ DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { -+ DWC_ERROR("Work %s still pending", wc->name); -+ } -+ } -+#endif -+ destroy_workqueue((struct workqueue_struct *)wq->wq); -+ DWC_SPINLOCK_FREE(wq->lock); -+ DWC_WAITQ_FREE(wq->waitq); -+ DWC_FREE(wq); -+} -+EXPORT_SYMBOL(DWC_WORKQ_FREE); -+ -+void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, char *format, ...) -+{ -+ int64_t flags; -+ work_container_t *container; -+ static char name[128]; -+ -+ va_list args; -+ va_start(args, format); -+ if (format) -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending ++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ -+ container->data = data; -+ container->cb = work_cb; -+ container->wq = wq; -+ if (format) { -+ container->name = DWC_STRDUP(name); -+ DWC_DEBUG("Queueing work: %s, contianer=%p", -+ container->name, container); -+ } else -+ container->name = NULL; -+ -+ INIT_WORK(&container->work.work, do_work); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); -+#endif -+ -+ queue_work(wq->wq, &container->work.work); -+ -+} -+EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE); -+ -+void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...) -+{ -+ int64_t flags; -+ work_container_t *container; -+ static char name[128]; -+ -+ va_list args; -+ va_start(args, format); -+ if (format) -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending ++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ -+ container->data = data; -+ container->cb = work_cb; -+ container->wq = wq; -+ if (format) { //GRAYG -+ container->name = DWC_STRDUP(name); -+ DWC_DEBUG("Queueing work: %s, contianer=%p", -+ container->name, container); -+ } else -+ container->name = NULL; -+ INIT_DELAYED_WORK(&container->work, do_work); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); -+#endif -+ -+ queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); -+ -+} -+EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED); -+ -+ -+int DWC_WORKQ_PENDING(dwc_workq_t *wq) -+{ -+ return wq->pending; -+} -+EXPORT_SYMBOL(DWC_WORKQ_PENDING); -+ -+dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) -+{ -+ spinlock_t *sl = (spinlock_t *)1; -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ sl = DWC_ALLOC(sizeof(*sl)); -+ spin_lock_init(sl); -+#endif -+ return (dwc_spinlock_t *)sl; -+} -+EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC); -+ -+void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) -+{ -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ DWC_FREE(lock); -+#endif -+} -+EXPORT_SYMBOL(DWC_SPINLOCK_FREE); -+ -+void DWC_SPINLOCK(dwc_spinlock_t *lock) -+{ -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_lock((spinlock_t *)lock); -+#endif -+} -+EXPORT_SYMBOL(DWC_SPINLOCK); -+ -+void DWC_SPINUNLOCK(dwc_spinlock_t *lock) -+{ -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_unlock((spinlock_t *)lock); -+#endif -+} -+EXPORT_SYMBOL(DWC_SPINUNLOCK); -+ -+void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags) -+{ -+ unsigned long f; -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_lock_irqsave((spinlock_t *)lock, f); -+#else -+ local_irq_save(f); -+#endif -+ *flags = f; -+} -+EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE); -+ -+void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags) -+{ -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_unlock_irqrestore((spinlock_t *)lock, flags); -+#else -+ // in kernel 2.6.31, at least, we check for unsigned long -+ local_irq_restore((unsigned long)flags); -+#endif -+} -+EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE); -+ -+dwc_mutex_t *DWC_MUTEX_ALLOC(void) -+{ -+ dwc_mutex_t *mutex = (dwc_mutex_t*)DWC_ALLOC(sizeof(struct mutex)); -+ struct mutex *m = (struct mutex *)mutex; -+ mutex_init(m); -+ return mutex; -+} -+EXPORT_SYMBOL(DWC_MUTEX_ALLOC); -+ -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+#else -+void DWC_MUTEX_FREE(dwc_mutex_t *mutex) -+{ -+ mutex_destroy((struct mutex *)mutex); -+ DWC_FREE(mutex); -+} -+EXPORT_SYMBOL(DWC_MUTEX_FREE); -+#endif -+ -+void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) -+{ -+ struct mutex *m = (struct mutex *)mutex; -+ mutex_lock(m); -+} -+EXPORT_SYMBOL(DWC_MUTEX_LOCK); -+ -+int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) -+{ -+ struct mutex *m = (struct mutex *)mutex; -+ return mutex_trylock(m); -+} -+EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK); -+ -+void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) -+{ -+ struct mutex *m = (struct mutex *)mutex; -+ mutex_unlock(m); -+} -+EXPORT_SYMBOL(DWC_MUTEX_UNLOCK); -+ -+dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data) -+{ -+ struct task_struct *thread = kthread_run(thread_function, data, name); -+ if (thread == ERR_PTR(-ENOMEM)) { -+ return NULL; -+ } -+ return (dwc_thread_t *)thread; -+} -+EXPORT_SYMBOL(DWC_THREAD_RUN); -+ -+int DWC_THREAD_STOP(dwc_thread_t *thread) -+{ -+ return kthread_stop((struct task_struct *)thread); -+} -+EXPORT_SYMBOL(DWC_THREAD_STOP); -+ -+dwc_bool_t DWC_THREAD_SHOULD_STOP() -+{ -+ return kthread_should_stop(); -+} -+EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP); -+ -+/* Timers */ -+ -+struct dwc_timer -+{ -+ struct timer_list *t; -+ char *name; -+ dwc_timer_callback_t cb; -+ void *data; -+ uint8_t scheduled; -+ dwc_spinlock_t *lock; -+}; -+ -+static void set_scheduled(dwc_timer_t *t, int s) -+{ -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(t->lock, &flags); -+ t->scheduled = s; -+ DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags); -+} -+ -+static int get_scheduled(dwc_timer_t *t) -+{ -+ int s; -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(t->lock, &flags); -+ s = t->scheduled; -+ DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags); -+ return s; -+} -+ -+static void timer_callback(unsigned long data) -+{ -+ dwc_timer_t *timer = (dwc_timer_t *)data; -+ set_scheduled(timer, 0); -+ DWC_DEBUG("Timer %s callback", timer->name); -+ timer->cb(timer->data); -+} -+ -+dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) -+{ -+ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); -+ if (!t) { -+ DWC_ERROR("Cannot allocate memory for timer"); -+ return NULL; -+ } -+ t->t = DWC_ALLOC(sizeof(*t->t)); -+ if (!t->t) { -+ DWC_ERROR("Cannot allocate memory for timer->t"); -+ goto no_timer; -+ } -+ -+ t->name = DWC_STRDUP(name); -+ if (!t->name) { -+ DWC_ERROR("Cannot allocate memory for timer->name"); -+ goto no_name; -+ } -+ -+ t->lock = DWC_SPINLOCK_ALLOC(); -+ if (!t->lock) { -+ DWC_ERROR("Cannot allocate memory for lock"); -+ goto no_lock; -+ } -+ t->scheduled = 0; -+ t->t->base = &boot_tvec_bases; -+ t->t->expires = jiffies; -+ setup_timer(t->t, timer_callback, (unsigned long)t); -+ -+ t->cb = cb; -+ t->data = data; -+ -+ return t; -+ -+ no_lock: -+ DWC_FREE(t->name); -+ no_name: -+ DWC_FREE(t->t); -+ no_timer: -+ DWC_FREE(t); -+ return NULL; -+} -+EXPORT_SYMBOL(DWC_TIMER_ALLOC); -+ -+void DWC_TIMER_FREE(dwc_timer_t *timer) -+{ -+ if (get_scheduled(timer)) { -+ del_timer(timer->t); -+ } -+ -+ DWC_SPINLOCK_FREE(timer->lock); -+ DWC_FREE(timer->t); -+ DWC_FREE(timer->name); -+ DWC_FREE(timer); -+} -+EXPORT_SYMBOL(DWC_TIMER_FREE); -+ -+void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) -+{ -+ if (!get_scheduled(timer)) { -+ set_scheduled(timer, 1); -+ //cgg: DWC_DEBUG("Scheduling timer %s to expire in +%d msec", timer->name, time); -+ timer->t->expires = jiffies + msecs_to_jiffies(time); -+ add_timer(timer->t); -+ } -+ else { -+ //cgg: DWC_DEBUG("Modifying timer %s to expire in +%d msec", timer->name, time); -+ mod_timer(timer->t, jiffies + msecs_to_jiffies(time)); -+ } -+} -+EXPORT_SYMBOL(DWC_TIMER_SCHEDULE); -+ -+void DWC_TIMER_CANCEL(dwc_timer_t *timer) -+{ -+ del_timer(timer->t); -+} -+EXPORT_SYMBOL(DWC_TIMER_CANCEL); -+ -+struct dwc_tasklet -+{ -+ struct tasklet_struct t; -+ dwc_tasklet_callback_t cb; -+ void *data; -+}; -+ -+static void tasklet_callback(unsigned long data) -+{ -+ dwc_tasklet_t *t = (dwc_tasklet_t *)data; -+ t->cb(t->data); -+} -+ -+dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data) -+{ -+ dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t)); -+ -+ if(t) { -+ t->data = data; -+ t->cb = cb; -+ tasklet_init(&t->t, tasklet_callback, (unsigned long)t); -+ } else { -+ DWC_ERROR("Cannot allocate memory for tasklet\n"); -+ } -+ -+ return t; -+} -+EXPORT_SYMBOL(DWC_TASK_ALLOC); -+ -+void DWC_TASK_FREE(dwc_tasklet_t *t) -+{ -+ DWC_FREE(t); -+} -+EXPORT_SYMBOL(DWC_TASK_FREE); -+ -+void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) -+{ -+ tasklet_schedule(&task->t); -+} -+EXPORT_SYMBOL(DWC_TASK_SCHEDULE); -+ -+/* Timing */ -+ -+void DWC_UDELAY(uint32_t usecs) -+{ -+ udelay(usecs); -+} -+EXPORT_SYMBOL(DWC_UDELAY); -+ -+void DWC_MDELAY(uint32_t msecs) -+{ -+ mdelay(msecs); -+} -+EXPORT_SYMBOL(DWC_MDELAY); -+ -+void DWC_MSLEEP(uint32_t msecs) -+{ -+ msleep(msecs); -+} -+EXPORT_SYMBOL(DWC_MSLEEP); -+ -+uint32_t DWC_TIME(void) -+{ -+ return jiffies_to_msecs(jiffies); -+} -+EXPORT_SYMBOL(DWC_TIME); -+ -+ -+/* Wait Queues */ -+ -+struct dwc_waitq -+{ -+ wait_queue_head_t queue; -+ int abort; -+}; -+ -+dwc_waitq_t *DWC_WAITQ_ALLOC(void) -+{ -+ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ init_waitqueue_head(&wq->queue); -+ wq->abort = 0; -+ return wq; -+} -+EXPORT_SYMBOL(DWC_WAITQ_ALLOC); -+ -+void DWC_WAITQ_FREE(dwc_waitq_t *wq) -+{ -+ DWC_FREE(wq); -+} -+EXPORT_SYMBOL(DWC_WAITQ_FREE); -+ -+static int32_t check_result(dwc_waitq_t *wq, int result) -+{ int32_t msecs; -+ if (result > 0) { -+ msecs = jiffies_to_msecs(result); -+ if (!msecs) { -+ return 1; -+ } -+ return msecs; -+ } -+ -+ if (result == 0) { -+ return -DWC_E_TIMEOUT; -+ } -+ -+ if ((result == -ERESTARTSYS) || (wq->abort == 1)) { -+ return -DWC_E_ABORT; -+ } -+ -+ return -DWC_E_UNKNOWN; -+} -+ -+int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data) -+{ -+ int result = wait_event_interruptible(wq->queue, -+ condition(data) || wq->abort); -+ return check_result(wq, result); -+} -+EXPORT_SYMBOL(DWC_WAITQ_WAIT); -+ -+int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, -+ void *data, int32_t msecs) -+{ -+ int result = wait_event_interruptible_timeout(wq->queue, -+ condition(data) || wq->abort, -+ msecs_to_jiffies(msecs)); -+ return check_result(wq, result); -+} -+EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT); -+ -+void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) -+{ -+ wake_up_interruptible(&wq->queue); -+} -+EXPORT_SYMBOL(DWC_WAITQ_TRIGGER); -+ -+void DWC_WAITQ_ABORT(dwc_waitq_t *wq) -+{ -+ wq->abort = 1; -+ DWC_WAITQ_TRIGGER(wq); -+} -+EXPORT_SYMBOL(DWC_WAITQ_ABORT); -diff --git a/drivers/usb/host/dwc_common_port/dwc_list.h b/drivers/usb/host/dwc_common_port/dwc_list.h -new file mode 100644 -index 0000000..b29afe0 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_list.h -@@ -0,0 +1,616 @@ -+/* $OpenBSD: queue.h,v 1.26 2004/05/04 16:59:32 grange Exp $ */ -+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ -+ -+/* -+ * Copyright (c) 1991, 1993 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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. -+ * -+ * @(#)queue.h 8.5 (Berkeley) 8/20/94 -+ */ -+ -+#ifndef _SYS_QUEUE_H_ -+#define _SYS_QUEUE_H_ -+ -+ -+/** @file -+ * -+ * This file defines linked list operations. It is derived from BSD with -+ * only the MACRO names being prefixed with DWC_. This is because a few of -+ * these names conflict with those on Linux. For documentation on use, see the -+ * inline comments in the source code. The original license for this source -+ * code applies and is preserved in the dwc_list.h source file. -+ */ -+ -+/* -+ * This file defines five types of data structures: singly-linked lists, -+ * lists, simple queues, tail queues, and circular queues. -+ * -+ * -+ * A singly-linked list is headed by a single forward pointer. The elements -+ * are singly linked for minimum space and pointer manipulation overhead at -+ * the expense of O(n) removal for arbitrary elements. New elements can be -+ * added to the list after an existing element or at the head of the list. -+ * Elements being removed from the head of the list should use the explicit -+ * macro for this purpose for optimum efficiency. A singly-linked list may -+ * only be traversed in the forward direction. Singly-linked lists are ideal -+ * for applications with large datasets and few or no removals or for -+ * implementing a LIFO queue. -+ * -+ * A list is headed by a single forward pointer (or an array of forward -+ * pointers for a hash table header). The elements are doubly linked -+ * so that an arbitrary element can be removed without a need to -+ * traverse the list. New elements can be added to the list before -+ * or after an existing element or at the head of the list. A list -+ * may only be traversed in the forward direction. -+ * -+ * A simple queue is headed by a pair of pointers, one the head of the -+ * list and the other to the tail of the list. The elements are singly -+ * linked to save space, so elements can only be removed from the -+ * head of the list. New elements can be added to the list before or after -+ * an existing element, at the head of the list, or at the end of the -+ * list. A simple queue may only be traversed in the forward direction. -+ * -+ * A tail queue is headed by a pair of pointers, one to the head of the -+ * list and the other to the tail of the list. The elements are doubly -+ * linked so that an arbitrary element can be removed without a need to -+ * traverse the list. New elements can be added to the list before or -+ * after an existing element, at the head of the list, or at the end of -+ * the list. A tail queue may be traversed in either direction. -+ * -+ * A circle queue is headed by a pair of pointers, one to the head of the -+ * list and the other to the tail of the list. The elements are doubly -+ * linked so that an arbitrary element can be removed without a need to -+ * traverse the list. New elements can be added to the list before or after -+ * an existing element, at the head of the list, or at the end of the list. -+ * A circle queue may be traversed in either direction, but has a more -+ * complex end of list detection. -+ * -+ * For details on the use of these macros, see the queue(3) manual page. -+ */ -+ -+/* -+ * Double-linked List. -+ */ -+ -+typedef struct dwc_list_link { -+ struct dwc_list_link *next; -+ struct dwc_list_link *prev; -+} dwc_list_link_t; -+ -+#define DWC_LIST_INIT(link) do{ \ -+ (link)->next = (link); \ -+ (link)->prev = (link); \ -+} while(0) -+ -+#define DWC_LIST_FIRST(link) ((link)->next) -+#define DWC_LIST_LAST(link) ((link)->prev) -+#define DWC_LIST_END(link) (link) -+#define DWC_LIST_NEXT(link) ((link)->next) -+#define DWC_LIST_PREV(link) ((link)->prev) -+#define DWC_LIST_EMPTY(link) \ -+ (DWC_LIST_FIRST(link) == DWC_LIST_END(link)) -+#define DWC_LIST_ENTRY(link, type, field) (type *) \ -+ ((uint8_t *)(link) - (size_t)(&((type *)0)->field)) -+ -+#define DWC_LIST_INSERT_HEAD(list, link) do { \ -+ (link)->next = (list)->next; \ -+ (link)->prev = (list); \ -+ (list)->next->prev = link; \ -+ (list)->next = link; \ -+} while(0) -+ -+#define DWC_LIST_INSERT_TAIL(list, link) do { \ -+ (link)->next = list; \ -+ (link)->prev = (list)->prev; \ -+ (list)->prev->next = link; \ -+ (list)->prev = link; \ -+} while(0) -+ -+#define DWC_LIST_REMOVE(link) do { \ -+ (link)->next->prev = (link)->prev; \ -+ (link)->prev->next = (link)->next; \ -+} while(0) -+ -+#define DWC_LIST_REMOVE_INIT(link) do { \ -+ DWC_LIST_REMOVE(link); \ -+ DWC_LIST_INIT(link); \ -+} while(0) -+ -+#define DWC_LIST_MOVE_HEAD(list, link) do { \ -+ DWC_LIST_REMOVE(link); \ -+ DWC_LIST_INSERT_HEAD(list, link); \ -+} while(0) -+ -+#define DWC_LIST_MOVE_TAIL(list, link) do { \ -+ DWC_LIST_REMOVE(link); \ -+ DWC_LIST_INSERT_TAIL(list, link); \ -+} while(0) -+ -+#define DWC_LIST_FOREACH(var, list) \ -+ for((var) = DWC_LIST_FIRST(list); \ -+ (var) != DWC_LIST_END(list); \ -+ (var) = DWC_LIST_NEXT(var)) -+ -+#define DWC_LIST_FOREACH_SAFE(var, var2, list) \ -+ for((var) = DWC_LIST_FIRST(list), var2 = DWC_LIST_NEXT(var); \ -+ (var) != DWC_LIST_END(list); \ -+ (var) = (var2), var2 = DWC_LIST_NEXT(var2)) -+ -+#define DWC_LIST_FOREACH_REVERSE(var, list) \ -+ for((var) = DWC_LIST_LAST(list); \ -+ (var) != DWC_LIST_END(list); \ -+ (var) = DWC_LIST_PREV(var)) -+ -+/* -+ * Singly-linked List definitions. -+ */ -+#define DWC_SLIST_HEAD(name, type) \ -+struct name { \ -+ struct type *slh_first; /* first element */ \ -+} -+ -+#define DWC_SLIST_HEAD_INITIALIZER(head) \ -+ { NULL } -+ -+#define DWC_SLIST_ENTRY(type) \ -+struct { \ -+ struct type *sle_next; /* next element */ \ -+} -+ -+/* -+ * Singly-linked List access methods. -+ */ -+#define DWC_SLIST_FIRST(head) ((head)->slh_first) -+#define DWC_SLIST_END(head) NULL -+#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) -+#define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next) -+ -+#define DWC_SLIST_FOREACH(var, head, field) \ -+ for((var) = SLIST_FIRST(head); \ -+ (var) != SLIST_END(head); \ -+ (var) = SLIST_NEXT(var, field)) -+ -+#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ -+ for ((varp) = &SLIST_FIRST((head)); \ -+ ((var) = *(varp)) != SLIST_END(head); \ -+ (varp) = &SLIST_NEXT((var), field)) -+ -+/* -+ * Singly-linked List functions. -+ */ -+#define DWC_SLIST_INIT(head) { \ -+ SLIST_FIRST(head) = SLIST_END(head); \ -+} -+ -+#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ -+ (elm)->field.sle_next = (slistelm)->field.sle_next; \ -+ (slistelm)->field.sle_next = (elm); \ -+} while (0) -+ -+#define DWC_SLIST_INSERT_HEAD(head, elm, field) do { \ -+ (elm)->field.sle_next = (head)->slh_first; \ -+ (head)->slh_first = (elm); \ -+} while (0) -+ -+#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do { \ -+ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ -+} while (0) -+ -+#define DWC_SLIST_REMOVE_HEAD(head, field) do { \ -+ (head)->slh_first = (head)->slh_first->field.sle_next; \ -+} while (0) -+ -+#define DWC_SLIST_REMOVE(head, elm, type, field) do { \ -+ if ((head)->slh_first == (elm)) { \ -+ SLIST_REMOVE_HEAD((head), field); \ -+ } \ -+ else { \ -+ struct type *curelm = (head)->slh_first; \ -+ while( curelm->field.sle_next != (elm) ) \ -+ curelm = curelm->field.sle_next; \ -+ curelm->field.sle_next = \ -+ curelm->field.sle_next->field.sle_next; \ -+ } \ -+} while (0) -+ -+#if 0 -+ -+/* -+ * List definitions. -+ */ -+#define DWC_LIST_HEAD(name, type) \ -+struct name { \ -+ struct type *lh_first; /* first element */ \ -+} -+ -+#define DWC_LIST_HEAD_INITIALIZER(head) \ -+ { NULL } -+ -+#define DWC_LIST_ENTRY(type) \ -+struct { \ -+ struct type *le_next; /* next element */ \ -+ struct type **le_prev; /* address of previous next element */ \ -+} -+ -+/* -+ * List access methods -+ */ -+#define DWC_LIST_FIRST(head) ((head)->lh_first) -+#define DWC_LIST_END(head) NULL -+#define DWC_LIST_EMPTY(head) (DWC_LIST_FIRST(head) == DWC_LIST_END(head)) -+#define DWC_LIST_NEXT(elm, field) ((elm)->field.le_next) -+ -+#define DWC_LIST_FOREACH(var, head, field) \ -+ for((var) = DWC_LIST_FIRST(head); \ -+ (var)!= DWC_LIST_END(head); \ -+ (var) = DWC_LIST_NEXT(var, field)) -+#define DWC_LIST_FOREACH_SAFE(var, var2, head, field) \ -+ for((var) = DWC_LIST_FIRST(head), var2 = DWC_LIST_NEXT(var, field); \ -+ (var) != DWC_LIST_END(head); \ -+ (var) = var2, var2 = DWC_LIST_NEXT(var, field)) -+ -+/* -+ * List functions. -+ */ -+#define DWC_LIST_INIT(head) do { \ -+ DWC_LIST_FIRST(head) = DWC_LIST_END(head); \ -+} while (0) -+ -+#define DWC_LIST_INSERT_AFTER(listelm, elm, field) do { \ -+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ -+ (listelm)->field.le_next->field.le_prev = \ -+ &(elm)->field.le_next; \ -+ (listelm)->field.le_next = (elm); \ -+ (elm)->field.le_prev = &(listelm)->field.le_next; \ -+} while (0) -+ -+#define DWC_LIST_INSERT_BEFORE(listelm, elm, field) do { \ -+ (elm)->field.le_prev = (listelm)->field.le_prev; \ -+ (elm)->field.le_next = (listelm); \ -+ *(listelm)->field.le_prev = (elm); \ -+ (listelm)->field.le_prev = &(elm)->field.le_next; \ -+} while (0) -+ -+#define DWC_LIST_INSERT_HEAD(head, elm, field) do { \ -+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ -+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ -+ (head)->lh_first = (elm); \ -+ (elm)->field.le_prev = &(head)->lh_first; \ -+} while (0) -+ -+#define DWC_LIST_REMOVE(elm, field) do { \ -+ if ((elm)->field.le_next != NULL) \ -+ (elm)->field.le_next->field.le_prev = \ -+ (elm)->field.le_prev; \ -+ *(elm)->field.le_prev = (elm)->field.le_next; \ -+} while (0) -+ -+#define DWC_LIST_REPLACE(elm, elm2, field) do { \ -+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ -+ (elm2)->field.le_next->field.le_prev = \ -+ &(elm2)->field.le_next; \ -+ (elm2)->field.le_prev = (elm)->field.le_prev; \ -+ *(elm2)->field.le_prev = (elm2); \ -+} while (0) -+ -+#endif -+ -+/* -+ * Simple queue definitions. -+ */ -+#define DWC_SIMPLEQ_HEAD(name, type) \ -+struct name { \ -+ struct type *sqh_first; /* first element */ \ -+ struct type **sqh_last; /* addr of last next element */ \ -+} -+ -+#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ -+ { NULL, &(head).sqh_first } -+ -+#define DWC_SIMPLEQ_ENTRY(type) \ -+struct { \ -+ struct type *sqe_next; /* next element */ \ -+} -+ -+/* -+ * Simple queue access methods. -+ */ -+#define DWC_SIMPLEQ_FIRST(head) ((head)->sqh_first) -+#define DWC_SIMPLEQ_END(head) NULL -+#define DWC_SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) -+#define DWC_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) -+ -+#define DWC_SIMPLEQ_FOREACH(var, head, field) \ -+ for((var) = SIMPLEQ_FIRST(head); \ -+ (var) != SIMPLEQ_END(head); \ -+ (var) = SIMPLEQ_NEXT(var, field)) -+ -+/* -+ * Simple queue functions. -+ */ -+#define DWC_SIMPLEQ_INIT(head) do { \ -+ (head)->sqh_first = NULL; \ -+ (head)->sqh_last = &(head)->sqh_first; \ -+} while (0) -+ -+#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ -+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ -+ (head)->sqh_last = &(elm)->field.sqe_next; \ -+ (head)->sqh_first = (elm); \ -+} while (0) -+ -+#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ -+ (elm)->field.sqe_next = NULL; \ -+ *(head)->sqh_last = (elm); \ -+ (head)->sqh_last = &(elm)->field.sqe_next; \ -+} while (0) -+ -+#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ -+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ -+ (head)->sqh_last = &(elm)->field.sqe_next; \ -+ (listelm)->field.sqe_next = (elm); \ -+} while (0) -+ -+#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do { \ -+ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ -+ (head)->sqh_last = &(head)->sqh_first; \ -+} while (0) -+ -+/* -+ * Tail queue definitions. -+ */ -+#define DWC_TAILQ_HEAD(name, type) \ -+struct name { \ -+ struct type *tqh_first; /* first element */ \ -+ struct type **tqh_last; /* addr of last next element */ \ -+} -+ -+#define DWC_TAILQ_HEAD_INITIALIZER(head) \ -+ { NULL, &(head).tqh_first } -+ -+#define DWC_TAILQ_ENTRY(type) \ -+struct { \ -+ struct type *tqe_next; /* next element */ \ -+ struct type **tqe_prev; /* address of previous next element */ \ -+} -+ -+/* -+ * tail queue access methods -+ */ -+#define DWC_TAILQ_FIRST(head) ((head)->tqh_first) -+#define DWC_TAILQ_END(head) NULL -+#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -+#define DWC_TAILQ_LAST(head, headname) \ -+ (*(((struct headname *)((head)->tqh_last))->tqh_last)) -+/* XXX */ -+#define DWC_TAILQ_PREV(elm, headname, field) \ -+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) -+#define DWC_TAILQ_EMPTY(head) \ -+ (TAILQ_FIRST(head) == TAILQ_END(head)) -+ -+#define DWC_TAILQ_FOREACH(var, head, field) \ -+ for((var) = TAILQ_FIRST(head); \ -+ (var) != TAILQ_END(head); \ -+ (var) = TAILQ_NEXT(var, field)) -+ -+#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ -+ for((var) = TAILQ_LAST(head, headname); \ -+ (var) != TAILQ_END(head); \ -+ (var) = TAILQ_PREV(var, headname, field)) -+ -+/* -+ * Tail queue functions. -+ */ -+#define DWC_TAILQ_INIT(head) do { \ -+ (head)->tqh_first = NULL; \ -+ (head)->tqh_last = &(head)->tqh_first; \ -+} while (0) -+ -+#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do { \ -+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ -+ (head)->tqh_first->field.tqe_prev = \ -+ &(elm)->field.tqe_next; \ -+ else \ -+ (head)->tqh_last = &(elm)->field.tqe_next; \ -+ (head)->tqh_first = (elm); \ -+ (elm)->field.tqe_prev = &(head)->tqh_first; \ -+} while (0) -+ -+#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do { \ -+ (elm)->field.tqe_next = NULL; \ -+ (elm)->field.tqe_prev = (head)->tqh_last; \ -+ *(head)->tqh_last = (elm); \ -+ (head)->tqh_last = &(elm)->field.tqe_next; \ -+} while (0) -+ -+#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ -+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ -+ (elm)->field.tqe_next->field.tqe_prev = \ -+ &(elm)->field.tqe_next; \ -+ else \ -+ (head)->tqh_last = &(elm)->field.tqe_next; \ -+ (listelm)->field.tqe_next = (elm); \ -+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ -+} while (0) -+ -+#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ -+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ -+ (elm)->field.tqe_next = (listelm); \ -+ *(listelm)->field.tqe_prev = (elm); \ -+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ -+} while (0) -+ -+#define DWC_TAILQ_REMOVE(head, elm, field) do { \ -+ if (((elm)->field.tqe_next) != NULL) \ -+ (elm)->field.tqe_next->field.tqe_prev = \ -+ (elm)->field.tqe_prev; \ -+ else \ -+ (head)->tqh_last = (elm)->field.tqe_prev; \ -+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ -+} while (0) -+ -+#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do { \ -+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ -+ (elm2)->field.tqe_next->field.tqe_prev = \ -+ &(elm2)->field.tqe_next; \ -+ else \ -+ (head)->tqh_last = &(elm2)->field.tqe_next; \ -+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ -+ *(elm2)->field.tqe_prev = (elm2); \ -+} while (0) -+ -+/* -+ * Circular queue definitions. -+ */ -+#define DWC_CIRCLEQ_HEAD(name, type) \ -+struct name { \ -+ struct type *cqh_first; /* first element */ \ -+ struct type *cqh_last; /* last element */ \ -+} -+ -+#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ -+ { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) } -+ -+#define DWC_CIRCLEQ_ENTRY(type) \ -+struct { \ -+ struct type *cqe_next; /* next element */ \ -+ struct type *cqe_prev; /* previous element */ \ -+} -+ -+/* -+ * Circular queue access methods -+ */ -+#define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first) -+#define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last) -+#define DWC_CIRCLEQ_END(head) ((void *)(head)) -+#define DWC_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) -+#define DWC_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) -+#define DWC_CIRCLEQ_EMPTY(head) \ -+ (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head)) -+ -+#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL)) -+ -+#define DWC_CIRCLEQ_FOREACH(var, head, field) \ -+ for((var) = DWC_CIRCLEQ_FIRST(head); \ -+ (var) != DWC_CIRCLEQ_END(head); \ -+ (var) = DWC_CIRCLEQ_NEXT(var, field)) -+ -+#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ -+ for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ -+ (var) != DWC_CIRCLEQ_END(head); \ -+ (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field)) -+ -+#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ -+ for((var) = DWC_CIRCLEQ_LAST(head); \ -+ (var) != DWC_CIRCLEQ_END(head); \ -+ (var) = DWC_CIRCLEQ_PREV(var, field)) -+ -+/* -+ * Circular queue functions. -+ */ -+#define DWC_CIRCLEQ_INIT(head) do { \ -+ (head)->cqh_first = DWC_CIRCLEQ_END(head); \ -+ (head)->cqh_last = DWC_CIRCLEQ_END(head); \ -+} while (0) -+ -+#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ -+ (elm)->field.cqe_next = NULL; \ -+ (elm)->field.cqe_prev = NULL; \ -+} while (0) -+ -+#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ -+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ -+ (elm)->field.cqe_prev = (listelm); \ -+ if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ -+ (head)->cqh_last = (elm); \ -+ else \ -+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ -+ (listelm)->field.cqe_next = (elm); \ -+} while (0) -+ -+#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ -+ (elm)->field.cqe_next = (listelm); \ -+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ -+ if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ -+ (head)->cqh_first = (elm); \ -+ else \ -+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ -+ (listelm)->field.cqe_prev = (elm); \ -+} while (0) -+ -+#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ -+ (elm)->field.cqe_next = (head)->cqh_first; \ -+ (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head); \ -+ if ((head)->cqh_last == DWC_CIRCLEQ_END(head)) \ -+ (head)->cqh_last = (elm); \ -+ else \ -+ (head)->cqh_first->field.cqe_prev = (elm); \ -+ (head)->cqh_first = (elm); \ -+} while (0) -+ -+#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ -+ (elm)->field.cqe_next = DWC_CIRCLEQ_END(head); \ -+ (elm)->field.cqe_prev = (head)->cqh_last; \ -+ if ((head)->cqh_first == DWC_CIRCLEQ_END(head)) \ -+ (head)->cqh_first = (elm); \ -+ else \ -+ (head)->cqh_last->field.cqe_next = (elm); \ -+ (head)->cqh_last = (elm); \ -+} while (0) -+ -+#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ -+ if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ -+ (head)->cqh_last = (elm)->field.cqe_prev; \ -+ else \ -+ (elm)->field.cqe_next->field.cqe_prev = \ -+ (elm)->field.cqe_prev; \ -+ if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ -+ (head)->cqh_first = (elm)->field.cqe_next; \ -+ else \ -+ (elm)->field.cqe_prev->field.cqe_next = \ -+ (elm)->field.cqe_next; \ -+} while (0) -+ -+#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ -+ DWC_CIRCLEQ_REMOVE(head, elm, field); \ -+ DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ -+} while (0) -+ -+#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ -+ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ -+ DWC_CIRCLEQ_END(head)) \ -+ (head).cqh_last = (elm2); \ -+ else \ -+ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ -+ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ -+ DWC_CIRCLEQ_END(head)) \ -+ (head).cqh_first = (elm2); \ -+ else \ -+ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ -+} while (0) -+ -+#endif /* !_SYS_QUEUE_H_ */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_mem.c b/drivers/usb/host/dwc_common_port/dwc_mem.c -new file mode 100644 -index 0000000..f2f9bc6 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_mem.c -@@ -0,0 +1,172 @@ -+#include "dwc_os.h" -+#include "dwc_list.h" -+ -+/* Memory Debugging */ -+#ifdef DEBUG_MEMORY -+ -+struct allocation -+{ -+ void *addr; -+ char *func; -+ int line; -+ uint32_t size; -+ int dma; -+ DWC_CIRCLEQ_ENTRY(allocation) entry; -+}; -+ -+DWC_CIRCLEQ_HEAD(allocation_queue, allocation); -+ -+struct allocation_manager -+{ -+ struct allocation_queue allocations; -+ -+ /* statistics */ -+ int num; -+ int num_freed; -+ int num_active; -+ uint32_t total; -+ uint32_t current; -+ uint32_t max; -+}; -+ -+ -+static struct allocation_manager *manager = NULL; -+ -+static void add_allocation(uint32_t size, char const* func, int line, void *addr, int dma) -+{ -+ struct allocation *a = __DWC_ALLOC_ATOMIC(sizeof(*a)); -+ a->func = __DWC_ALLOC_ATOMIC(DWC_STRLEN(func)+1); -+ DWC_MEMCPY(a->func, func, DWC_STRLEN(func)+1); -+ a->line = line; -+ a->size = size; -+ a->addr = addr; -+ a->dma = dma; -+ DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry); -+ -+ /* Update stats */ -+ manager->num ++; -+ manager->num_active ++; -+ manager->total += size; -+ manager->current += size; -+ if (manager->max < manager->current) { -+ manager->max = manager->current; -+ } -+} -+ -+static struct allocation *find_allocation(void *addr) -+{ -+ struct allocation *a; -+ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { -+ if (a->addr == addr) { -+ return a; -+ } -+ } -+ return NULL; -+} -+ -+static void free_allocation(void *addr, char const* func, int line) -+{ -+ struct allocation *a = find_allocation(addr); -+ if (!a && func && (line >= 0)) { -+ DWC_ASSERT(0, "Free of address %p that was never allocated or already freed %s:%d", addr, func, line); -+ return; -+ } -+ DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry); -+ -+ manager->num_active --; -+ manager->num_freed ++; -+ manager->current -= a->size; -+ __DWC_FREE(a->func); -+ __DWC_FREE(a); -+} -+ -+void dwc_memory_debug_start(void) -+{ -+ DWC_ASSERT(manager == NULL, "Memory debugging has already started\n"); -+ if (manager == NULL) { -+ manager = __DWC_ALLOC(sizeof(*manager)); -+ } -+ -+ DWC_CIRCLEQ_INIT(&manager->allocations); -+ manager->num = 0; -+ manager->num_freed = 0; -+ manager->num_active = 0; -+ manager->total = 0; -+ manager->current = 0; -+ manager->max = 0; -+} -+ -+void dwc_memory_debug_stop(void) -+{ -+ struct allocation *a; -+ dwc_memory_debug_report(); -+ -+ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { -+ DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line); -+ free_allocation(a->addr, NULL, -1); -+ } -+ -+ __DWC_FREE(manager); -+} -+ -+void dwc_memory_debug_report(void) -+{ -+ struct allocation *a; -+ DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n"); -+ DWC_PRINTF("Num Allocations = %d\n", manager->num); -+ DWC_PRINTF("Freed = %d\n", manager->num_freed); -+ DWC_PRINTF("Active = %d\n", manager->num_active); -+ DWC_PRINTF("Current Memory Used = %d\n", manager->current); -+ DWC_PRINTF("Total Memory Used = %d\n", manager->total); -+ DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max); -+ DWC_PRINTF("Unfreed allocations:\n"); -+ -+ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { -+ DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", a->addr, a->size, a->func, a->line, a->dma); -+ } -+} -+ -+ -+ -+/* The replacement functions */ -+void *dwc_alloc_debug(uint32_t size, char const* func, int line) -+{ -+ void *addr = __DWC_ALLOC(size); -+ add_allocation(size, func, line, addr, 0); -+ return addr; -+} -+ -+void *dwc_alloc_atomic_debug(uint32_t size, char const* func, int line) -+{ -+ void *addr = __DWC_ALLOC_ATOMIC(size); -+ add_allocation(size, func, line, addr, 0); -+ return addr; -+} -+ -+void dwc_free_debug(void *addr, char const* func, int line) -+{ -+ free_allocation(addr, func, line); -+ __DWC_FREE(addr); -+} -+ -+void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line) -+{ -+ void *addr = __DWC_DMA_ALLOC(size, dma_addr); -+ add_allocation(size, func, line, addr, 1); -+ return addr; -+} -+ -+void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line) -+{ -+ void *addr = __DWC_DMA_ALLOC_ATOMIC(size, dma_addr); -+ add_allocation(size, func, line, addr, 1); -+ return addr; -+} -+ -+void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line) -+{ -+ free_allocation(virt_addr, func, line); -+ __DWC_DMA_FREE(size, virt_addr, dma_addr); -+} -+ -+#endif /* DEBUG_MEMORY */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.c b/drivers/usb/host/dwc_common_port/dwc_notifier.c -new file mode 100644 -index 0000000..e44bb81 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c -@@ -0,0 +1,256 @@ -+#include "dwc_notifier.h" -+#include "dwc_list.h" -+ -+typedef struct dwc_observer -+{ -+ void *observer; -+ dwc_notifier_callback_t callback; -+ void *data; -+ char *notification; -+ DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry; -+} observer_t; -+ -+DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer); -+ -+typedef struct dwc_notifier -+{ -+ void *object; -+ struct observer_queue observers; -+ DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry; -+} notifier_t; -+ -+DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier); -+ -+typedef struct manager -+{ -+ dwc_workq_t *wq; -+ dwc_mutex_t *mutex; -+ struct notifier_queue notifiers; -+} manager_t; -+ -+static manager_t *manager = NULL; -+ -+static void create_manager(void) -+{ -+ manager = DWC_ALLOC(sizeof(manager_t)); -+ DWC_CIRCLEQ_INIT(&manager->notifiers); -+ manager->wq = DWC_WORKQ_ALLOC("DWC Notification WorkQ"); -+} -+ -+static void free_manager(void) -+{ -+ DWC_WORKQ_FREE(manager->wq); -+ /* All notifiers must have unregistered themselves before this module -+ * can be removed. Hitting this assertion indicates a programmer -+ * error. */ -+ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), "Notification manager being freed before all notifiers have been removed"); -+ DWC_FREE(manager); -+} -+ -+#ifdef DEBUG -+static void dump_manager(void) -+{ -+ notifier_t *n; -+ observer_t *o; -+ DWC_ASSERT(manager, "Notification manager not found"); -+ DWC_DEBUG("List of all notifiers and observers:"); -+ DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { -+ DWC_DEBUG("Notifier %p has observers:", n->object); -+ DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) { -+ DWC_DEBUG(" %p watching %s", o->observer, o->notification); -+ } -+ } -+} -+#else -+#define dump_manager(...) -+#endif -+ -+static observer_t *alloc_observer(void *observer, char *notification, dwc_notifier_callback_t callback, void *data) -+{ -+ observer_t *new_observer = DWC_ALLOC(sizeof(observer_t)); -+ DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry); -+ new_observer->observer = observer; -+ new_observer->notification = notification; -+ new_observer->callback = callback; -+ new_observer->data = data; -+ return new_observer; -+} -+ -+static void free_observer(observer_t *observer) -+{ -+ DWC_FREE(observer); -+} -+ -+static notifier_t *alloc_notifier(void *object) -+{ -+ notifier_t *notifier; -+ -+ if (!object) { -+ return NULL; -+ } -+ -+ notifier = DWC_ALLOC(sizeof(notifier_t)); -+ DWC_CIRCLEQ_INIT(¬ifier->observers); -+ DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry); -+ -+ notifier->object = object; -+ return notifier; -+} -+ -+static void free_notifier(notifier_t *notifier) -+{ -+ observer_t *observer; -+ DWC_CIRCLEQ_FOREACH(observer, ¬ifier->observers, list_entry) { -+ free_observer(observer); -+ } -+ DWC_FREE(notifier); -+} -+ -+static notifier_t *find_notifier(void *object) -+{ -+ notifier_t *notifier; -+ if (!object) { -+ return NULL; -+ } -+ DWC_ASSERT(manager, "Notification manager not found"); -+ DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) { -+ if (notifier->object == object) { -+ return notifier; -+ } -+ } -+ return NULL; -+} -+ -+void dwc_alloc_notification_manager(void) -+{ -+ create_manager(); -+} -+ -+void dwc_free_notification_manager(void) -+{ -+ free_manager(); -+} -+ -+dwc_notifier_t *dwc_register_notifier(void *object) -+{ -+ notifier_t *notifier = find_notifier(object); -+ DWC_ASSERT(manager, "Notification manager not found"); -+ if (notifier) { -+ DWC_ERROR("Notifier %p is already registered", object); -+ return NULL; -+ } -+ -+ notifier = alloc_notifier(object); -+ DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); -+ -+ -+ DWC_INFO("Notifier %p registered", object); -+ dump_manager(); -+ -+ return notifier; -+} -+ -+void dwc_unregister_notifier(dwc_notifier_t *notifier) -+{ -+ DWC_ASSERT(manager, "Notification manager not found"); -+ if (!DWC_CIRCLEQ_EMPTY(¬ifier->observers)) { -+ observer_t *o; -+ DWC_ERROR("Notifier %p has active observers when removing", notifier->object); -+ DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { -+ DWC_DEBUG(" %p watching %s", o->observer, o->notification); -+ } -+ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers), "Notifier %p has active observers when removing", notifier); -+ } -+ -+ DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry); -+ free_notifier(notifier); -+ -+ DWC_INFO("Notifier unregistered"); -+ dump_manager(); -+} -+ -+/* Add an observer to observe the notifier for a particular state, event, or notification. */ -+int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *data) -+{ -+ notifier_t *notifier = find_notifier(object); -+ observer_t *new_observer; -+ if (!notifier) { -+ DWC_ERROR("Notifier %p is not found when adding observer", object); -+ return -1; -+ } -+ -+ new_observer = alloc_observer(observer, notification, callback, data); -+ -+ DWC_CIRCLEQ_INSERT_TAIL(¬ifier->observers, new_observer, list_entry); -+ -+ DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p", -+ observer, object, notification, callback, data); -+ -+ dump_manager(); -+ return 0; -+} -+ -+int dwc_remove_observer(void *observer) -+{ -+ notifier_t *n; -+ DWC_ASSERT(manager, "Notification manager not found"); -+ DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { -+ observer_t *o; -+ observer_t *o2; -+ DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) { -+ if (o->observer == observer) { -+ DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry); -+ DWC_INFO("Removing observer %p from notifier %p watching notification %s:", -+ o->observer, n->object, o->notification); -+ free_observer(o); -+ } -+ } -+ } -+ -+ dump_manager(); -+ return 0; -+} -+ -+typedef struct callback_data -+{ -+ dwc_notifier_callback_t cb; -+ void *observer; -+ void *data; -+ void *object; -+ void *notification; -+ void *notification_data; -+} cb_data_t; -+ -+static void cb_task(void *data) -+{ -+ cb_data_t *cb = (cb_data_t *)data; -+ cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data); -+ DWC_FREE(cb); -+} -+ -+void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data) -+{ -+ observer_t *o; -+ DWC_ASSERT(manager, "Notification manager not found"); -+ DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { -+ int len = DWC_STRLEN(notification); -+ if (DWC_STRLEN(o->notification) != len) { -+ continue; -+ } -+ -+ if (DWC_STRNCMP(o->notification, notification, len) == 0) { -+ cb_data_t *cb_data = DWC_ALLOC(sizeof(cb_data_t)); -+ cb_data->cb = o->callback; -+ cb_data->observer = o->observer; -+ cb_data->data = o->data; -+ cb_data->object = notifier->object; -+ cb_data->notification = notification; -+ cb_data->notification_data = notification_data; -+ DWC_DEBUG("Observer found %p for notification %s", o->observer, notification); -+ DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data, -+ "Notify callback from %p for Notification %s, to observer %p", -+ cb_data->object, notification, cb_data->observer); -+ } -+ } -+} -+ -diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.h b/drivers/usb/host/dwc_common_port/dwc_notifier.h -new file mode 100644 -index 0000000..a1388d1 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h -@@ -0,0 +1,112 @@ -+ -+#ifndef __DWC_NOTIFIER_H__ -+#define __DWC_NOTIFIER_H__ -+ -+#include "dwc_os.h" -+ -+/** @file -+ * -+ * A simple implementation of the Observer pattern. Any "module" can -+ * register as an observer or notifier. The notion of "module" is abstract and -+ * can mean anything used to identify either an observer or notifier. Usually -+ * it will be a pointer to a data structure which contains some state, ie an -+ * object. -+ * -+ * Before any notifiers can be added, the global notification manager must be -+ * brought up with dwc_alloc_notification_manager(). -+ * dwc_free_notification_manager() will bring it down and free all resources. -+ * These would typically be called upon module load and unload. The -+ * notification manager is a single global instance that handles all registered -+ * observable modules and observers so this should be done only once. -+ * -+ * A module can be observable by using Notifications to publicize some general -+ * information about it's state or operation. It does not care who listens, or -+ * even if anyone listens, or what they do with the information. The observable -+ * modules do not need to know any information about it's observers or their -+ * interface, or their state or data. -+ * -+ * Any module can register to emit Notifications. It should publish a list of -+ * notifications that it can emit and their behavior, such as when they will get -+ * triggered, and what information will be provided to the observer. Then it -+ * should register itself as an observable module. See dwc_register_notifier(). -+ * -+ * Any module can observe any observable, registered module, provided it has a -+ * handle to the other module and knows what notifications to observe. See -+ * dwc_add_observer(). -+ * -+ * A function of type dwc_notifier_callback_t is called whenever a notification -+ * is triggered with one or more observers observing it. This function is -+ * called in it's own process so it may sleep or block if needed. It is -+ * guaranteed to be called sometime after the notification has occurred and will -+ * be called once per each time the notification is triggered. It will NOT be -+ * called in the same process context used to trigger the notification. -+ * -+ * @section Limitiations -+ * -+ * Keep in mind that Notifications that can be triggered in rapid sucession may -+ * schedule too many processes too handle. Be aware of this limitation when -+ * designing to use notifications, and only add notifications for appropriate -+ * observable information. -+ * -+ * Also Notification callbacks are not synchronous. If you need to synchronize -+ * the behavior between module/observer you must use other means. And perhaps -+ * that will mean Notifications are not the proper solution. -+ */ -+ -+struct dwc_notifier; -+typedef struct dwc_notifier dwc_notifier_t; -+ -+/** The callback function must be of this type. -+ * -+ * @param object This is the object that is being observed. -+ * @param notification This is the notification that was triggered. -+ * @param observer This is the observer -+ * @param notification_data This is notification-specific data that the notifier -+ * has included in this notification. The value of this should be published in -+ * the documentation of the observable module with the notifications. -+ * @param user_data This is any custom data that the observer provided when -+ * adding itself as an observer to the notification. */ -+typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, void *notification_data, void *user_data); -+ -+/** Brings up the notification manager. */ -+extern void dwc_alloc_notification_manager(void); -+/** Brings down the notification manager. */ -+extern void dwc_free_notification_manager(void); -+ -+/** This function register an observable module. A dwc_notifier_t object is -+ * returned to the observable module. This is an opaque object that is used by -+ * the observable module to trigger notifications. This object should only be -+ * accessible to functions that are authorized to trigger notifications for this -+ * module. Observers do not need this object. */ -+extern dwc_notifier_t *dwc_register_notifier(void *object); -+ -+/** This function unregister an observable module. All observers have to be -+ * removed prior to unregistration. */ -+extern void dwc_unregister_notifier(dwc_notifier_t *notifier); -+ -+/** Add a module as an observer to the observable module. The observable module -+ * needs to have previously registered with the notification manager. -+ * -+ * @param observer The observer module -+ * @param object The module to observe -+ * @param notification The notification to observe -+ * @param callback The callback function to call -+ * @param user_data Any additional user data to pass into the callback function */ -+extern int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *user_data); -+ -+/** Removes the specified observer from all notifications that it is currently -+ * observing. */ -+extern int dwc_remove_observer(void *observer); -+ -+/** This function triggers a Notification. It should be called by the -+ * observable module, or any module or library which the observable module -+ * allows to trigger notification on it's behalf. Such as the dwc_cc_t. -+ * -+ * dwc_notify is a non-blocking function. Callbacks are scheduled called in -+ * their own process context for each trigger. Callbacks can be blocking. -+ * dwc_notify can be called from interrupt context if needed. -+ * -+ */ -+void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data); -+ -+#endif /* __DWC_NOTIFIER_H__ */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h -new file mode 100644 -index 0000000..453966a ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_os.h -@@ -0,0 +1,925 @@ -+/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_os.h $ -+ * $Revision: #2 $ -+ * $Date: 2009/04/02 $ -+ * $Change: 1224130 $ -+ * -+ * Synopsys Portability Library Software 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_OS_H_ -+#define _DWC_OS_H_ -+ -+/** @file -+ * -+ * DWC portability library, low level os-wrapper functions -+ * -+ */ -+ -+/* These basic types need to be defined by some OS header file or custom header -+ * file for your specific target architecture. -+ * -+ * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t -+ * -+ * Any custom or alternate header file must be added and enabled here. -+ */ -+ -+#ifdef DWC_LINUX -+# include -+# ifdef CONFIG_DEBUG_MUTEXES -+# include -+# endif -+#else -+# include -+#endif -+ -+ -+/** @name Primitive Types and Values */ -+ -+/** We define a boolean type for consistency. Can be either YES or NO */ -+typedef uint8_t dwc_bool_t; -+#define YES 1 -+#define NO 0 -+ -+/** @todo make them positive and return the negative error code */ -+/** @name Error Codes */ -+#define DWC_E_INVALID 1001 -+#define DWC_E_NO_MEMORY 1002 -+#define DWC_E_NO_DEVICE 1003 -+#define DWC_E_NOT_SUPPORTED 1004 -+#define DWC_E_TIMEOUT 1005 -+#define DWC_E_BUSY 1006 -+#define DWC_E_AGAIN 1007 -+#define DWC_E_RESTART 1008 -+#define DWC_E_ABORT 1009 -+#define DWC_E_SHUTDOWN 1010 -+#define DWC_E_NO_DATA 1011 -+#define DWC_E_DISCONNECT 2000 -+#define DWC_E_UNKNOWN 3000 -+#define DWC_E_NO_STREAM_RES 4001 -+#define DWC_E_COMMUNICATION 4002 -+#define DWC_E_OVERFLOW 4003 -+#define DWC_E_PROTOCOL 4004 -+#define DWC_E_IN_PROGRESS 4005 -+#define DWC_E_PIPE 4006 -+#define DWC_E_IO 4007 -+#define DWC_E_NO_SPACE 4008 -+ -+/** @name Tracing/Logging Functions -+ * -+ * These function provide the capability to add tracing, debugging, and error -+ * messages, as well exceptions as assertions. The WUDEV uses these -+ * extensively. These could be logged to the main console, the serial port, an -+ * internal buffer, etc. These functions could also be no-op if they are too -+ * expensive on your system. By default undefining the DEBUG macro already -+ * no-ops some of these functions. */ -+ -+#include -+ -+/** Returns non-zero if in interrupt context. */ -+extern dwc_bool_t DWC_IN_IRQ(void); -+#define dwc_in_irq DWC_IN_IRQ -+ -+/** Returns "IRQ" if DWC_IN_IRQ is true. */ -+static inline char *dwc_irq(void) { -+ return DWC_IN_IRQ() ? "IRQ" : ""; -+} -+ -+/** -+ * A vprintf() clone. Just call vprintf if you've got it. -+ */ -+extern void DWC_VPRINTF(char *format, va_list args); -+#define dwc_vprintf DWC_VPRINTF -+ -+/** -+ * A vsnprintf() clone. Just call vprintf if you've got it. -+ */ -+extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args); -+#define dwc_vsnprintf DWC_VSNPRINTF -+ -+/** -+ * printf() clone. Just call printf if you've go it. -+ */ -+extern void DWC_PRINTF(char *format, ...) -+/* This provides compiler level static checking of the parameters if you're -+ * using GCC. */ -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); -+#else -+ ; -+#endif -+#define dwc_printf DWC_PRINTF -+ -+/** -+ * sprintf() clone. Just call sprintf if you've got it. -+ */ -+extern int DWC_SPRINTF(char *string, char *format, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 2, 3))); -+#else -+ ; -+#endif -+#define dwc_sprintf DWC_SPRINTF -+ -+/** -+ * snprintf() clone. Just call snprintf if you've got it. -+ */ -+extern int DWC_SNPRINTF(char *string, int size, char *format, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 3, 4))); -+#else -+ ; -+#endif -+#define dwc_snprintf DWC_SNPRINTF -+ -+/** -+ * Prints a WARNING message. On systems that don't differentiate between -+ * warnings and regular log messages, just print it. Indicates that something -+ * may be wrong with the driver. Works like printf(). -+ * -+ * Use the DWC_WARN macro to call this function. -+ */ -+extern void __DWC_WARN(char *format, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); -+#else -+ ; -+#endif -+ -+/** -+ * Prints an error message. On systems that don't differentiate between errors -+ * and regular log messages, just print it. Indicates that something went wrong -+ * with the driver, but it can be recovered from. Works like printf(). -+ * -+ * Use the DWC_ERROR macro to call this function. -+ */ -+extern void __DWC_ERROR(char *format, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); -+#else -+ ; -+#endif -+ -+/** -+ * Prints an exception error message and takes some user-defined action such as -+ * print out a backtrace or trigger a breakpoint. Indicates that something went -+ * abnormally wrong with the driver such as programmer error, or other -+ * exceptional condition. It should not be ignored so even on systems without -+ * printing capability, some action should be taken to notify the developer of -+ * it. Works like printf(). -+ */ -+extern void DWC_EXCEPTION(char *format, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); -+#else -+ ; -+#endif -+#define dwc_exception DWC_EXCEPTION -+ -+#ifdef DEBUG -+/** -+ * Prints out a debug message. Used for logging/trace messages. -+ * -+ * Use the DWC_DEBUG macro to call this function -+ */ -+extern void __DWC_DEBUG(char *format, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); -+#else -+ ; -+#endif -+#else -+#define __DWC_DEBUG printk -+#include -+#endif -+ -+/** -+ * Prints out a Debug message. -+ */ -+#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", __func__, dwc_irq(), ## _args) -+#define dwc_debug DWC_DEBUG -+/** -+ * Prints out an informative message. -+ */ -+#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", dwc_irq(), ## _args) -+#define dwc_info DWC_INFO -+/** -+ * Prints out a warning message. -+ */ -+#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) -+#define dwc_warn DWC_WARN -+/** -+ * Prints out an error message. -+ */ -+#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) -+#define dwc_error DWC_ERROR -+ -+#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) -+#define dwc_proto_error DWC_PROTO_ERROR -+ -+#ifdef DEBUG -+/** Prints out a exception error message if the _expr expression fails. Disabled -+ * if DEBUG is not enabled. */ -+#define DWC_ASSERT(_expr, _format, _args...) if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), __FILE__, __LINE__, ## _args); } -+#else -+#define DWC_ASSERT(_x...) -+#endif -+#define dwc_assert DWC_ASSERT -+ -+/** @name Byter Ordering -+ * The following functions are for conversions between processor's byte ordering -+ * and specific ordering you want. -+ */ -+ -+/** Converts 32 bit data in CPU byte ordering to little endian. */ -+extern uint32_t DWC_CPU_TO_LE32(void *p); -+#define dwc_cpu_to_le32 DWC_CPU_TO_LE32 -+/** Converts 32 bit data in CPU byte orderint to big endian. */ -+extern uint32_t DWC_CPU_TO_BE32(void *p); -+#define dwc_cpu_to_be32 DWC_CPU_TO_BE32 -+ -+/** Converts 32 bit little endian data to CPU byte ordering. */ -+extern uint32_t DWC_LE32_TO_CPU(void *p); -+#define dwc_le32_to_cpu DWC_LE32_TO_CPU -+/** Converts 32 bit big endian data to CPU byte ordering. */ -+extern uint32_t DWC_BE32_TO_CPU(void *p); -+#define dwc_be32_to_cpu DWC_BE32_TO_CPU -+ -+/** Converts 16 bit data in CPU byte ordering to little endian. */ -+extern uint16_t DWC_CPU_TO_LE16(void *p); -+#define dwc_cpu_to_le16 DWC_CPU_TO_LE16 -+/** Converts 16 bit data in CPU byte orderint to big endian. */ -+extern uint16_t DWC_CPU_TO_BE16(void *p); -+#define dwc_cpu_to_be16 DWC_CPU_TO_BE16 -+ -+/** Converts 16 bit little endian data to CPU byte ordering. */ -+extern uint16_t DWC_LE16_TO_CPU(void *p); -+#define dwc_le16_to_cpu DWC_LE16_TO_CPU -+/** Converts 16 bit bi endian data to CPU byte ordering. */ -+extern uint16_t DWC_BE16_TO_CPU(void *p); -+#define dwc_be16_to_cpu DWC_BE16_TO_CPU -+ -+/** @name Register Read/Write -+ * -+ * The following five functions should be implemented to read/write registers of -+ * 32-bit and 64-bit sizes. All modules use this to read/write register values. -+ * The reg value is a pointer to the register calculated from the void *base -+ * variable passed into the driver when it is started. */ -+ -+/** Reads the content of a 32-bit register. */ -+extern uint32_t DWC_READ_REG32(uint32_t volatile *reg); -+#define dwc_read_reg32 DWC_READ_REG32 -+/** Reads the content of a 64-bit register. */ -+extern uint64_t DWC_READ_REG64(uint64_t volatile *reg); -+#define dwc_read_reg64 DWC_READ_REG64 -+/** Writes to a 32-bit register. */ -+extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value); -+#define dwc_write_reg32 DWC_WRITE_REG32 -+/** Writes to a 64-bit register. */ -+extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value); -+#define dwc_write_reg64 DWC_WRITE_REG64 -+/** -+ * Modify bit values in a register. Using the -+ * algorithm: (reg_contents & ~clear_mask) | set_mask. -+ */ -+extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); -+#define dwc_modify_reg32 DWC_MODIFY_REG32 -+ -+/** @cond */ -+ -+/** @name Some convenience MACROS used internally. Define DEBUG_REGS to log the -+ * register writes. */ -+ -+#ifdef DEBUG_REGS -+ -+#define dwc_define_read_write_reg_n(_reg,_container_type) \ -+static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ -+ return DWC_READ_REG32(&container->regs->_reg[num]); \ -+} \ -+static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ -+ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, &(((uint32_t*)container->regs->_reg)[num]), data); \ -+ DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ -+} -+ -+#define dwc_define_read_write_reg(_reg,_container_type) \ -+static inline uint32_t dwc_read_##_reg(_container_type *container) { \ -+ return DWC_READ_REG32(&container->regs->_reg); \ -+} \ -+static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ -+ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ -+ DWC_WRITE_REG32(&container->regs->_reg, data); \ -+} -+ -+#else -+ -+#define dwc_define_read_write_reg_n(_reg,_container_type) \ -+static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ -+ return DWC_READ_REG32(&container->regs->_reg[num]); \ -+} \ -+static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ -+ DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ -+} -+ -+#define dwc_define_read_write_reg(_reg,_container_type) \ -+static inline uint32_t dwc_read_##_reg(_container_type *container) { \ -+ return DWC_READ_REG32(&container->regs->_reg); \ -+} \ -+static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ -+ DWC_WRITE_REG32(&container->regs->_reg, data); \ -+} -+ -+#endif -+ -+/** @endcond */ -+ -+ -+/** @name Crypto Functions -+ * -+ * These are the low-level cryptographic functions used by the driver. */ -+ -+/** Perform AES CBC */ -+extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out); -+#define dwc_aes_cbc DWC_AES_CBC -+/** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */ -+extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length); -+#define dwc_random_bytes DWC_RANDOM_BYTES -+/** Perform the SHA-256 hash function */ -+extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out); -+#define dwc_sha256 DWC_SHA256 -+/** Calculated the HMAC-SHA256 */ -+extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out); -+#define dwc_hmac_sha256 DWC_HMAC_SHA256 -+ -+ -+/** @name Memory Allocation -+ * -+ * These function provide access to memory allocation. There are only 2 DMA -+ * functions and 3 Regular memory functions that need to be implemented. None -+ * of the memory debugging routines need to be implemented. The allocation -+ * routines all ZERO the contents of the memory. -+ * -+ * Defining DEBUG_MEMORY turns on memory debugging and statistic gathering. -+ * This checks for memory leaks, keeping track of alloc/free pairs. It also -+ * keeps track of how much memory the driver is using at any given time. */ -+ -+#define DWC_PAGE_SIZE 4096 -+#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff) -+#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0) -+ -+#define DWC_INVALID_DMA_ADDR 0x0 -+ -+typedef uint32_t dwc_dma_t; -+ -+/** @todo these functions will be added in the future */ -+#if 0 -+/** -+ * Creates a DMA pool from which you can allocate DMA buffers. Buffers -+ * allocated from this pool will be guaranteed to meet the size, alignment, and -+ * boundary requirements specified. -+ * -+ * @param[in] size Specifies the size of the buffers that will be allocated from -+ * this pool. -+ * @param[in] align Specifies the byte alignment requirements of the buffers -+ * allocated from this pool. Must be a power of 2. -+ * @param[in] boundary Specifies the N-byte boundary that buffers allocated from -+ * this pool must not cross. -+ * -+ * @returns A pointer to an internal opaque structure which is not to be -+ * accessed outside of these library functions. Use this handle to specify -+ * which pools to allocate/free DMA buffers from and also to destroy the pool, -+ * when you are done with it. -+ */ -+extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary); -+/** -+ * Destroy a DMA pool. All buffers allocated from that pool must be freed first. -+ */ -+extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool); -+/** -+ * Allocate a buffer from the specified DMA pool and zeros its contents. -+ */ -+extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr); -+/** -+ * Free a previously allocated buffer from the DMA pool. -+ */ -+extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr); -+#endif -+ -+ -+/** Allocates a DMA capable buffer and zeroes its contents. */ -+extern void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr); -+ -+/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */ -+extern void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr); -+ -+/** Frees a previosly allocated buffer. */ -+extern void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr); -+ -+/** Allocates a block of memory and zeroes its contents. */ -+extern void *__DWC_ALLOC(uint32_t size); -+ -+/** Allocates a block of memory and zeroes its contents, in an atomic manner -+ * which can be used inside interrupt context. The size should be sufficiently -+ * small, a few KB at most, such that failures are not likely to occur. Can just call -+ * __DWC_ALLOC if it is atomic. */ -+extern void *__DWC_ALLOC_ATOMIC(uint32_t size); -+ -+/** Frees a previously allocated buffer. */ -+extern void __DWC_FREE(void *addr); -+ -+#ifndef DEBUG_MEMORY -+ -+#define DWC_ALLOC(_size_) __DWC_ALLOC(_size_) -+#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(_size_) -+#define DWC_FREE(_addr_) __DWC_FREE(_addr_) -+#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(_size_,_dma_) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(_size_,_virt_,_dma_) -+ -+#else -+ -+extern void *dwc_alloc_debug(uint32_t size, char const *func, int line); -+extern void *dwc_alloc_atomic_debug(uint32_t size, char const *func, int line); -+extern void dwc_free_debug(void *addr, char const *func, int line); -+extern void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line); -+extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line); -+extern void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line); -+ -+extern void dwc_memory_debug_start(void); -+extern void dwc_memory_debug_stop(void); -+extern void dwc_memory_debug_report(void); -+ -+#define DWC_ALLOC(_size_) (dwc_alloc_debug(_size_, __func__, __LINE__)) -+#define DWC_ALLOC_ATOMIC(_size_) (dwc_alloc_atomic_debug(_size_, __func__, __LINE__)) -+#define DWC_FREE(_addr_) (dwc_free_debug(_addr_, __func__, __LINE__)) -+#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(_size_, _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(_size_, _dma_, __func__, __LINE__) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(_size_, _virt_, _dma_, __func__, __LINE__) -+ -+#endif /* DEBUG_MEMORY */ -+ -+#define dwc_alloc DWC_ALLOC -+#define dwc_alloc_atomic DWC_ALLOC_ATOMIC -+#define dwc_free DWC_FREE -+#define dwc_dma_alloc DWC_DMA_ALLOC -+#define dwc_dma_alloc_atomic DWC_DMA_ALLOC_ATOMIC -+#define dwc_dma_free DWC_DMA_FREE -+ -+ -+/** @name Memory and String Processing */ -+ -+/** memset() clone */ -+extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size); -+#define dwc_memset DWC_MEMSET -+/** memcpy() clone */ -+extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size); -+#define dwc_memcpy DWC_MEMCPY -+/** memmove() clone */ -+extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size); -+#define dwc_memmove DWC_MEMMOVE -+/** memcmp() clone */ -+extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size); -+#define dwc_memcmp DWC_MEMCMP -+/** strcmp() clone */ -+extern int DWC_STRCMP(void *s1, void *s2); -+#define dwc_strcmp DWC_STRCMP -+/** strncmp() clone */ -+extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size); -+#define dwc_strncmp DWC_STRNCMP -+/** strlen() clone, for NULL terminated ASCII strings */ -+extern int DWC_STRLEN(char const *str); -+#define dwc_strlen DWC_STRLEN -+/** strcpy() clone, for NULL terminated ASCII strings */ -+extern char *DWC_STRCPY(char *to, const char *from); -+#define dwc_strcpy DWC_STRCPY -+ -+/** strdup() clone. If you wish to use memory allocation debugging, this -+ * implementation of strdup should use the DWC_* memory routines instead of -+ * calling a predefined strdup. Otherwise the memory allocated by this routine -+ * will not be seen by the debugging routines. */ -+extern char *DWC_STRDUP(char const *str); -+#define dwc_strdup DWC_STRDUP -+ -+/** NOT an atoi() clone. Read the description carefully. Returns an integer -+ * converted from the string str in base 10 unless the string begins with a "0x" -+ * in which case it is base 16. String must be a NULL terminated sequence of -+ * ASCII characters and may optionally begin with whitespace, a + or -, and a -+ * "0x" prefix if base 16. The remaining characters must be valid digits for -+ * the number and end with a NULL character. If any invalid characters are -+ * encountered or it returns with a negative error code and the results of the -+ * conversion are undefined. On sucess it returns 0. Overflow conditions are -+ * undefined. An example implementation using atoi() can be referenced from the -+ * Linux implementation. */ -+extern int DWC_ATOI(char *str, int32_t *value); -+#define dwc_atoi DWC_ATOI -+/** Same as above but for unsigned. */ -+extern int DWC_ATOUI(char *str, uint32_t *value); -+#define dwc_atoui DWC_ATOUI -+/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */ -+extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len); -+#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE -+ -+/** @name Wait queues -+ * -+ * Wait queues provide a means of synchronizing between threads or processes. A -+ * process can block on a waitq if some condition is not true, waiting for it to -+ * become true. When the waitq is triggered all waiting process will get -+ * unblocked and the condition will be check again. Waitqs should be triggered -+ * every time a condition can potentially change.*/ -+struct dwc_waitq; -+typedef struct dwc_waitq dwc_waitq_t; -+ -+/** The type of waitq condition callback function. This is called every time -+ * condition is evaluated. */ -+typedef int (*dwc_waitq_condition_t)(void *data); -+ -+/** Allocate a waitq */ -+extern dwc_waitq_t *DWC_WAITQ_ALLOC(void); -+#define dwc_waitq_alloc DWC_WAITQ_ALLOC -+/** Free a waitq */ -+extern void DWC_WAITQ_FREE(dwc_waitq_t *wq); -+#define dwc_waitq_free DWC_WAITQ_FREE -+ -+/** Check the condition and if it is false, block on the waitq. When unblocked, check the -+ * condition again. The function returns when the condition becomes true. The return value -+ * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */ -+extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data); -+#define dwc_waitq_wait DWC_WAITQ_WAIT; -+/** Check the condition and if it is false, block on the waitq. When unblocked, -+ * check the condition again. The function returns when the condition become -+ * true or the timeout has passed. The return value is 0 on condition true or -+ * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on -+ * error. */ -+extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data, int32_t msecs); -+#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT -+/** Trigger a waitq, unblocking all processes. This should be called whenever a condition -+ * has potentially changed. */ -+extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq); -+#define dwc_waitq_trigger DWC_WAITQ_TRIGGER -+/** Unblock all processes waiting on the waitq with an ABORTED result. */ -+extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq); -+#define dwc_waitq_abort DWC_WAITQ_ABORT -+ -+/** @name Threads -+ * -+ * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP -+ * whenever it is woken up, and then return. The DWC_THREAD_STOP function -+ * returns the value from the thread. -+ */ -+ -+struct dwc_thread; -+typedef struct dwc_thread dwc_thread_t; -+ -+/** The thread function */ -+typedef int (*dwc_thread_function_t)(void *data); -+ -+/** Create a thread and start it running the thread_function. Returns a handle -+ * to the thread */ -+extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data); -+#define dwc_thread_run DWC_THREAD_RUN -+/** Stops a thread. Return the value returned by the thread. Or will return -+ * DWC_ABORT if the thread never started. */ -+extern int DWC_THREAD_STOP(dwc_thread_t *thread); -+#define dwc_thread_stop DWC_THREAD_STOP -+/** Signifies to the thread that it must stop. */ -+extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void); -+#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP -+ -+/** @name Work queues -+ * -+ * Workqs are used to queue a callback function to be called at some later time, -+ * in another thread. */ -+struct dwc_workq; -+typedef struct dwc_workq dwc_workq_t; -+ -+/** The type of the callback function to be called. */ -+typedef void (*dwc_work_callback_t)(void *data); -+ -+/** Allocate a workq */ -+extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name); -+#define dwc_workq_alloc DWC_WORKQ_ALLOC -+/** Free a workq. All work must be completed before being freed. */ -+extern void DWC_WORKQ_FREE(dwc_workq_t *workq); -+#define dwc_workq_free DWC_WORKQ_FREE -+/** Schedule a callback on the workq, passing in data. The function will be -+ * scheduled at some later time. */ -+extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, char *format, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 4, 5))); -+#else -+ ; -+#endif -+#define dwc_workq_schedule DWC_WORKQ_SCHEDULE -+ -+/** Schedule a callback on the workq, that will be called until at least -+ * given number miliseconds have passed. */ -+extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...) -+#ifdef __GNUC__ -+ __attribute__ ((format(printf, 5, 6))); -+#else -+ ; -+#endif -+#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED -+ -+/** The number of processes in the workq */ -+extern int DWC_WORKQ_PENDING(dwc_workq_t *workq); -+#define dwc_workq_pending DWC_WORKQ_PENDING -+/** Blocks until all the work in the workq is complete or timed out. Returns < -+ * 0 on timeout. */ -+extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout); -+#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE -+ -+ -+/** @name Tasklets -+ * -+ */ -+struct dwc_tasklet; -+typedef struct dwc_tasklet dwc_tasklet_t; -+ -+typedef void (*dwc_tasklet_callback_t)(void *data); -+ -+extern dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data); -+#define dwc_task_alloc DWC_TASK_ALLOC -+extern void DWC_TASK_FREE(dwc_tasklet_t *t); -+#define dwc_task_free DWC_TASK_FREE -+extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task); -+#define dwc_task_schedule DWC_TASK_SCHEDULE -+ -+ -+/** @name Timer -+ * -+ * Callbacks must be small and atomic. -+ */ -+struct dwc_timer; -+typedef struct dwc_timer dwc_timer_t; -+ -+typedef void (*dwc_timer_callback_t)(void *data); -+ -+extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data); -+#define dwc_timer_alloc DWC_TIMER_ALLOC -+extern void DWC_TIMER_FREE(dwc_timer_t *timer); -+#define dwc_timer_free DWC_TIMER_FREE -+ -+/** Schedules the timer to run at time ms from now. And will repeat at every -+ * repeat_interval msec therafter -+ * -+ * Modifies a timer that is still awaiting execution to a new expiration time. -+ * The mod_time is added to the old time. */ -+extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time); -+#define dwc_timer_schedule DWC_TIMER_SCHEDULE -+ -+/** Disables the timer from execution. */ -+extern void DWC_TIMER_CANCEL(dwc_timer_t *timer); -+#define dwc_timer_cancel DWC_TIMER_CANCEL -+ -+ -+ -+/** @name Spinlocks -+ * -+ * These locks are used when the work between the lock/unlock is atomic and -+ * short. Interrupts are also disabled during the lock/unlock and thus they are -+ * suitable to lock between interrupt/non-interrupt context. They also lock -+ * between processes if you have multiple CPUs or Preemption. If you don't have -+ * multiple CPUS or Preemption, then the you can simply implement the -+ * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts. Because -+ * the work between the lock/unlock is atomic, the process context will never -+ * change, and so you never have to lock between processes. */ -+ -+struct dwc_spinlock; -+typedef struct dwc_spinlock dwc_spinlock_t; -+ -+/** Returns an initialized lock variable. This function should allocate and -+ * initialize the OS-specific data structure used for locking. This data -+ * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should -+ * be freed by the DWC_FREE_LOCK when it is no longer used. */ -+extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void); -+#define dwc_spinlock_alloc DWC_SPINLOCK_ALLOC -+ -+/** Frees an initialized lock variable. */ -+extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock); -+#define dwc_spinlock_free DWC_SPINLOCK_FREE -+ -+/** Disables interrupts and blocks until it acquires the lock. -+ * -+ * @param lock Pointer to the spinlock. -+ * @param flags Unsigned long for irq flags storage. -+ */ -+extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags); -+#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE -+ -+/** Re-enables the interrupt and releases the lock. -+ * -+ * @param lock Pointer to the spinlock. -+ * @param flags Unsigned long for irq flags storage. Must be the same as was -+ * passed into DWC_LOCK. -+ */ -+extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags); -+#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE -+ -+/** Blocks until it acquires the lock. -+ * -+ * @param lock Pointer to the spinlock. -+ */ -+extern void DWC_SPINLOCK(dwc_spinlock_t *lock); -+#define dwc_spinlock DWC_SPINLOCK -+ -+/** Releases the lock. -+ * -+ * @param lock Pointer to the spinlock. -+ */ -+extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock); -+#define dwc_spinunlock DWC_SPINUNLOCK -+ -+/** @name Mutexes -+ * -+ * Unlike spinlocks Mutexes lock only between processes and the work between the -+ * lock/unlock CAN block, therefore it CANNOT be called from interrupt context. -+ */ -+ -+struct dwc_mutex; -+typedef struct dwc_mutex dwc_mutex_t; -+ -+ -+/* For Linux Mutex Debugging make it inline because the debugging routines use -+ * the symbol to determine recursive locking. This makes it falsely think -+ * recursive locking occurs. */ -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \ -+ __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \ -+ mutex_init((struct mutex *)__mutexp); \ -+}) -+#endif -+extern dwc_mutex_t *DWC_MUTEX_ALLOC(void); -+#define dwc_mutex_alloc DWC_MUTEX_ALLOC -+ -+/* For memory leak debugging when using Linux Mutex Debugging */ -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+#define DWC_MUTEX_FREE(__mutexp) do { \ -+ mutex_destroy((struct mutex *)__mutexp); \ -+ DWC_FREE(__mutexp); \ -+} while(0) -+#else -+extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex); -+#define dwc_mutex_free DWC_MUTEX_FREE -+#endif -+ -+extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex); -+#define dwc_mutex_lock DWC_MUTEX_LOCK -+/** Non-blocking lock returns 1 on successful lock. */ -+extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex); -+#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK -+extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex); -+#define dwc_mutex_unlock DWC_MUTEX_UNLOCK -+ -+ -+ -+ -+/** @name Time */ -+ -+/** Microsecond delay. -+ * -+ * @param usecs Microseconds to delay. -+ */ -+extern void DWC_UDELAY(uint32_t usecs); -+#define dwc_udelay DWC_UDELAY -+ -+/** Millisecond delay. -+ * -+ * @param msecs Milliseconds to delay. -+ */ -+extern void DWC_MDELAY(uint32_t msecs); -+#define dwc_mdelay DWC_MDELAY -+ -+/** Non-busy waiting. -+ * Sleeps for specified number of milliseconds. -+ * -+ * @param msecs Milliseconds to sleep. -+ */ -+extern void DWC_MSLEEP(uint32_t msecs); -+#define dwc_msleep DWC_MSLEEP -+ -+extern uint32_t DWC_TIME(void); -+#define dwc_time DWC_TIME -+ -+#endif // _DWC_OS_H_ -+ -+ -+ -+ -+/** @mainpage DWC Portability and Common Library -+ * -+ * This is the documentation for the DWC Portability and Common Library. -+ * -+ * @section intro Introduction -+ * -+ * The DWC Portability library consists of wrapper calls and data structures to -+ * all low-level functions which are typically provided by the OS. The WUDEV -+ * driver uses only these functions. In order to port the WUDEV driver, only -+ * the functions in this library need to be re-implemented, with the same -+ * behavior as documented here. -+ * -+ * The Common library consists of higher level functions, which rely only on -+ * calling the functions from the DWC Portability library. These common -+ * routines are shared across modules. Some of the common libraries need to be -+ * used directly by the driver programmer when porting WUDEV. Such as the -+ * parameter and notification libraries. -+ * -+ * @section low Portability Library OS Wrapper Functions -+ * -+ * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that -+ * needs to be implemented when porting, for example DWC_MUTEX_ALLOC(). All of -+ * these functions are included in the dwc_os.h file. -+ * -+ * There are many functions here covering a wide array of OS services. Please -+ * see dwc_os.h for details, and implementation notes for each function. -+ * -+ * @section common Common Library Functions -+ * -+ * Any function starting with dwc and in all lowercase is a common library -+ * routine. These functions have a portable implementation and do not need to -+ * be reimplemented when porting. The common routines can be used by any -+ * driver, and some must be used by the end user to control the drivers. For -+ * example, you must use the Parameter common library in order to set the -+ * parameters in the WUDEV module. -+ * -+ * The common libraries consist of the following: -+ * -+ * - Connection Contexts - Used internally and can be used by end-user. See dwc_cc.h -+ * - Parameters - Used internally and can be used by end-user. See dwc_params.h -+ * - Notifications - Used internally and can be used by end-user. See dwc_notifier.h -+ * - Lists - Used internally and can be used by end-user. See dwc_list.h -+ * - Memory Debugging - Used internally and can be used by end-user. See dwc_os.h -+ * - Modpow - Used internally only. See dwc_modpow.h -+ * - DH - Used internally only. See dwc_dh.h -+ * - Crypto - Used internally only. See dwc_crypto.h -+ * -+ * -+ * @section prereq Prerequistes For dwc_os.h -+ * @subsection types Data Types -+ * -+ * The dwc_os.h file assumes that several low-level data types are pre defined for the -+ * compilation environment. These data types are: -+ * -+ * - uint8_t - unsigned 8-bit data type -+ * - int8_t - signed 8-bit data type -+ * - uint16_t - unsigned 16-bit data type -+ * - int16_t - signed 16-bit data type -+ * - uint32_t - unsigned 32-bit data type -+ * - int32_t - signed 32-bit data type -+ * - uint64_t - unsigned 64-bit data type -+ * - int64_t - signed 64-bit data type -+ * -+ * Ensure that these are defined before using dwc_os.h. The easiest way to do -+ * that is to modify the top of the file to include the appropriate header. -+ * This is already done for the Linux environment. If the DWC_LINUX macro is -+ * defined, the correct header will be added. A standard header is -+ * also used for environments where standard C headers are available. -+ * -+ * @subsection stdarg Variable Arguments -+ * -+ * Variable arguments are provided by a standard C header . it is -+ * available in Both the Linux and ANSI C enviornment. An equivalent must be -+ * provided in your enviornment in order to use dwc_os.h with the debug and -+ * tracing message functionality. -+ * -+ * @subsection thread Threading -+ * -+ * WUDEV Core must be run on an operating system that provides for multiple -+ * threads/processes. Threading can be implemented in many ways, even in -+ * embedded systems without an operating system. At the bare minimum, the -+ * system should be able to start any number of processes at any time to handle -+ * special work. It need not be a pre-emptive system. Process context can -+ * change upon a call to a blocking function. The hardware interrupt context -+ * that calls the module's ISR() function must be differentiable from process -+ * context, even if your processes are impemented via a hardware interrupt. -+ * Further locking mechanism between process must exist (or be implemented), and -+ * process context must have a way to disable interrupts for a period of time to -+ * lock them out. If all of this exists, the functions in dwc_os.h related to -+ * threading should be able to be implemented with the defined behavior. -+ * -+ */ -diff --git a/drivers/usb/host/dwc_common_port/usb.h b/drivers/usb/host/dwc_common_port/usb.h -new file mode 100644 -index 0000000..2ee4252 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/usb.h -@@ -0,0 +1,850 @@ -+/* -+ * Copyright (c) 1998 The NetBSD Foundation, Inc. -+ * All rights reserved. -+ * -+ * This code is derived from software contributed to The NetBSD Foundation -+ * by Lennart Augustsson (lennart@augustsson.net) at -+ * Carlstedt Research & Technology. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. All advertising materials mentioning features or use of this software -+ * must display the following acknowledgement: -+ * This product includes software developed by the NetBSD -+ * Foundation, Inc. and its contributors. -+ * 4. Neither the name of The NetBSD Foundation nor the names of its -+ * contributors may be used to endorse or promote products derived -+ * from this software without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -+ * 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. -+ */ -+ -+/* Modified by Synopsys, Inc, 12/12/2007 */ -+ -+ -+#ifndef _USB_H_ -+#define _USB_H_ -+ -+#include "dwc_os.h" -+ -+/* -+ * The USB records contain some unaligned little-endian word -+ * components. The U[SG]ETW macros take care of both the alignment -+ * and endian problem and should always be used to access non-byte -+ * values. -+ */ -+typedef u_int8_t uByte; -+typedef u_int8_t uWord[2]; -+typedef u_int8_t uDWord[4]; -+ -+#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) -+ -+#if 1 -+#define UGETW(w) ((w)[0] | ((w)[1] << 8)) -+#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8)) -+#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24)) -+#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \ -+ (w)[1] = (u_int8_t)((v) >> 8), \ -+ (w)[2] = (u_int8_t)((v) >> 16), \ -+ (w)[3] = (u_int8_t)((v) >> 24)) -+#else -+/* -+ * On little-endian machines that can handle unanliged accesses -+ * (e.g. i386) these macros can be replaced by the following. -+ */ -+#define UGETW(w) (*(u_int16_t *)(w)) -+#define USETW(w,v) (*(u_int16_t *)(w) = (v)) -+#define UGETDW(w) (*(u_int32_t *)(w)) -+#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) -+#endif -+ -+#define UPACKED __attribute__((__packed__)) -+ -+typedef struct { -+ uByte bmRequestType; -+ uByte bRequest; -+ uWord wValue; -+ uWord wIndex; -+ uWord wLength; -+} UPACKED usb_device_request_t; -+ -+#define UT_GET_DIR(a) ((a) & 0x80) -+#define UT_WRITE 0x00 -+#define UT_READ 0x80 -+ -+#define UT_GET_TYPE(a) ((a) & 0x60) -+#define UT_STANDARD 0x00 -+#define UT_CLASS 0x20 -+#define UT_VENDOR 0x40 -+ -+#define UT_GET_RECIPIENT(a) ((a) & 0x1f) -+#define UT_DEVICE 0x00 -+#define UT_INTERFACE 0x01 -+#define UT_ENDPOINT 0x02 -+#define UT_OTHER 0x03 -+ -+#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE) -+#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE) -+#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT) -+#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE) -+#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE) -+#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT) -+#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE) -+#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE) -+#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER) -+#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT) -+#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE) -+#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE) -+#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER) -+#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT) -+#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE) -+#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE) -+#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER) -+#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT) -+#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE) -+#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE) -+#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER) -+#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT) -+ -+/* Requests */ -+#define UR_GET_STATUS 0x00 -+#define USTAT_STANDARD_STATUS 0x00 -+#define WUSTAT_WUSB_FEATURE 0x01 -+#define WUSTAT_CHANNEL_INFO 0x02 -+#define WUSTAT_RECEIVED_DATA 0x03 -+#define WUSTAT_MAS_AVAILABILITY 0x04 -+#define WUSTAT_CURRENT_TRANSMIT_POWER 0x05 -+#define UR_CLEAR_FEATURE 0x01 -+#define UR_SET_FEATURE 0x03 -+#define UR_SET_AND_TEST_FEATURE 0x0c -+#define UR_SET_ADDRESS 0x05 -+#define UR_GET_DESCRIPTOR 0x06 -+#define UDESC_DEVICE 0x01 -+#define UDESC_CONFIG 0x02 -+#define UDESC_STRING 0x03 -+#define UDESC_INTERFACE 0x04 -+#define UDESC_ENDPOINT 0x05 -+#define UDESC_DEVICE_QUALIFIER 0x06 -+#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 -+#define UDESC_INTERFACE_POWER 0x08 -+#define UDESC_OTG 0x09 -+#define WUDESC_SECURITY 0x0c -+#define WUDESC_KEY 0x0d -+#define WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf) -+#define WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4) -+#define WUD_KEY_TYPE_ASSOC 0x01 -+#define WUD_KEY_TYPE_GTK 0x02 -+#define WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6) -+#define WUD_KEY_ORIGIN_HOST 0x00 -+#define WUD_KEY_ORIGIN_DEVICE 0x01 -+#define WUDESC_ENCRYPTION_TYPE 0x0e -+#define WUDESC_BOS 0x0f -+#define WUDESC_DEVICE_CAPABILITY 0x10 -+#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11 -+#define UDESC_CS_DEVICE 0x21 /* class specific */ -+#define UDESC_CS_CONFIG 0x22 -+#define UDESC_CS_STRING 0x23 -+#define UDESC_CS_INTERFACE 0x24 -+#define UDESC_CS_ENDPOINT 0x25 -+#define UDESC_HUB 0x29 -+#define UR_SET_DESCRIPTOR 0x07 -+#define UR_GET_CONFIG 0x08 -+#define UR_SET_CONFIG 0x09 -+#define UR_GET_INTERFACE 0x0a -+#define UR_SET_INTERFACE 0x0b -+#define UR_SYNCH_FRAME 0x0c -+#define WUR_SET_ENCRYPTION 0x0d -+#define WUR_GET_ENCRYPTION 0x0e -+#define WUR_SET_HANDSHAKE 0x0f -+#define WUR_GET_HANDSHAKE 0x10 -+#define WUR_SET_CONNECTION 0x11 -+#define WUR_SET_SECURITY_DATA 0x12 -+#define WUR_GET_SECURITY_DATA 0x13 -+#define WUR_SET_WUSB_DATA 0x14 -+#define WUDATA_DRPIE_INFO 0x01 -+#define WUDATA_TRANSMIT_DATA 0x02 -+#define WUDATA_TRANSMIT_PARAMS 0x03 -+#define WUDATA_RECEIVE_PARAMS 0x04 -+#define WUDATA_TRANSMIT_POWER 0x05 -+#define WUR_LOOPBACK_DATA_WRITE 0x15 -+#define WUR_LOOPBACK_DATA_READ 0x16 -+#define WUR_SET_INTERFACE_DS 0x17 -+ -+/* Feature numbers */ -+#define UF_ENDPOINT_HALT 0 -+#define UF_DEVICE_REMOTE_WAKEUP 1 -+#define UF_TEST_MODE 2 -+#define UF_DEVICE_B_HNP_ENABLE 3 -+#define UF_DEVICE_A_HNP_SUPPORT 4 -+#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 -+#define WUF_WUSB 3 -+#define WUF_TX_DRPIE 0x0 -+#define WUF_DEV_XMIT_PACKET 0x1 -+#define WUF_COUNT_PACKETS 0x2 -+#define WUF_CAPTURE_PACKETS 0x3 -+ -+/* Class requests from the USB 2.0 hub spec, table 11-15 */ -+#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE) -+#define UCR_CLEAR_PORT_FEATURE (0x2300 | UR_CLEAR_FEATURE) -+#define UCR_GET_HUB_DESCRIPTOR (0xa000 | UR_GET_DESCRIPTOR) -+#define UCR_GET_HUB_STATUS (0xa000 | UR_GET_STATUS) -+#define UCR_GET_PORT_STATUS (0xa300 | UR_GET_STATUS) -+#define UCR_SET_HUB_FEATURE (0x2000 | UR_SET_FEATURE) -+#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE) -+#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE) -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bDescriptorSubtype; -+} UPACKED usb_descriptor_t; -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; -+ uWord bcdUSB; -+#define UD_USB_2_0 0x0200 -+#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) -+ uByte bDeviceClass; -+ uByte bDeviceSubClass; -+ uByte bDeviceProtocol; -+ uByte bMaxPacketSize; -+ /* The fields below are not part of the initial descriptor. */ -+ uWord idVendor; -+ uWord idProduct; -+ uWord bcdDevice; -+ uByte iManufacturer; -+ uByte iProduct; -+ uByte iSerialNumber; -+ uByte bNumConfigurations; -+} UPACKED usb_device_descriptor_t; -+#define USB_DEVICE_DESCRIPTOR_SIZE 18 -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; -+ uWord wTotalLength; -+ uByte bNumInterface; -+ uByte bConfigurationValue; -+ uByte iConfiguration; -+ uByte bmAttributes; -+#define UC_BUS_POWERED 0x80 -+#define UC_SELF_POWERED 0x40 -+#define UC_REMOTE_WAKEUP 0x20 -+ uByte bMaxPower; /* max current in 2 mA units */ -+#define UC_POWER_FACTOR 2 -+} UPACKED usb_config_descriptor_t; -+#define USB_CONFIG_DESCRIPTOR_SIZE 9 -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bInterfaceNumber; -+ uByte bAlternateSetting; -+ uByte bNumEndpoints; -+ uByte bInterfaceClass; -+ uByte bInterfaceSubClass; -+ uByte bInterfaceProtocol; -+ uByte iInterface; -+} UPACKED usb_interface_descriptor_t; -+#define USB_INTERFACE_DESCRIPTOR_SIZE 9 -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bEndpointAddress; -+#define UE_GET_DIR(a) ((a) & 0x80) -+#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7)) -+#define UE_DIR_IN 0x80 -+#define UE_DIR_OUT 0x00 -+#define UE_ADDR 0x0f -+#define UE_GET_ADDR(a) ((a) & UE_ADDR) -+ uByte bmAttributes; -+#define UE_XFERTYPE 0x03 -+#define UE_CONTROL 0x00 -+#define UE_ISOCHRONOUS 0x01 -+#define UE_BULK 0x02 -+#define UE_INTERRUPT 0x03 -+#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE) -+#define UE_ISO_TYPE 0x0c -+#define UE_ISO_ASYNC 0x04 -+#define UE_ISO_ADAPT 0x08 -+#define UE_ISO_SYNC 0x0c -+#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) -+ uWord wMaxPacketSize; -+ uByte bInterval; -+} UPACKED usb_endpoint_descriptor_t; -+#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; -+ uWord bString[127]; -+} UPACKED usb_string_descriptor_t; -+#define USB_MAX_STRING_LEN 128 -+#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */ -+ -+/* Hub specific request */ -+#define UR_GET_BUS_STATE 0x02 -+#define UR_CLEAR_TT_BUFFER 0x08 -+#define UR_RESET_TT 0x09 -+#define UR_GET_TT_STATE 0x0a -+#define UR_STOP_TT 0x0b -+ -+/* Hub features */ -+#define UHF_C_HUB_LOCAL_POWER 0 -+#define UHF_C_HUB_OVER_CURRENT 1 -+#define UHF_PORT_CONNECTION 0 -+#define UHF_PORT_ENABLE 1 -+#define UHF_PORT_SUSPEND 2 -+#define UHF_PORT_OVER_CURRENT 3 -+#define UHF_PORT_RESET 4 -+#define UHF_PORT_L1 5 -+#define UHF_PORT_POWER 8 -+#define UHF_PORT_LOW_SPEED 9 -+#define UHF_PORT_HIGH_SPEED 10 -+#define UHF_C_PORT_CONNECTION 16 -+#define UHF_C_PORT_ENABLE 17 -+#define UHF_C_PORT_SUSPEND 18 -+#define UHF_C_PORT_OVER_CURRENT 19 -+#define UHF_C_PORT_RESET 20 -+#define UHF_C_PORT_L1 23 -+#define UHF_PORT_TEST 21 -+#define UHF_PORT_INDICATOR 22 -+ -+typedef struct { -+ uByte bDescLength; -+ uByte bDescriptorType; -+ uByte bNbrPorts; -+ uWord wHubCharacteristics; -+#define UHD_PWR 0x0003 -+#define UHD_PWR_GANGED 0x0000 -+#define UHD_PWR_INDIVIDUAL 0x0001 -+#define UHD_PWR_NO_SWITCH 0x0002 -+#define UHD_COMPOUND 0x0004 -+#define UHD_OC 0x0018 -+#define UHD_OC_GLOBAL 0x0000 -+#define UHD_OC_INDIVIDUAL 0x0008 -+#define UHD_OC_NONE 0x0010 -+#define UHD_TT_THINK 0x0060 -+#define UHD_TT_THINK_8 0x0000 -+#define UHD_TT_THINK_16 0x0020 -+#define UHD_TT_THINK_24 0x0040 -+#define UHD_TT_THINK_32 0x0060 -+#define UHD_PORT_IND 0x0080 -+ uByte bPwrOn2PwrGood; /* delay in 2 ms units */ -+#define UHD_PWRON_FACTOR 2 -+ uByte bHubContrCurrent; -+ uByte DeviceRemovable[32]; /* max 255 ports */ -+#define UHD_NOT_REMOV(desc, i) \ -+ (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1) -+ /* deprecated */ uByte PortPowerCtrlMask[1]; -+} UPACKED usb_hub_descriptor_t; -+#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */ -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; -+ uWord bcdUSB; -+ uByte bDeviceClass; -+ uByte bDeviceSubClass; -+ uByte bDeviceProtocol; -+ uByte bMaxPacketSize0; -+ uByte bNumConfigurations; -+ uByte bReserved; -+} UPACKED usb_device_qualifier_t; -+#define USB_DEVICE_QUALIFIER_SIZE 10 -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bmAttributes; -+#define UOTG_SRP 0x01 -+#define UOTG_HNP 0x02 -+} UPACKED usb_otg_descriptor_t; -+ -+/* OTG feature selectors */ -+#define UOTG_B_HNP_ENABLE 3 -+#define UOTG_A_HNP_SUPPORT 4 -+#define UOTG_A_ALT_HNP_SUPPORT 5 -+ -+typedef struct { -+ uWord wStatus; -+/* Device status flags */ -+#define UDS_SELF_POWERED 0x0001 -+#define UDS_REMOTE_WAKEUP 0x0002 -+/* Endpoint status flags */ -+#define UES_HALT 0x0001 -+} UPACKED usb_status_t; -+ -+typedef struct { -+ uWord wHubStatus; -+#define UHS_LOCAL_POWER 0x0001 -+#define UHS_OVER_CURRENT 0x0002 -+ uWord wHubChange; -+} UPACKED usb_hub_status_t; -+ -+typedef struct { -+ uWord wPortStatus; -+#define UPS_CURRENT_CONNECT_STATUS 0x0001 -+#define UPS_PORT_ENABLED 0x0002 -+#define UPS_SUSPEND 0x0004 -+#define UPS_OVERCURRENT_INDICATOR 0x0008 -+#define UPS_RESET 0x0010 -+#define UPS_PORT_POWER 0x0100 -+#define UPS_LOW_SPEED 0x0200 -+#define UPS_HIGH_SPEED 0x0400 -+#define UPS_PORT_TEST 0x0800 -+#define UPS_PORT_INDICATOR 0x1000 -+ uWord wPortChange; -+#define UPS_C_CONNECT_STATUS 0x0001 -+#define UPS_C_PORT_ENABLED 0x0002 -+#define UPS_C_SUSPEND 0x0004 -+#define UPS_C_OVERCURRENT_INDICATOR 0x0008 -+#define UPS_C_PORT_RESET 0x0010 -+} UPACKED usb_port_status_t; -+ -+/* Device class codes */ -+#define UDCLASS_IN_INTERFACE 0x00 -+#define UDCLASS_COMM 0x02 -+#define UDCLASS_HUB 0x09 -+#define UDSUBCLASS_HUB 0x00 -+#define UDPROTO_FSHUB 0x00 -+#define UDPROTO_HSHUBSTT 0x01 -+#define UDPROTO_HSHUBMTT 0x02 -+#define UDCLASS_DIAGNOSTIC 0xdc -+#define UDCLASS_WIRELESS 0xe0 -+#define UDSUBCLASS_RF 0x01 -+#define UDPROTO_BLUETOOTH 0x01 -+#define UDCLASS_VENDOR 0xff -+ -+/* Interface class codes */ -+#define UICLASS_UNSPEC 0x00 -+ -+#define UICLASS_AUDIO 0x01 -+#define UISUBCLASS_AUDIOCONTROL 1 -+#define UISUBCLASS_AUDIOSTREAM 2 -+#define UISUBCLASS_MIDISTREAM 3 -+ -+#define UICLASS_CDC 0x02 /* communication */ -+#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 -+#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 -+#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 -+#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 -+#define UISUBCLASS_CAPI_CONTROLMODEL 5 -+#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 -+#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 -+#define UIPROTO_CDC_AT 1 -+ -+#define UICLASS_HID 0x03 -+#define UISUBCLASS_BOOT 1 -+#define UIPROTO_BOOT_KEYBOARD 1 -+ -+#define UICLASS_PHYSICAL 0x05 -+ -+#define UICLASS_IMAGE 0x06 -+ -+#define UICLASS_PRINTER 0x07 -+#define UISUBCLASS_PRINTER 1 -+#define UIPROTO_PRINTER_UNI 1 -+#define UIPROTO_PRINTER_BI 2 -+#define UIPROTO_PRINTER_1284 3 -+ -+#define UICLASS_MASS 0x08 -+#define UISUBCLASS_RBC 1 -+#define UISUBCLASS_SFF8020I 2 -+#define UISUBCLASS_QIC157 3 -+#define UISUBCLASS_UFI 4 -+#define UISUBCLASS_SFF8070I 5 -+#define UISUBCLASS_SCSI 6 -+#define UIPROTO_MASS_CBI_I 0 -+#define UIPROTO_MASS_CBI 1 -+#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ -+#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */ -+ -+#define UICLASS_HUB 0x09 -+#define UISUBCLASS_HUB 0 -+#define UIPROTO_FSHUB 0 -+#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */ -+#define UIPROTO_HSHUBMTT 1 -+ -+#define UICLASS_CDC_DATA 0x0a -+#define UISUBCLASS_DATA 0 -+#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ -+#define UIPROTO_DATA_HDLC 0x31 /* HDLC */ -+#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ -+#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */ -+#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */ -+#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ -+#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */ -+#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */ -+#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */ -+#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ -+#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ -+#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ -+#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */ -+ -+#define UICLASS_SMARTCARD 0x0b -+ -+/*#define UICLASS_FIRM_UPD 0x0c*/ -+ -+#define UICLASS_SECURITY 0x0d -+ -+#define UICLASS_DIAGNOSTIC 0xdc -+ -+#define UICLASS_WIRELESS 0xe0 -+#define UISUBCLASS_RF 0x01 -+#define UIPROTO_BLUETOOTH 0x01 -+ -+#define UICLASS_APPL_SPEC 0xfe -+#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 -+#define UISUBCLASS_IRDA 2 -+#define UIPROTO_IRDA 0 -+ -+#define UICLASS_VENDOR 0xff -+ -+ -+#define USB_HUB_MAX_DEPTH 5 -+ -+/* -+ * Minimum time a device needs to be powered down to go through -+ * a power cycle. XXX Are these time in the spec? -+ */ -+#define USB_POWER_DOWN_TIME 200 /* ms */ -+#define USB_PORT_POWER_DOWN_TIME 100 /* ms */ -+ -+#if 0 -+/* These are the values from the spec. */ -+#define USB_PORT_RESET_DELAY 10 /* ms */ -+#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */ -+#define USB_PORT_RESET_RECOVERY 10 /* ms */ -+#define USB_PORT_POWERUP_DELAY 100 /* ms */ -+#define USB_SET_ADDRESS_SETTLE 2 /* ms */ -+#define USB_RESUME_DELAY (20*5) /* ms */ -+#define USB_RESUME_WAIT 10 /* ms */ -+#define USB_RESUME_RECOVERY 10 /* ms */ -+#define USB_EXTRA_POWER_UP_TIME 0 /* ms */ -+#else -+/* Allow for marginal (i.e. non-conforming) devices. */ -+#define USB_PORT_RESET_DELAY 50 /* ms */ -+#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */ -+#define USB_PORT_RESET_RECOVERY 250 /* ms */ -+#define USB_PORT_POWERUP_DELAY 300 /* ms */ -+#define USB_SET_ADDRESS_SETTLE 10 /* ms */ -+#define USB_RESUME_DELAY (50*5) /* ms */ -+#define USB_RESUME_WAIT 50 /* ms */ -+#define USB_RESUME_RECOVERY 50 /* ms */ -+#define USB_EXTRA_POWER_UP_TIME 20 /* ms */ -+#endif -+ -+#define USB_MIN_POWER 100 /* mA */ -+#define USB_MAX_POWER 500 /* mA */ -+ -+#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ -+ -+ -+#define USB_UNCONFIG_NO 0 -+#define USB_UNCONFIG_INDEX (-1) -+ -+/*** ioctl() related stuff ***/ -+ -+struct usb_ctl_request { -+ int ucr_addr; -+ usb_device_request_t ucr_request; -+ void *ucr_data; -+ int ucr_flags; -+#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ -+ int ucr_actlen; /* actual length transferred */ -+}; -+ -+struct usb_alt_interface { -+ int uai_config_index; -+ int uai_interface_index; -+ int uai_alt_no; -+}; -+ -+#define USB_CURRENT_CONFIG_INDEX (-1) -+#define USB_CURRENT_ALT_INDEX (-1) -+ -+struct usb_config_desc { -+ int ucd_config_index; -+ usb_config_descriptor_t ucd_desc; -+}; -+ -+struct usb_interface_desc { -+ int uid_config_index; -+ int uid_interface_index; -+ int uid_alt_index; -+ usb_interface_descriptor_t uid_desc; -+}; -+ -+struct usb_endpoint_desc { -+ int ued_config_index; -+ int ued_interface_index; -+ int ued_alt_index; -+ int ued_endpoint_index; -+ usb_endpoint_descriptor_t ued_desc; -+}; -+ -+struct usb_full_desc { -+ int ufd_config_index; -+ u_int ufd_size; -+ u_char *ufd_data; -+}; -+ -+struct usb_string_desc { -+ int usd_string_index; -+ int usd_language_id; -+ usb_string_descriptor_t usd_desc; -+}; -+ -+struct usb_ctl_report_desc { -+ int ucrd_size; -+ u_char ucrd_data[1024]; /* filled data size will vary */ -+}; -+ -+typedef struct { u_int32_t cookie; } usb_event_cookie_t; -+ -+#define USB_MAX_DEVNAMES 4 -+#define USB_MAX_DEVNAMELEN 16 -+struct usb_device_info { -+ u_int8_t udi_bus; -+ u_int8_t udi_addr; /* device address */ -+ usb_event_cookie_t udi_cookie; -+ char udi_product[USB_MAX_STRING_LEN]; -+ char udi_vendor[USB_MAX_STRING_LEN]; -+ char udi_release[8]; -+ u_int16_t udi_productNo; -+ u_int16_t udi_vendorNo; -+ u_int16_t udi_releaseNo; -+ u_int8_t udi_class; -+ u_int8_t udi_subclass; -+ u_int8_t udi_protocol; -+ u_int8_t udi_config; -+ u_int8_t udi_speed; -+#define USB_SPEED_LOW 1 -+#define USB_SPEED_FULL 2 -+#define USB_SPEED_HIGH 3 -+ int udi_power; /* power consumption in mA, 0 if selfpowered */ -+ int udi_nports; -+ char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; -+ u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */ -+#define USB_PORT_ENABLED 0xff -+#define USB_PORT_SUSPENDED 0xfe -+#define USB_PORT_POWERED 0xfd -+#define USB_PORT_DISABLED 0xfc -+}; -+ -+struct usb_ctl_report { -+ int ucr_report; -+ u_char ucr_data[1024]; /* filled data size will vary */ -+}; -+ -+struct usb_device_stats { -+ u_long uds_requests[4]; /* indexed by transfer type UE_* */ -+}; -+ -+ -+ -+ -+#define WUSB_MIN_IE 0x80 -+#define WUSB_WCTA_IE 0x80 -+#define WUSB_WCONNECTACK_IE 0x81 -+#define WUSB_WHOSTINFO_IE 0x82 -+#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3) -+#define WUHI_CA_RECONN 0x00 -+#define WUHI_CA_LIMITED 0x01 -+#define WUHI_CA_ALL 0x03 -+#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3) -+#define WUSB_WCHCHANGEANNOUNCE_IE 0x83 -+#define WUSB_WDEV_DISCONNECT_IE 0x84 -+#define WUSB_WHOST_DISCONNECT_IE 0x85 -+#define WUSB_WRELEASE_CHANNEL_IE 0x86 -+#define WUSB_WWORK_IE 0x87 -+#define WUSB_WCHANNEL_STOP_IE 0x88 -+#define WUSB_WDEV_KEEPALIVE_IE 0x89 -+#define WUSB_WISOCH_DISCARD_IE 0x8A -+#define WUSB_WRESETDEVICE_IE 0x8B -+#define WUSB_WXMIT_PACKET_ADJUST_IE 0x8C -+#define WUSB_MAX_IE 0x8C -+ -+/* Device Notification Types */ -+ -+#define WUSB_DN_MIN 0x01 -+#define WUSB_DN_CONNECT 0x01 -+# define WUSB_DA_OLDCONN 0x00 -+# define WUSB_DA_NEWCONN 0x01 -+# define WUSB_DA_SELF_BEACON 0x02 -+# define WUSB_DA_DIR_BEACON 0x04 -+# define WUSB_DA_NO_BEACON 0x06 -+#define WUSB_DN_DISCONNECT 0x02 -+#define WUSB_DN_EPRDY 0x03 -+#define WUSB_DN_MASAVAILCHANGED 0x04 -+#define WUSB_DN_REMOTEWAKEUP 0x05 -+#define WUSB_DN_SLEEP 0x06 -+#define WUSB_DN_ALIVE 0x07 -+#define WUSB_DN_MAX 0x07 -+ -+ -+/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */ -+typedef struct wusb_hndshk_data { -+ uint8_t bMessageNumber; -+ uint8_t bStatus; -+ uint8_t tTKID[3]; -+ uint8_t bReserved; -+ uint8_t CDID[16]; -+ uint8_t Nonce[16]; -+ uint8_t MIC[8]; -+} UPACKED wusb_hndshk_data_t; -+#define WUSB_HANDSHAKE_LEN_FOR_MIC 38 -+ -+/* WUSB Connection Context */ -+typedef struct wusb_conn_context { -+ uint8_t CHID [16]; -+ uint8_t CDID [16]; -+ uint8_t CK [16]; -+} UPACKED wusb_conn_context_t; -+ -+/* WUSB Security Descriptor */ -+typedef struct wusb_security_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint16_t wTotalLength; -+ uint8_t bNumEncryptionTypes; -+} UPACKED wusb_security_desc_t; -+ -+/* WUSB Encryption Type Descriptor */ -+typedef struct wusb_encrypt_type_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ -+ uint8_t bEncryptionType; -+#define WUETD_UNSECURE 0 -+#define WUETD_WIRED 1 -+#define WUETD_CCM_1 2 -+#define WUETD_RSA_1 3 -+ -+ uint8_t bEncryptionValue; -+ uint8_t bAuthKeyIndex; -+} UPACKED wusb_encrypt_type_desc_t; -+ -+/* WUSB Key Descriptor */ -+typedef struct wusb_key_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint8_t tTKID[3]; -+ uint8_t bReserved; -+ uint8_t KeyData[1]; /* variable length */ -+} UPACKED wusb_key_desc_t; -+ -+/* WUSB BOS Descriptor (Binary device Object Store) */ -+typedef struct wusb_bos_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint16_t wTotalLength; -+ uint8_t bNumDeviceCaps; -+} UPACKED wusb_bos_desc_t; -+ -+ -+/* Device Capability Type Codes */ -+#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01 -+ -+/* Device Capability Descriptor */ -+typedef struct wusb_dev_cap_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint8_t bDevCapabilityType; -+ uint8_t caps[1]; /* Variable length */ -+} UPACKED wusb_dev_cap_desc_t; -+ -+/* Device Capability Descriptor */ -+typedef struct wusb_dev_cap_uwb_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint8_t bDevCapabilityType; -+ uint8_t bmAttributes; -+ uint16_t wPHYRates; /* Bitmap */ -+ uint8_t bmTFITXPowerInfo; -+ uint8_t bmFFITXPowerInfo; -+ uint16_t bmBandGroup; -+ uint8_t bReserved; -+} UPACKED wusb_dev_cap_uwb_desc_t; -+ -+/* Wireless USB Endpoint Companion Descriptor */ -+typedef struct wusb_endpoint_companion_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint8_t bMaxBurst; -+ uint8_t bMaxSequence; -+ uint16_t wMaxStreamDelay; -+ uint16_t wOverTheAirPacketSize; -+ uint8_t bOverTheAirInterval; -+ uint8_t bmCompAttributes; -+} UPACKED wusb_endpoint_companion_desc_t; -+ -+ -+/* Wireless USB Numeric Association M1 Data Structure */ -+typedef struct wusb_m1_data { -+ uint8_t version; -+ uint16_t langId; -+ uint8_t deviceFriendlyNameLength; -+ uint8_t sha_256_m3[32]; -+ uint8_t deviceFriendlyName[256]; -+} UPACKED wusb_m1_data_t; -+ -+typedef struct wusb_m2_data { -+ uint8_t version; -+ uint16_t langId; -+ uint8_t hostFriendlyNameLength; -+ uint8_t pkh[384]; -+ uint8_t hostFriendlyName[256]; -+} UPACKED wusb_m2_data_t; -+ -+typedef struct wusb_m3_data { -+ uint8_t pkd[384]; -+ uint8_t nd; -+} UPACKED wusb_m3_data_t; -+ -+typedef struct wusb_m4_data { -+ uint32_t _attributeTypeIdAndLength_1; -+ uint16_t associationTypeId; -+ -+ uint32_t _attributeTypeIdAndLength_2; -+ uint16_t associationSubTypeId; -+ -+ uint32_t _attributeTypeIdAndLength_3; -+ uint32_t length; -+ -+ uint32_t _attributeTypeIdAndLength_4; -+ uint32_t associationStatus; -+ -+ uint32_t _attributeTypeIdAndLength_5; -+ uint8_t chid[16]; -+ -+ uint32_t _attributeTypeIdAndLength_6; -+ uint8_t cdid[16]; -+ -+ uint32_t _attributeTypeIdAndLength_7; -+ uint8_t bandGroups[2]; -+} UPACKED wusb_m4_data_t; -+ -+ -+ -+ -+#endif /* _USB_H_ */ -diff --git a/drivers/usb/host/dwc_otg/Makefile b/drivers/usb/host/dwc_otg/Makefile -new file mode 100644 -index 0000000..fed13f4 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/Makefile -@@ -0,0 +1,80 @@ -+# -+# Makefile for DWC_otg Highspeed USB controller driver -+# -+ -+ifneq ($(KERNELRELEASE),) -+ -+ifeq ($(BUS_INTERFACE),) -+ # BUS_INTERFACE = -DLM_INTERFACE -+ BUS_INTERFACE = -DPLATFORM_INTERFACE=1 -+endif -+ -+ifeq ($(CONFIG_USB_DEBUG),y) -+CPPFLAGS += -DDEBUG -+endif -+ -+# Use one of the following flags to compile the software in host-only or -+# device-only mode. -+#CPPFLAGS += -DDWC_HOST_ONLY -+#CPPFLAGS += -DDWC_DEVICE_ONLY -+ -+CPPFLAGS += -Dlinux -DDWC_HS_ELECT_TST -+#CGG: CPPFLAGS += -DDWC_EN_ISOC -+CPPFLAGS += -I$(obj)/../dwc_common_port -+#CPPFLAGS += -I$(PORTLIB) -+CPPFLAGS += -DDWC_LINUX -+CPPFLAGS += $(CFI) -+CPPFLAGS += $(BUS_INTERFACE) -+ -+obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o -+ -+dwc_otg-objs := dwc_otg_driver.o dwc_otg_attr.o -+dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o -+dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o -+dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o -+ifneq ($(CFI),) -+dwc_otg-objs += dwc_otg_cfi.o -+endif -+ -+kernrelwd := $(subst ., ,$(KERNELRELEASE)) -+kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) -+ -+ifneq ($(kernrel3),2.6.20) -+EXTRA_CFLAGS += $(CPPFLAGS) -+endif -+ -+else -+ -+PWD := $(shell pwd) -+PORTLIB := $(PWD)/../dwc_common_port -+ -+# Command paths -+CTAGS := $(CTAGS) -+DOXYGEN := $(DOXYGEN) -+ -+default: portlib -+ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules -+ -+install: default -+ifneq ($(INSTALL_MOD_PATH),) -+ $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install -+ $(MAKE) -C$(KDIR) M=$(PWD) modules_install -+else -+ @echo "No install path defined" -+endif -+ -+portlib: -+ $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules -+ cp $(PORTLIB)/Module.symvers $(PWD)/ -+ -+docs: $(wildcard *.[hc]) doc/doxygen.cfg -+ $(DOXYGEN) doc/doxygen.cfg -+ -+tags: $(wildcard *.[hc]) -+ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) -+ -+ -+clean: -+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions -+ -+endif -diff --git a/drivers/usb/host/dwc_otg/doc/doxygen.cfg b/drivers/usb/host/dwc_otg/doc/doxygen.cfg -new file mode 100644 -index 0000000..ddd0a10 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg -@@ -0,0 +1,224 @@ -+# Doxyfile 1.3.9.1 -+ -+#--------------------------------------------------------------------------- -+# Project related configuration options -+#--------------------------------------------------------------------------- -+PROJECT_NAME = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver" -+PROJECT_NUMBER = v2.90a -+OUTPUT_DIRECTORY = ./doc/ -+CREATE_SUBDIRS = NO -+OUTPUT_LANGUAGE = English -+BRIEF_MEMBER_DESC = YES -+REPEAT_BRIEF = YES -+ABBREVIATE_BRIEF = "The $name class" \ -+ "The $name widget" \ -+ "The $name file" \ -+ is \ -+ provides \ -+ specifies \ -+ contains \ -+ represents \ -+ a \ -+ an \ -+ the -+ALWAYS_DETAILED_SEC = NO -+INLINE_INHERITED_MEMB = NO -+FULL_PATH_NAMES = NO -+STRIP_FROM_PATH = -+STRIP_FROM_INC_PATH = -+SHORT_NAMES = NO -+JAVADOC_AUTOBRIEF = YES -+MULTILINE_CPP_IS_BRIEF = NO -+INHERIT_DOCS = YES -+DISTRIBUTE_GROUP_DOC = NO -+TAB_SIZE = 8 -+ALIASES = -+OPTIMIZE_OUTPUT_FOR_C = YES -+OPTIMIZE_OUTPUT_JAVA = NO -+SUBGROUPING = YES -+#--------------------------------------------------------------------------- -+# Build related configuration options -+#--------------------------------------------------------------------------- -+EXTRACT_ALL = NO -+EXTRACT_PRIVATE = YES -+EXTRACT_STATIC = YES -+EXTRACT_LOCAL_CLASSES = YES -+EXTRACT_LOCAL_METHODS = NO -+HIDE_UNDOC_MEMBERS = NO -+HIDE_UNDOC_CLASSES = NO -+HIDE_FRIEND_COMPOUNDS = NO -+HIDE_IN_BODY_DOCS = NO -+INTERNAL_DOCS = NO -+CASE_SENSE_NAMES = NO -+HIDE_SCOPE_NAMES = NO -+SHOW_INCLUDE_FILES = YES -+INLINE_INFO = YES -+SORT_MEMBER_DOCS = NO -+SORT_BRIEF_DOCS = NO -+SORT_BY_SCOPE_NAME = NO -+GENERATE_TODOLIST = YES -+GENERATE_TESTLIST = YES -+GENERATE_BUGLIST = YES -+GENERATE_DEPRECATEDLIST= YES -+ENABLED_SECTIONS = -+MAX_INITIALIZER_LINES = 30 -+SHOW_USED_FILES = YES -+SHOW_DIRECTORIES = YES -+#--------------------------------------------------------------------------- -+# configuration options related to warning and progress messages -+#--------------------------------------------------------------------------- -+QUIET = YES -+WARNINGS = YES -+WARN_IF_UNDOCUMENTED = NO -+WARN_IF_DOC_ERROR = YES -+WARN_FORMAT = "$file:$line: $text" -+WARN_LOGFILE = -+#--------------------------------------------------------------------------- -+# configuration options related to the input files -+#--------------------------------------------------------------------------- -+INPUT = . -+FILE_PATTERNS = *.c \ -+ *.h \ -+ ./linux/*.c \ -+ ./linux/*.h -+RECURSIVE = NO -+EXCLUDE = ./test/ \ -+ ./dwc_otg/.AppleDouble/ -+EXCLUDE_SYMLINKS = YES -+EXCLUDE_PATTERNS = *.mod.* -+EXAMPLE_PATH = -+EXAMPLE_PATTERNS = * -+EXAMPLE_RECURSIVE = NO -+IMAGE_PATH = -+INPUT_FILTER = -+FILTER_PATTERNS = -+FILTER_SOURCE_FILES = NO -+#--------------------------------------------------------------------------- -+# configuration options related to source browsing -+#--------------------------------------------------------------------------- -+SOURCE_BROWSER = YES -+INLINE_SOURCES = NO -+STRIP_CODE_COMMENTS = YES -+REFERENCED_BY_RELATION = NO -+REFERENCES_RELATION = NO -+VERBATIM_HEADERS = NO -+#--------------------------------------------------------------------------- -+# configuration options related to the alphabetical class index -+#--------------------------------------------------------------------------- -+ALPHABETICAL_INDEX = NO -+COLS_IN_ALPHA_INDEX = 5 -+IGNORE_PREFIX = -+#--------------------------------------------------------------------------- -+# configuration options related to the HTML output -+#--------------------------------------------------------------------------- -+GENERATE_HTML = YES -+HTML_OUTPUT = html -+HTML_FILE_EXTENSION = .html -+HTML_HEADER = -+HTML_FOOTER = -+HTML_STYLESHEET = -+HTML_ALIGN_MEMBERS = YES -+GENERATE_HTMLHELP = NO -+CHM_FILE = -+HHC_LOCATION = -+GENERATE_CHI = NO -+BINARY_TOC = NO -+TOC_EXPAND = NO -+DISABLE_INDEX = NO -+ENUM_VALUES_PER_LINE = 4 -+GENERATE_TREEVIEW = YES -+TREEVIEW_WIDTH = 250 -+#--------------------------------------------------------------------------- -+# configuration options related to the LaTeX output -+#--------------------------------------------------------------------------- -+GENERATE_LATEX = NO -+LATEX_OUTPUT = latex -+LATEX_CMD_NAME = latex -+MAKEINDEX_CMD_NAME = makeindex -+COMPACT_LATEX = NO -+PAPER_TYPE = a4wide -+EXTRA_PACKAGES = -+LATEX_HEADER = -+PDF_HYPERLINKS = NO -+USE_PDFLATEX = NO -+LATEX_BATCHMODE = NO -+LATEX_HIDE_INDICES = NO -+#--------------------------------------------------------------------------- -+# configuration options related to the RTF output -+#--------------------------------------------------------------------------- -+GENERATE_RTF = NO -+RTF_OUTPUT = rtf -+COMPACT_RTF = NO -+RTF_HYPERLINKS = NO -+RTF_STYLESHEET_FILE = -+RTF_EXTENSIONS_FILE = -+#--------------------------------------------------------------------------- -+# configuration options related to the man page output -+#--------------------------------------------------------------------------- -+GENERATE_MAN = NO -+MAN_OUTPUT = man -+MAN_EXTENSION = .3 -+MAN_LINKS = NO -+#--------------------------------------------------------------------------- -+# configuration options related to the XML output -+#--------------------------------------------------------------------------- -+GENERATE_XML = NO -+XML_OUTPUT = xml -+XML_SCHEMA = -+XML_DTD = -+XML_PROGRAMLISTING = YES -+#--------------------------------------------------------------------------- -+# configuration options for the AutoGen Definitions output -+#--------------------------------------------------------------------------- -+GENERATE_AUTOGEN_DEF = NO -+#--------------------------------------------------------------------------- -+# configuration options related to the Perl module output -+#--------------------------------------------------------------------------- -+GENERATE_PERLMOD = NO -+PERLMOD_LATEX = NO -+PERLMOD_PRETTY = YES -+PERLMOD_MAKEVAR_PREFIX = -+#--------------------------------------------------------------------------- -+# Configuration options related to the preprocessor -+#--------------------------------------------------------------------------- -+ENABLE_PREPROCESSING = YES -+MACRO_EXPANSION = YES -+EXPAND_ONLY_PREDEF = YES -+SEARCH_INCLUDES = YES -+INCLUDE_PATH = -+INCLUDE_FILE_PATTERNS = -+PREDEFINED = DEVICE_ATTR DWC_EN_ISOC -+EXPAND_AS_DEFINED = DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW DWC_OTG_DEVICE_ATTR_BITFIELD_STORE DWC_OTG_DEVICE_ATTR_BITFIELD_RW DWC_OTG_DEVICE_ATTR_BITFIELD_RO DWC_OTG_DEVICE_ATTR_REG_SHOW DWC_OTG_DEVICE_ATTR_REG_STORE DWC_OTG_DEVICE_ATTR_REG32_RW DWC_OTG_DEVICE_ATTR_REG32_RO DWC_EN_ISOC -+SKIP_FUNCTION_MACROS = NO -+#--------------------------------------------------------------------------- -+# Configuration::additions related to external references -+#--------------------------------------------------------------------------- -+TAGFILES = -+GENERATE_TAGFILE = -+ALLEXTERNALS = NO -+EXTERNAL_GROUPS = YES -+PERL_PATH = /usr/bin/perl -+#--------------------------------------------------------------------------- -+# Configuration options related to the dot tool -+#--------------------------------------------------------------------------- -+CLASS_DIAGRAMS = YES -+HIDE_UNDOC_RELATIONS = YES -+HAVE_DOT = NO -+CLASS_GRAPH = YES -+COLLABORATION_GRAPH = YES -+UML_LOOK = NO -+TEMPLATE_RELATIONS = NO -+INCLUDE_GRAPH = YES -+INCLUDED_BY_GRAPH = YES -+CALL_GRAPH = NO -+GRAPHICAL_HIERARCHY = YES -+DOT_IMAGE_FORMAT = png -+DOT_PATH = -+DOTFILE_DIRS = -+MAX_DOT_GRAPH_DEPTH = 1000 -+GENERATE_LEGEND = YES -+DOT_CLEANUP = YES -+#--------------------------------------------------------------------------- -+# Configuration::additions related to the search engine -+#--------------------------------------------------------------------------- -+SEARCHENGINE = NO -diff --git a/drivers/usb/host/dwc_otg/dummy_audio.c b/drivers/usb/host/dwc_otg/dummy_audio.c -new file mode 100644 -index 0000000..530ac8b ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dummy_audio.c -@@ -0,0 +1,1575 @@ -+/* -+ * zero.c -- Gadget Zero, for USB development -+ * -+ * Copyright (C) 2003-2004 David Brownell -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions, and the following disclaimer, -+ * without modification. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. The names of the above-listed copyright holders may not be used -+ * to endorse or promote products derived from this software without -+ * specific prior written permission. -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -+ * CONTRIBUTORS 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. -+ */ -+ -+ -+/* -+ * Gadget Zero only needs two bulk endpoints, and is an example of how you -+ * can write a hardware-agnostic gadget driver running inside a USB device. -+ * -+ * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't -+ * affect most of the driver. -+ * -+ * Use it with the Linux host/master side "usbtest" driver to get a basic -+ * functional test of your device-side usb stack, or with "usb-skeleton". -+ * -+ * It supports two similar configurations. One sinks whatever the usb host -+ * writes, and in return sources zeroes. The other loops whatever the host -+ * writes back, so the host can read it. Module options include: -+ * -+ * buflen=N default N=4096, buffer size used -+ * qlen=N default N=32, how many buffers in the loopback queue -+ * loopdefault default false, list loopback config first -+ * -+ * Many drivers will only have one configuration, letting them be much -+ * simpler if they also don't support high speed operation (like this -+ * driver does). -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) -+# include -+#else -+# include -+#endif -+ -+#include -+ -+ -+/*-------------------------------------------------------------------------*/ -+/*-------------------------------------------------------------------------*/ -+ -+ -+static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len) -+{ -+ int count = 0; -+ u8 c; -+ u16 uchar; -+ -+ /* this insists on correct encodings, though not minimal ones. -+ * BUT it currently rejects legit 4-byte UTF-8 code points, -+ * which need surrogate pairs. (Unicode 3.1 can use them.) -+ */ -+ while (len != 0 && (c = (u8) *s++) != 0) { -+ if (unlikely(c & 0x80)) { -+ // 2-byte sequence: -+ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx -+ if ((c & 0xe0) == 0xc0) { -+ uchar = (c & 0x1f) << 6; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c; -+ -+ // 3-byte sequence (most CJKV characters): -+ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx -+ } else if ((c & 0xf0) == 0xe0) { -+ uchar = (c & 0x0f) << 12; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c << 6; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c; -+ -+ /* no bogus surrogates */ -+ if (0xd800 <= uchar && uchar <= 0xdfff) -+ goto fail; -+ -+ // 4-byte sequence (surrogate pairs, currently rare): -+ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx -+ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx -+ // (uuuuu = wwww + 1) -+ // FIXME accept the surrogate code points (only) -+ -+ } else -+ goto fail; -+ } else -+ uchar = c; -+ put_unaligned (cpu_to_le16 (uchar), cp++); -+ count++; -+ len--; -+ } -+ return count; -+fail: -+ return -1; -+} -+ -+ -+/** -+ * usb_gadget_get_string - fill out a string descriptor -+ * @table: of c strings encoded using UTF-8 -+ * @id: string id, from low byte of wValue in get string descriptor -+ * @buf: at least 256 bytes -+ * -+ * Finds the UTF-8 string matching the ID, and converts it into a -+ * string descriptor in utf16-le. -+ * Returns length of descriptor (always even) or negative errno -+ * -+ * If your driver needs stings in multiple languages, you'll probably -+ * "switch (wIndex) { ... }" in your ep0 string descriptor logic, -+ * using this routine after choosing which set of UTF-8 strings to use. -+ * Note that US-ASCII is a strict subset of UTF-8; any string bytes with -+ * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1 -+ * characters (which are also widely used in C strings). -+ */ -+int -+usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) -+{ -+ struct usb_string *s; -+ int len; -+ -+ /* descriptor 0 has the language id */ -+ if (id == 0) { -+ buf [0] = 4; -+ buf [1] = USB_DT_STRING; -+ buf [2] = (u8) table->language; -+ buf [3] = (u8) (table->language >> 8); -+ return 4; -+ } -+ for (s = table->strings; s && s->s; s++) -+ if (s->id == id) -+ break; -+ -+ /* unrecognized: stall. */ -+ if (!s || !s->s) -+ return -EINVAL; -+ -+ /* string descriptors have length, tag, then UTF16-LE text */ -+ len = min ((size_t) 126, strlen (s->s)); -+ memset (buf + 2, 0, 2 * len); /* zero all the bytes */ -+ len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len); -+ if (len < 0) -+ return -EINVAL; -+ buf [0] = (len + 1) * 2; -+ buf [1] = USB_DT_STRING; -+ return buf [0]; -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+/*-------------------------------------------------------------------------*/ -+ -+ -+/** -+ * usb_descriptor_fillbuf - fill buffer with descriptors -+ * @buf: Buffer to be filled -+ * @buflen: Size of buf -+ * @src: Array of descriptor pointers, terminated by null pointer. -+ * -+ * Copies descriptors into the buffer, returning the length or a -+ * negative error code if they can't all be copied. Useful when -+ * assembling descriptors for an associated set of interfaces used -+ * as part of configuring a composite device; or in other cases where -+ * sets of descriptors need to be marshaled. -+ */ -+int -+usb_descriptor_fillbuf(void *buf, unsigned buflen, -+ const struct usb_descriptor_header **src) -+{ -+ u8 *dest = buf; -+ -+ if (!src) -+ return -EINVAL; -+ -+ /* fill buffer from src[] until null descriptor ptr */ -+ for (; 0 != *src; src++) { -+ unsigned len = (*src)->bLength; -+ -+ if (len > buflen) -+ return -EINVAL; -+ memcpy(dest, *src, len); -+ buflen -= len; -+ dest += len; -+ } -+ return dest - (u8 *)buf; -+} -+ -+ -+/** -+ * usb_gadget_config_buf - builts a complete configuration descriptor -+ * @config: Header for the descriptor, including characteristics such -+ * as power requirements and number of interfaces. -+ * @desc: Null-terminated vector of pointers to the descriptors (interface, -+ * endpoint, etc) defining all functions in this device configuration. -+ * @buf: Buffer for the resulting configuration descriptor. -+ * @length: Length of buffer. If this is not big enough to hold the -+ * entire configuration descriptor, an error code will be returned. -+ * -+ * This copies descriptors into the response buffer, building a descriptor -+ * for that configuration. It returns the buffer length or a negative -+ * status code. The config.wTotalLength field is set to match the length -+ * of the result, but other descriptor fields (including power usage and -+ * interface count) must be set by the caller. -+ * -+ * Gadget drivers could use this when constructing a config descriptor -+ * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the -+ * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed. -+ */ -+int usb_gadget_config_buf( -+ const struct usb_config_descriptor *config, -+ void *buf, -+ unsigned length, -+ const struct usb_descriptor_header **desc -+) -+{ -+ struct usb_config_descriptor *cp = buf; -+ int len; -+ -+ /* config descriptor first */ -+ if (length < USB_DT_CONFIG_SIZE || !desc) -+ return -EINVAL; -+ *cp = *config; -+ -+ /* then interface/endpoint/class/vendor/... */ -+ len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, -+ length - USB_DT_CONFIG_SIZE, desc); -+ if (len < 0) -+ return len; -+ len += USB_DT_CONFIG_SIZE; -+ if (len > 0xffff) -+ return -EINVAL; -+ -+ /* patch up the config descriptor */ -+ cp->bLength = USB_DT_CONFIG_SIZE; -+ cp->bDescriptorType = USB_DT_CONFIG; -+ cp->wTotalLength = cpu_to_le16(len); -+ cp->bmAttributes |= USB_CONFIG_ATT_ONE; -+ return len; -+} -+ -+/*-------------------------------------------------------------------------*/ -+/*-------------------------------------------------------------------------*/ -+ -+ -+#define RBUF_LEN (1024*1024) -+static int rbuf_start; -+static int rbuf_len; -+static __u8 rbuf[RBUF_LEN]; -+ -+/*-------------------------------------------------------------------------*/ -+ -+#define DRIVER_VERSION "St Patrick's Day 2004" -+ -+static const char shortname [] = "zero"; -+static const char longname [] = "YAMAHA YST-MS35D USB Speaker "; -+ -+static const char source_sink [] = "source and sink data"; -+static const char loopback [] = "loop input to output"; -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* -+ * driver assumes self-powered hardware, and -+ * has no way for users to trigger remote wakeup. -+ * -+ * this version autoconfigures as much as possible, -+ * which is reasonable for most "bulk-only" drivers. -+ */ -+static const char *EP_IN_NAME; /* source */ -+static const char *EP_OUT_NAME; /* sink */ -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* big enough to hold our biggest descriptor */ -+#define USB_BUFSIZ 512 -+ -+struct zero_dev { -+ spinlock_t lock; -+ struct usb_gadget *gadget; -+ struct usb_request *req; /* for control responses */ -+ -+ /* when configured, we have one of two configs: -+ * - source data (in to host) and sink it (out from host) -+ * - or loop it back (out from host back in to host) -+ */ -+ u8 config; -+ struct usb_ep *in_ep, *out_ep; -+ -+ /* autoresume timer */ -+ struct timer_list resume; -+}; -+ -+#define xprintk(d,level,fmt,args...) \ -+ dev_printk(level , &(d)->gadget->dev , fmt , ## args) -+ -+#ifdef DEBUG -+#define DBG(dev,fmt,args...) \ -+ xprintk(dev , KERN_DEBUG , fmt , ## args) -+#else -+#define DBG(dev,fmt,args...) \ -+ do { } while (0) -+#endif /* DEBUG */ -+ -+#ifdef VERBOSE -+#define VDBG DBG -+#else -+#define VDBG(dev,fmt,args...) \ -+ do { } while (0) -+#endif /* VERBOSE */ -+ -+#define ERROR(dev,fmt,args...) \ -+ xprintk(dev , KERN_ERR , fmt , ## args) -+#define WARN(dev,fmt,args...) \ -+ xprintk(dev , KERN_WARNING , fmt , ## args) -+#define INFO(dev,fmt,args...) \ -+ xprintk(dev , KERN_INFO , fmt , ## args) -+ -+/*-------------------------------------------------------------------------*/ -+ -+static unsigned buflen = 4096; -+static unsigned qlen = 32; -+static unsigned pattern = 0; -+ -+module_param (buflen, uint, S_IRUGO|S_IWUSR); -+module_param (qlen, uint, S_IRUGO|S_IWUSR); -+module_param (pattern, uint, S_IRUGO|S_IWUSR); -+ -+/* -+ * if it's nonzero, autoresume says how many seconds to wait -+ * before trying to wake up the host after suspend. -+ */ -+static unsigned autoresume = 0; -+module_param (autoresume, uint, 0); -+ -+/* -+ * Normally the "loopback" configuration is second (index 1) so -+ * it's not the default. Here's where to change that order, to -+ * work better with hosts where config changes are problematic. -+ * Or controllers (like superh) that only support one config. -+ */ -+static int loopdefault = 0; -+ -+module_param (loopdefault, bool, S_IRUGO|S_IWUSR); -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* Thanks to NetChip Technologies for donating this product ID. -+ * -+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! -+ * Instead: allocate your own, using normal USB-IF procedures. -+ */ -+#ifndef CONFIG_USB_ZERO_HNPTEST -+#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ -+#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */ -+#else -+#define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */ -+#define DRIVER_PRODUCT_NUM 0xbadd -+#endif -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* -+ * DESCRIPTORS ... most are static, but strings and (full) -+ * configuration descriptors are built on demand. -+ */ -+ -+/* -+#define STRING_MANUFACTURER 25 -+#define STRING_PRODUCT 42 -+#define STRING_SERIAL 101 -+*/ -+#define STRING_MANUFACTURER 1 -+#define STRING_PRODUCT 2 -+#define STRING_SERIAL 3 -+ -+#define STRING_SOURCE_SINK 250 -+#define STRING_LOOPBACK 251 -+ -+/* -+ * This device advertises two configurations; these numbers work -+ * on a pxa250 as well as more flexible hardware. -+ */ -+#define CONFIG_SOURCE_SINK 3 -+#define CONFIG_LOOPBACK 2 -+ -+/* -+static struct usb_device_descriptor -+device_desc = { -+ .bLength = sizeof device_desc, -+ .bDescriptorType = USB_DT_DEVICE, -+ -+ .bcdUSB = __constant_cpu_to_le16 (0x0200), -+ .bDeviceClass = USB_CLASS_VENDOR_SPEC, -+ -+ .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM), -+ .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM), -+ .iManufacturer = STRING_MANUFACTURER, -+ .iProduct = STRING_PRODUCT, -+ .iSerialNumber = STRING_SERIAL, -+ .bNumConfigurations = 2, -+}; -+*/ -+static struct usb_device_descriptor -+device_desc = { -+ .bLength = sizeof device_desc, -+ .bDescriptorType = USB_DT_DEVICE, -+ .bcdUSB = __constant_cpu_to_le16 (0x0100), -+ .bDeviceClass = USB_CLASS_PER_INTERFACE, -+ .bDeviceSubClass = 0, -+ .bDeviceProtocol = 0, -+ .bMaxPacketSize0 = 64, -+ .bcdDevice = __constant_cpu_to_le16 (0x0100), -+ .idVendor = __constant_cpu_to_le16 (0x0499), -+ .idProduct = __constant_cpu_to_le16 (0x3002), -+ .iManufacturer = STRING_MANUFACTURER, -+ .iProduct = STRING_PRODUCT, -+ .iSerialNumber = STRING_SERIAL, -+ .bNumConfigurations = 1, -+}; -+ -+static struct usb_config_descriptor -+z_config = { -+ .bLength = sizeof z_config, -+ .bDescriptorType = USB_DT_CONFIG, -+ -+ /* compute wTotalLength on the fly */ -+ .bNumInterfaces = 2, -+ .bConfigurationValue = 1, -+ .iConfiguration = 0, -+ .bmAttributes = 0x40, -+ .bMaxPower = 0, /* self-powered */ -+}; -+ -+ -+static struct usb_otg_descriptor -+otg_descriptor = { -+ .bLength = sizeof otg_descriptor, -+ .bDescriptorType = USB_DT_OTG, -+ -+ .bmAttributes = USB_OTG_SRP, -+}; -+ -+/* one interface in each configuration */ -+#ifdef CONFIG_USB_GADGET_DUALSPEED -+ -+/* -+ * usb 2.0 devices need to expose both high speed and full speed -+ * descriptors, unless they only run at full speed. -+ * -+ * that means alternate endpoint descriptors (bigger packets) -+ * and a "device qualifier" ... plus more construction options -+ * for the config descriptor. -+ */ -+ -+static struct usb_qualifier_descriptor -+dev_qualifier = { -+ .bLength = sizeof dev_qualifier, -+ .bDescriptorType = USB_DT_DEVICE_QUALIFIER, -+ -+ .bcdUSB = __constant_cpu_to_le16 (0x0200), -+ .bDeviceClass = USB_CLASS_VENDOR_SPEC, -+ -+ .bNumConfigurations = 2, -+}; -+ -+ -+struct usb_cs_as_general_descriptor { -+ __u8 bLength; -+ __u8 bDescriptorType; -+ -+ __u8 bDescriptorSubType; -+ __u8 bTerminalLink; -+ __u8 bDelay; -+ __u16 wFormatTag; -+} __attribute__ ((packed)); -+ -+struct usb_cs_as_format_descriptor { -+ __u8 bLength; -+ __u8 bDescriptorType; -+ -+ __u8 bDescriptorSubType; -+ __u8 bFormatType; -+ __u8 bNrChannels; -+ __u8 bSubframeSize; -+ __u8 bBitResolution; -+ __u8 bSamfreqType; -+ __u8 tLowerSamFreq[3]; -+ __u8 tUpperSamFreq[3]; -+} __attribute__ ((packed)); -+ -+static const struct usb_interface_descriptor -+z_audio_control_if_desc = { -+ .bLength = sizeof z_audio_control_if_desc, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 0, -+ .bAlternateSetting = 0, -+ .bNumEndpoints = 0, -+ .bInterfaceClass = USB_CLASS_AUDIO, -+ .bInterfaceSubClass = 0x1, -+ .bInterfaceProtocol = 0, -+ .iInterface = 0, -+}; -+ -+static const struct usb_interface_descriptor -+z_audio_if_desc = { -+ .bLength = sizeof z_audio_if_desc, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 1, -+ .bAlternateSetting = 0, -+ .bNumEndpoints = 0, -+ .bInterfaceClass = USB_CLASS_AUDIO, -+ .bInterfaceSubClass = 0x2, -+ .bInterfaceProtocol = 0, -+ .iInterface = 0, -+}; -+ -+static const struct usb_interface_descriptor -+z_audio_if_desc2 = { -+ .bLength = sizeof z_audio_if_desc, -+ .bDescriptorType = USB_DT_INTERFACE, -+ .bInterfaceNumber = 1, -+ .bAlternateSetting = 1, -+ .bNumEndpoints = 1, -+ .bInterfaceClass = USB_CLASS_AUDIO, -+ .bInterfaceSubClass = 0x2, -+ .bInterfaceProtocol = 0, -+ .iInterface = 0, -+}; -+ -+static const struct usb_cs_as_general_descriptor -+z_audio_cs_as_if_desc = { -+ .bLength = 7, -+ .bDescriptorType = 0x24, -+ -+ .bDescriptorSubType = 0x01, -+ .bTerminalLink = 0x01, -+ .bDelay = 0x0, -+ .wFormatTag = __constant_cpu_to_le16 (0x0001) -+}; -+ -+ -+static const struct usb_cs_as_format_descriptor -+z_audio_cs_as_format_desc = { -+ .bLength = 0xe, -+ .bDescriptorType = 0x24, -+ -+ .bDescriptorSubType = 2, -+ .bFormatType = 1, -+ .bNrChannels = 1, -+ .bSubframeSize = 1, -+ .bBitResolution = 8, -+ .bSamfreqType = 0, -+ .tLowerSamFreq = {0x7e, 0x13, 0x00}, -+ .tUpperSamFreq = {0xe2, 0xd6, 0x00}, -+}; -+ -+static const struct usb_endpoint_descriptor -+z_iso_ep = { -+ .bLength = 0x09, -+ .bDescriptorType = 0x05, -+ .bEndpointAddress = 0x04, -+ .bmAttributes = 0x09, -+ .wMaxPacketSize = 0x0038, -+ .bInterval = 0x01, -+ .bRefresh = 0x00, -+ .bSynchAddress = 0x00, -+}; -+ -+static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; -+ -+// 9 bytes -+static char z_ac_interface_header_desc[] = -+{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 }; -+ -+// 12 bytes -+static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, -+ 0x03, 0x00, 0x00, 0x00}; -+// 13 bytes -+static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00, -+ 0x02, 0x00, 0x02, 0x00, 0x00}; -+// 9 bytes -+static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02, -+ 0x00}; -+ -+static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, -+ 0x00}; -+ -+static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; -+ -+static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00, -+ 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00}; -+ -+static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00, -+ 0x00}; -+ -+static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; -+ -+static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, -+ 0x00}; -+ -+static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; -+ -+static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00, -+ 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00}; -+ -+static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00, -+ 0x00}; -+ -+static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; -+ -+static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00, -+ 0x00}; -+ -+static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; -+ -+static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, -+ 0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00}; -+ -+static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00, -+ 0x00}; -+ -+static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; -+ -+static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00, -+ 0x00}; -+ -+static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; -+ -+static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00, -+ 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00}; -+ -+static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00, -+ 0x00}; -+ -+static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; -+ -+static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00, -+ 0x00}; -+ -+static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; -+ -+static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00, -+ 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00}; -+ -+static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00, -+ 0x00}; -+ -+static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; -+ -+ -+ -+static const struct usb_descriptor_header *z_function [] = { -+ (struct usb_descriptor_header *) &z_audio_control_if_desc, -+ (struct usb_descriptor_header *) &z_ac_interface_header_desc, -+ (struct usb_descriptor_header *) &z_0, -+ (struct usb_descriptor_header *) &z_1, -+ (struct usb_descriptor_header *) &z_2, -+ (struct usb_descriptor_header *) &z_audio_if_desc, -+ (struct usb_descriptor_header *) &z_audio_if_desc2, -+ (struct usb_descriptor_header *) &z_audio_cs_as_if_desc, -+ (struct usb_descriptor_header *) &z_audio_cs_as_format_desc, -+ (struct usb_descriptor_header *) &z_iso_ep, -+ (struct usb_descriptor_header *) &z_iso_ep2, -+ (struct usb_descriptor_header *) &za_0, -+ (struct usb_descriptor_header *) &za_1, -+ (struct usb_descriptor_header *) &za_2, -+ (struct usb_descriptor_header *) &za_3, -+ (struct usb_descriptor_header *) &za_4, -+ (struct usb_descriptor_header *) &za_5, -+ (struct usb_descriptor_header *) &za_6, -+ (struct usb_descriptor_header *) &za_7, -+ (struct usb_descriptor_header *) &za_8, -+ (struct usb_descriptor_header *) &za_9, -+ (struct usb_descriptor_header *) &za_10, -+ (struct usb_descriptor_header *) &za_11, -+ (struct usb_descriptor_header *) &za_12, -+ (struct usb_descriptor_header *) &za_13, -+ (struct usb_descriptor_header *) &za_14, -+ (struct usb_descriptor_header *) &za_15, -+ (struct usb_descriptor_header *) &za_16, -+ (struct usb_descriptor_header *) &za_17, -+ (struct usb_descriptor_header *) &za_18, -+ (struct usb_descriptor_header *) &za_19, -+ (struct usb_descriptor_header *) &za_20, -+ (struct usb_descriptor_header *) &za_21, -+ (struct usb_descriptor_header *) &za_22, -+ (struct usb_descriptor_header *) &za_23, -+ (struct usb_descriptor_header *) &za_24, -+ NULL, -+}; -+ -+/* maxpacket and other transfer characteristics vary by speed. */ -+#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) -+ -+#else -+ -+/* if there's no high speed support, maxpacket doesn't change. */ -+#define ep_desc(g,hs,fs) fs -+ -+#endif /* !CONFIG_USB_GADGET_DUALSPEED */ -+ -+static char manufacturer [40]; -+//static char serial [40]; -+static char serial [] = "Ser 00 em"; -+ -+/* static strings, in UTF-8 */ -+static struct usb_string strings [] = { -+ { STRING_MANUFACTURER, manufacturer, }, -+ { STRING_PRODUCT, longname, }, -+ { STRING_SERIAL, serial, }, -+ { STRING_LOOPBACK, loopback, }, -+ { STRING_SOURCE_SINK, source_sink, }, -+ { } /* end of list */ -+}; -+ -+static struct usb_gadget_strings stringtab = { -+ .language = 0x0409, /* en-us */ -+ .strings = strings, -+}; -+ -+/* -+ * config descriptors are also handcrafted. these must agree with code -+ * that sets configurations, and with code managing interfaces and their -+ * altsettings. other complexity may come from: -+ * -+ * - high speed support, including "other speed config" rules -+ * - multiple configurations -+ * - interfaces with alternate settings -+ * - embedded class or vendor-specific descriptors -+ * -+ * this handles high speed, and has a second config that could as easily -+ * have been an alternate interface setting (on most hardware). -+ * -+ * NOTE: to demonstrate (and test) more USB capabilities, this driver -+ * should include an altsetting to test interrupt transfers, including -+ * high bandwidth modes at high speed. (Maybe work like Intel's test -+ * device?) -+ */ -+static int -+config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index) -+{ -+ int len; -+ const struct usb_descriptor_header **function; -+ -+ function = z_function; -+ len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function); -+ if (len < 0) -+ return len; -+ ((struct usb_config_descriptor *) buf)->bDescriptorType = type; -+ return len; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static struct usb_request * -+alloc_ep_req (struct usb_ep *ep, unsigned length) -+{ -+ struct usb_request *req; -+ -+ req = usb_ep_alloc_request (ep, GFP_ATOMIC); -+ if (req) { -+ req->length = length; -+ req->buf = usb_ep_alloc_buffer (ep, length, -+ &req->dma, GFP_ATOMIC); -+ if (!req->buf) { -+ usb_ep_free_request (ep, req); -+ req = NULL; -+ } -+ } -+ return req; -+} -+ -+static void free_ep_req (struct usb_ep *ep, struct usb_request *req) -+{ -+ if (req->buf) -+ usb_ep_free_buffer (ep, req->buf, req->dma, req->length); -+ usb_ep_free_request (ep, req); -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+/* optionally require specific source/sink data patterns */ -+ -+static int -+check_read_data ( -+ struct zero_dev *dev, -+ struct usb_ep *ep, -+ struct usb_request *req -+) -+{ -+ unsigned i; -+ u8 *buf = req->buf; -+ -+ for (i = 0; i < req->actual; i++, buf++) { -+ switch (pattern) { -+ /* all-zeroes has no synchronization issues */ -+ case 0: -+ if (*buf == 0) -+ continue; -+ break; -+ /* mod63 stays in sync with short-terminated transfers, -+ * or otherwise when host and gadget agree on how large -+ * each usb transfer request should be. resync is done -+ * with set_interface or set_config. -+ */ -+ case 1: -+ if (*buf == (u8)(i % 63)) -+ continue; -+ break; -+ } -+ ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf); -+ usb_ep_set_halt (ep); -+ return -EINVAL; -+ } -+ return 0; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void zero_reset_config (struct zero_dev *dev) -+{ -+ if (dev->config == 0) -+ return; -+ -+ DBG (dev, "reset config\n"); -+ -+ /* just disable endpoints, forcing completion of pending i/o. -+ * all our completion handlers free their requests in this case. -+ */ -+ if (dev->in_ep) { -+ usb_ep_disable (dev->in_ep); -+ dev->in_ep = NULL; -+ } -+ if (dev->out_ep) { -+ usb_ep_disable (dev->out_ep); -+ dev->out_ep = NULL; -+ } -+ dev->config = 0; -+ del_timer (&dev->resume); -+} -+ -+#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos)) -+ -+static void -+zero_isoc_complete (struct usb_ep *ep, struct usb_request *req) -+{ -+ struct zero_dev *dev = ep->driver_data; -+ int status = req->status; -+ int i, j; -+ -+ switch (status) { -+ -+ case 0: /* normal completion? */ -+ //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual); -+ for (i=0, j=rbuf_start; iactual; i++) { -+ //printk ("%02x ", ((__u8*)req->buf)[i]); -+ rbuf[j] = ((__u8*)req->buf)[i]; -+ j++; -+ if (j >= RBUF_LEN) j=0; -+ } -+ rbuf_start = j; -+ //printk ("\n\n"); -+ -+ if (rbuf_len < RBUF_LEN) { -+ rbuf_len += req->actual; -+ if (rbuf_len > RBUF_LEN) { -+ rbuf_len = RBUF_LEN; -+ } -+ } -+ -+ break; -+ -+ /* this endpoint is normally active while we're configured */ -+ case -ECONNABORTED: /* hardware forced ep reset */ -+ case -ECONNRESET: /* request dequeued */ -+ case -ESHUTDOWN: /* disconnect from host */ -+ VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status, -+ req->actual, req->length); -+ if (ep == dev->out_ep) -+ check_read_data (dev, ep, req); -+ free_ep_req (ep, req); -+ return; -+ -+ case -EOVERFLOW: /* buffer overrun on read means that -+ * we didn't provide a big enough -+ * buffer. -+ */ -+ default: -+#if 1 -+ DBG (dev, "%s complete --> %d, %d/%d\n", ep->name, -+ status, req->actual, req->length); -+#endif -+ case -EREMOTEIO: /* short read */ -+ break; -+ } -+ -+ status = usb_ep_queue (ep, req, GFP_ATOMIC); -+ if (status) { -+ ERROR (dev, "kill %s: resubmit %d bytes --> %d\n", -+ ep->name, req->length, status); -+ usb_ep_set_halt (ep); -+ /* FIXME recover later ... somehow */ -+ } -+} -+ -+static struct usb_request * -+zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags) -+{ -+ struct usb_request *req; -+ int status; -+ -+ req = alloc_ep_req (ep, 512); -+ if (!req) -+ return NULL; -+ -+ req->complete = zero_isoc_complete; -+ -+ status = usb_ep_queue (ep, req, gfp_flags); -+ if (status) { -+ struct zero_dev *dev = ep->driver_data; -+ -+ ERROR (dev, "start %s --> %d\n", ep->name, status); -+ free_ep_req (ep, req); -+ req = NULL; -+ } -+ -+ return req; -+} -+ -+/* change our operational config. this code must agree with the code -+ * that returns config descriptors, and altsetting code. -+ * -+ * it's also responsible for power management interactions. some -+ * configurations might not work with our current power sources. -+ * -+ * note that some device controller hardware will constrain what this -+ * code can do, perhaps by disallowing more than one configuration or -+ * by limiting configuration choices (like the pxa2xx). -+ */ -+static int -+zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags) -+{ -+ int result = 0; -+ struct usb_gadget *gadget = dev->gadget; -+ const struct usb_endpoint_descriptor *d; -+ struct usb_ep *ep; -+ -+ if (number == dev->config) -+ return 0; -+ -+ zero_reset_config (dev); -+ -+ gadget_for_each_ep (ep, gadget) { -+ -+ if (strcmp (ep->name, "ep4") == 0) { -+ -+ d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6 -+ result = usb_ep_enable (ep, d); -+ -+ if (result == 0) { -+ ep->driver_data = dev; -+ dev->in_ep = ep; -+ -+ if (zero_start_isoc_ep (ep, gfp_flags) != 0) { -+ -+ dev->in_ep = ep; -+ continue; -+ } -+ -+ usb_ep_disable (ep); -+ result = -EIO; -+ } -+ } -+ -+ } -+ -+ dev->config = number; -+ return result; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req) -+{ -+ if (req->status || req->actual != req->length) -+ DBG ((struct zero_dev *) ep->driver_data, -+ "setup complete --> %d, %d/%d\n", -+ req->status, req->actual, req->length); -+} -+ -+/* -+ * The setup() callback implements all the ep0 functionality that's -+ * not handled lower down, in hardware or the hardware driver (like -+ * device and endpoint feature flags, and their status). It's all -+ * housekeeping for the gadget function we're implementing. Most of -+ * the work is in config-specific setup. -+ */ -+static int -+zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) -+{ -+ struct zero_dev *dev = get_gadget_data (gadget); -+ struct usb_request *req = dev->req; -+ int value = -EOPNOTSUPP; -+ -+ /* usually this stores reply data in the pre-allocated ep0 buffer, -+ * but config change events will reconfigure hardware. -+ */ -+ req->zero = 0; -+ switch (ctrl->bRequest) { -+ -+ case USB_REQ_GET_DESCRIPTOR: -+ -+ switch (ctrl->wValue >> 8) { -+ -+ case USB_DT_DEVICE: -+ value = min (ctrl->wLength, (u16) sizeof device_desc); -+ memcpy (req->buf, &device_desc, value); -+ break; -+#ifdef CONFIG_USB_GADGET_DUALSPEED -+ case USB_DT_DEVICE_QUALIFIER: -+ if (!gadget->is_dualspeed) -+ break; -+ value = min (ctrl->wLength, (u16) sizeof dev_qualifier); -+ memcpy (req->buf, &dev_qualifier, value); -+ break; -+ -+ case USB_DT_OTHER_SPEED_CONFIG: -+ if (!gadget->is_dualspeed) -+ break; -+ // FALLTHROUGH -+#endif /* CONFIG_USB_GADGET_DUALSPEED */ -+ case USB_DT_CONFIG: -+ value = config_buf (gadget, req->buf, -+ ctrl->wValue >> 8, -+ ctrl->wValue & 0xff); -+ if (value >= 0) -+ value = min (ctrl->wLength, (u16) value); -+ break; -+ -+ case USB_DT_STRING: -+ /* wIndex == language code. -+ * this driver only handles one language, you can -+ * add string tables for other languages, using -+ * any UTF-8 characters -+ */ -+ value = usb_gadget_get_string (&stringtab, -+ ctrl->wValue & 0xff, req->buf); -+ if (value >= 0) { -+ value = min (ctrl->wLength, (u16) value); -+ } -+ break; -+ } -+ break; -+ -+ /* currently two configs, two speeds */ -+ case USB_REQ_SET_CONFIGURATION: -+ if (ctrl->bRequestType != 0) -+ goto unknown; -+ -+ spin_lock (&dev->lock); -+ value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC); -+ spin_unlock (&dev->lock); -+ break; -+ case USB_REQ_GET_CONFIGURATION: -+ if (ctrl->bRequestType != USB_DIR_IN) -+ goto unknown; -+ *(u8 *)req->buf = dev->config; -+ value = min (ctrl->wLength, (u16) 1); -+ break; -+ -+ /* until we add altsetting support, or other interfaces, -+ * only 0/0 are possible. pxa2xx only supports 0/0 (poorly) -+ * and already killed pending endpoint I/O. -+ */ -+ case USB_REQ_SET_INTERFACE: -+ -+ if (ctrl->bRequestType != USB_RECIP_INTERFACE) -+ goto unknown; -+ spin_lock (&dev->lock); -+ if (dev->config) { -+ u8 config = dev->config; -+ -+ /* resets interface configuration, forgets about -+ * previous transaction state (queued bufs, etc) -+ * and re-inits endpoint state (toggle etc) -+ * no response queued, just zero status == success. -+ * if we had more than one interface we couldn't -+ * use this "reset the config" shortcut. -+ */ -+ zero_reset_config (dev); -+ zero_set_config (dev, config, GFP_ATOMIC); -+ value = 0; -+ } -+ spin_unlock (&dev->lock); -+ break; -+ case USB_REQ_GET_INTERFACE: -+ if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) { -+ value = ctrl->wLength; -+ break; -+ } -+ else { -+ if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) -+ goto unknown; -+ if (!dev->config) -+ break; -+ if (ctrl->wIndex != 0) { -+ value = -EDOM; -+ break; -+ } -+ *(u8 *)req->buf = 0; -+ value = min (ctrl->wLength, (u16) 1); -+ } -+ break; -+ -+ /* -+ * These are the same vendor-specific requests supported by -+ * Intel's USB 2.0 compliance test devices. We exceed that -+ * device spec by allowing multiple-packet requests. -+ */ -+ case 0x5b: /* control WRITE test -- fill the buffer */ -+ if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) -+ goto unknown; -+ if (ctrl->wValue || ctrl->wIndex) -+ break; -+ /* just read that many bytes into the buffer */ -+ if (ctrl->wLength > USB_BUFSIZ) -+ break; -+ value = ctrl->wLength; -+ break; -+ case 0x5c: /* control READ test -- return the buffer */ -+ if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) -+ goto unknown; -+ if (ctrl->wValue || ctrl->wIndex) -+ break; -+ /* expect those bytes are still in the buffer; send back */ -+ if (ctrl->wLength > USB_BUFSIZ -+ || ctrl->wLength != req->length) -+ break; -+ value = ctrl->wLength; -+ break; -+ -+ case 0x01: // SET_CUR -+ case 0x02: -+ case 0x03: -+ case 0x04: -+ case 0x05: -+ value = ctrl->wLength; -+ break; -+ case 0x81: -+ switch (ctrl->wValue) { -+ case 0x0201: -+ case 0x0202: -+ ((u8*)req->buf)[0] = 0x00; -+ ((u8*)req->buf)[1] = 0xe3; -+ break; -+ case 0x0300: -+ case 0x0500: -+ ((u8*)req->buf)[0] = 0x00; -+ break; -+ } -+ //((u8*)req->buf)[0] = 0x81; -+ //((u8*)req->buf)[1] = 0x81; -+ value = ctrl->wLength; -+ break; -+ case 0x82: -+ switch (ctrl->wValue) { -+ case 0x0201: -+ case 0x0202: -+ ((u8*)req->buf)[0] = 0x00; -+ ((u8*)req->buf)[1] = 0xc3; -+ break; -+ case 0x0300: -+ case 0x0500: -+ ((u8*)req->buf)[0] = 0x00; -+ break; -+ } -+ //((u8*)req->buf)[0] = 0x82; -+ //((u8*)req->buf)[1] = 0x82; -+ value = ctrl->wLength; -+ break; -+ case 0x83: -+ switch (ctrl->wValue) { -+ case 0x0201: -+ case 0x0202: -+ ((u8*)req->buf)[0] = 0x00; -+ ((u8*)req->buf)[1] = 0x00; -+ break; -+ case 0x0300: -+ ((u8*)req->buf)[0] = 0x60; -+ break; -+ case 0x0500: -+ ((u8*)req->buf)[0] = 0x18; -+ break; -+ } -+ //((u8*)req->buf)[0] = 0x83; -+ //((u8*)req->buf)[1] = 0x83; -+ value = ctrl->wLength; -+ break; -+ case 0x84: -+ switch (ctrl->wValue) { -+ case 0x0201: -+ case 0x0202: -+ ((u8*)req->buf)[0] = 0x00; -+ ((u8*)req->buf)[1] = 0x01; -+ break; -+ case 0x0300: -+ case 0x0500: -+ ((u8*)req->buf)[0] = 0x08; -+ break; -+ } -+ //((u8*)req->buf)[0] = 0x84; -+ //((u8*)req->buf)[1] = 0x84; -+ value = ctrl->wLength; -+ break; -+ case 0x85: -+ ((u8*)req->buf)[0] = 0x85; -+ ((u8*)req->buf)[1] = 0x85; -+ value = ctrl->wLength; -+ break; -+ -+ -+ default: -+unknown: -+ printk("unknown control req%02x.%02x v%04x i%04x l%d\n", -+ ctrl->bRequestType, ctrl->bRequest, -+ ctrl->wValue, ctrl->wIndex, ctrl->wLength); -+ } -+ -+ /* respond with data transfer before status phase? */ -+ if (value >= 0) { -+ req->length = value; -+ req->zero = value < ctrl->wLength -+ && (value % gadget->ep0->maxpacket) == 0; -+ value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); -+ if (value < 0) { -+ DBG (dev, "ep_queue < 0 --> %d\n", value); -+ req->status = 0; -+ zero_setup_complete (gadget->ep0, req); -+ } -+ } -+ -+ /* device either stalls (value < 0) or reports success */ -+ return value; -+} -+ -+static void -+zero_disconnect (struct usb_gadget *gadget) -+{ -+ struct zero_dev *dev = get_gadget_data (gadget); -+ unsigned long flags; -+ -+ spin_lock_irqsave (&dev->lock, flags); -+ zero_reset_config (dev); -+ -+ /* a more significant application might have some non-usb -+ * activities to quiesce here, saving resources like power -+ * or pushing the notification up a network stack. -+ */ -+ spin_unlock_irqrestore (&dev->lock, flags); -+ -+ /* next we may get setup() calls to enumerate new connections; -+ * or an unbind() during shutdown (including removing module). -+ */ -+} -+ -+static void -+zero_autoresume (unsigned long _dev) -+{ -+ struct zero_dev *dev = (struct zero_dev *) _dev; -+ int status; -+ -+ /* normally the host would be woken up for something -+ * more significant than just a timer firing... -+ */ -+ if (dev->gadget->speed != USB_SPEED_UNKNOWN) { -+ status = usb_gadget_wakeup (dev->gadget); -+ DBG (dev, "wakeup --> %d\n", status); -+ } -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void -+zero_unbind (struct usb_gadget *gadget) -+{ -+ struct zero_dev *dev = get_gadget_data (gadget); -+ -+ DBG (dev, "unbind\n"); -+ -+ /* we've already been disconnected ... no i/o is active */ -+ if (dev->req) -+ free_ep_req (gadget->ep0, dev->req); -+ del_timer_sync (&dev->resume); -+ kfree (dev); -+ set_gadget_data (gadget, NULL); -+} -+ -+static int -+zero_bind (struct usb_gadget *gadget) -+{ -+ struct zero_dev *dev; -+ //struct usb_ep *ep; -+ -+ printk("binding\n"); -+ /* -+ * DRIVER POLICY CHOICE: you may want to do this differently. -+ * One thing to avoid is reusing a bcdDevice revision code -+ * with different host-visible configurations or behavior -+ * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc -+ */ -+ //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201); -+ -+ -+ /* ok, we made sense of the hardware ... */ -+ dev = kmalloc (sizeof *dev, SLAB_KERNEL); -+ if (!dev) -+ return -ENOMEM; -+ memset (dev, 0, sizeof *dev); -+ spin_lock_init (&dev->lock); -+ dev->gadget = gadget; -+ set_gadget_data (gadget, dev); -+ -+ /* preallocate control response and buffer */ -+ dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); -+ if (!dev->req) -+ goto enomem; -+ dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ, -+ &dev->req->dma, GFP_KERNEL); -+ if (!dev->req->buf) -+ goto enomem; -+ -+ dev->req->complete = zero_setup_complete; -+ -+ device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; -+ -+#ifdef CONFIG_USB_GADGET_DUALSPEED -+ /* assume ep0 uses the same value for both speeds ... */ -+ dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; -+ -+ /* and that all endpoints are dual-speed */ -+ //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; -+ //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; -+#endif -+ -+ usb_gadget_set_selfpowered (gadget); -+ -+ init_timer (&dev->resume); -+ dev->resume.function = zero_autoresume; -+ dev->resume.data = (unsigned long) dev; -+ -+ gadget->ep0->driver_data = dev; -+ -+ INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname); -+ INFO (dev, "using %s, OUT %s IN %s\n", gadget->name, -+ EP_OUT_NAME, EP_IN_NAME); -+ -+ snprintf (manufacturer, sizeof manufacturer, -+ UTS_SYSNAME " " UTS_RELEASE " with %s", -+ gadget->name); -+ -+ return 0; -+ -+enomem: -+ zero_unbind (gadget); -+ return -ENOMEM; -+} -+ -+/*-------------------------------------------------------------------------*/ -+ -+static void -+zero_suspend (struct usb_gadget *gadget) -+{ -+ struct zero_dev *dev = get_gadget_data (gadget); -+ -+ if (gadget->speed == USB_SPEED_UNKNOWN) -+ return; -+ -+ if (autoresume) { -+ mod_timer (&dev->resume, jiffies + (HZ * autoresume)); -+ DBG (dev, "suspend, wakeup in %d seconds\n", autoresume); -+ } else -+ DBG (dev, "suspend\n"); -+} -+ -+static void -+zero_resume (struct usb_gadget *gadget) -+{ -+ struct zero_dev *dev = get_gadget_data (gadget); -+ -+ DBG (dev, "resume\n"); -+ del_timer (&dev->resume); -+} -+ -+ -+/*-------------------------------------------------------------------------*/ -+ -+static struct usb_gadget_driver zero_driver = { -+#ifdef CONFIG_USB_GADGET_DUALSPEED -+ .speed = USB_SPEED_HIGH, -+#else -+ .speed = USB_SPEED_FULL, -+#endif -+ .function = (char *) longname, -+ .bind = zero_bind, -+ .unbind = zero_unbind, -+ -+ .setup = zero_setup, -+ .disconnect = zero_disconnect, -+ -+ .suspend = zero_suspend, -+ .resume = zero_resume, -+ -+ .driver = { -+ .name = (char *) shortname, -+ // .shutdown = ... -+ // .suspend = ... -+ // .resume = ... -+ }, -+}; -+ -+MODULE_AUTHOR ("David Brownell"); -+MODULE_LICENSE ("Dual BSD/GPL"); -+ -+static struct proc_dir_entry *pdir, *pfile; -+ -+static int isoc_read_data (char *page, char **start, -+ off_t off, int count, -+ int *eof, void *data) -+{ -+ int i; -+ static int c = 0; -+ static int done = 0; -+ static int s = 0; -+ -+/* -+ printk ("\ncount: %d\n", count); -+ printk ("rbuf_start: %d\n", rbuf_start); -+ printk ("rbuf_len: %d\n", rbuf_len); -+ printk ("off: %d\n", off); -+ printk ("start: %p\n\n", *start); -+*/ -+ if (done) { -+ c = 0; -+ done = 0; -+ *eof = 1; -+ return 0; -+ } -+ -+ if (c == 0) { -+ if (rbuf_len == RBUF_LEN) -+ s = rbuf_start; -+ else s = 0; -+ } -+ -+ for (i=0; i= rbuf_len) { -+ *eof = 1; -+ done = 1; -+ } -+ -+ -+ return i; -+} -+ -+static int __init init (void) -+{ -+ -+ int retval = 0; -+ -+ pdir = proc_mkdir("isoc_test", NULL); -+ if(pdir == NULL) { -+ retval = -ENOMEM; -+ printk("Error creating dir\n"); -+ goto done; -+ } -+ pdir->owner = THIS_MODULE; -+ -+ pfile = create_proc_read_entry("isoc_data", -+ 0444, pdir, -+ isoc_read_data, -+ NULL); -+ if (pfile == NULL) { -+ retval = -ENOMEM; -+ printk("Error creating file\n"); -+ goto no_file; -+ } -+ pfile->owner = THIS_MODULE; -+ -+ return usb_gadget_register_driver (&zero_driver); -+ -+ no_file: -+ remove_proc_entry("isoc_data", NULL); -+ done: -+ return retval; -+} -+module_init (init); -+ -+static void __exit cleanup (void) -+{ -+ -+ usb_gadget_unregister_driver (&zero_driver); -+ -+ remove_proc_entry("isoc_data", pdir); -+ remove_proc_entry("isoc_test", NULL); -+} -+module_exit (cleanup); -diff --git a/drivers/usb/host/dwc_otg/dwc_cfi_common.h b/drivers/usb/host/dwc_otg/dwc_cfi_common.h -new file mode 100644 -index 0000000..be56af4 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h -@@ -0,0 +1,142 @@ -+/* ========================================================================== -+ * 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. -+ * ========================================================================== */ -+ -+#if !defined(__DWC_CFI_COMMON_H__) -+#define __DWC_CFI_COMMON_H__ -+ -+//#include -+ -+/** -+ * @file -+ * -+ * This file contains the CFI specific common constants, interfaces -+ * (functions and macros) and structures for Linux. No PCD specific -+ * data structure or definition is to be included in this file. -+ * -+ */ -+ -+/** This is a request for all Core Features */ -+#define VEN_CORE_GET_FEATURES 0xB1 -+ -+/** This is a request to get the value of a specific Core Feature */ -+#define VEN_CORE_GET_FEATURE 0xB2 -+ -+/** This command allows the host to set the value of a specific Core Feature */ -+#define VEN_CORE_SET_FEATURE 0xB3 -+ -+/** This command allows the host to set the default values of -+ * either all or any specific Core Feature -+ */ -+#define VEN_CORE_RESET_FEATURES 0xB4 -+ -+/** This command forces the PCD to write the deferred values of a Core Features */ -+#define VEN_CORE_ACTIVATE_FEATURES 0xB5 -+ -+/** This request reads a DWORD value from a register at the specified offset */ -+#define VEN_CORE_READ_REGISTER 0xB6 -+ -+/** This request writes a DWORD value into a register at the specified offset */ -+#define VEN_CORE_WRITE_REGISTER 0xB7 -+ -+/** This structure is the header of the Core Features dataset returned to -+ * the Host -+ */ -+struct cfi_all_features_header { -+/** The features header structure length is */ -+#define CFI_ALL_FEATURES_HDR_LEN 8 -+ /** -+ * The total length of the features dataset returned to the Host -+ */ -+ uint16_t wTotalLen; -+ -+ /** -+ * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H). -+ * This field identifies the version of the CFI Specification with which -+ * the device is compliant. -+ */ -+ uint16_t wVersion; -+ -+ /** The ID of the Core */ -+ uint16_t wCoreID; -+#define CFI_CORE_ID_UDC 1 -+#define CFI_CORE_ID_OTG 2 -+#define CFI_CORE_ID_WUDEV 3 -+ -+ /** Number of features returned by VEN_CORE_GET_FEATURES request */ -+ uint16_t wNumFeatures; -+} UPACKED; -+ -+typedef struct cfi_all_features_header cfi_all_features_header_t; -+ -+/** This structure is a header of the Core Feature descriptor dataset returned to -+ * the Host after the VEN_CORE_GET_FEATURES request -+ */ -+struct cfi_feature_desc_header { -+#define CFI_FEATURE_DESC_HDR_LEN 8 -+ -+ /** The feature ID */ -+ uint16_t wFeatureID; -+ -+ /** Length of this feature descriptor in bytes - including the -+ * length of the feature name string -+ */ -+ uint16_t wLength; -+ -+ /** The data length of this feature in bytes */ -+ uint16_t wDataLength; -+ -+ /** -+ * Attributes of this features -+ * D0: Access rights -+ * 0 - Read/Write -+ * 1 - Read only -+ */ -+ uint8_t bmAttributes; -+#define CFI_FEATURE_ATTR_RO 1 -+#define CFI_FEATURE_ATTR_RW 0 -+ -+ /** Length of the feature name in bytes */ -+ uint8_t bNameLen; -+ -+ /** The feature name buffer */ -+ //uint8_t *name; -+} UPACKED; -+ -+typedef struct cfi_feature_desc_header cfi_feature_desc_header_t; -+ -+/** -+ * This structure describes a NULL terminated string referenced by its id field. -+ * It is very similar to usb_string structure but has the id field type set to 16-bit. -+ */ -+struct cfi_string { -+ uint16_t id; -+ const uint8_t *s; -+}; -+typedef struct cfi_string cfi_string_t; -+ -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -new file mode 100644 -index 0000000..26ff76f ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -@@ -0,0 +1,1316 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $ -+ * $Revision: #35 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225160 $ -+ * -+ * 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. -+ * ========================================================================== */ -+ -+/** @file -+ * -+ * The diagnostic interface will provide access to the controller for -+ * bringing up the hardware and testing. The Linux driver attributes -+ * feature will be used to provide the Linux Diagnostic -+ * Interface. These attributes are accessed through sysfs. -+ */ -+ -+/** @page "Linux Module Attributes" -+ * -+ * The Linux module attributes feature is used to provide the Linux -+ * Diagnostic Interface. These attributes are accessed through sysfs. -+ * The diagnostic interface will provide access to the controller for -+ * bringing up the hardware and testing. -+ -+ The following table shows the attributes. -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
Name Description Access
mode Returns the current mode: 0 for device mode, 1 for host mode Read
hnpcapable Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register. -+ Read returns the current value. Read/Write
srpcapable Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register. -+ Read returns the current value. Read/Write
hsic_connect Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register. -+ Read returns the current value. Read/Write
inv_sel_hsic Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register. -+ Read returns the current value. Read/Write
hnp Initiates the Host Negotiation Protocol. Read returns the status. Read/Write
srp Initiates the Session Request Protocol. Read returns the status. Read/Write
buspower Gets or sets the Power State of the bus (0 - Off or 1 - On) Read/Write
bussuspend Suspends the USB bus. Read/Write
busconnected Gets the connection status of the bus Read
gotgctl Gets or sets the Core Control Status Register. Read/Write
gusbcfg Gets or sets the Core USB Configuration Register Read/Write
grxfsiz Gets or sets the Receive FIFO Size Register Read/Write
gnptxfsiz Gets or sets the non-periodic Transmit Size Register Read/Write
gpvndctl Gets or sets the PHY Vendor Control Register Read/Write
ggpio Gets the value in the lower 16-bits of the General Purpose IO Register -+ or sets the upper 16 bits. Read/Write
guid Gets or sets the value of the User ID Register Read/Write
gsnpsid Gets the value of the Synopsys ID Regester Read
devspeed Gets or sets the device speed setting in the DCFG register Read/Write
enumspeed Gets the device enumeration Speed. Read
hptxfsiz Gets the value of the Host Periodic Transmit FIFO Read
hprt0 Gets or sets the value in the Host Port Control and Status Register Read/Write
regoffset Sets the register offset for the next Register Access Read/Write
regvalue Gets or sets the value of the register at the offset in the regoffset attribute. Read/Write
remote_wakeup On read, shows the status of Remote Wakeup. On write, initiates a remote -+ wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote -+ Wakeup signalling bit in the Device Control Register is set for 1 -+ milli-second. Read/Write
regdump Dumps the contents of core registers. Read
spramdump Dumps the contents of core registers. Read
hcddump Dumps the current HCD state. Read
hcd_frrem Shows the average value of the Frame Remaining -+ field in the Host Frame Number/Frame Remaining register when an SOF interrupt -+ occurs. This can be used to determine the average interrupt latency. Also -+ shows the average Frame Remaining value for start_transfer and the "a" and -+ "b" sample points. The "a" and "b" sample points may be used during debugging -+ bto determine how long it takes to execute a section of the HCD code. Read
rd_reg_test Displays the time required to read the GNPTXFSIZ register many times -+ (the output shows the number of times the register is read). -+ Read
wr_reg_test Displays the time required to write the GNPTXFSIZ register many times -+ (the output shows the number of times the register is written). -+ Read
lpm_response Gets or sets lpm_response mode. Applicable only in device mode. -+ Write
sleep_local_dev Generetates sleep signaling. Applicable only in host mode. -+ Write
sleep_status Shows sleep status of device. -+ Read
-+ -+ Example usage: -+ To get the current mode: -+ cat /sys/devices/lm0/mode -+ -+ To power down the USB: -+ echo 0 > /sys/devices/lm0/buspower -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* permission constants */ -+#include -+#include -+#include -+#include -+ -+ -+#ifdef LM_INTERFACE -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#else -+/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - -+ here we use definitions stolen from arm-integrator headers -+*/ -+#include -+#endif -+#elif defined(PLATFORM_INTERFACE) -+#include -+#endif -+ -+#include -+ -+#include "dwc_os.h" -+#include "dwc_otg_driver.h" -+#include "dwc_otg_attr.h" -+#include "dwc_otg_core_if.h" -+#include "dwc_otg_pcd_if.h" -+#include "dwc_otg_hcd_if.h" -+ -+/* -+ * MACROs for defining sysfs attribute -+ */ -+#ifdef LM_INTERFACE -+ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ -+ uint32_t val; \ -+ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ -+ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ -+} -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+{ \ -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ -+ uint32_t set = simple_strtoul(buf, NULL, 16); \ -+ dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ -+ return count; \ -+} -+ -+#elif defined(PCI_INTERFACE) -+ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ -+ uint32_t val; \ -+ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ -+ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ -+} -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+{ \ -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ -+ uint32_t set = simple_strtoul(buf, NULL, 16); \ -+ dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ -+ return count; \ -+} -+ -+#elif defined(PLATFORM_INTERFACE) -+ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct platform_device *platform_dev = \ -+ container_of(_dev, struct platform_device, dev); \ -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \ -+ uint32_t val; \ -+ DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \ -+ __func__, _dev, platform_dev, otg_dev); \ -+ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ -+ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ -+} -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+{ \ -+ struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \ -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \ -+ uint32_t set = simple_strtoul(buf, NULL, 16); \ -+ dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ -+ return count; \ -+} -+#endif -+ -+/* -+ * MACROs for defining sysfs attribute for 32-bit registers -+ */ -+#ifdef LM_INTERFACE -+#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ -+ uint32_t val; \ -+ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ -+ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ -+} -+#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+{ \ -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ -+ uint32_t val = simple_strtoul(buf, NULL, 16); \ -+ dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ -+ return count; \ -+} -+#elif defined(PCI_INTERFACE) -+#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ -+ uint32_t val; \ -+ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ -+ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ -+} -+#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+{ \ -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ -+ uint32_t val = simple_strtoul(buf, NULL, 16); \ -+ dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ -+ return count; \ -+} -+ -+#elif defined(PLATFORM_INTERFACE) -+#include "dwc_otg_dbg.h" -+#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ -+{ \ -+ struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \ -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \ -+ uint32_t val; \ -+ DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \ -+ __func__, _dev, platform_dev, otg_dev); \ -+ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ -+ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ -+} -+#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ -+static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ -+ const char *buf, size_t count) \ -+{ \ -+ struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \ -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \ -+ uint32_t val = simple_strtoul(buf, NULL, 16); \ -+ dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ -+ return count; \ -+} -+ -+#endif -+ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \ -+DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ -+DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ -+DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); -+ -+#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \ -+DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ -+DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); -+ -+#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \ -+DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ -+DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ -+DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); -+ -+#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \ -+DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ -+DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); -+ -+/** @name Functions for Show/Store of Attributes */ -+/**@{*/ -+ -+/** -+ * Show the register offset of the Register Access. -+ */ -+static ssize_t regoffset_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = container_of(_dev, -+ struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", -+ otg_dev->reg_offset); -+} -+ -+/** -+ * Set the register offset for the next Register Access Read/Write -+ */ -+static ssize_t regoffset_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = container_of(_dev, -+ struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ uint32_t offset = simple_strtoul(buf, NULL, 16); -+ if (offset < SZ_256K) { -+ otg_dev->reg_offset = offset; -+ } else { -+ dev_err(_dev, "invalid offset\n"); -+ } -+ -+ return count; -+} -+ -+DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store); -+ -+/** -+ * Show the value of the register at the offset in the reg_offset -+ * attribute. -+ */ -+static ssize_t regvalue_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ uint32_t val; -+ volatile uint32_t *addr; -+ -+ if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { -+ /* Calculate the address */ -+ addr = (uint32_t *) (otg_dev->reg_offset + -+ (uint8_t *) otg_dev->base); -+ val = dwc_read_reg32(addr); -+ return snprintf(buf, -+ sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, -+ "Reg@0x%06x = 0x%08x\n", otg_dev->reg_offset, -+ val); -+ } else { -+ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->reg_offset); -+ return sprintf(buf, "invalid offset\n"); -+ } -+} -+ -+/** -+ * Store the value in the register at the offset in the reg_offset -+ * attribute. -+ * -+ */ -+static ssize_t regvalue_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ volatile uint32_t *addr; -+ uint32_t val = simple_strtoul(buf, NULL, 16); -+ //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val); -+ if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { -+ /* Calculate the address */ -+ addr = (uint32_t *) (otg_dev->reg_offset + -+ (uint8_t *) otg_dev->base); -+ dwc_write_reg32(addr, val); -+ } else { -+ dev_err(_dev, "Invalid Register Offset (0x%08x)\n", -+ otg_dev->reg_offset); -+ } -+ return count; -+} -+ -+DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store); -+ -+/* -+ * Attributes -+ */ -+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "Mode"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC"); -+ -+//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); -+//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected"); -+ -+DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg, -+ &(otg_dev->core_if->core_global_regs->gusbcfg), -+ "GUSBCFG"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz, -+ &(otg_dev->core_if->core_global_regs->grxfsiz), -+ "GRXFSIZ"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz, -+ &(otg_dev->core_if->core_global_regs->gnptxfsiz), -+ "GNPTXFSIZ"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl, -+ &(otg_dev->core_if->core_global_regs->gpvndctl), -+ "GPVNDCTL"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio, -+ &(otg_dev->core_if->core_global_regs->ggpio), -+ "GGPIO"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid), -+ "GUID"); -+DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid, -+ &(otg_dev->core_if->core_global_regs->gsnpsid), -+ "GSNPSID"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed"); -+ -+DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz, -+ &(otg_dev->core_if->core_global_regs->hptxfsiz), -+ "HPTXFSIZ"); -+DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0"); -+ -+/** -+ * @todo Add code to initiate the HNP. -+ */ -+/** -+ * Show the HNP status bit -+ */ -+static ssize_t hnp_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ return sprintf(buf, "HstNegScs = 0x%x\n", -+ dwc_otg_get_hnpstatus(otg_dev->core_if)); -+} -+ -+/** -+ * Set the HNP Request bit -+ */ -+static ssize_t hnp_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ uint32_t in = simple_strtoul(buf, NULL, 16); -+ dwc_otg_set_hnpreq(otg_dev->core_if, in); -+ return count; -+} -+ -+DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store); -+ -+/** -+ * @todo Add code to initiate the SRP. -+ */ -+/** -+ * Show the SRP status bit -+ */ -+static ssize_t srp_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifndef DWC_HOST_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ return sprintf(buf, "SesReqScs = 0x%x\n", -+ dwc_otg_get_srpstatus(otg_dev->core_if)); -+#else -+ return sprintf(buf, "Host Only Mode!\n"); -+#endif -+} -+ -+/** -+ * Set the SRP Request bit -+ */ -+static ssize_t srp_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifndef DWC_HOST_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ dwc_otg_pcd_initiate_srp(otg_dev->pcd); -+#endif -+ return count; -+} -+ -+DEVICE_ATTR(srp, 0644, srp_show, srp_store); -+ -+/** -+ * @todo Need to do more for power on/off? -+ */ -+/** -+ * Show the Bus Power status -+ */ -+static ssize_t buspower_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ return sprintf(buf, "Bus Power = 0x%x\n", -+ dwc_otg_get_prtpower(otg_dev->core_if)); -+} -+ -+/** -+ * Set the Bus Power status -+ */ -+static ssize_t buspower_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ uint32_t on = simple_strtoul(buf, NULL, 16); -+ dwc_otg_set_prtpower(otg_dev->core_if, on); -+ return count; -+} -+ -+DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store); -+ -+/** -+ * @todo Need to do more for suspend? -+ */ -+/** -+ * Show the Bus Suspend status -+ */ -+static ssize_t bussuspend_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ return sprintf(buf, "Bus Suspend = 0x%x\n", -+ dwc_otg_get_prtsuspend(otg_dev->core_if)); -+} -+ -+/** -+ * Set the Bus Suspend status -+ */ -+static ssize_t bussuspend_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ uint32_t in = simple_strtoul(buf, NULL, 16); -+ dwc_otg_set_prtsuspend(otg_dev->core_if, in); -+ return count; -+} -+ -+DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); -+ -+/** -+ * Show the status of Remote Wakeup. -+ */ -+static ssize_t remote_wakeup_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifndef DWC_HOST_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ return sprintf(buf, -+ "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n", -+ dwc_otg_get_remotewakesig(otg_dev->core_if), -+ dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd), -+ dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if)); -+#else -+ return sprintf(buf, "Host Only Mode!\n"); -+#endif /* DWC_HOST_ONLY */ -+} -+ -+/** -+ * Initiate a remote wakeup of the host. The Device control register -+ * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable -+ * flag is set. -+ * -+ */ -+static ssize_t remote_wakeup_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifndef DWC_HOST_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ uint32_t val = simple_strtoul(buf, NULL, 16); -+ -+ if (val & 1) { -+ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1); -+ } else { -+ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0); -+ } -+#endif /* DWC_HOST_ONLY */ -+ return count; -+} -+ -+DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show, -+ remote_wakeup_store); -+ -+/** -+ * Dump global registers and either host or device registers (depending on the -+ * current mode of the core). -+ */ -+static ssize_t regdump_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ dwc_otg_dump_global_registers(otg_dev->core_if); -+ if (dwc_otg_is_host_mode(otg_dev->core_if)) { -+ dwc_otg_dump_host_registers(otg_dev->core_if); -+ } else { -+ dwc_otg_dump_dev_registers(otg_dev->core_if); -+ -+ } -+ return sprintf(buf, "Register Dump\n"); -+} -+ -+DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0); -+ -+/** -+ * Dump global registers and either host or device registers (depending on the -+ * current mode of the core). -+ */ -+static ssize_t spramdump_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ dwc_otg_dump_spram(otg_dev->core_if); -+ -+ return sprintf(buf, "SPRAM Dump\n"); -+} -+ -+DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0); -+ -+/** -+ * Dump the current hcd state. -+ */ -+static ssize_t hcddump_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifndef DWC_DEVICE_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ dwc_otg_hcd_dump_state(otg_dev->hcd); -+#endif /* DWC_DEVICE_ONLY */ -+ return sprintf(buf, "HCD Dump\n"); -+} -+ -+DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0); -+ -+/** -+ * Dump the average frame remaining at SOF. This can be used to -+ * determine average interrupt latency. Frame remaining is also shown for -+ * start transfer and two additional sample points. -+ */ -+static ssize_t hcd_frrem_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifndef DWC_DEVICE_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ dwc_otg_hcd_dump_frrem(otg_dev->hcd); -+#endif /* DWC_DEVICE_ONLY */ -+ return sprintf(buf, "HCD Dump Frame Remaining\n"); -+} -+ -+DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0); -+ -+/** -+ * Displays the time required to read the GNPTXFSIZ register many times (the -+ * output shows the number of times the register is read). -+ */ -+#define RW_REG_COUNT 10000000 -+#define MSEC_PER_JIFFIE 1000/HZ -+static ssize_t rd_reg_test_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ int i; -+ int time; -+ int start_jiffies; -+ -+ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", -+ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); -+ start_jiffies = jiffies; -+ for (i = 0; i < RW_REG_COUNT; i++) { -+ dwc_otg_get_gnptxfsiz(otg_dev->core_if); -+ } -+ time = jiffies - start_jiffies; -+ return sprintf(buf, -+ "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", -+ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); -+} -+ -+DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0); -+ -+/** -+ * Displays the time required to write the GNPTXFSIZ register many times (the -+ * output shows the number of times the register is written). -+ */ -+static ssize_t wr_reg_test_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ uint32_t reg_val; -+ int i; -+ int time; -+ int start_jiffies; -+ -+ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", -+ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); -+ reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if); -+ start_jiffies = jiffies; -+ for (i = 0; i < RW_REG_COUNT; i++) { -+ dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val); -+ } -+ time = jiffies - start_jiffies; -+ return sprintf(buf, -+ "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", -+ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); -+} -+ -+DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0); -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ -+/** -+* Show the lpm_response attribute. -+*/ -+static ssize_t lpmresp_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) -+ return sprintf(buf, "** LPM is DISABLED **\n"); -+ -+ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { -+ return sprintf(buf, "** Current mode is not device mode\n"); -+ } -+ return sprintf(buf, "lpm_response = %d\n", -+ dwc_otg_get_lpmresponse(otg_dev->core_if)); -+} -+ -+/** -+* Store the lpm_response attribute. -+*/ -+static ssize_t lpmresp_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ uint32_t val = simple_strtoul(buf, NULL, 16); -+ -+ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { -+ return 0; -+ } -+ -+ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { -+ return 0; -+ } -+ -+ dwc_otg_set_lpmresponse(otg_dev->core_if, val); -+ return count; -+} -+ -+DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store); -+ -+/** -+* Show the sleep_status attribute. -+*/ -+static ssize_t sleepstatus_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ -+ return sprintf(buf, "Sleep Status = %d\n", -+ dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)); -+} -+ -+/** -+ * Store the sleep_status attribure. -+ */ -+static ssize_t sleepstatus_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ dwc_otg_core_if_t *core_if = otg_dev->core_if; -+ -+ if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) { -+ if (dwc_otg_is_host_mode(core_if)) { -+ -+ DWC_PRINTF("Host initiated resume\n"); -+ dwc_otg_set_prtresume(otg_dev->core_if, 1); -+ } -+ } -+ -+ return count; -+} -+ -+DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show, -+ sleepstatus_store); -+ -+#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */ -+ -+/**@}*/ -+ -+/** -+ * Create the device files -+ */ -+void dwc_otg_attr_create ( -+#ifdef LM_INTERFACE -+ struct lm_device *dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *dev -+#endif -+ ) -+ -+{ -+ int error; -+ -+ error = device_create_file(&dev->dev, &dev_attr_regoffset); -+ error = device_create_file(&dev->dev, &dev_attr_regvalue); -+ error = device_create_file(&dev->dev, &dev_attr_mode); -+ error = device_create_file(&dev->dev, &dev_attr_hnpcapable); -+ error = device_create_file(&dev->dev, &dev_attr_srpcapable); -+ error = device_create_file(&dev->dev, &dev_attr_hsic_connect); -+ error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic); -+ error = device_create_file(&dev->dev, &dev_attr_hnp); -+ error = device_create_file(&dev->dev, &dev_attr_srp); -+ error = device_create_file(&dev->dev, &dev_attr_buspower); -+ error = device_create_file(&dev->dev, &dev_attr_bussuspend); -+ error = device_create_file(&dev->dev, &dev_attr_busconnected); -+ error = device_create_file(&dev->dev, &dev_attr_gotgctl); -+ error = device_create_file(&dev->dev, &dev_attr_gusbcfg); -+ error = device_create_file(&dev->dev, &dev_attr_grxfsiz); -+ error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz); -+ error = device_create_file(&dev->dev, &dev_attr_gpvndctl); -+ error = device_create_file(&dev->dev, &dev_attr_ggpio); -+ error = device_create_file(&dev->dev, &dev_attr_guid); -+ error = device_create_file(&dev->dev, &dev_attr_gsnpsid); -+ error = device_create_file(&dev->dev, &dev_attr_devspeed); -+ error = device_create_file(&dev->dev, &dev_attr_enumspeed); -+ error = device_create_file(&dev->dev, &dev_attr_hptxfsiz); -+ error = device_create_file(&dev->dev, &dev_attr_hprt0); -+ error = device_create_file(&dev->dev, &dev_attr_remote_wakeup); -+ error = device_create_file(&dev->dev, &dev_attr_regdump); -+ error = device_create_file(&dev->dev, &dev_attr_spramdump); -+ error = device_create_file(&dev->dev, &dev_attr_hcddump); -+ error = device_create_file(&dev->dev, &dev_attr_hcd_frrem); -+ error = device_create_file(&dev->dev, &dev_attr_rd_reg_test); -+ error = device_create_file(&dev->dev, &dev_attr_wr_reg_test); -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ error = device_create_file(&dev->dev, &dev_attr_lpm_response); -+ error = device_create_file(&dev->dev, &dev_attr_sleep_status); -+#endif -+} -+ -+/** -+ * Remove the device files -+ */ -+void dwc_otg_attr_remove ( -+#ifdef LM_INTERFACE -+ struct lm_device *dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *dev -+#endif -+ ) -+ -+{ -+ device_remove_file(&dev->dev, &dev_attr_regoffset); -+ device_remove_file(&dev->dev, &dev_attr_regvalue); -+ device_remove_file(&dev->dev, &dev_attr_mode); -+ device_remove_file(&dev->dev, &dev_attr_hnpcapable); -+ device_remove_file(&dev->dev, &dev_attr_srpcapable); -+ device_remove_file(&dev->dev, &dev_attr_hsic_connect); -+ device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic); -+ device_remove_file(&dev->dev, &dev_attr_hnp); -+ device_remove_file(&dev->dev, &dev_attr_srp); -+ device_remove_file(&dev->dev, &dev_attr_buspower); -+ device_remove_file(&dev->dev, &dev_attr_bussuspend); -+ device_remove_file(&dev->dev, &dev_attr_busconnected); -+ device_remove_file(&dev->dev, &dev_attr_gotgctl); -+ device_remove_file(&dev->dev, &dev_attr_gusbcfg); -+ device_remove_file(&dev->dev, &dev_attr_grxfsiz); -+ device_remove_file(&dev->dev, &dev_attr_gnptxfsiz); -+ device_remove_file(&dev->dev, &dev_attr_gpvndctl); -+ device_remove_file(&dev->dev, &dev_attr_ggpio); -+ device_remove_file(&dev->dev, &dev_attr_guid); -+ device_remove_file(&dev->dev, &dev_attr_gsnpsid); -+ device_remove_file(&dev->dev, &dev_attr_devspeed); -+ device_remove_file(&dev->dev, &dev_attr_enumspeed); -+ device_remove_file(&dev->dev, &dev_attr_hptxfsiz); -+ device_remove_file(&dev->dev, &dev_attr_hprt0); -+ device_remove_file(&dev->dev, &dev_attr_remote_wakeup); -+ device_remove_file(&dev->dev, &dev_attr_regdump); -+ device_remove_file(&dev->dev, &dev_attr_spramdump); -+ device_remove_file(&dev->dev, &dev_attr_hcddump); -+ device_remove_file(&dev->dev, &dev_attr_hcd_frrem); -+ device_remove_file(&dev->dev, &dev_attr_rd_reg_test); -+ device_remove_file(&dev->dev, &dev_attr_wr_reg_test); -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ device_remove_file(&dev->dev, &dev_attr_lpm_response); -+ device_remove_file(&dev->dev, &dev_attr_sleep_status); -+#endif -+} -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -new file mode 100644 -index 0000000..b59651d ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -@@ -0,0 +1,88 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $ -+ * $Revision: #11 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225160 $ -+ * -+ * 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. -+ * ========================================================================== */ -+ -+#if !defined(__DWC_OTG_ATTR_H__) -+#define __DWC_OTG_ATTR_H__ -+ -+/** @file -+ * This file contains the interface to the Linux device attributes. -+ */ -+extern struct device_attribute dev_attr_regoffset; -+extern struct device_attribute dev_attr_regvalue; -+ -+extern struct device_attribute dev_attr_mode; -+extern struct device_attribute dev_attr_hnpcapable; -+extern struct device_attribute dev_attr_srpcapable; -+extern struct device_attribute dev_attr_hnp; -+extern struct device_attribute dev_attr_srp; -+extern struct device_attribute dev_attr_buspower; -+extern struct device_attribute dev_attr_bussuspend; -+extern struct device_attribute dev_attr_busconnected; -+extern struct device_attribute dev_attr_gotgctl; -+extern struct device_attribute dev_attr_gusbcfg; -+extern struct device_attribute dev_attr_grxfsiz; -+extern struct device_attribute dev_attr_gnptxfsiz; -+extern struct device_attribute dev_attr_gpvndctl; -+extern struct device_attribute dev_attr_ggpio; -+extern struct device_attribute dev_attr_guid; -+extern struct device_attribute dev_attr_gsnpsid; -+extern struct device_attribute dev_attr_devspeed; -+extern struct device_attribute dev_attr_enumspeed; -+extern struct device_attribute dev_attr_hptxfsiz; -+extern struct device_attribute dev_attr_hprt0; -+#ifdef CONFIG_USB_DWC_OTG_LPM -+extern struct device_attribute dev_attr_lpm_response; -+extern struct device_attribute dev_attr_sleep_local_dev; -+extern struct device_attribute devi_attr_sleep_status; -+#endif -+ -+void dwc_otg_attr_create ( -+#ifdef LM_INTERFACE -+ struct lm_device *dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *dev -+#endif -+ ); -+ -+void dwc_otg_attr_remove ( -+#ifdef LM_INTERFACE -+ struct lm_device *dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *dev -+#endif -+ ); -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.c b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c -new file mode 100644 -index 0000000..7fe7255 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c -@@ -0,0 +1,1876 @@ -+/* ========================================================================== -+ * 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. -+ * ========================================================================== */ -+ -+/** @file -+ * -+ * This file contains the most of the CFI implementation for the OTG. -+ */ -+ -+#ifdef DWC_UTE_CFI -+ -+#include "dwc_otg_pcd.h" -+#include "dwc_otg_cfi.h" -+ -+/** This definition should actually migrate to the Portability Library */ -+#define DWC_CONSTANT_CPU_TO_LE16(x) (x) -+ -+extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex); -+ -+static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen); -+static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, -+ struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *ctrl_req); -+static int cfi_set_feature_value(struct dwc_otg_pcd *pcd); -+static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *req); -+static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *req); -+static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *req); -+static int cfi_preproc_reset(struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *req); -+static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep); -+ -+static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if); -+static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue); -+static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue); -+ -+static uint8_t resize_fifos(dwc_otg_core_if_t * core_if); -+ -+/** This is the header of the all features descriptor */ -+static cfi_all_features_header_t all_props_desc_header = { -+ .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100), -+ .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG), -+ .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9), -+}; -+ -+/** This is an array of statically allocated feature descriptors */ -+static cfi_feature_desc_header_t prop_descs[] = { -+ -+ /* FT_ID_DMA_MODE */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE), -+ .bmAttributes = CFI_FEATURE_ATTR_RW, -+ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1), -+ }, -+ -+ /* FT_ID_DMA_BUFFER_SETUP */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP), -+ .bmAttributes = CFI_FEATURE_ATTR_RW, -+ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), -+ }, -+ -+ /* FT_ID_DMA_BUFF_ALIGN */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN), -+ .bmAttributes = CFI_FEATURE_ATTR_RW, -+ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), -+ }, -+ -+ /* FT_ID_DMA_CONCAT_SETUP */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP), -+ .bmAttributes = CFI_FEATURE_ATTR_RW, -+ //.wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), -+ }, -+ -+ /* FT_ID_DMA_CIRCULAR */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR), -+ .bmAttributes = CFI_FEATURE_ATTR_RW, -+ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), -+ }, -+ -+ /* FT_ID_THRESHOLD_SETUP */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP), -+ .bmAttributes = CFI_FEATURE_ATTR_RW, -+ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), -+ }, -+ -+ /* FT_ID_DFIFO_DEPTH */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH), -+ .bmAttributes = CFI_FEATURE_ATTR_RO, -+ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), -+ }, -+ -+ /* FT_ID_TX_FIFO_DEPTH */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH), -+ .bmAttributes = CFI_FEATURE_ATTR_RW, -+ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), -+ }, -+ -+ /* FT_ID_RX_FIFO_DEPTH */ -+ { -+ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH), -+ .bmAttributes = CFI_FEATURE_ATTR_RW, -+ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), -+ } -+}; -+ -+/** The table of feature names */ -+cfi_string_t prop_name_table[] = { -+ {FT_ID_DMA_MODE, "dma_mode"}, -+ {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"}, -+ {FT_ID_DMA_BUFF_ALIGN, "buffer_align"}, -+ {FT_ID_DMA_CONCAT_SETUP, "concat_setup"}, -+ {FT_ID_DMA_CIRCULAR, "buffer_circular"}, -+ {FT_ID_THRESHOLD_SETUP, "threshold_setup"}, -+ {FT_ID_DFIFO_DEPTH, "dfifo_depth"}, -+ {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"}, -+ {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"}, -+ {} -+}; -+ -+/************************************************************************/ -+ -+/** -+ * Returns the name of the feature by its ID -+ * or NULL if no featute ID matches. -+ * -+ */ -+const uint8_t *get_prop_name(uint16_t prop_id, int *len) -+{ -+ cfi_string_t *pstr; -+ *len = 0; -+ -+ for (pstr = prop_name_table; pstr && pstr->s; pstr++) { -+ if (pstr->id == prop_id) { -+ *len = DWC_STRLEN(pstr->s); -+ return pstr->s; -+ } -+ } -+ return NULL; -+} -+ -+/** -+ * This function handles all CFI specific control requests. -+ * -+ * Return a negative value to stall the DCE. -+ */ -+int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl) -+{ -+ int retval = 0; -+ dwc_otg_pcd_ep_t *ep = NULL; -+ cfiobject_t *cfi = pcd->cfi; -+ struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd); -+ uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength); -+ uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue); -+ uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex); -+ uint32_t regaddr = 0; -+ uint32_t regval = 0; -+ -+ /* Save this Control Request in the CFI object. -+ * The data field will be assigned in the data stage completion CB function. -+ */ -+ cfi->ctrl_req = *ctrl; -+ cfi->ctrl_req.data = NULL; -+ -+ cfi->need_gadget_att = 0; -+ cfi->need_status_in_complete = 0; -+ -+ switch (ctrl->bRequest) { -+ case VEN_CORE_GET_FEATURES: -+ retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN); -+ if (retval >= 0) { -+ //dump_msg(cfi->buf_in.buf, retval); -+ ep = &pcd->ep0; -+ -+ retval = min((uint16_t) retval, wLen); -+ /* Transfer this buffer to the host through the EP0-IN EP */ -+ ep->dwc_ep.dma_addr = cfi->buf_in.addr; -+ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; -+ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; -+ ep->dwc_ep.xfer_len = retval; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; -+ -+ pcd->ep0_pending = 1; -+ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); -+ } -+ retval = 0; -+ break; -+ -+ case VEN_CORE_GET_FEATURE: -+ CFI_INFO("VEN_CORE_GET_FEATURE\n"); -+ retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN, -+ pcd, ctrl); -+ if (retval >= 0) { -+ ep = &pcd->ep0; -+ -+ retval = min((uint16_t) retval, wLen); -+ /* Transfer this buffer to the host through the EP0-IN EP */ -+ ep->dwc_ep.dma_addr = cfi->buf_in.addr; -+ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; -+ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; -+ ep->dwc_ep.xfer_len = retval; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; -+ -+ pcd->ep0_pending = 1; -+ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); -+ } -+ CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval); -+ dump_msg(cfi->buf_in.buf, retval); -+ break; -+ -+ case VEN_CORE_SET_FEATURE: -+ CFI_INFO("VEN_CORE_SET_FEATURE\n"); -+ /* Set up an XFER to get the data stage of the control request, -+ * which is the new value of the feature to be modified. -+ */ -+ ep = &pcd->ep0; -+ ep->dwc_ep.is_in = 0; -+ ep->dwc_ep.dma_addr = cfi->buf_out.addr; -+ ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf; -+ ep->dwc_ep.xfer_buff = cfi->buf_out.buf; -+ ep->dwc_ep.xfer_len = wLen; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; -+ -+ pcd->ep0_pending = 1; -+ /* Read the control write's data stage */ -+ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); -+ retval = 0; -+ break; -+ -+ case VEN_CORE_RESET_FEATURES: -+ CFI_INFO("VEN_CORE_RESET_FEATURES\n"); -+ cfi->need_gadget_att = 1; -+ cfi->need_status_in_complete = 1; -+ retval = cfi_preproc_reset(pcd, ctrl); -+ CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval); -+ break; -+ -+ case VEN_CORE_ACTIVATE_FEATURES: -+ CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n"); -+ break; -+ -+ case VEN_CORE_READ_REGISTER: -+ CFI_INFO("VEN_CORE_READ_REGISTER\n"); -+ /* wValue optionally contains the HI WORD of the register offset and -+ * wIndex contains the LOW WORD of the register offset -+ */ -+ if (wValue == 0) { -+ /* @TODO - MAS - fix the access to the base field */ -+ regaddr = 0; -+ //regaddr = (uint32_t) pcd->otg_dev->base; -+ //GET_CORE_IF(pcd)->co -+ regaddr |= wIndex; -+ } else { -+ regaddr = (wValue << 16) | wIndex; -+ } -+ -+ /* Read a 32-bit value of the memory at the regaddr */ -+ regval = dwc_read_reg32((uint32_t *) regaddr); -+ -+ ep = &pcd->ep0; -+ dwc_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t)); -+ ep->dwc_ep.is_in = 1; -+ ep->dwc_ep.dma_addr = cfi->buf_in.addr; -+ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; -+ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; -+ ep->dwc_ep.xfer_len = wLen; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; -+ -+ pcd->ep0_pending = 1; -+ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); -+ cfi->need_gadget_att = 0; -+ retval = 0; -+ break; -+ -+ case VEN_CORE_WRITE_REGISTER: -+ CFI_INFO("VEN_CORE_WRITE_REGISTER\n"); -+ /* Set up an XFER to get the data stage of the control request, -+ * which is the new value of the register to be modified. -+ */ -+ ep = &pcd->ep0; -+ ep->dwc_ep.is_in = 0; -+ ep->dwc_ep.dma_addr = cfi->buf_out.addr; -+ ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf; -+ ep->dwc_ep.xfer_buff = cfi->buf_out.buf; -+ ep->dwc_ep.xfer_len = wLen; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; -+ -+ pcd->ep0_pending = 1; -+ /* Read the control write's data stage */ -+ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); -+ retval = 0; -+ break; -+ -+ default: -+ retval = -DWC_E_NOT_SUPPORTED; -+ break; -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function prepares the core features descriptors and copies its -+ * raw representation into the buffer . -+ * -+ * The buffer structure is as follows: -+ * all_features_header (8 bytes) -+ * features_#1 (8 bytes + feature name string length) -+ * features_#2 (8 bytes + feature name string length) -+ * ..... -+ * features_#n - where n=the total count of feature descriptors -+ */ -+static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen) -+{ -+ cfi_feature_desc_header_t *prop_hdr = prop_descs; -+ cfi_feature_desc_header_t *prop; -+ cfi_all_features_header_t *all_props_hdr = &all_props_desc_header; -+ cfi_all_features_header_t *tmp; -+ uint8_t *tmpbuf = buf; -+ const uint8_t *pname = NULL; -+ int i, j, namelen = 0, totlen; -+ -+ /* Prepare and copy the core features into the buffer */ -+ CFI_INFO("%s:\n", __func__); -+ -+ tmp = (cfi_all_features_header_t *) tmpbuf; -+ *tmp = *all_props_hdr; -+ tmpbuf += CFI_ALL_FEATURES_HDR_LEN; -+ -+ j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t); -+ for (i = 0; i < j; i++, prop_hdr++) { -+ pname = get_prop_name(prop_hdr->wFeatureID, &namelen); -+ prop = (cfi_feature_desc_header_t *) tmpbuf; -+ *prop = *prop_hdr; -+ -+ prop->bNameLen = namelen; -+ prop->wLength = -+ DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN + -+ namelen); -+ -+ tmpbuf += CFI_FEATURE_DESC_HDR_LEN; -+ dwc_memcpy(tmpbuf, pname, namelen); -+ tmpbuf += namelen; -+ } -+ -+ totlen = tmpbuf - buf; -+ -+ if (totlen > 0) { -+ tmp = (cfi_all_features_header_t *) buf; -+ tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen); -+ } -+ -+ return totlen; -+} -+ -+/** -+ * This function releases all the dynamic memory in the CFI object. -+ */ -+static void cfi_release(cfiobject_t * cfiobj) -+{ -+ cfi_ep_t *cfiep; -+ dwc_list_link_t *tmp; -+ -+ CFI_INFO("%s\n", __func__); -+ -+ if (cfiobj->buf_in.buf) { -+ dwc_dma_free(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, -+ cfiobj->buf_in.addr); -+ cfiobj->buf_in.buf = NULL; -+ } -+ -+ if (cfiobj->buf_out.buf) { -+ dwc_dma_free(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, -+ cfiobj->buf_out.addr); -+ cfiobj->buf_out.buf = NULL; -+ } -+ -+ /* Free the Buffer Setup values for each EP */ -+ //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) { -+ DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) { -+ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); -+ cfi_free_ep_bs_dyn_data(cfiep); -+ } -+} -+ -+/** -+ * This function frees the dynamically allocated EP buffer setup data. -+ */ -+static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep) -+{ -+ if (cfiep->bm_sg) { -+ dwc_free(cfiep->bm_sg); -+ cfiep->bm_sg = NULL; -+ } -+ -+ if (cfiep->bm_align) { -+ dwc_free(cfiep->bm_align); -+ cfiep->bm_align = NULL; -+ } -+ -+ if (cfiep->bm_concat) { -+ if (NULL != cfiep->bm_concat->wTxBytes) { -+ dwc_free(cfiep->bm_concat->wTxBytes); -+ cfiep->bm_concat->wTxBytes = NULL; -+ } -+ dwc_free(cfiep->bm_concat); -+ cfiep->bm_concat = NULL; -+ } -+} -+ -+/** -+ * This function initializes the default values of the features -+ * for a specific endpoint and should be called only once when -+ * the EP is enabled first time. -+ */ -+static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep) -+{ -+ int retval = 0; -+ -+ cfiep->bm_sg = dwc_alloc(sizeof(ddma_sg_buffer_setup_t)); -+ if (NULL == cfiep->bm_sg) { -+ CFI_INFO("Failed to allocate memory for SG feature value\n"); -+ return -DWC_E_NO_MEMORY; -+ } -+ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); -+ -+ /* For the Concatenation feature's default value we do not allocate -+ * memory for the wTxBytes field - it will be done in the set_feature_value -+ * request handler. -+ */ -+ cfiep->bm_concat = dwc_alloc(sizeof(ddma_concat_buffer_setup_t)); -+ if (NULL == cfiep->bm_concat) { -+ CFI_INFO -+ ("Failed to allocate memory for CONCATENATION feature value\n"); -+ dwc_free(cfiep->bm_sg); -+ return -DWC_E_NO_MEMORY; -+ } -+ dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); -+ -+ cfiep->bm_align = dwc_alloc(sizeof(ddma_align_buffer_setup_t)); -+ if (NULL == cfiep->bm_align) { -+ CFI_INFO -+ ("Failed to allocate memory for Alignment feature value\n"); -+ dwc_free(cfiep->bm_sg); -+ dwc_free(cfiep->bm_concat); -+ return -DWC_E_NO_MEMORY; -+ } -+ dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t)); -+ -+ return retval; -+} -+ -+/** -+ * The callback function that notifies the CFI on the activation of -+ * an endpoint in the PCD. The following steps are done in this function: -+ * -+ * Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's -+ * active endpoint) -+ * Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP -+ * Set the Buffer Mode to standard -+ * Initialize the default values for all EP modes (SG, Circular, Concat, Align) -+ * Add the cfi_ep_t object to the list of active endpoints in the CFI object -+ */ -+static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, -+ struct dwc_otg_pcd_ep *ep) -+{ -+ cfi_ep_t *cfiep; -+ int retval = -DWC_E_NOT_SUPPORTED; -+ -+ CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__, -+ "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress); -+ /* MAS - Check whether this endpoint already is in the list */ -+ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); -+ -+ if (NULL == cfiep) { -+ /* Allocate a cfi_ep_t object */ -+ cfiep = dwc_alloc(sizeof(cfi_ep_t)); -+ if (NULL == cfiep) { -+ CFI_INFO -+ ("Unable to allocate memory for in function %s\n", -+ __func__); -+ return -DWC_E_NO_MEMORY; -+ } -+ dwc_memset(cfiep, 0, sizeof(cfi_ep_t)); -+ -+ /* Save the dwc_otg_pcd_ep pointer in the cfiep object */ -+ cfiep->ep = ep; -+ -+ /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */ -+ ep->dwc_ep.descs = -+ dwc_dma_alloc(MAX_DMA_DESCS_PER_EP * -+ sizeof(dwc_otg_dma_desc_t), -+ &ep->dwc_ep.descs_dma_addr); -+ -+ if (NULL == ep->dwc_ep.descs) { -+ dwc_free(cfiep); -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ DWC_LIST_INIT(&cfiep->lh); -+ -+ /* Set the buffer mode to BM_STANDARD. It will be modified -+ * when building descriptors for a specific buffer mode */ -+ ep->dwc_ep.buff_mode = BM_STANDARD; -+ -+ /* Create and initialize the default values for this EP's Buffer modes */ -+ if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0) -+ return retval; -+ -+ /* Add the cfi_ep_t object to the CFI object's list of active endpoints */ -+ DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh); -+ retval = 0; -+ } else { /* The sought EP already is in the list */ -+ CFI_INFO("%s: The sought EP already is in the list\n", -+ __func__); -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function is called when the data stage of a 3-stage Control Write request -+ * is complete. -+ * -+ */ -+static int cfi_ctrl_write_complete(struct cfiobject *cfi, -+ struct dwc_otg_pcd *pcd) -+{ -+ uint32_t addr, reg_value; -+ uint16_t wIndex, wValue; -+ uint8_t bRequest; -+ uint8_t *buf = cfi->buf_out.buf; -+ //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved; -+ struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req; -+ int retval = -DWC_E_NOT_SUPPORTED; -+ -+ CFI_INFO("%s\n", __func__); -+ -+ bRequest = ctrl_req->bRequest; -+ wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); -+ wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); -+ -+ /* -+ * Save the pointer to the data stage in the ctrl_req's field. -+ * The request should be already saved in the command stage by now. -+ */ -+ ctrl_req->data = cfi->buf_out.buf; -+ cfi->need_status_in_complete = 0; -+ cfi->need_gadget_att = 0; -+ -+ switch (bRequest) { -+ case VEN_CORE_WRITE_REGISTER: -+ /* The buffer contains raw data of the new value for the register */ -+ reg_value = *((uint32_t *) buf); -+ if (wValue == 0) { -+ addr = 0; -+ //addr = (uint32_t) pcd->otg_dev->base; -+ addr += wIndex; -+ } else { -+ addr = (wValue << 16) | wIndex; -+ } -+ -+ //writel(reg_value, addr); -+ -+ retval = 0; -+ cfi->need_status_in_complete = 1; -+ break; -+ -+ case VEN_CORE_SET_FEATURE: -+ /* The buffer contains raw data of the new value of the feature */ -+ retval = cfi_set_feature_value(pcd); -+ if (retval < 0) -+ return retval; -+ -+ cfi->need_status_in_complete = 1; -+ break; -+ -+ default: -+ break; -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function builds the DMA descriptors for the SG buffer mode. -+ */ -+static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, -+ dwc_otg_pcd_request_t * req) -+{ -+ struct dwc_otg_pcd_ep *ep = cfiep->ep; -+ ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg; -+ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; -+ struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs; -+ dma_addr_t buff_addr = req->dma; -+ int i; -+ uint32_t txsize, off; -+ -+ txsize = sgval->wSize; -+ off = sgval->bOffset; -+ -+// CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", -+// __func__, cfiep->ep->ep.name, txsize, off); -+ -+ for (i = 0; i < sgval->bCount; i++) { -+ desc->status.b.bs = BS_HOST_BUSY; -+ desc->buf = buff_addr; -+ desc->status.b.l = 0; -+ desc->status.b.ioc = 0; -+ desc->status.b.sp = 0; -+ desc->status.b.bytes = txsize; -+ desc->status.b.bs = BS_HOST_READY; -+ -+ /* Set the next address of the buffer */ -+ buff_addr += txsize + off; -+ desc_last = desc; -+ desc++; -+ } -+ -+ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ -+ desc_last->status.b.l = 1; -+ desc_last->status.b.ioc = 1; -+ desc_last->status.b.sp = ep->dwc_ep.sent_zlp; -+ /* Save the last DMA descriptor pointer */ -+ cfiep->dma_desc_last = desc_last; -+ cfiep->desc_count = sgval->bCount; -+} -+ -+/** -+ * This function builds the DMA descriptors for the Concatenation buffer mode. -+ */ -+static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, -+ dwc_otg_pcd_request_t * req) -+{ -+ struct dwc_otg_pcd_ep *ep = cfiep->ep; -+ ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat; -+ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; -+ struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs; -+ dma_addr_t buff_addr = req->dma; -+ int i; -+ uint16_t *txsize; -+ -+ txsize = concatval->wTxBytes; -+ -+ for (i = 0; i < concatval->hdr.bDescCount; i++) { -+ desc->buf = buff_addr; -+ desc->status.b.bs = BS_HOST_BUSY; -+ desc->status.b.l = 0; -+ desc->status.b.ioc = 0; -+ desc->status.b.sp = 0; -+ desc->status.b.bytes = *txsize; -+ desc->status.b.bs = BS_HOST_READY; -+ -+ txsize++; -+ /* Set the next address of the buffer */ -+ buff_addr += UGETW(ep->desc->wMaxPacketSize); -+ desc_last = desc; -+ desc++; -+ } -+ -+ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ -+ desc_last->status.b.l = 1; -+ desc_last->status.b.ioc = 1; -+ desc_last->status.b.sp = ep->dwc_ep.sent_zlp; -+ cfiep->dma_desc_last = desc_last; -+ cfiep->desc_count = concatval->hdr.bDescCount; -+} -+ -+/** -+ * This function builds the DMA descriptors for the Circular buffer mode -+ */ -+static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, -+ dwc_otg_pcd_request_t * req) -+{ -+ /* @todo: MAS - add implementation when this feature needs to be tested */ -+} -+ -+/** -+ * This function builds the DMA descriptors for the Alignment buffer mode -+ */ -+static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, -+ dwc_otg_pcd_request_t * req) -+{ -+ struct dwc_otg_pcd_ep *ep = cfiep->ep; -+ ddma_align_buffer_setup_t *alignval = cfiep->bm_align; -+ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; -+ dma_addr_t buff_addr = req->dma; -+ -+ desc->status.b.bs = BS_HOST_BUSY; -+ desc->status.b.l = 1; -+ desc->status.b.ioc = 1; -+ desc->status.b.sp = ep->dwc_ep.sent_zlp; -+ desc->status.b.bytes = req->length; -+ /* Adjust the buffer alignment */ -+ desc->buf = (buff_addr + alignval->bAlign); -+ desc->status.b.bs = BS_HOST_READY; -+ cfiep->dma_desc_last = desc; -+ cfiep->desc_count = 1; -+} -+ -+/** -+ * This function builds the DMA descriptors chain for different modes of the -+ * buffer setup of an endpoint. -+ */ -+static void cfi_build_descriptors(struct cfiobject *cfi, -+ struct dwc_otg_pcd *pcd, -+ struct dwc_otg_pcd_ep *ep, -+ dwc_otg_pcd_request_t * req) -+{ -+ cfi_ep_t *cfiep; -+ -+ /* Get the cfiep by the dwc_otg_pcd_ep */ -+ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); -+ if (NULL == cfiep) { -+ CFI_INFO("%s: Unable to find a matching active endpoint\n", -+ __func__); -+ return; -+ } -+ -+ cfiep->xfer_len = req->length; -+ -+ /* Iterate through all the DMA descriptors */ -+ switch (cfiep->ep->dwc_ep.buff_mode) { -+ case BM_SG: -+ cfi_build_sg_descs(cfi, cfiep, req); -+ break; -+ -+ case BM_CONCAT: -+ cfi_build_concat_descs(cfi, cfiep, req); -+ break; -+ -+ case BM_CIRCULAR: -+ cfi_build_circ_descs(cfi, cfiep, req); -+ break; -+ -+ case BM_ALIGN: -+ cfi_build_align_descs(cfi, cfiep, req); -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+/** -+ * Allocate DMA buffer for different Buffer modes. -+ */ -+static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, -+ struct dwc_otg_pcd_ep *ep, dma_addr_t * dma, -+ unsigned size, gfp_t flags) -+{ -+ return dwc_dma_alloc(size, dma); -+} -+ -+/** -+ * This function initializes the CFI object. -+ */ -+int init_cfi(cfiobject_t * cfiobj) -+{ -+ CFI_INFO("%s\n", __func__); -+ -+ /* Allocate a buffer for IN XFERs */ -+ cfiobj->buf_in.buf = -+ dwc_dma_alloc(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); -+ if (NULL == cfiobj->buf_in.buf) { -+ CFI_INFO("Unable to allocate buffer for INs\n"); -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ /* Allocate a buffer for OUT XFERs */ -+ cfiobj->buf_out.buf = -+ dwc_dma_alloc(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); -+ if (NULL == cfiobj->buf_out.buf) { -+ CFI_INFO("Unable to allocate buffer for OUT\n"); -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ /* Initialize the callback function pointers */ -+ cfiobj->ops.release = cfi_release; -+ cfiobj->ops.ep_enable = cfi_ep_enable; -+ cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete; -+ cfiobj->ops.build_descriptors = cfi_build_descriptors; -+ cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf; -+ -+ /* Initialize the list of active endpoints in the CFI object */ -+ DWC_LIST_INIT(&cfiobj->active_eps); -+ -+ return 0; -+} -+ -+/** -+ * This function reads the required feature's current value into the buffer -+ * -+ * @retval: Returns negative as error, or the data length of the feature -+ */ -+static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, -+ struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *ctrl_req) -+{ -+ int retval = -DWC_E_NOT_SUPPORTED; -+ struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd); -+ uint16_t dfifo, rxfifo, txfifo; -+ -+ switch (ctrl_req->wIndex) { -+ /* Whether the DDMA is enabled or not */ -+ case FT_ID_DMA_MODE: -+ *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0; -+ retval = 1; -+ break; -+ -+ case FT_ID_DMA_BUFFER_SETUP: -+ retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req); -+ break; -+ -+ case FT_ID_DMA_BUFF_ALIGN: -+ retval = cfi_ep_get_align_val(buf, pcd, ctrl_req); -+ break; -+ -+ case FT_ID_DMA_CONCAT_SETUP: -+ retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req); -+ break; -+ -+ case FT_ID_DMA_CIRCULAR: -+ CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n"); -+ break; -+ -+ case FT_ID_THRESHOLD_SETUP: -+ CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n"); -+ break; -+ -+ case FT_ID_DFIFO_DEPTH: -+ dfifo = get_dfifo_size(coreif); -+ *((uint16_t *) buf) = dfifo; -+ retval = sizeof(uint16_t); -+ break; -+ -+ case FT_ID_TX_FIFO_DEPTH: -+ retval = get_txfifo_size(pcd, ctrl_req->wValue); -+ if (retval >= 0) { -+ txfifo = retval; -+ *((uint16_t *) buf) = txfifo; -+ retval = sizeof(uint16_t); -+ } -+ break; -+ -+ case FT_ID_RX_FIFO_DEPTH: -+ retval = get_rxfifo_size(coreif, ctrl_req->wValue); -+ if (retval >= 0) { -+ rxfifo = retval; -+ *((uint16_t *) buf) = rxfifo; -+ retval = sizeof(uint16_t); -+ } -+ break; -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function resets the SG for the specified EP to its default value -+ */ -+static int cfi_reset_sg_val(cfi_ep_t * cfiep) -+{ -+ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); -+ return 0; -+} -+ -+/** -+ * This function resets the Alignment for the specified EP to its default value -+ */ -+static int cfi_reset_align_val(cfi_ep_t * cfiep) -+{ -+ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); -+ return 0; -+} -+ -+/** -+ * This function resets the Concatenation for the specified EP to its default value -+ * This function will also set the value of the wTxBytes field to NULL after -+ * freeing the memory previously allocated for this field. -+ */ -+static int cfi_reset_concat_val(cfi_ep_t * cfiep) -+{ -+ /* First we need to free the wTxBytes field */ -+ if (cfiep->bm_concat->wTxBytes) { -+ dwc_free(cfiep->bm_concat->wTxBytes); -+ cfiep->bm_concat->wTxBytes = NULL; -+ } -+ -+ dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); -+ return 0; -+} -+ -+/** -+ * This function resets all the buffer setups of the specified endpoint -+ */ -+static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep) -+{ -+ cfi_reset_sg_val(cfiep); -+ cfi_reset_align_val(cfiep); -+ cfi_reset_concat_val(cfiep); -+ return 0; -+} -+ -+static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr, -+ uint8_t rx_rst, uint8_t tx_rst) -+{ -+ int retval = -DWC_E_INVALID; -+ uint16_t tx_siz[15]; -+ uint16_t rx_siz = 0; -+ dwc_otg_pcd_ep_t *ep = NULL; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; -+ -+ if (rx_rst) { -+ rx_siz = params->dev_rx_fifo_size; -+ params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz; -+ } -+ -+ if (tx_rst) { -+ if (ep_addr == 0) { -+ int i; -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ tx_siz[i] = -+ core_if->core_params->dev_tx_fifo_size[i]; -+ core_if->core_params->dev_tx_fifo_size[i] = -+ core_if->init_txfsiz[i]; -+ } -+ } else { -+ -+ ep = get_ep_by_addr(pcd, ep_addr); -+ -+ if (NULL == ep) { -+ CFI_INFO -+ ("%s: Unable to get the endpoint addr=0x%02x\n", -+ __func__, ep_addr); -+ return -DWC_E_INVALID; -+ } -+ -+ tx_siz[0] = -+ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - -+ 1]; -+ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = -+ GET_CORE_IF(pcd)->init_txfsiz[ep->dwc_ep. -+ tx_fifo_num - 1]; -+ } -+ } -+ -+ if (resize_fifos(GET_CORE_IF(pcd))) { -+ retval = 0; -+ } else { -+ CFI_INFO -+ ("%s: Error resetting the feature Reset All(FIFO size)\n", -+ __func__); -+ if (rx_rst) { -+ params->dev_rx_fifo_size = rx_siz; -+ } -+ -+ if (tx_rst) { -+ if (ep_addr == 0) { -+ int i; -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; -+ i++) { -+ core_if->core_params-> -+ dev_tx_fifo_size[i] = tx_siz[i]; -+ } -+ } else { -+ params->dev_tx_fifo_size[ep->dwc_ep. -+ tx_fifo_num - 1] = -+ tx_siz[0]; -+ } -+ } -+ retval = -DWC_E_INVALID; -+ } -+ return retval; -+} -+ -+static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr) -+{ -+ int retval = 0; -+ cfi_ep_t *cfiep; -+ cfiobject_t *cfi = pcd->cfi; -+ dwc_list_link_t *tmp; -+ -+ retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1); -+ if (retval < 0) { -+ return retval; -+ } -+ -+ /* If the EP address is known then reset the features for only that EP */ -+ if (addr) { -+ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ if (NULL == cfiep) { -+ CFI_INFO("%s: Error getting the EP address 0x%02x\n", -+ __func__, addr); -+ return -DWC_E_INVALID; -+ } -+ retval = cfi_ep_reset_all_setup_vals(cfiep); -+ cfiep->ep->dwc_ep.buff_mode = BM_STANDARD; -+ } -+ /* Otherwise (wValue == 0), reset all features of all EP's */ -+ else { -+ /* Traverse all the active EP's and reset the feature(s) value(s) */ -+ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { -+ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { -+ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); -+ retval = cfi_ep_reset_all_setup_vals(cfiep); -+ cfiep->ep->dwc_ep.buff_mode = BM_STANDARD; -+ if (retval < 0) { -+ CFI_INFO -+ ("%s: Error resetting the feature Reset All\n", -+ __func__); -+ return retval; -+ } -+ } -+ } -+ return retval; -+} -+ -+static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd, -+ uint8_t addr) -+{ -+ int retval = 0; -+ cfi_ep_t *cfiep; -+ cfiobject_t *cfi = pcd->cfi; -+ dwc_list_link_t *tmp; -+ -+ /* If the EP address is known then reset the features for only that EP */ -+ if (addr) { -+ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ if (NULL == cfiep) { -+ CFI_INFO("%s: Error getting the EP address 0x%02x\n", -+ __func__, addr); -+ return -DWC_E_INVALID; -+ } -+ retval = cfi_reset_sg_val(cfiep); -+ } -+ /* Otherwise (wValue == 0), reset all features of all EP's */ -+ else { -+ /* Traverse all the active EP's and reset the feature(s) value(s) */ -+ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { -+ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { -+ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); -+ retval = cfi_reset_sg_val(cfiep); -+ if (retval < 0) { -+ CFI_INFO -+ ("%s: Error resetting the feature Buffer Setup\n", -+ __func__); -+ return retval; -+ } -+ } -+ } -+ return retval; -+} -+ -+static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr) -+{ -+ int retval = 0; -+ cfi_ep_t *cfiep; -+ cfiobject_t *cfi = pcd->cfi; -+ dwc_list_link_t *tmp; -+ -+ /* If the EP address is known then reset the features for only that EP */ -+ if (addr) { -+ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ if (NULL == cfiep) { -+ CFI_INFO("%s: Error getting the EP address 0x%02x\n", -+ __func__, addr); -+ return -DWC_E_INVALID; -+ } -+ retval = cfi_reset_concat_val(cfiep); -+ } -+ /* Otherwise (wValue == 0), reset all features of all EP's */ -+ else { -+ /* Traverse all the active EP's and reset the feature(s) value(s) */ -+ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { -+ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { -+ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); -+ retval = cfi_reset_concat_val(cfiep); -+ if (retval < 0) { -+ CFI_INFO -+ ("%s: Error resetting the feature Concatenation Value\n", -+ __func__); -+ return retval; -+ } -+ } -+ } -+ return retval; -+} -+ -+static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr) -+{ -+ int retval = 0; -+ cfi_ep_t *cfiep; -+ cfiobject_t *cfi = pcd->cfi; -+ dwc_list_link_t *tmp; -+ -+ /* If the EP address is known then reset the features for only that EP */ -+ if (addr) { -+ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ if (NULL == cfiep) { -+ CFI_INFO("%s: Error getting the EP address 0x%02x\n", -+ __func__, addr); -+ return -DWC_E_INVALID; -+ } -+ retval = cfi_reset_align_val(cfiep); -+ } -+ /* Otherwise (wValue == 0), reset all features of all EP's */ -+ else { -+ /* Traverse all the active EP's and reset the feature(s) value(s) */ -+ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { -+ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { -+ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); -+ retval = cfi_reset_align_val(cfiep); -+ if (retval < 0) { -+ CFI_INFO -+ ("%s: Error resetting the feature Aliignment Value\n", -+ __func__); -+ return retval; -+ } -+ } -+ } -+ return retval; -+ -+} -+ -+static int cfi_preproc_reset(struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *req) -+{ -+ int retval = 0; -+ -+ switch (req->wIndex) { -+ case 0: -+ /* Reset all features */ -+ retval = cfi_handle_reset_all(pcd, req->wValue & 0xff); -+ break; -+ -+ case FT_ID_DMA_BUFFER_SETUP: -+ /* Reset the SG buffer setup */ -+ retval = -+ cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff); -+ break; -+ -+ case FT_ID_DMA_CONCAT_SETUP: -+ /* Reset the Concatenation buffer setup */ -+ retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff); -+ break; -+ -+ case FT_ID_DMA_BUFF_ALIGN: -+ /* Reset the Alignment buffer setup */ -+ retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff); -+ break; -+ -+ case FT_ID_TX_FIFO_DEPTH: -+ retval = -+ cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1); -+ pcd->cfi->need_gadget_att = 0; -+ break; -+ -+ case FT_ID_RX_FIFO_DEPTH: -+ retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0); -+ pcd->cfi->need_gadget_att = 0; -+ break; -+ default: -+ break; -+ } -+ return retval; -+} -+ -+/** -+ * This function sets a new value for the SG buffer setup. -+ */ -+static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd) -+{ -+ uint8_t inaddr, outaddr; -+ cfi_ep_t *epin, *epout; -+ ddma_sg_buffer_setup_t *psgval; -+ uint32_t desccount, size; -+ -+ CFI_INFO("%s\n", __func__); -+ -+ psgval = (ddma_sg_buffer_setup_t *) buf; -+ desccount = (uint32_t) psgval->bCount; -+ size = (uint32_t) psgval->wSize; -+ -+ /* Check the DMA descriptor count */ -+ if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) { -+ CFI_INFO -+ ("%s: The count of DMA Descriptors should be between 1 and %d\n", -+ __func__, MAX_DMA_DESCS_PER_EP); -+ return -DWC_E_INVALID; -+ } -+ -+ /* Check the DMA descriptor count */ -+ -+ if (size == 0) { -+ -+ CFI_INFO("%s: The transfer size should be at least 1 byte\n", -+ __func__); -+ -+ return -DWC_E_INVALID; -+ -+ } -+ -+ inaddr = psgval->bInEndpointAddress; -+ outaddr = psgval->bOutEndpointAddress; -+ -+ epin = get_cfi_ep_by_addr(pcd->cfi, inaddr); -+ epout = get_cfi_ep_by_addr(pcd->cfi, outaddr); -+ -+ if (NULL == epin || NULL == epout) { -+ CFI_INFO -+ ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n", -+ __func__, inaddr, outaddr); -+ return -DWC_E_INVALID; -+ } -+ -+ epin->ep->dwc_ep.buff_mode = BM_SG; -+ dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); -+ -+ epout->ep->dwc_ep.buff_mode = BM_SG; -+ dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); -+ -+ return 0; -+} -+ -+/** -+ * This function sets a new value for the buffer Alignment setup. -+ */ -+static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd) -+{ -+ cfi_ep_t *ep; -+ uint8_t addr; -+ ddma_align_buffer_setup_t *palignval; -+ -+ palignval = (ddma_align_buffer_setup_t *) buf; -+ addr = palignval->bEndpointAddress; -+ -+ ep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ -+ if (NULL == ep) { -+ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", -+ __func__, addr); -+ return -DWC_E_INVALID; -+ } -+ -+ ep->ep->dwc_ep.buff_mode = BM_ALIGN; -+ dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t)); -+ -+ return 0; -+} -+ -+/** -+ * This function sets a new value for the Concatenation buffer setup. -+ */ -+static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd) -+{ -+ uint8_t addr; -+ cfi_ep_t *ep; -+ struct _ddma_concat_buffer_setup_hdr *pConcatValHdr; -+ uint16_t *pVals; -+ uint32_t desccount; -+ int i; -+ uint16_t mps; -+ -+ pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf; -+ desccount = (uint32_t) pConcatValHdr->bDescCount; -+ pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN); -+ -+ /* Check the DMA descriptor count */ -+ if (desccount > MAX_DMA_DESCS_PER_EP) { -+ CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n", -+ __func__, MAX_DMA_DESCS_PER_EP); -+ return -DWC_E_INVALID; -+ } -+ -+ addr = pConcatValHdr->bEndpointAddress; -+ ep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ if (NULL == ep) { -+ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", -+ __func__, addr); -+ return -DWC_E_INVALID; -+ } -+ -+ mps = UGETW(ep->ep->desc->wMaxPacketSize); -+ -+#if 0 -+ for (i = 0; i < desccount; i++) { -+ CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]); -+ } -+ CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps); -+#endif -+ -+ /* Check the wTxSizes to be less than or equal to the mps */ -+ for (i = 0; i < desccount; i++) { -+ if (pVals[i] > mps) { -+ CFI_INFO -+ ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n", -+ __func__, i, pVals[i]); -+ return -DWC_E_INVALID; -+ } -+ } -+ -+ ep->ep->dwc_ep.buff_mode = BM_CONCAT; -+ dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN); -+ -+ /* Free the previously allocated storage for the wTxBytes */ -+ if (ep->bm_concat->wTxBytes) { -+ dwc_free(ep->bm_concat->wTxBytes); -+ } -+ -+ /* Allocate a new storage for the wTxBytes field */ -+ ep->bm_concat->wTxBytes = -+ dwc_alloc(sizeof(uint16_t) * pConcatValHdr->bDescCount); -+ if (NULL == ep->bm_concat->wTxBytes) { -+ CFI_INFO("%s: Unable to allocate memory\n", __func__); -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ /* Copy the new values into the wTxBytes filed */ -+ dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN, -+ sizeof(uint16_t) * pConcatValHdr->bDescCount); -+ -+ return 0; -+} -+ -+/** -+ * This function calculates the total of all FIFO sizes -+ * -+ * @param core_if Programming view of DWC_otg controller -+ * -+ * @return The total of data FIFO sizes. -+ * -+ */ -+static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if) -+{ -+ dwc_otg_core_params_t *params = core_if->core_params; -+ uint16_t dfifo_total = 0; -+ int i; -+ -+ /* The shared RxFIFO size */ -+ dfifo_total = -+ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; -+ -+ /* Add up each TxFIFO size to the total */ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ dfifo_total += params->dev_tx_fifo_size[i]; -+ } -+ -+ return dfifo_total; -+} -+ -+/** -+ * This function returns Rx FIFO size -+ * -+ * @param core_if Programming view of DWC_otg controller -+ * -+ * @return The total of data FIFO sizes. -+ * -+ */ -+static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue) -+{ -+ switch (wValue >> 8) { -+ case 0: -+ return (core_if->pwron_rxfsiz < -+ 32768) ? core_if->pwron_rxfsiz : 32768; -+ break; -+ case 1: -+ return core_if->core_params->dev_rx_fifo_size; -+ break; -+ default: -+ return -DWC_E_INVALID; -+ break; -+ } -+} -+ -+/** -+ * This function returns Tx FIFO size for IN EP -+ * -+ * @param core_if Programming view of DWC_otg controller -+ * -+ * @return The total of data FIFO sizes. -+ * -+ */ -+static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ -+ ep = get_ep_by_addr(pcd, wValue & 0xff); -+ -+ if (NULL == ep) { -+ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", -+ __func__, wValue & 0xff); -+ return -DWC_E_INVALID; -+ } -+ -+ if (!ep->dwc_ep.is_in) { -+ CFI_INFO -+ ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n", -+ __func__, wValue & 0xff); -+ return -DWC_E_INVALID; -+ } -+ -+ switch (wValue >> 8) { -+ case 0: -+ return (GET_CORE_IF(pcd)-> -+ pwron_txfsiz[ep->dwc_ep.tx_fifo_num - 1] < -+ 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->dwc_ep. -+ tx_fifo_num - -+ 1] : 32768; -+ break; -+ case 1: -+ return GET_CORE_IF(pcd)->core_params->dev_tx_fifo_size[ep-> -+ dwc_ep. -+ num - 1]; -+ break; -+ default: -+ return -DWC_E_INVALID; -+ break; -+ } -+} -+ -+/** -+ * This function checks if the submitted combination of -+ * device mode FIFO sizes is possible or not. -+ * -+ * @param core_if Programming view of DWC_otg controller -+ * -+ * @return 1 if possible, 0 otherwise. -+ * -+ */ -+static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if) -+{ -+ uint16_t dfifo_actual = 0; -+ dwc_otg_core_params_t *params = core_if->core_params; -+ uint16_t start_addr = 0; -+ int i; -+ -+ dfifo_actual = -+ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ dfifo_actual += params->dev_tx_fifo_size[i]; -+ } -+ -+ if (dfifo_actual > core_if->total_fifo_size) { -+ return 0; -+ } -+ -+ if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16) -+ return 0; -+ -+ if (params->dev_nperio_tx_fifo_size > 32768 -+ || params->dev_nperio_tx_fifo_size < 16) -+ return 0; -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ -+ if (params->dev_tx_fifo_size[i] > 768 -+ || params->dev_tx_fifo_size[i] < 4) -+ return 0; -+ } -+ -+ if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz) -+ return 0; -+ start_addr = params->dev_rx_fifo_size; -+ -+ if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz) -+ return 0; -+ start_addr += params->dev_nperio_tx_fifo_size; -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ -+ if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i]) -+ return 0; -+ start_addr += params->dev_tx_fifo_size[i]; -+ } -+ -+ return 1; -+} -+ -+/** -+ * This function resizes Device mode FIFOs -+ * -+ * @param core_if Programming view of DWC_otg controller -+ * -+ * @return 1 if successful, 0 otherwise -+ * -+ */ -+static uint8_t resize_fifos(dwc_otg_core_if_t * core_if) -+{ -+ int i = 0; -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ dwc_otg_core_params_t *params = core_if->core_params; -+ uint32_t rx_fifo_size; -+ fifosize_data_t nptxfifosize; -+ fifosize_data_t txfifosize[15]; -+ -+ uint32_t rx_fsz_bak; -+ uint32_t nptxfsz_bak; -+ uint32_t txfsz_bak[15]; -+ -+ uint16_t start_address; -+ uint8_t retval = 1; -+ -+ if (!check_fifo_sizes(core_if)) { -+ return 0; -+ } -+ -+ /* Configure data FIFO sizes */ -+ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { -+ rx_fsz_bak = dwc_read_reg32(&global_regs->grxfsiz); -+ rx_fifo_size = params->dev_rx_fifo_size; -+ dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size); -+ -+ /* -+ * Tx FIFOs These FIFOs are numbered from 1 to 15. -+ * Indexes of the FIFO size module parameters in the -+ * dev_tx_fifo_size array and the FIFO size registers in -+ * the dptxfsiz_dieptxf array run from 0 to 14. -+ */ -+ -+ /* Non-periodic Tx FIFO */ -+ nptxfsz_bak = dwc_read_reg32(&global_regs->gnptxfsiz); -+ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; -+ start_address = params->dev_rx_fifo_size; -+ nptxfifosize.b.startaddr = start_address; -+ -+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32); -+ -+ start_address += nptxfifosize.b.depth; -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ txfsz_bak[i] = -+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]); -+ -+ txfifosize[i].b.depth = params->dev_tx_fifo_size[i]; -+ txfifosize[i].b.startaddr = start_address; -+ dwc_write_reg32(&global_regs->dptxfsiz_dieptxf[i], -+ txfifosize[i].d32); -+ -+ start_address += txfifosize[i].b.depth; -+ } -+ -+ /** Check if register values are set correctly */ -+ if (rx_fifo_size != dwc_read_reg32(&global_regs->grxfsiz)) { -+ retval = 0; -+ } -+ -+ if (nptxfifosize.d32 != dwc_read_reg32(&global_regs->gnptxfsiz)) { -+ retval = 0; -+ } -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ if (txfifosize[i].d32 != -+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i])) { -+ retval = 0; -+ } -+ } -+ -+ /** If register values are not set correctly, reset old values */ -+ if (retval == 0) { -+ dwc_write_reg32(&global_regs->grxfsiz, rx_fsz_bak); -+ -+ /* Non-periodic Tx FIFO */ -+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfsz_bak); -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ dwc_write_reg32(&global_regs-> -+ dptxfsiz_dieptxf[i], -+ txfsz_bak[i]); -+ } -+ } -+ } else { -+ return 0; -+ } -+ -+ /* Flush the FIFOs */ -+ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ -+ dwc_otg_flush_rx_fifo(core_if); -+ -+ return retval; -+} -+ -+/** -+ * This function sets a new value for the buffer Alignment setup. -+ */ -+static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd) -+{ -+ int retval; -+ uint32_t fsiz; -+ uint16_t size; -+ uint16_t ep_addr; -+ dwc_otg_pcd_ep_t *ep; -+ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; -+ tx_fifo_size_setup_t *ptxfifoval; -+ -+ ptxfifoval = (tx_fifo_size_setup_t *) buf; -+ ep_addr = ptxfifoval->bEndpointAddress; -+ size = ptxfifoval->wDepth; -+ -+ ep = get_ep_by_addr(pcd, ep_addr); -+ -+ CFI_INFO -+ ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n", -+ __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num); -+ -+ if (NULL == ep) { -+ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", -+ __func__, ep_addr); -+ return -DWC_E_INVALID; -+ } -+ -+ fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1]; -+ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size; -+ -+ if (resize_fifos(GET_CORE_IF(pcd))) { -+ retval = 0; -+ } else { -+ CFI_INFO -+ ("%s: Error setting the feature Tx FIFO Size for EP%d\n", -+ __func__, ep_addr); -+ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz; -+ retval = -DWC_E_INVALID; -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function sets a new value for the buffer Alignment setup. -+ */ -+static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd) -+{ -+ int retval; -+ uint32_t fsiz; -+ uint16_t size; -+ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; -+ rx_fifo_size_setup_t *prxfifoval; -+ -+ prxfifoval = (rx_fifo_size_setup_t *) buf; -+ size = prxfifoval->wDepth; -+ -+ fsiz = params->dev_rx_fifo_size; -+ params->dev_rx_fifo_size = size; -+ -+ if (resize_fifos(GET_CORE_IF(pcd))) { -+ retval = 0; -+ } else { -+ CFI_INFO("%s: Error setting the feature Rx FIFO Size\n", -+ __func__); -+ params->dev_rx_fifo_size = fsiz; -+ retval = -DWC_E_INVALID; -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function reads the SG of an EP's buffer setup into the buffer buf -+ */ -+static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *req) -+{ -+ int retval = -DWC_E_INVALID; -+ uint8_t addr; -+ cfi_ep_t *ep; -+ -+ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ -+ addr = req->wValue & 0xFF; -+ if (addr == 0) /* The address should be non-zero */ -+ return retval; -+ -+ ep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ if (NULL == ep) { -+ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", -+ __func__, addr); -+ return retval; -+ } -+ -+ dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN); -+ retval = BS_SG_VAL_DESC_LEN; -+ return retval; -+} -+ -+/** -+ * This function reads the Concatenation value of an EP's buffer mode into -+ * the buffer buf -+ */ -+static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *req) -+{ -+ int retval = -DWC_E_INVALID; -+ uint8_t addr; -+ cfi_ep_t *ep; -+ uint8_t desc_count; -+ -+ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ -+ addr = req->wValue & 0xFF; -+ if (addr == 0) /* The address should be non-zero */ -+ return retval; -+ -+ ep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ if (NULL == ep) { -+ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", -+ __func__, addr); -+ return retval; -+ } -+ -+ /* Copy the header to the buffer */ -+ dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN); -+ /* Advance the buffer pointer by the header size */ -+ buf += BS_CONCAT_VAL_HDR_LEN; -+ -+ desc_count = ep->bm_concat->hdr.bDescCount; -+ /* Copy alll the wTxBytes to the buffer */ -+ dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count); -+ -+ retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count; -+ return retval; -+} -+ -+/** -+ * This function reads the buffer Alignment value of an EP's buffer mode into -+ * the buffer buf -+ * -+ * @return The total number of bytes copied to the buffer or negative error code. -+ */ -+static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd, -+ struct cfi_usb_ctrlrequest *req) -+{ -+ int retval = -DWC_E_INVALID; -+ uint8_t addr; -+ cfi_ep_t *ep; -+ -+ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ -+ addr = req->wValue & 0xFF; -+ if (addr == 0) /* The address should be non-zero */ -+ return retval; -+ -+ ep = get_cfi_ep_by_addr(pcd->cfi, addr); -+ if (NULL == ep) { -+ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", -+ __func__, addr); -+ return retval; -+ } -+ -+ dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN); -+ retval = BS_ALIGN_VAL_HDR_LEN; -+ -+ return retval; -+} -+ -+/** -+ * This function sets a new value for the specified feature -+ * -+ * @param pcd A pointer to the PCD object -+ * -+ * @return 0 if successful, negative error code otherwise to stall the DCE. -+ */ -+static int cfi_set_feature_value(struct dwc_otg_pcd *pcd) -+{ -+ int retval = -DWC_E_NOT_SUPPORTED; -+ uint16_t wIndex, wValue; -+ uint8_t bRequest; -+ struct dwc_otg_core_if *coreif; -+ cfiobject_t *cfi = pcd->cfi; -+ struct cfi_usb_ctrlrequest *ctrl_req; -+ uint8_t *buf; -+ ctrl_req = &cfi->ctrl_req; -+ -+ buf = pcd->cfi->ctrl_req.data; -+ -+ coreif = GET_CORE_IF(pcd); -+ bRequest = ctrl_req->bRequest; -+ wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); -+ wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); -+ -+ /* See which feature is to be modified */ -+ switch (wIndex) { -+ case FT_ID_DMA_BUFFER_SETUP: -+ /* Modify the feature */ -+ if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0) -+ return retval; -+ -+ /* And send this request to the gadget */ -+ cfi->need_gadget_att = 1; -+ break; -+ -+ case FT_ID_DMA_BUFF_ALIGN: -+ if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0) -+ return retval; -+ cfi->need_gadget_att = 1; -+ break; -+ -+ case FT_ID_DMA_CONCAT_SETUP: -+ /* Modify the feature */ -+ if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0) -+ return retval; -+ cfi->need_gadget_att = 1; -+ break; -+ -+ case FT_ID_DMA_CIRCULAR: -+ CFI_INFO("FT_ID_DMA_CIRCULAR\n"); -+ break; -+ -+ case FT_ID_THRESHOLD_SETUP: -+ CFI_INFO("FT_ID_THRESHOLD_SETUP\n"); -+ break; -+ -+ case FT_ID_DFIFO_DEPTH: -+ CFI_INFO("FT_ID_DFIFO_DEPTH\n"); -+ break; -+ -+ case FT_ID_TX_FIFO_DEPTH: -+ CFI_INFO("FT_ID_TX_FIFO_DEPTH\n"); -+ if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0) -+ return retval; -+ cfi->need_gadget_att = 0; -+ break; -+ -+ case FT_ID_RX_FIFO_DEPTH: -+ CFI_INFO("FT_ID_RX_FIFO_DEPTH\n"); -+ if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0) -+ return retval; -+ cfi->need_gadget_att = 0; -+ break; -+ } -+ -+ return retval; -+} -+ -+#endif //DWC_UTE_CFI -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.h b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h -new file mode 100644 -index 0000000..0215224 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h -@@ -0,0 +1,319 @@ -+/* ========================================================================== -+ * 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. -+ * ========================================================================== */ -+ -+#if !defined(__DWC_OTG_CFI_H__) -+#define __DWC_OTG_CFI_H__ -+ -+#include "dwc_otg_pcd.h" -+#include "dwc_cfi_common.h" -+ -+/** -+ * @file -+ * -+ * This file contains the CFI related OTG PCD specific common constants, interfaces -+ * (functions and macros) and data structures. -+ * -+ */ -+ -+struct dwc_otg_pcd; -+struct dwc_otg_pcd_ep; -+ -+/** OTG CFI Features (properties) ID constants */ -+/** This is a request for all Core Features */ -+#define FT_ID_DMA_MODE 0x0001 -+#define FT_ID_DMA_BUFFER_SETUP 0x0002 -+#define FT_ID_DMA_BUFF_ALIGN 0x0003 -+#define FT_ID_DMA_CONCAT_SETUP 0x0004 -+#define FT_ID_DMA_CIRCULAR 0x0005 -+#define FT_ID_THRESHOLD_SETUP 0x0006 -+#define FT_ID_DFIFO_DEPTH 0x0007 -+#define FT_ID_TX_FIFO_DEPTH 0x0008 -+#define FT_ID_RX_FIFO_DEPTH 0x0009 -+ -+/**********************************************************/ -+#define CFI_INFO_DEF -+ -+#ifdef CFI_INFO_DEF -+#define CFI_INFO(fmt...) DWC_PRINTF("CFI: " fmt); -+#else -+#define CFI_INFO(fmt...) -+#endif -+ -+#define min(x,y) ({ \ -+ x < y ? x : y; }) -+ -+#define max(x,y) ({ \ -+ x > y ? x : y; }) -+ -+/** -+ * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is -+ * also used for setting up a buffer for Circular DDMA. -+ */ -+struct _ddma_sg_buffer_setup { -+#define BS_SG_VAL_DESC_LEN 6 -+ /* The OUT EP address */ -+ uint8_t bOutEndpointAddress; -+ /* The IN EP address */ -+ uint8_t bInEndpointAddress; -+ /* Number of bytes to put between transfer segments (must be DWORD boundaries) */ -+ uint8_t bOffset; -+ /* The number of transfer segments (a DMA descriptors per each segment) */ -+ uint8_t bCount; -+ /* Size (in byte) of each transfer segment */ -+ uint16_t wSize; -+} __attribute__ ((packed)); -+typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t; -+ -+/** Descriptor DMA Concatenation Buffer setup structure */ -+struct _ddma_concat_buffer_setup_hdr { -+#define BS_CONCAT_VAL_HDR_LEN 4 -+ /* The endpoint for which the buffer is to be set up */ -+ uint8_t bEndpointAddress; -+ /* The count of descriptors to be used */ -+ uint8_t bDescCount; -+ /* The total size of the transfer */ -+ uint16_t wSize; -+} __attribute__ ((packed)); -+typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t; -+ -+/** Descriptor DMA Concatenation Buffer setup structure */ -+struct _ddma_concat_buffer_setup { -+ /* The SG header */ -+ ddma_concat_buffer_setup_hdr_t hdr; -+ -+ /* The XFER sizes pointer (allocated dynamically) */ -+ uint16_t *wTxBytes; -+} __attribute__ ((packed)); -+typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t; -+ -+/** Descriptor DMA Alignment Buffer setup structure */ -+struct _ddma_align_buffer_setup { -+#define BS_ALIGN_VAL_HDR_LEN 2 -+ uint8_t bEndpointAddress; -+ uint8_t bAlign; -+} __attribute__ ((packed)); -+typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t; -+ -+/** Transmit FIFO Size setup structure */ -+struct _tx_fifo_size_setup { -+ uint8_t bEndpointAddress; -+ uint16_t wDepth; -+} __attribute__ ((packed)); -+typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t; -+ -+/** Transmit FIFO Size setup structure */ -+struct _rx_fifo_size_setup { -+ uint16_t wDepth; -+} __attribute__ ((packed)); -+typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t; -+ -+/** -+ * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest -+ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer -+ * to the data returned in the data stage of a 3-stage Control Write requests. -+ */ -+struct cfi_usb_ctrlrequest { -+ uint8_t bRequestType; -+ uint8_t bRequest; -+ uint16_t wValue; -+ uint16_t wIndex; -+ uint16_t wLength; -+ uint8_t *data; -+} UPACKED; -+ -+/*---------------------------------------------------------------------------*/ -+ -+/** -+ * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures. -+ * This structure is used to store the buffer setup data for any -+ * enabled endpoint in the PCD. -+ */ -+struct cfi_ep { -+ /* Entry for the list container */ -+ dwc_list_link_t lh; -+ /* Pointer to the active PCD endpoint structure */ -+ struct dwc_otg_pcd_ep *ep; -+ /* The last descriptor in the chain of DMA descriptors of the endpoint */ -+ struct dwc_otg_dma_desc *dma_desc_last; -+ /* The SG feature value */ -+ ddma_sg_buffer_setup_t *bm_sg; -+ /* The Circular feature value */ -+ ddma_sg_buffer_setup_t *bm_circ; -+ /* The Concatenation feature value */ -+ ddma_concat_buffer_setup_t *bm_concat; -+ /* The Alignment feature value */ -+ ddma_align_buffer_setup_t *bm_align; -+ /* XFER length */ -+ uint32_t xfer_len; -+ /* -+ * Count of DMA descriptors currently used. -+ * The total should not exceed the MAX_DMA_DESCS_PER_EP value -+ * defined in the dwc_otg_cil.h -+ */ -+ uint32_t desc_count; -+}; -+typedef struct cfi_ep cfi_ep_t; -+ -+typedef struct cfi_dma_buff { -+#define CFI_IN_BUF_LEN 1024 -+#define CFI_OUT_BUF_LEN 1024 -+ dma_addr_t addr; -+ uint8_t *buf; -+} cfi_dma_buff_t; -+ -+struct cfiobject; -+ -+/** -+ * This is the interface for the CFI operations. -+ * -+ * @param ep_enable Called when any endpoint is enabled and activated. -+ * @param release Called when the CFI object is released and it needs to correctly -+ * deallocate the dynamic memory -+ * @param ctrl_write_complete Called when the data stage of the request is complete -+ */ -+typedef struct cfi_ops { -+ int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, -+ struct dwc_otg_pcd_ep * ep); -+ void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, -+ struct dwc_otg_pcd_ep * ep, dma_addr_t * dma, -+ unsigned size, gfp_t flags); -+ void (*release) (struct cfiobject * cfi); -+ int (*ctrl_write_complete) (struct cfiobject * cfi, -+ struct dwc_otg_pcd * pcd); -+ void (*build_descriptors) (struct cfiobject * cfi, -+ struct dwc_otg_pcd * pcd, -+ struct dwc_otg_pcd_ep * ep, -+ dwc_otg_pcd_request_t * req); -+} cfi_ops_t; -+ -+struct cfiobject { -+ cfi_ops_t ops; -+ struct dwc_otg_pcd *pcd; -+ struct usb_gadget *gadget; -+ -+ /* Buffers used to send/receive CFI-related request data */ -+ cfi_dma_buff_t buf_in; -+ cfi_dma_buff_t buf_out; -+ -+ /* CFI specific Control request wrapper */ -+ struct cfi_usb_ctrlrequest ctrl_req; -+ -+ /* The list of active EP's in the PCD of type cfi_ep_t */ -+ dwc_list_link_t active_eps; -+ -+ /* This flag shall control the propagation of a specific request -+ * to the gadget's processing routines. -+ * 0 - no gadget handling -+ * 1 - the gadget needs to know about this request (w/o completing a status -+ * phase - just return a 0 to the _setup callback) -+ */ -+ uint8_t need_gadget_att; -+ -+ /* Flag indicating whether the status IN phase needs to be -+ * completed by the PCD -+ */ -+ uint8_t need_status_in_complete; -+}; -+typedef struct cfiobject cfiobject_t; -+ -+#define DUMP_MSG -+ -+#if defined(DUMP_MSG) -+static inline void dump_msg(const u8 * buf, unsigned int length) -+{ -+ unsigned int start, num, i; -+ char line[52], *p; -+ -+ if (length >= 512) -+ return; -+ -+ start = 0; -+ while (length > 0) { -+ num = min(length, 16u); -+ p = line; -+ for (i = 0; i < num; ++i) { -+ if (i == 8) -+ *p++ = ' '; -+ DWC_SPRINTF(p, " %02x", buf[i]); -+ p += 3; -+ } -+ *p = 0; -+ DWC_DEBUG("%6x: %s\n", start, line); -+ buf += num; -+ start += num; -+ length -= num; -+ } -+} -+#else -+static inline void dump_msg(const u8 * buf, unsigned int length) -+{ -+} -+#endif -+ -+/** -+ * This function returns a pointer to cfi_ep_t object with the addr address. -+ */ -+static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi, -+ uint8_t addr) -+{ -+ struct cfi_ep *pcfiep; -+ dwc_list_link_t *tmp; -+ -+ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { -+ pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); -+ -+ if (pcfiep->ep->desc->bEndpointAddress == addr) { -+ return pcfiep; -+ } -+ } -+ -+ return NULL; -+} -+ -+/** -+ * This function returns a pointer to cfi_ep_t object that matches -+ * the dwc_otg_pcd_ep object. -+ */ -+static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi, -+ struct dwc_otg_pcd_ep *ep) -+{ -+ struct cfi_ep *pcfiep = NULL; -+ dwc_list_link_t *tmp; -+ -+ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { -+ pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); -+ if (pcfiep->ep == ep) { -+ return pcfiep; -+ } -+ } -+ return NULL; -+} -+ -+int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); -+ -+#endif /* (__DWC_OTG_CFI_H__) */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -new file mode 100644 -index 0000000..ccfe6b5 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -@@ -0,0 +1,5410 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $ -+ * $Revision: #159 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237465 $ -+ * -+ * 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. -+ * ========================================================================== */ -+ -+/** @file -+ * -+ * The Core Interface Layer provides basic services for accessing and -+ * managing the DWC_otg hardware. These services are used by both the -+ * Host Controller Driver and the Peripheral Controller Driver. -+ * -+ * The CIL manages the memory map for the core so that the HCD and PCD -+ * don't have to do this separately. It also handles basic tasks like -+ * reading/writing the registers and data FIFOs in the controller. -+ * Some of the data access functions provide encapsulation of several -+ * operations required to perform a task, such as writing multiple -+ * registers to start a transfer. Finally, the CIL performs basic -+ * services that are not specific to either the host or device modes -+ * of operation. These services include management of the OTG Host -+ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A -+ * Diagnostic API is also provided to allow testing of the controller -+ * hardware. -+ * -+ * The Core Interface Layer has the following requirements: -+ * - Provides basic controller operations. -+ * - Minimal use of OS services. -+ * - The OS services used will be abstracted by using inline functions -+ * or macros. -+ * -+ */ -+ -+#include "dwc_os.h" -+#include "dwc_otg_regs.h" -+#include "dwc_otg_cil.h" -+ -+static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if); -+ -+/** -+ * This function is called to initialize the DWC_otg CSR data -+ * structures. The register addresses in the device and host -+ * structures are initialized from the base address supplied by the -+ * caller. The calling function must make the OS calls to get the -+ * base address of the DWC_otg controller registers. The core_params -+ * argument holds the parameters that specify how the core should be -+ * configured. -+ * -+ * @param reg_base_addr Base address of DWC_otg core registers -+ * -+ */ -+dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) -+{ -+ dwc_otg_core_if_t *core_if = 0; -+ dwc_otg_dev_if_t *dev_if = 0; -+ dwc_otg_host_if_t *host_if = 0; -+ uint8_t *reg_base = (uint8_t *) reg_base_addr; -+ int i = 0; -+ -+ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr); -+ -+ core_if = dwc_alloc(sizeof(dwc_otg_core_if_t)); -+ -+ if (core_if == 0) { -+ DWC_DEBUGPL(DBG_CIL, -+ "Allocation of dwc_otg_core_if_t failed\n"); -+ return 0; -+ } -+ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base; -+ -+ /* -+ * Allocate the Device Mode structures. -+ */ -+ dev_if = dwc_alloc(sizeof(dwc_otg_dev_if_t)); -+ -+ if (dev_if == 0) { -+ DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n"); -+ dwc_free(core_if); -+ return 0; -+ } -+ -+ dev_if->dev_global_regs = -+ (dwc_otg_device_global_regs_t *) (reg_base + -+ DWC_DEV_GLOBAL_REG_OFFSET); -+ -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *) -+ (reg_base + DWC_DEV_IN_EP_REG_OFFSET + -+ (i * DWC_EP_REG_OFFSET)); -+ -+ dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *) -+ (reg_base + DWC_DEV_OUT_EP_REG_OFFSET + -+ (i * DWC_EP_REG_OFFSET)); -+ DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n", -+ i, &dev_if->in_ep_regs[i]->diepctl); -+ DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n", -+ i, &dev_if->out_ep_regs[i]->doepctl); -+ } -+ -+ dev_if->speed = 0; // unknown -+ -+ core_if->dev_if = dev_if; -+ -+ /* -+ * Allocate the Host Mode structures. -+ */ -+ host_if = dwc_alloc(sizeof(dwc_otg_host_if_t)); -+ -+ if (host_if == 0) { -+ DWC_DEBUGPL(DBG_CIL, -+ "Allocation of dwc_otg_host_if_t failed\n"); -+ dwc_free(dev_if); -+ dwc_free(core_if); -+ return 0; -+ } -+ -+ 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)); -+ DWC_DEBUGPL(DBG_CILV, "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)); -+ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08x\n", -+ i, (unsigned)core_if->data_fifo[i]); -+ } -+ -+ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET); -+ -+ /* Initiate lx_state to L3 disconnected state */ -+ core_if->lx_state = DWC_OTG_L3; -+ /* -+ * 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); -+ -+ DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); -+ DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); -+ DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32); -+ DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); -+ -+ core_if->hcfg.d32 = -+ dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg); -+ core_if->dcfg.d32 = -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ -+ DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32); -+ DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32); -+ -+ DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode); -+ DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture); -+ DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep); -+ DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n", -+ core_if->hwcfg2.b.num_host_chan); -+ DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n", -+ core_if->hwcfg2.b.nonperio_tx_q_depth); -+ DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n", -+ core_if->hwcfg2.b.host_perio_tx_q_depth); -+ DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n", -+ core_if->hwcfg2.b.dev_token_q_depth); -+ -+ DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n", -+ core_if->hwcfg3.b.dfifo_depth); -+ DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n", -+ core_if->hwcfg3.b.xfer_size_cntr_width); -+ -+ /* -+ * Set the SRP sucess bit for FS-I2c -+ */ -+ core_if->srp_success = 0; -+ core_if->srp_timer_started = 0; -+ -+ /* -+ * Create new workqueue and init works -+ */ -+ core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg"); -+ if (core_if->wq_otg == 0) { -+ DWC_WARN("DWC_WORKQ_ALLOC failed\n"); -+ dwc_free(host_if); -+ dwc_free(dev_if); -+ dwc_free(core_if); -+ return 0; -+ } -+ -+ core_if->snpsid = dwc_read_reg32(&core_if->core_global_regs->gsnpsid); -+ -+ DWC_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)); -+ -+ core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer", -+ w_wakeup_detected, core_if); -+ if (core_if->wkp_timer == 0) { -+ DWC_WARN("DWC_TIMER_ALLOC failed\n"); -+ dwc_free(host_if); -+ dwc_free(dev_if); -+ DWC_WORKQ_FREE(core_if->wq_otg); -+ dwc_free(core_if); -+ return 0; -+ } -+ -+ if (dwc_otg_setup_params(core_if)) { -+ DWC_WARN("Error while setting core params\n"); -+ } -+ -+ return core_if; -+} -+ -+/** -+ * This function frees the structures allocated by dwc_otg_cil_init(). -+ * -+ * @param core_if The core interface pointer returned from -+ * dwc_otg_cil_init(). -+ * -+ */ -+void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if) -+{ -+ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); -+ -+ /* Disable all interrupts */ -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 1, 0); -+ dwc_write_reg32(&core_if->core_global_regs->gintmsk, 0); -+ -+ if (core_if->wq_otg) { -+ DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500); -+ DWC_WORKQ_FREE(core_if->wq_otg); -+ } -+ if (core_if->dev_if) { -+ dwc_free(core_if->dev_if); -+ } -+ if (core_if->host_if) { -+ dwc_free(core_if->host_if); -+ } -+ dwc_free(core_if); -+ DWC_TIMER_FREE(core_if->wkp_timer); -+ DWC_FREE(core_if->core_params); -+} -+ -+/** -+ * This function enables the controller's Global Interrupt in the AHB Config -+ * register. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if) -+{ -+ gahbcfg_data_t ahbcfg = {.d32 = 0 }; -+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); -+} -+ -+/** -+ * This function disables the controller's Global Interrupt in the AHB Config -+ * register. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if) -+{ -+ gahbcfg_data_t ahbcfg = {.d32 = 0 }; -+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ -+ DWC_PRINTF("%x -> %x\n", (unsigned int)&core_if->core_global_regs->gahbcfg, ahbcfg.d32); -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); -+} -+ -+/** -+ * This function initializes the commmon interrupts, used in both -+ * device and host modes. -+ * -+ * @param core_if Programming view of the DWC_otg controller -+ * -+ */ -+static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if) -+{ -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ /* Clear any pending OTG Interrupts */ -+ dwc_write_reg32(&global_regs->gotgint, 0xFFFFFFFF); -+ -+ /* Clear any pending interrupts */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* -+ * Enable the interrupts in the GINTMSK. -+ */ -+ intr_mask.b.modemismatch = 1; -+ intr_mask.b.otgintr = 1; -+ -+ if (!core_if->dma_enable) { -+ intr_mask.b.rxstsqlvl = 1; -+ } -+ -+ intr_mask.b.conidstschng = 1; -+ intr_mask.b.wkupintr = 1; -+ intr_mask.b.disconnect = 1; -+ intr_mask.b.usbsuspend = 1; -+ intr_mask.b.sessreqintr = 1; -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ if (core_if->core_params->lpm_enable) { -+ intr_mask.b.lpmtranrcvd = 1; -+ } -+#endif -+ dwc_write_reg32(&global_regs->gintmsk, intr_mask.d32); -+} -+ -+/** -+ * 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; -+ } -+ -+ DWC_DEBUGPL(DBG_CIL, "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); -+} -+ -+/** -+ * Initializes the DevSpd field of the DCFG register depending on the PHY type -+ * and the enumeration speed of the device. -+ */ -+static void init_devspd(dwc_otg_core_if_t * core_if) -+{ -+ uint32_t val; -+ dcfg_data_t dcfg; -+ -+ 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 = 0x3; -+ } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { -+ /* High speed PHY running at full speed */ -+ val = 0x1; -+ } else { -+ /* High speed PHY running at high speed */ -+ val = 0x0; -+ } -+ -+ DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); -+ -+ dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.b.devspd = val; -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); -+} -+ -+/** -+ * This function calculates the number of IN EPS -+ * using GHWCFG1 and GHWCFG2 registers values -+ * -+ * @param core_if Programming view of the DWC_otg controller -+ */ -+static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if) -+{ -+ uint32_t num_in_eps = 0; -+ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; -+ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3; -+ uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps; -+ int i; -+ -+ for (i = 0; i < num_eps; ++i) { -+ if (!(hwcfg1 & 0x1)) -+ num_in_eps++; -+ -+ hwcfg1 >>= 2; -+ } -+ -+ if (core_if->hwcfg4.b.ded_fifo_en) { -+ num_in_eps = -+ (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps; -+ } -+ -+ return num_in_eps; -+} -+ -+/** -+ * This function calculates the number of OUT EPS -+ * using GHWCFG1 and GHWCFG2 registers values -+ * -+ * @param core_if Programming view of the DWC_otg controller -+ */ -+static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if) -+{ -+ uint32_t num_out_eps = 0; -+ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; -+ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2; -+ int i; -+ -+ for (i = 0; i < num_eps; ++i) { -+ if (!(hwcfg1 & 0x1)) -+ num_out_eps++; -+ -+ hwcfg1 >>= 2; -+ } -+ return num_out_eps; -+} -+ -+/** -+ * 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) -+{ -+ int i = 0; -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ gahbcfg_data_t ahbcfg = {.d32 = 0 }; -+ gusbcfg_data_t usbcfg = {.d32 = 0 }; -+ gi2cctl_data_t i2cctl = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_CILV, "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. */ -+ dev_if->num_in_eps = calc_num_in_eps(core_if); -+ dev_if->num_out_eps = calc_num_out_eps(core_if); -+ -+ DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n", -+ core_if->hwcfg4.b.num_dev_perio_in_ep); -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { -+ dev_if->perio_tx_fifo_size[i] = -+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16; -+ DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", -+ i, dev_if->perio_tx_fifo_size[i]); -+ } -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ dev_if->tx_fifo_size[i] = -+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16; -+ DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", -+ i, dev_if->perio_tx_fifo_size[i]); -+ } -+ -+ 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; -+ -+ DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "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; -+ DWC_DEBUGPL(DBG_CIL, "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); -+ } else { -+ init_devspd(core_if); -+ } -+ -+ if (core_if->core_params->i2c_enable) { -+ DWC_DEBUGPL(DBG_CIL, "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) { -+ /* ULPI interface */ -+ usbcfg.b.phyif = 0; -+ usbcfg.b.ddrsel = -+ core_if->core_params->phy_ulpi_ddr; -+ } else { -+ /* 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)) { -+ DWC_DEBUGPL(DBG_CIL, "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: -+ DWC_DEBUGPL(DBG_CIL, "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: -+ DWC_DEBUGPL(DBG_CIL, "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: -+ DWC_DEBUGPL(DBG_CIL, "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) { -+ DWC_PRINTF("Using Descriptor DMA mode\n"); -+ } else { -+ DWC_PRINTF("Using Buffer DMA mode\n"); -+ -+ } -+ } else { -+ DWC_PRINTF("Using Slave mode\n"); -+ core_if->dma_desc_enable = 0; -+ } -+ -+ ahbcfg.b.dmaenable = core_if->dma_enable; -+ 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; -+ DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n", -+ ((core_if->pti_enh_enable) ? "enabled" : "disabled")); -+ DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n", -+ ((core_if->multiproc_int_enable) ? "enabled" : "disabled")); -+ -+ /* -+ * 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); -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ if (core_if->core_params->lpm_enable) { -+ glpmcfg_data_t lpmcfg = {.d32 = 0 }; -+ -+ /* To enable LPM support set lpm_cap_en bit */ -+ lpmcfg.b.lpm_cap_en = 1; -+ -+ /* Make AppL1Res ACK */ -+ lpmcfg.b.appl_resp = 1; -+ -+ /* Retry 3 times */ -+ lpmcfg.b.retry_count = 3; -+ -+ dwc_modify_reg32(&core_if->core_global_regs->glpmcfg, -+ 0, lpmcfg.d32); -+ -+ } -+#endif -+ 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); -+ } -+ -+ /* Enable common interrupts */ -+ dwc_otg_enable_common_interrupts(core_if); -+ -+ /* Do device or host intialization based on mode during PCD -+ * and HCD initialization */ -+ if (dwc_otg_is_host_mode(core_if)) { -+ DWC_DEBUGPL(DBG_ANY, "Host Mode\n"); -+ core_if->op_state = A_HOST; -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "Device Mode\n"); -+ core_if->op_state = B_PERIPHERAL; -+#ifdef DWC_DEVICE_ONLY -+ dwc_otg_core_dev_init(core_if); -+#endif -+ } -+} -+ -+/** -+ * This function enables the Device mode interrupts. -+ * -+ * @param core_if Programming view of DWC_otg controller -+ */ -+void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) -+{ -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ -+ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); -+ -+ /* Disable all interrupts. */ -+ dwc_write_reg32(&global_regs->gintmsk, 0); -+ -+ /* Clear any pending interrupts */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* Enable the common interrupts */ -+ dwc_otg_enable_common_interrupts(core_if); -+ -+ /* Enable interrupts */ -+ intr_mask.b.usbreset = 1; -+ intr_mask.b.enumdone = 1; -+ -+ if (!core_if->multiproc_int_enable) { -+ intr_mask.b.inepintr = 1; -+ intr_mask.b.outepintr = 1; -+ } -+ -+ intr_mask.b.erlysuspend = 1; -+ -+ if (core_if->en_multiple_tx_fifo == 0) { -+ intr_mask.b.epmismatch = 1; -+ } -+#ifdef DWC_EN_ISOC -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable == 0) { -+ if (core_if->pti_enh_enable) { -+ dctl_data_t dctl = {.d32 = 0 }; -+ dctl.b.ifrmnum = 1; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs->dctl, 0, -+ dctl.d32); -+ } else { -+ intr_mask.b.incomplisoin = 1; -+ intr_mask.b.incomplisoout = 1; -+ } -+ } -+ } else { -+ intr_mask.b.incomplisoin = 1; -+ intr_mask.b.incomplisoout = 1; -+ } -+#endif /* DWC_EN_ISOC */ -+ -+ /** @todo NGS: Should this be a module parameter? */ -+#ifdef USE_PERIODIC_EP -+ intr_mask.b.isooutdrop = 1; -+ intr_mask.b.eopframe = 1; -+ intr_mask.b.incomplisoin = 1; -+ intr_mask.b.incomplisoout = 1; -+#endif -+ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); -+ -+ DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, -+ dwc_read_reg32(&global_regs->gintmsk)); -+} -+ -+/** -+ * This function initializes the DWC_otg controller registers for -+ * device mode. -+ * -+ * @param core_if Programming view of DWC_otg controller -+ * -+ */ -+void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) -+{ -+ int i; -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ dwc_otg_core_params_t *params = core_if->core_params; -+ dcfg_data_t dcfg = {.d32 = 0 }; -+ grstctl_t resetctl = {.d32 = 0 }; -+ uint32_t rx_fifo_size; -+ fifosize_data_t nptxfifosize; -+ fifosize_data_t txfifosize; -+ dthrctl_data_t dthrctl; -+ fifosize_data_t ptxfifosize; -+ -+ /* Restart the Phy Clock */ -+ dwc_write_reg32(core_if->pcgcctl, 0); -+ -+ /* Device configuration register */ -+ init_devspd(core_if); -+ dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg); -+ dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0; -+ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80; -+ -+ dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ -+ /* Configure data FIFO sizes */ -+ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { -+ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", -+ core_if->total_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", -+ params->dev_rx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", -+ params->dev_nperio_tx_fifo_size); -+ -+ /* Rx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ -+#ifdef DWC_UTE_CFI -+ core_if->pwron_rxfsiz = dwc_read_reg32(&global_regs->grxfsiz); -+ core_if->init_rxfsiz = params->dev_rx_fifo_size; -+#endif -+ rx_fifo_size = params->dev_rx_fifo_size; -+ dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size); -+ -+ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ -+ /** Set Periodic Tx FIFO Mask all bits 0 */ -+ core_if->p_tx_msk = 0; -+ -+ /** Set Tx FIFO Mask all bits 0 */ -+ core_if->tx_msk = 0; -+ -+ if (core_if->en_multiple_tx_fifo == 0) { -+ /* Non-periodic Tx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ -+ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; -+ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; -+ -+ dwc_write_reg32(&global_regs->gnptxfsiz, -+ nptxfifosize.d32); -+ -+ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ -+ /**@todo NGS: Fix Periodic FIFO Sizing! */ -+ /* -+ * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15. -+ * Indexes of the FIFO size module parameters in the -+ * dev_perio_tx_fifo_size array and the FIFO size registers in -+ * the dptxfsiz array run from 0 to 14. -+ */ -+ /** @todo Finish debug of this */ -+ ptxfifosize.b.startaddr = -+ nptxfifosize.b.startaddr + nptxfifosize.b.depth; -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; -+ i++) { -+ ptxfifosize.b.depth = -+ params->dev_perio_tx_fifo_size[i]; -+ DWC_DEBUGPL(DBG_CIL, -+ "initial dptxfsiz_dieptxf[%d]=%08x\n", -+ i, -+ dwc_read_reg32(&global_regs-> -+ dptxfsiz_dieptxf -+ [i])); -+ dwc_write_reg32(&global_regs-> -+ dptxfsiz_dieptxf[i], -+ ptxfifosize.d32); -+ DWC_DEBUGPL(DBG_CIL, -+ "new dptxfsiz_dieptxf[%d]=%08x\n", -+ i, -+ dwc_read_reg32(&global_regs-> -+ dptxfsiz_dieptxf -+ [i])); -+ ptxfifosize.b.startaddr += ptxfifosize.b.depth; -+ } -+ } else { -+ /* -+ * Tx FIFOs These FIFOs are numbered from 1 to 15. -+ * Indexes of the FIFO size module parameters in the -+ * dev_tx_fifo_size array and the FIFO size registers in -+ * the dptxfsiz_dieptxf array run from 0 to 14. -+ */ -+ -+ /* Non-periodic Tx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ -+#ifdef DWC_UTE_CFI -+ core_if->pwron_gnptxfsiz = -+ (dwc_read_reg32(&global_regs->gnptxfsiz) >> 16); -+ core_if->init_gnptxfsiz = -+ params->dev_nperio_tx_fifo_size; -+#endif -+ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; -+ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; -+ -+ dwc_write_reg32(&global_regs->gnptxfsiz, -+ nptxfifosize.d32); -+ -+ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ -+ txfifosize.b.startaddr = -+ nptxfifosize.b.startaddr + nptxfifosize.b.depth; -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ -+ txfifosize.b.depth = -+ params->dev_tx_fifo_size[i]; -+ -+ DWC_DEBUGPL(DBG_CIL, -+ "initial dptxfsiz_dieptxf[%d]=%08x\n", -+ i, -+ dwc_read_reg32(&global_regs-> -+ dptxfsiz_dieptxf -+ [i])); -+ -+#ifdef DWC_UTE_CFI -+ core_if->pwron_txfsiz[i] = -+ (dwc_read_reg32 -+ (&global_regs->dptxfsiz_dieptxf[i]) >> 16); -+ core_if->init_txfsiz[i] = -+ params->dev_tx_fifo_size[i]; -+#endif -+ dwc_write_reg32(&global_regs-> -+ dptxfsiz_dieptxf[i], -+ txfifosize.d32); -+ -+ DWC_DEBUGPL(DBG_CIL, -+ "new dptxfsiz_dieptxf[%d]=%08x\n", -+ i, -+ dwc_read_reg32(&global_regs-> -+ dptxfsiz_dieptxf -+ [i])); -+ -+ txfifosize.b.startaddr += txfifosize.b.depth; -+ } -+ } -+ } -+ /* Flush the FIFOs */ -+ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ -+ dwc_otg_flush_rx_fifo(core_if); -+ -+ /* Flush the Learning Queue. */ -+ resetctl.b.intknqflsh = 1; -+ dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); -+ -+ /* Clear all pending Device Interrupts */ -+ /** @todo - if the condition needed to be checked -+ * or in any case all pending interrutps should be cleared? -+ */ -+ if (core_if->multiproc_int_enable) { -+ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -+ dwc_write_reg32(&dev_if->dev_global_regs-> -+ diepeachintmsk[i], 0); -+ } -+ -+ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { -+ dwc_write_reg32(&dev_if->dev_global_regs-> -+ doepeachintmsk[i], 0); -+ } -+ -+ dwc_write_reg32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); -+ dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk, 0); -+ } else { -+ dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, 0); -+ dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, 0); -+ dwc_write_reg32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); -+ dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, 0); -+ } -+ -+ for (i = 0; i <= dev_if->num_in_eps; i++) { -+ depctl_data_t depctl; -+ depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); -+ if (depctl.b.epena) { -+ depctl.d32 = 0; -+ depctl.b.epdis = 1; -+ depctl.b.snak = 1; -+ } else { -+ depctl.d32 = 0; -+ } -+ -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); -+ -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->dieptsiz, 0); -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepdma, 0); -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepint, 0xFF); -+ } -+ -+ for (i = 0; i <= dev_if->num_out_eps; i++) { -+ depctl_data_t depctl; -+ depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); -+ if (depctl.b.epena) { -+ depctl.d32 = 0; -+ depctl.b.epdis = 1; -+ depctl.b.snak = 1; -+ } else { -+ depctl.d32 = 0; -+ } -+ -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); -+ -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doeptsiz, 0); -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepdma, 0); -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepint, 0xFF); -+ } -+ -+ if (core_if->en_multiple_tx_fifo && core_if->dma_enable) { -+ dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1; -+ dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1; -+ dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1; -+ -+ dev_if->rx_thr_length = params->rx_thr_length; -+ dev_if->tx_thr_length = params->tx_thr_length; -+ -+ dev_if->setup_desc_index = 0; -+ -+ dthrctl.d32 = 0; -+ dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en; -+ dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en; -+ dthrctl.b.tx_thr_len = dev_if->tx_thr_length; -+ dthrctl.b.rx_thr_en = dev_if->rx_thr_en; -+ dthrctl.b.rx_thr_len = dev_if->rx_thr_length; -+ dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio; -+ -+ dwc_write_reg32(&dev_if->dev_global_regs->dtknqr3_dthrctl, -+ dthrctl.d32); -+ -+ DWC_DEBUGPL(DBG_CIL, -+ "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n", -+ dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en, -+ dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len, -+ dthrctl.b.rx_thr_len); -+ -+ } -+ -+ dwc_otg_enable_device_interrupts(core_if); -+ -+ { -+ diepmsk_data_t msk = {.d32 = 0 }; -+ msk.b.txfifoundrn = 1; -+ if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&dev_if->dev_global_regs-> -+ diepeachintmsk[0], msk.d32, msk.d32); -+ } else { -+ dwc_modify_reg32(&dev_if->dev_global_regs->diepmsk, -+ msk.d32, msk.d32); -+ } -+ } -+ -+ if (core_if->multiproc_int_enable) { -+ /* Set NAK on Babble */ -+ dctl_data_t dctl = {.d32 = 0 }; -+ dctl.b.nakonbble = 1; -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ } -+} -+ -+/** -+ * This function enables the Host mode interrupts. -+ * -+ * @param core_if Programming view of DWC_otg controller -+ */ -+void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if) -+{ -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if); -+ -+ /* Disable all interrupts. */ -+ dwc_write_reg32(&global_regs->gintmsk, 0); -+ -+ /* Clear any pending interrupts. */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* Enable the common interrupts */ -+ dwc_otg_enable_common_interrupts(core_if); -+ -+ /* -+ * Enable host mode interrupts without disturbing common -+ * interrupts. -+ */ -+ -+ /* Do not need sof interrupt for Descriptor DMA*/ -+ if (!core_if->dma_desc_enable) -+ intr_mask.b.sofintr = 1; -+ intr_mask.b.portintr = 1; -+ intr_mask.b.hcintr = 1; -+ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); -+} -+ -+/** -+ * This function disables the Host Mode interrupts. -+ * -+ * @param core_if Programming view of DWC_otg controller -+ */ -+void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if) -+{ -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__); -+ -+ /* -+ * Disable host mode interrupts without disturbing common -+ * interrupts. -+ */ -+ intr_mask.b.sofintr = 1; -+ intr_mask.b.portintr = 1; -+ intr_mask.b.hcintr = 1; -+ intr_mask.b.ptxfempty = 1; -+ intr_mask.b.nptxfempty = 1; -+ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 0); -+} -+ -+/** -+ * 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 }; -+ -+ DWC_DEBUGPL(DBG_CILV, "%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)))) { -+ -+ DWC_ERROR("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) { -+ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", -+ core_if->total_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", -+ params->host_rx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", -+ params->host_nperio_tx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n", -+ params->host_perio_tx_fifo_size); -+ -+ /* Rx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ dwc_write_reg32(&global_regs->grxfsiz, -+ params->host_rx_fifo_size); -+ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ -+ /* Non-periodic Tx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "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); -+ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); -+ -+ /* Periodic Tx FIFO */ -+ DWC_DEBUGPL(DBG_CIL, "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); -+ DWC_DEBUGPL(DBG_CIL, "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); -+ DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs); -+ do { -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (++count > 1000) { -+ DWC_ERROR -+ ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n", -+ __func__, i, hcchar.d32, &hc_regs->hcchar); -+ break; -+ } -+ dwc_udelay(1); -+ } while (hcchar.b.chen); -+ } -+ } -+ -+ /* Turn on the vbus power. */ -+ DWC_PRINTF("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); -+ DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); -+ if (hprt0.b.prtpwr == 0) { -+ hprt0.b.prtpwr = 1; -+ dwc_write_reg32(host_if->hprt0, hprt0.d32); -+ } -+ } -+ -+ dwc_otg_enable_host_interrupts(core_if); -+} -+ -+/** -+ * 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, dwc_hc_t * hc) -+{ -+ uint32_t intr_enable; -+ hcintmsk_data_t hc_intr_mask; -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ hcchar_data_t hcchar; -+ hcsplt_data_t hcsplt; -+ -+ uint8_t hc_num = hc->hc_num; -+ 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); -+ -+ /* Enable channel interrupts required for this transfer. */ -+ hc_intr_mask.d32 = 0; -+ hc_intr_mask.b.chhltd = 1; -+ if (core_if->dma_enable) { -+ /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */ -+ if (!core_if->dma_desc_enable) -+ hc_intr_mask.b.ahberr = 1; -+ else { -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) -+ hc_intr_mask.b.xfercompl = 1; -+ } -+ -+ if (hc->error_state && !hc->do_split && -+ hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { -+ hc_intr_mask.b.ack = 1; -+ if (hc->ep_is_in) { -+ hc_intr_mask.b.datatglerr = 1; -+ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) { -+ hc_intr_mask.b.nak = 1; -+ } -+ } -+ } -+ } else { -+ switch (hc->ep_type) { -+ case DWC_OTG_EP_TYPE_CONTROL: -+ case DWC_OTG_EP_TYPE_BULK: -+ hc_intr_mask.b.xfercompl = 1; -+ hc_intr_mask.b.stall = 1; -+ hc_intr_mask.b.xacterr = 1; -+ hc_intr_mask.b.datatglerr = 1; -+ if (hc->ep_is_in) { -+ hc_intr_mask.b.bblerr = 1; -+ } else { -+ hc_intr_mask.b.nak = 1; -+ hc_intr_mask.b.nyet = 1; -+ if (hc->do_ping) { -+ hc_intr_mask.b.ack = 1; -+ } -+ } -+ -+ if (hc->do_split) { -+ hc_intr_mask.b.nak = 1; -+ if (hc->complete_split) { -+ hc_intr_mask.b.nyet = 1; -+ } else { -+ hc_intr_mask.b.ack = 1; -+ } -+ } -+ -+ if (hc->error_state) { -+ hc_intr_mask.b.ack = 1; -+ } -+ break; -+ case DWC_OTG_EP_TYPE_INTR: -+ hc_intr_mask.b.xfercompl = 1; -+ hc_intr_mask.b.nak = 1; -+ hc_intr_mask.b.stall = 1; -+ hc_intr_mask.b.xacterr = 1; -+ hc_intr_mask.b.datatglerr = 1; -+ hc_intr_mask.b.frmovrun = 1; -+ -+ if (hc->ep_is_in) { -+ hc_intr_mask.b.bblerr = 1; -+ } -+ if (hc->error_state) { -+ hc_intr_mask.b.ack = 1; -+ } -+ if (hc->do_split) { -+ if (hc->complete_split) { -+ hc_intr_mask.b.nyet = 1; -+ } else { -+ hc_intr_mask.b.ack = 1; -+ } -+ } -+ break; -+ case DWC_OTG_EP_TYPE_ISOC: -+ hc_intr_mask.b.xfercompl = 1; -+ hc_intr_mask.b.frmovrun = 1; -+ hc_intr_mask.b.ack = 1; -+ -+ if (hc->ep_is_in) { -+ hc_intr_mask.b.xacterr = 1; -+ hc_intr_mask.b.bblerr = 1; -+ } -+ break; -+ } -+ } -+ dwc_write_reg32(&hc_regs->hcintmsk, hc_intr_mask.d32); -+ -+ /* Enable the top level host channel interrupt. */ -+ intr_enable = (1 << hc_num); -+ dwc_modify_reg32(&host_if->host_global_regs->haintmsk, 0, intr_enable); -+ -+ /* Make sure host channel interrupts are enabled. */ -+ gintmsk.b.hcintr = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); -+ -+ /* -+ * Program the HCCHARn register with the endpoint characteristics for -+ * the current transfer. -+ */ -+ hcchar.d32 = 0; -+ hcchar.b.devaddr = hc->dev_addr; -+ hcchar.b.epnum = hc->ep_num; -+ hcchar.b.epdir = hc->ep_is_in; -+ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); -+ hcchar.b.eptype = hc->ep_type; -+ hcchar.b.mps = hc->max_packet; -+ -+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr); -+ DWC_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum); -+ DWC_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir); -+ DWC_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev); -+ DWC_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype); -+ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); -+ DWC_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt); -+ -+ /* -+ * Program the HCSPLIT register for SPLITs -+ */ -+ hcsplt.d32 = 0; -+ if (hc->do_split) { -+ DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", -+ hc->hc_num, -+ hc->complete_split ? "CSPLIT" : "SSPLIT"); -+ hcsplt.b.compsplt = hc->complete_split; -+ hcsplt.b.xactpos = hc->xact_pos; -+ hcsplt.b.hubaddr = hc->hub_addr; -+ hcsplt.b.prtaddr = hc->port_addr; -+ DWC_DEBUGPL(DBG_HCDV, " comp split %d\n", hc->complete_split); -+ DWC_DEBUGPL(DBG_HCDV, " xact pos %d\n", hc->xact_pos); -+ DWC_DEBUGPL(DBG_HCDV, " hub addr %d\n", hc->hub_addr); -+ DWC_DEBUGPL(DBG_HCDV, " port addr %d\n", hc->port_addr); -+ DWC_DEBUGPL(DBG_HCDV, " is_in %d\n", hc->ep_is_in); -+ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); -+ DWC_DEBUGPL(DBG_HCDV, " xferlen: %d\n", hc->xfer_len); -+ } -+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); -+ -+} -+ -+/** -+ * Attempts to halt a host channel. This function should only be called in -+ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under -+ * normal circumstances in DMA mode, the controller halts the channel when the -+ * transfer is complete or a condition occurs that requires application -+ * intervention. -+ * -+ * In slave mode, checks for a free request queue entry, then sets the Channel -+ * Enable and Channel Disable bits of the Host Channel Characteristics -+ * register of the specified channel to intiate the halt. If there is no free -+ * request queue entry, sets only the Channel Disable bit of the HCCHARn -+ * register to flush requests for this channel. In the latter case, sets a -+ * flag to indicate that the host channel needs to be halted when a request -+ * queue slot is open. -+ * -+ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the -+ * HCCHARn register. The controller ensures there is space in the request -+ * queue before submitting the halt request. -+ * -+ * Some time may elapse before the core flushes any posted requests for this -+ * host channel and halts. The Channel Halted interrupt handler completes the -+ * deactivation of the host channel. -+ * -+ * @param core_if Controller register interface. -+ * @param hc Host channel to halt. -+ * @param halt_status Reason for halting the channel. -+ */ -+void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if, -+ dwc_hc_t * hc, dwc_otg_halt_status_e halt_status) -+{ -+ gnptxsts_data_t nptxsts; -+ hptxsts_data_t hptxsts; -+ hcchar_data_t hcchar; -+ dwc_otg_hc_regs_t *hc_regs; -+ dwc_otg_core_global_regs_t *global_regs; -+ dwc_otg_host_global_regs_t *host_global_regs; -+ -+ DWC_DEBUGPL(DBG_HW2937, " dwc_otg_hc_halt(%d)\n", hc->hc_num); -+ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ global_regs = core_if->core_global_regs; -+ host_global_regs = core_if->host_if->host_global_regs; -+ -+ DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS), -+ "halt_status = %d\n", halt_status); -+ -+ if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || -+ halt_status == DWC_OTG_HC_XFER_AHB_ERR) { -+ /* -+ * Disable all channel interrupts except Ch Halted. The QTD -+ * and QH state associated with this transfer has been cleared -+ * (in the case of URB_DEQUEUE), so the channel needs to be -+ * shut down carefully to prevent crashes. -+ */ -+ hcintmsk_data_t hcintmsk; -+ hcintmsk.d32 = 0; -+ hcintmsk.b.chhltd = 1; -+ dwc_write_reg32(&hc_regs->hcintmsk, hcintmsk.d32); -+ -+ /* -+ * Make sure no other interrupts besides halt are currently -+ * pending. Handling another interrupt could cause a crash due -+ * to the QTD and QH state. -+ */ -+ dwc_write_reg32(&hc_regs->hcint, ~hcintmsk.d32); -+ -+ /* -+ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR -+ * even if the channel was already halted for some other -+ * reason. -+ */ -+ hc->halt_status = halt_status; -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen == 0) { -+ /* -+ * The channel is either already halted or it hasn't -+ * started yet. In DMA mode, the transfer may halt if -+ * it finishes normally or a condition occurs that -+ * requires driver intervention. Don't want to halt -+ * the channel again. In either Slave or DMA mode, -+ * it's possible that the transfer has been assigned -+ * to a channel, but not started yet when an URB is -+ * dequeued. Don't want to halt a channel that hasn't -+ * started yet. -+ */ -+ return; -+ } -+ } -+ if (hc->halt_pending) { -+ /* -+ * A halt has already been issued for this channel. This might -+ * happen when a transfer is aborted by a higher level in -+ * the stack. -+ */ -+#ifdef DEBUG -+ DWC_PRINTF -+ ("*** %s: Channel %d, _hc->halt_pending already set ***\n", -+ __func__, hc->hc_num); -+ -+#endif -+ return; -+ } -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* No need to set the bit in DDMA for disabling the channel */ -+ //TODO check it everywhere channel is disabled -+ if(!core_if->core_params->dma_desc_enable) -+ hcchar.b.chen = 1; -+ hcchar.b.chdis = 1; -+ -+ if (!core_if->dma_enable) { -+ /* Check for space in the request queue to issue the halt. */ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || -+ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { -+ nptxsts.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ if (nptxsts.b.nptxqspcavail == 0) { -+ hcchar.b.chen = 0; -+ } -+ } else { -+ hptxsts.d32 = -+ dwc_read_reg32(&host_global_regs->hptxsts); -+ if ((hptxsts.b.ptxqspcavail == 0) -+ || (core_if->queuing_high_bandwidth)) { -+ hcchar.b.chen = 0; -+ } -+ } -+ } -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ hc->halt_status = halt_status; -+ -+ if (hcchar.b.chen) { -+ hc->halt_pending = 1; -+ hc->halt_on_queue = 0; -+ } else { -+ hc->halt_on_queue = 1; -+ } -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32); -+ DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending); -+ DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue); -+ DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status); -+ -+ return; -+} -+ -+/** -+ * Clears the transfer state for a host channel. This function is normally -+ * called after a transfer is done and the host channel is being released. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param hc Identifies the host channel to clean up. -+ */ -+void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) -+{ -+ dwc_otg_hc_regs_t *hc_regs; -+ -+ hc->xfer_started = 0; -+ -+ /* -+ * Clear channel interrupt enables and any unhandled channel interrupt -+ * conditions. -+ */ -+ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ dwc_write_reg32(&hc_regs->hcintmsk, 0); -+ dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF); -+#ifdef DEBUG -+ DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]); -+#endif -+} -+ -+/** -+ * Sets the channel property that indicates in which frame a periodic transfer -+ * should occur. This is always set to the _next_ frame. This function has no -+ * effect on non-periodic transfers. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param hc Identifies the host channel to set up and its properties. -+ * @param hcchar Current value of the HCCHAR register for the specified host -+ * channel. -+ */ -+static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if, -+ dwc_hc_t * hc, hcchar_data_t * hcchar) -+{ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ hfnum_data_t hfnum; -+ hfnum.d32 = -+ dwc_read_reg32(&core_if->host_if->host_global_regs->hfnum); -+ -+ /* 1 if _next_ frame is odd, 0 if it's even */ -+ hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; -+#ifdef DEBUG -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split -+ && !hc->complete_split) { -+ switch (hfnum.b.frnum & 0x7) { -+ case 7: -+ core_if->hfnum_7_samples++; -+ core_if->hfnum_7_frrem_accum += hfnum.b.frrem; -+ break; -+ case 0: -+ core_if->hfnum_0_samples++; -+ core_if->hfnum_0_frrem_accum += hfnum.b.frrem; -+ break; -+ default: -+ core_if->hfnum_other_samples++; -+ core_if->hfnum_other_frrem_accum += -+ hfnum.b.frrem; -+ break; -+ } -+ } -+#endif -+ } -+} -+ -+#ifdef DEBUG -+void hc_xfer_timeout(void *ptr) -+{ -+ hc_xfer_info_t *xfer_info = (hc_xfer_info_t *) ptr; -+ int hc_num = xfer_info->hc->hc_num; -+ DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num); -+ DWC_WARN(" start_hcchar_val 0x%08x\n", -+ xfer_info->core_if->start_hcchar_val[hc_num]); -+} -+#endif -+ -+void set_pid_isoc(dwc_hc_t * hc) -+{ -+ /* Set up the initial PID for the transfer. */ -+ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) { -+ if (hc->ep_is_in) { -+ if (hc->multi_count == 1) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA0; -+ } else if (hc->multi_count == 2) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA1; -+ } else { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA2; -+ } -+ } else { -+ if (hc->multi_count == 1) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA0; -+ } else { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_MDATA; -+ } -+ } -+ } else { -+ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; -+ } -+} -+ -+/** -+ * This function does the setup for a data transfer for a host channel and -+ * starts the transfer. May be called in either Slave mode or DMA mode. In -+ * Slave mode, the caller must ensure that there is sufficient space in the -+ * request queue and Tx Data FIFO. -+ * -+ * For an OUT transfer in Slave mode, it loads a data packet into the -+ * appropriate FIFO. If necessary, additional data packets will be loaded in -+ * the Host ISR. -+ * -+ * For an IN transfer in Slave mode, a data packet is requested. The data -+ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, -+ * additional data packets are requested in the Host ISR. -+ * -+ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ -+ * register along with a packet count of 1 and the channel is enabled. This -+ * causes a single PING transaction to occur. Other fields in HCTSIZ are -+ * simply set to 0 since no data transfer occurs in this case. -+ * -+ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with -+ * all the information required to perform the subsequent data transfer. In -+ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the -+ * controller performs the entire PING protocol, then starts the data -+ * transfer. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param hc Information needed to initialize the host channel. The xfer_len -+ * value may be reduced to accommodate the max widths of the XferSize and -+ * PktCnt fields in the HCTSIZn register. The multi_count value may be changed -+ * to reflect the final xfer_len value. -+ */ -+void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) -+{ -+ hcchar_data_t hcchar; -+ hctsiz_data_t hctsiz; -+ uint16_t num_packets; -+ uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size; -+ uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count; -+ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ -+ hctsiz.d32 = 0; -+ -+ if (hc->do_ping) { -+ if (!core_if->dma_enable) { -+ dwc_otg_hc_do_ping(core_if, hc); -+ hc->xfer_started = 1; -+ return; -+ } else { -+ hctsiz.b.dopng = 1; -+ } -+ } -+ -+ if (hc->do_split) { -+ num_packets = 1; -+ -+ if (hc->complete_split && !hc->ep_is_in) { -+ /* For CSPLIT OUT Transfer, set the size to 0 so the -+ * core doesn't expect any data written to the FIFO */ -+ hc->xfer_len = 0; -+ } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) { -+ hc->xfer_len = hc->max_packet; -+ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) { -+ hc->xfer_len = 188; -+ } -+ -+ hctsiz.b.xfersize = hc->xfer_len; -+ } else { -+ /* -+ * Ensure that the transfer length and packet count will fit -+ * in the widths allocated for them in the HCTSIZn register. -+ */ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * Make sure the transfer size is no larger than one -+ * (micro)frame's worth of data. (A check was done -+ * when the periodic transfer was accepted to ensure -+ * that a (micro)frame's worth of data can be -+ * programmed into a channel.) -+ */ -+ uint32_t max_periodic_len = -+ hc->multi_count * hc->max_packet; -+ if (hc->xfer_len > max_periodic_len) { -+ hc->xfer_len = max_periodic_len; -+ } else { -+ } -+ } else if (hc->xfer_len > max_hc_xfer_size) { -+ /* Make sure that xfer_len is a multiple of max packet size. */ -+ hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1; -+ } -+ -+ if (hc->xfer_len > 0) { -+ num_packets = -+ (hc->xfer_len + hc->max_packet - -+ 1) / hc->max_packet; -+ if (num_packets > max_hc_pkt_count) { -+ num_packets = max_hc_pkt_count; -+ hc->xfer_len = num_packets * hc->max_packet; -+ } -+ } else { -+ /* Need 1 packet for transfer length of 0. */ -+ num_packets = 1; -+ } -+ -+ if (hc->ep_is_in) { -+ /* Always program an integral # of max packets for IN transfers. */ -+ hc->xfer_len = num_packets * hc->max_packet; -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * Make sure that the multi_count field matches the -+ * actual transfer length. -+ */ -+ hc->multi_count = num_packets; -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) -+ set_pid_isoc(hc); -+ -+ hctsiz.b.xfersize = hc->xfer_len; -+ } -+ -+ hc->start_pkt_count = num_packets; -+ hctsiz.b.pktcnt = num_packets; -+ hctsiz.b.pid = hc->data_pid_start; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); -+ DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt); -+ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); -+ -+ if (core_if->dma_enable) { -+ dwc_dma_t dma_addr; -+ if (hc->align_buff) { -+ dma_addr = hc->align_buff; -+ } else { -+ dma_addr = (uint32_t)hc->xfer_buff; -+ } -+ dwc_write_reg32(&hc_regs->hcdma, dma_addr); -+ } -+ -+ /* Start the split */ -+ if (hc->do_split) { -+ hcsplt_data_t hcsplt; -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ hcsplt.b.spltena = 1; -+ dwc_write_reg32(&hc_regs->hcsplt, hcsplt.d32); -+ } -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.multicnt = hc->multi_count; -+ hc_set_even_odd_frame(core_if, hc, &hcchar); -+#ifdef DEBUG -+ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; -+ if (hcchar.b.chdis) { -+ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", -+ __func__, hc->hc_num, hcchar.d32); -+ } -+#endif -+ -+ /* 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); -+ -+ hc->xfer_started = 1; -+ hc->requests++; -+ -+ if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) { -+ /* Load OUT packet into the appropriate Tx FIFO. */ -+ dwc_otg_hc_write_packet(core_if, hc); -+ } -+#ifdef DEBUG -+ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) { -+ DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n", -+ hc->hc_num, core_if);//GRAYG -+ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; -+ core_if->hc_xfer_info[hc->hc_num].hc = hc; -+ /* Start a timer for this transfer. */ -+ DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); -+ } -+#endif -+} -+ -+/** -+ * This function does the setup for a data transfer for a host channel -+ * and starts the transfer in Descriptor DMA mode. -+ * -+ * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. -+ * Sets PID and NTD values. For periodic transfers -+ * initializes SCHED_INFO field with micro-frame bitmap. -+ * -+ * Initializes HCDMA register with descriptor list address and CTD value -+ * then starts the transfer via enabling the channel. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param hc Information needed to initialize the host channel. -+ */ -+void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) -+{ -+ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ hcchar_data_t hcchar; -+ hctsiz_data_t hctsiz; -+ hcdma_data_t hcdma; -+ -+ hctsiz.d32 = 0; -+ -+ if (hc->do_ping && !hc->ep_is_in) -+ hctsiz.b_ddma.dopng = 1; -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) -+ set_pid_isoc(hc); -+ -+ /* Packet Count and Xfer Size are not used in Descriptor DMA mode */ -+ hctsiz.b_ddma.pid = hc->data_pid_start; -+ hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ -+ hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); -+ DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); -+ -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ hcdma.d32 = 0; -+ hcdma.b.dma_addr = ((uint32_t)hc->desc_list_addr) >> 11; -+ -+ /* Always start from first descriptor. */ -+ hcdma.b.ctd = 0; -+ dwc_write_reg32(&hc_regs->hcdma, hcdma.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.multicnt = hc->multi_count; -+ -+#ifdef DEBUG -+ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; -+ if (hcchar.b.chdis) { -+ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", -+ __func__, hc->hc_num, hcchar.d32); -+ } -+#endif -+ -+ /* 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); -+ -+ hc->xfer_started = 1; -+ hc->requests++; -+ -+#ifdef DEBUG -+ if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) { -+ DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n", -+ hc->hc_num, core_if);//GRAYG -+ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; -+ core_if->hc_xfer_info[hc->hc_num].hc = hc; -+ /* Start a timer for this transfer. */ -+ DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); -+ } -+ -+#endif -+ -+} -+ -+/** -+ * This function continues a data transfer that was started by previous call -+ * to dwc_otg_hc_start_transfer. The caller must ensure there is -+ * sufficient space in the request queue and Tx Data FIFO. This function -+ * should only be called in Slave mode. In DMA mode, the controller acts -+ * autonomously to complete transfers programmed to a host channel. -+ * -+ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO -+ * if there is any data remaining to be queued. For an IN transfer, another -+ * data packet is always requested. For the SETUP phase of a control transfer, -+ * this function does nothing. -+ * -+ * @return 1 if a new request is queued, 0 if no more requests are required -+ * for this transfer. -+ */ -+int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) -+{ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ -+ if (hc->do_split) { -+ /* SPLITs always queue just once per channel */ -+ return 0; -+ } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { -+ /* SETUPs are queued only once since they can't be NAKed. */ -+ return 0; -+ } else if (hc->ep_is_in) { -+ /* -+ * Always queue another request for other IN transfers. If -+ * back-to-back INs are issued and NAKs are received for both, -+ * the driver may still be processing the first NAK when the -+ * second NAK is received. When the interrupt handler clears -+ * the NAK interrupt for the first NAK, the second NAK will -+ * not be seen. So we can't depend on the NAK interrupt -+ * handler to requeue a NAKed request. Instead, IN requests -+ * are issued each time this function is called. When the -+ * transfer completes, the extra requests for the channel will -+ * be flushed. -+ */ -+ hcchar_data_t hcchar; -+ dwc_otg_hc_regs_t *hc_regs = -+ core_if->host_if->hc_regs[hc->hc_num]; -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hc_set_even_odd_frame(core_if, hc, &hcchar); -+ hcchar.b.chen = 1; -+ hcchar.b.chdis = 0; -+ DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", -+ hcchar.d32); -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ hc->requests++; -+ return 1; -+ } else { -+ /* OUT transfers. */ -+ if (hc->xfer_count < hc->xfer_len) { -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ hcchar_data_t hcchar; -+ dwc_otg_hc_regs_t *hc_regs; -+ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hc_set_even_odd_frame(core_if, hc, &hcchar); -+ } -+ -+ /* Load OUT packet into the appropriate Tx FIFO. */ -+ dwc_otg_hc_write_packet(core_if, hc); -+ hc->requests++; -+ return 1; -+ } else { -+ return 0; -+ } -+ } -+} -+ -+/** -+ * Starts a PING transfer. This function should only be called in Slave mode. -+ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled. -+ */ -+void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) -+{ -+ hcchar_data_t hcchar; -+ hctsiz_data_t hctsiz; -+ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ -+ hctsiz.d32 = 0; -+ hctsiz.b.dopng = 1; -+ hctsiz.b.pktcnt = 1; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.chen = 1; -+ hcchar.b.chdis = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+} -+ -+/* -+ * This function writes a packet into the Tx FIFO associated with the Host -+ * Channel. For a channel associated with a non-periodic EP, the non-periodic -+ * Tx FIFO is written. For a channel associated with a periodic EP, the -+ * periodic Tx FIFO is written. This function should only be called in Slave -+ * mode. -+ * -+ * Upon return the xfer_buff and xfer_count fields in _hc are incremented by -+ * then number of bytes written to the Tx FIFO. -+ */ -+void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) -+{ -+ uint32_t i; -+ uint32_t remaining_count; -+ uint32_t byte_count; -+ uint32_t dword_count; -+ -+ uint32_t *data_buff = (uint32_t *) (hc->xfer_buff); -+ uint32_t *data_fifo = core_if->data_fifo[hc->hc_num]; -+ -+ remaining_count = hc->xfer_len - hc->xfer_count; -+ if (remaining_count > hc->max_packet) { -+ byte_count = hc->max_packet; -+ } else { -+ byte_count = remaining_count; -+ } -+ -+ dword_count = (byte_count + 3) / 4; -+ -+ if ((((unsigned long)data_buff) & 0x3) == 0) { -+ /* xfer_buff is DWORD aligned. */ -+ for (i = 0; i < dword_count; i++, data_buff++) { -+ dwc_write_reg32(data_fifo, *data_buff); -+ } -+ } else { -+ /* xfer_buff is not DWORD aligned. */ -+ for (i = 0; i < dword_count; i++, data_buff++) { -+ uint32_t data; -+ data = -+ (data_buff[0] | data_buff[1] << 8 | data_buff[2] << -+ 16 | data_buff[3] << 24); -+ dwc_write_reg32(data_fifo, data); -+ } -+ } -+ -+ hc->xfer_count += byte_count; -+ hc->xfer_buff += byte_count; -+} -+ -+/** -+ * Gets the current USB frame number. This is the frame number from the last -+ * SOF packet. -+ */ -+uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if) -+{ -+ dsts_data_t dsts; -+ dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ -+ /* read current frame/microframe number from DSTS register */ -+ return dsts.b.soffn; -+} -+ -+/** -+ * This function reads a setup packet from the Rx FIFO into the destination -+ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) -+ * Interrupt routine when a SETUP packet has been received in Slave mode. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param dest Destination buffer for packet data. -+ */ -+void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest) -+{ -+ /* Get the 8 bytes of a setup transaction data */ -+ -+ /* Pop 2 DWORDS off the receive data FIFO into memory */ -+ dest[0] = dwc_read_reg32(core_if->data_fifo[0]); -+ dest[1] = dwc_read_reg32(core_if->data_fifo[0]); -+} -+ -+/** -+ * This function enables EP0 OUT to receive SETUP packets and configures EP0 -+ * IN for transmitting packets. It is normally called when the -+ * "Enumeration Done" interrupt occurs. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP0 data. -+ */ -+void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ dsts_data_t dsts; -+ depctl_data_t diepctl; -+ depctl_data_t doepctl; -+ dctl_data_t dctl = {.d32 = 0 }; -+ -+ /* Read the Device Status and Endpoint 0 Control registers */ -+ dsts.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dsts); -+ diepctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl); -+ doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl); -+ -+ /* Set the MPS of the IN EP based on the enumeration speed */ -+ switch (dsts.b.enumspd) { -+ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: -+ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: -+ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: -+ diepctl.b.mps = DWC_DEP0CTL_MPS_64; -+ break; -+ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: -+ diepctl.b.mps = DWC_DEP0CTL_MPS_8; -+ break; -+ } -+ -+ dwc_write_reg32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); -+ -+ /* Enable OUT EP for receive */ -+ doepctl.b.epena = 1; -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); -+ -+#ifdef VERBOSE -+ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", -+ dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); -+ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", -+ dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl)); -+#endif -+ dctl.b.cgnpinnak = 1; -+ -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); -+ DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n", -+ dwc_read_reg32(&dev_if->dev_global_regs->dctl)); -+} -+ -+/** -+ * This function activates an EP. The Device EP control register for -+ * the EP is configured as defined in the ep structure. Note: This -+ * function is not used for EP0. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to activate. -+ */ -+void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ depctl_data_t depctl; -+ volatile uint32_t *addr; -+ daint_data_t daintmsk = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, -+ (ep->is_in ? "IN" : "OUT")); -+ -+ /* Read DEPCTLn register */ -+ if (ep->is_in == 1) { -+ addr = &dev_if->in_ep_regs[ep->num]->diepctl; -+ daintmsk.ep.in = 1 << ep->num; -+ } else { -+ addr = &dev_if->out_ep_regs[ep->num]->doepctl; -+ daintmsk.ep.out = 1 << ep->num; -+ } -+ -+ /* If the EP is already active don't change the EP Control -+ * register. */ -+ depctl.d32 = dwc_read_reg32(addr); -+ if (!depctl.b.usbactep) { -+ depctl.b.mps = ep->maxpacket; -+ depctl.b.eptype = ep->type; -+ depctl.b.txfnum = ep->tx_fifo_num; -+ -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ depctl.b.setd0pid = 1; // ??? -+ } else { -+ depctl.b.setd0pid = 1; -+ } -+ depctl.b.usbactep = 1; -+ -+ dwc_write_reg32(addr, depctl.d32); -+ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", dwc_read_reg32(addr)); -+ } -+ -+ /* Enable the Interrupt for this EP */ -+ if (core_if->multiproc_int_enable) { -+ if (ep->is_in == 1) { -+ diepmsk_data_t diepmsk = {.d32 = 0 }; -+ diepmsk.b.xfercompl = 1; -+ diepmsk.b.timeout = 1; -+ diepmsk.b.epdisabled = 1; -+ diepmsk.b.ahberr = 1; -+ diepmsk.b.intknepmis = 1; -+ diepmsk.b.txfifoundrn = 1; //????? -+ -+ if (core_if->dma_desc_enable) { -+ diepmsk.b.bna = 1; -+ } -+/* -+ if(core_if->dma_enable) { -+ doepmsk.b.nak = 1; -+ } -+*/ -+ dwc_write_reg32(&dev_if->dev_global_regs-> -+ diepeachintmsk[ep->num], diepmsk.d32); -+ -+ } else { -+ doepmsk_data_t doepmsk = {.d32 = 0 }; -+ doepmsk.b.xfercompl = 1; -+ doepmsk.b.ahberr = 1; -+ doepmsk.b.epdisabled = 1; -+ -+ if (core_if->dma_desc_enable) { -+ doepmsk.b.bna = 1; -+ } -+/* -+ doepmsk.b.babble = 1; -+ doepmsk.b.nyet = 1; -+ doepmsk.b.nak = 1; -+*/ -+ dwc_write_reg32(&dev_if->dev_global_regs-> -+ doepeachintmsk[ep->num], doepmsk.d32); -+ } -+ dwc_modify_reg32(&dev_if->dev_global_regs->deachintmsk, -+ 0, daintmsk.d32); -+ } else { -+ dwc_modify_reg32(&dev_if->dev_global_regs->daintmsk, -+ 0, daintmsk.d32); -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", -+ dwc_read_reg32(&dev_if->dev_global_regs->daintmsk)); -+ -+ ep->stall_clear_flag = 0; -+ return; -+} -+ -+/** -+ * This function deactivates an EP. This is done by clearing the USB Active -+ * EP bit in the Device EP control register. Note: This function is not used -+ * for EP0. EP0 cannot be deactivated. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to deactivate. -+ */ -+void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ depctl_data_t depctl = {.d32 = 0 }; -+ volatile uint32_t *addr; -+ daint_data_t daintmsk = {.d32 = 0 }; -+ -+ /* Read DEPCTLn register */ -+ if (ep->is_in == 1) { -+ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; -+ daintmsk.ep.in = 1 << ep->num; -+ } else { -+ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; -+ daintmsk.ep.out = 1 << ep->num; -+ } -+ -+ depctl.d32 = dwc_read_reg32(addr); -+ -+ depctl.b.usbactep = 0; -+ -+ if (core_if->dma_desc_enable) -+ depctl.b.epdis = 1; -+ -+ dwc_write_reg32(addr, depctl.d32); -+ -+ /* Disable the Interrupt for this EP */ -+ if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->deachintmsk, -+ daintmsk.d32, 0); -+ -+ if (ep->is_in == 1) { -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs-> -+ diepeachintmsk[ep->num], 0); -+ } else { -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs-> -+ doepeachintmsk[ep->num], 0); -+ } -+ } else { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->daintmsk, -+ daintmsk.d32, 0); -+ } -+} -+ -+/** -+ * This function initializes dma descriptor chain. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ */ -+static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ uint32_t offset; -+ uint32_t xfer_est; -+ int i; -+ -+ ep->desc_cnt = (ep->total_len / ep->maxxfer) + -+ ((ep->total_len % ep->maxxfer) ? 1 : 0); -+ if (!ep->desc_cnt) -+ ep->desc_cnt = 1; -+ -+ dma_desc = ep->desc_addr; -+ xfer_est = ep->total_len; -+ offset = 0; -+ for (i = 0; i < ep->desc_cnt; ++i) { -+ /** DMA Descriptor Setup */ -+ if (xfer_est > ep->maxxfer) { -+ dma_desc->status.b.bs = BS_HOST_BUSY; -+ dma_desc->status.b.l = 0; -+ dma_desc->status.b.ioc = 0; -+ dma_desc->status.b.sp = 0; -+ dma_desc->status.b.bytes = ep->maxxfer; -+ dma_desc->buf = ep->dma_addr + offset; -+ dma_desc->status.b.bs = BS_HOST_READY; -+ -+ xfer_est -= ep->maxxfer; -+ offset += ep->maxxfer; -+ } else { -+ dma_desc->status.b.bs = BS_HOST_BUSY; -+ dma_desc->status.b.l = 1; -+ dma_desc->status.b.ioc = 1; -+ if (ep->is_in) { -+ dma_desc->status.b.sp = -+ (xfer_est % -+ ep->maxpacket) ? 1 : ((ep-> -+ sent_zlp) ? 1 : 0); -+ dma_desc->status.b.bytes = xfer_est; -+ } else { -+ dma_desc->status.b.bytes = -+ xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); -+ } -+ -+ dma_desc->buf = ep->dma_addr + offset; -+ dma_desc->status.b.bs = BS_HOST_READY; -+ } -+ dma_desc++; -+ } -+} -+ -+/** -+ * This function does the setup for a data transfer for an EP and -+ * starts the transfer. For an IN transfer, the packets will be -+ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, -+ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ */ -+ -+void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ depctl_data_t depctl; -+ deptsiz_data_t deptsiz; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); -+ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " -+ "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n", -+ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, -+ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff, -+ ep->total_len); -+ /* IN endpoint */ -+ if (ep->is_in == 1) { -+ dwc_otg_dev_in_ep_regs_t *in_regs = -+ core_if->dev_if->in_ep_regs[ep->num]; -+ -+ gnptxsts_data_t gtxstatus; -+ -+ gtxstatus.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ -+ if (core_if->en_multiple_tx_fifo == 0 -+ && gtxstatus.b.nptxqspcavail == 0) { -+#ifdef DEBUG -+ DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32); -+#endif -+ return; -+ } -+ -+ depctl.d32 = dwc_read_reg32(&(in_regs->diepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz)); -+ -+ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? -+ ep->maxxfer : (ep->total_len - ep->xfer_len); -+ -+ /* Zero Length Packet? */ -+ if ((ep->xfer_len - ep->xfer_count) == 0) { -+ deptsiz.b.xfersize = 0; -+ deptsiz.b.pktcnt = 1; -+ } else { -+ /* Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; -+ deptsiz.b.pktcnt = -+ (ep->xfer_len - ep->xfer_count - 1 + -+ ep->maxpacket) / ep->maxpacket; -+ } -+ -+ /* Write the DMA register */ -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable == 0) { -+ dwc_write_reg32(&in_regs->dieptsiz, -+ deptsiz.d32); -+ dwc_write_reg32(&(in_regs->diepdma), -+ (uint32_t) ep->dma_addr); -+ } else { -+#ifdef DWC_UTE_CFI -+ /* The descriptor chain should be already initialized by now */ -+ if (ep->buff_mode != BM_STANDARD) { -+ dwc_write_reg32(&in_regs->diepdma, -+ ep->descs_dma_addr); -+ } else { -+#endif -+ init_dma_desc_chain(core_if, ep); -+ /** DIEPDMAn Register write */ -+ dwc_write_reg32(&in_regs->diepdma, -+ ep->dma_desc_addr); -+#ifdef DWC_UTE_CFI -+ } -+#endif -+ } -+ } else { -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ if (ep->type != DWC_OTG_EP_TYPE_ISOC) { -+ /** -+ * Enable the Non-Periodic Tx FIFO empty interrupt, -+ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, -+ * the data will be written into the fifo by the ISR. -+ */ -+ if (core_if->en_multiple_tx_fifo == 0) { -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if-> -+ core_global_regs-> -+ gintmsk, intr_mask.d32, -+ intr_mask.d32); -+ } else { -+ /* Enable the Tx FIFO Empty Interrupt for this EP */ -+ if (ep->xfer_len > 0) { -+ uint32_t fifoemptymsk = 0; -+ fifoemptymsk = 1 << ep->num; -+ dwc_modify_reg32(&core_if-> -+ dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, -+ 0, -+ fifoemptymsk); -+ -+ } -+ } -+ } -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ depctl.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -+ depctl.b.nextep = ep->num; -+ dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl, -+ depctl.d32); -+ -+ } else { -+ /* OUT endpoint */ -+ dwc_otg_dev_out_ep_regs_t *out_regs = -+ core_if->dev_if->out_ep_regs[ep->num]; -+ -+ depctl.d32 = dwc_read_reg32(&(out_regs->doepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz)); -+ -+ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? -+ ep->maxxfer : (ep->total_len - ep->xfer_len); -+ -+ /* Program the transfer size and packet count as follows: -+ * -+ * pktcnt = N -+ * xfersize = N * maxpacket -+ */ -+ if ((ep->xfer_len - ep->xfer_count) == 0) { -+ /* Zero Length Packet */ -+ deptsiz.b.xfersize = ep->maxpacket; -+ deptsiz.b.pktcnt = 1; -+ } else { -+ deptsiz.b.pktcnt = -+ (ep->xfer_len - ep->xfer_count + -+ (ep->maxpacket - 1)) / ep->maxpacket; -+ ep->xfer_len = -+ deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; -+ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n", -+ ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt); -+ -+ if (core_if->dma_enable) { -+ if (!core_if->dma_desc_enable) { -+ dwc_write_reg32(&out_regs->doeptsiz, -+ deptsiz.d32); -+ -+ dwc_write_reg32(&(out_regs->doepdma), -+ (uint32_t) ep->dma_addr); -+ } else { -+#ifdef DWC_UTE_CFI -+ /* The descriptor chain should be already initialized by now */ -+ if (ep->buff_mode != BM_STANDARD) { -+ dwc_write_reg32(&out_regs->doepdma, -+ ep->descs_dma_addr); -+ } else { -+#endif -+ -+ init_dma_desc_chain(core_if, ep); -+ -+ /** DOEPDMAn Register write */ -+ dwc_write_reg32(&out_regs->doepdma, -+ ep->dma_desc_addr); -+#ifdef DWC_UTE_CFI -+ } -+#endif -+ } -+ } else { -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ } -+ -+ /* EP enable */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ -+ dwc_write_reg32(&out_regs->doepctl, depctl.d32); -+ -+ DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", -+ dwc_read_reg32(&out_regs->doepctl), -+ dwc_read_reg32(&out_regs->doeptsiz)); -+ DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ daintmsk), -+ dwc_read_reg32(&core_if->core_global_regs-> -+ gintmsk)); -+ } -+} -+ -+/** -+ * This function setup a zero length transfer in Buffer DMA and -+ * Slave modes for usb requests with zero field set -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ * -+ */ -+void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ -+ depctl_data_t depctl; -+ deptsiz_data_t deptsiz; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); -+ DWC_PRINTF("zero length transfer is called\n"); -+ -+ /* IN endpoint */ -+ if (ep->is_in == 1) { -+ dwc_otg_dev_in_ep_regs_t *in_regs = -+ core_if->dev_if->in_ep_regs[ep->num]; -+ -+ depctl.d32 = dwc_read_reg32(&(in_regs->diepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz)); -+ -+ deptsiz.b.xfersize = 0; -+ deptsiz.b.pktcnt = 1; -+ -+ /* Write the DMA register */ -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable == 0) { -+ dwc_write_reg32(&in_regs->dieptsiz, -+ deptsiz.d32); -+ dwc_write_reg32(&(in_regs->diepdma), -+ (uint32_t) ep->dma_addr); -+ } -+ } else { -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ /** -+ * Enable the Non-Periodic Tx FIFO empty interrupt, -+ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, -+ * the data will be written into the fifo by the ISR. -+ */ -+ if (core_if->en_multiple_tx_fifo == 0) { -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs-> -+ gintmsk, intr_mask.d32, -+ intr_mask.d32); -+ } else { -+ /* Enable the Tx FIFO Empty Interrupt for this EP */ -+ if (ep->xfer_len > 0) { -+ uint32_t fifoemptymsk = 0; -+ fifoemptymsk = 1 << ep->num; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, -+ 0, fifoemptymsk); -+ } -+ } -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ depctl.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -+ depctl.b.nextep = ep->num; -+ dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl, -+ depctl.d32); -+ -+ } else { -+ /* OUT endpoint */ -+ dwc_otg_dev_out_ep_regs_t *out_regs = -+ core_if->dev_if->out_ep_regs[ep->num]; -+ -+ depctl.d32 = dwc_read_reg32(&(out_regs->doepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz)); -+ -+ /* Zero Length Packet */ -+ deptsiz.b.xfersize = ep->maxpacket; -+ deptsiz.b.pktcnt = 1; -+ -+ if (core_if->dma_enable) { -+ if (!core_if->dma_desc_enable) { -+ dwc_write_reg32(&out_regs->doeptsiz, -+ deptsiz.d32); -+ -+ dwc_write_reg32(&(out_regs->doepdma), -+ (uint32_t) ep->dma_addr); -+ } -+ } else { -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ } -+ -+ /* EP enable */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ -+ dwc_write_reg32(&out_regs->doepctl, depctl.d32); -+ -+ } -+} -+ -+/** -+ * This function does the setup for a data transfer for EP0 and starts -+ * the transfer. For an IN transfer, the packets will be loaded into -+ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are -+ * unloaded from the Rx FIFO in the ISR. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP0 data. -+ */ -+void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ depctl_data_t depctl; -+ deptsiz0_data_t deptsiz; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ -+ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " -+ "xfer_buff=%p start_xfer_buff=%p \n", -+ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, -+ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); -+ -+ ep->total_len = ep->xfer_len; -+ -+ /* IN endpoint */ -+ if (ep->is_in == 1) { -+ dwc_otg_dev_in_ep_regs_t *in_regs = -+ core_if->dev_if->in_ep_regs[0]; -+ -+ gnptxsts_data_t gtxstatus; -+ -+ gtxstatus.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ -+ if (core_if->en_multiple_tx_fifo == 0 -+ && gtxstatus.b.nptxqspcavail == 0) { -+#ifdef DEBUG -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", -+ dwc_read_reg32(&in_regs->diepctl)); -+ DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", -+ deptsiz.d32, -+ deptsiz.b.xfersize, deptsiz.b.pktcnt); -+ DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n", -+ gtxstatus.d32); -+#endif -+ return; -+ } -+ -+ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ -+ /* Zero Length Packet? */ -+ if (ep->xfer_len == 0) { -+ deptsiz.b.xfersize = 0; -+ deptsiz.b.pktcnt = 1; -+ } else { -+ /* Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ if (ep->xfer_len > ep->maxpacket) { -+ ep->xfer_len = ep->maxpacket; -+ deptsiz.b.xfersize = ep->maxpacket; -+ } else { -+ deptsiz.b.xfersize = ep->xfer_len; -+ } -+ deptsiz.b.pktcnt = 1; -+ -+ } -+ DWC_DEBUGPL(DBG_PCDV, -+ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", -+ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, -+ deptsiz.d32); -+ -+ /* Write the DMA register */ -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable == 0) { -+ dwc_write_reg32(&in_regs->dieptsiz, -+ deptsiz.d32); -+ -+ dwc_write_reg32(&(in_regs->diepdma), -+ (uint32_t) ep->dma_addr); -+ } else { -+ dma_desc = core_if->dev_if->in_desc_addr; -+ -+ /** DMA Descriptor Setup */ -+ dma_desc->status.b.bs = BS_HOST_BUSY; -+ dma_desc->status.b.l = 1; -+ dma_desc->status.b.ioc = 1; -+ dma_desc->status.b.sp = -+ (ep->xfer_len == ep->maxpacket) ? 0 : 1; -+ dma_desc->status.b.bytes = ep->xfer_len; -+ dma_desc->buf = ep->dma_addr; -+ dma_desc->status.b.bs = BS_HOST_READY; -+ -+ /** DIEPDMA0 Register write */ -+ dwc_write_reg32(&in_regs->diepdma, -+ core_if->dev_if-> -+ dma_in_desc_addr); -+ } -+ } else { -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ /** -+ * Enable the Non-Periodic Tx FIFO empty interrupt, the -+ * data will be written into the fifo by the ISR. -+ */ -+ if (!core_if->dma_enable) { -+ if (core_if->en_multiple_tx_fifo == 0) { -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs-> -+ gintmsk, intr_mask.d32, -+ intr_mask.d32); -+ } else { -+ /* Enable the Tx FIFO Empty Interrupt for this EP */ -+ if (ep->xfer_len > 0) { -+ uint32_t fifoemptymsk = 0; -+ fifoemptymsk |= 1 << ep->num; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, -+ 0, fifoemptymsk); -+ } -+ } -+ } -+ } else { -+ /* OUT endpoint */ -+ dwc_otg_dev_out_ep_regs_t *out_regs = -+ core_if->dev_if->out_ep_regs[0]; -+ -+ depctl.d32 = dwc_read_reg32(&out_regs->doepctl); -+ deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz); -+ -+ /* Program the transfer size and packet count as follows: -+ * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) -+ * pktcnt = N */ -+ /* Zero Length Packet */ -+ deptsiz.b.xfersize = ep->maxpacket; -+ deptsiz.b.pktcnt = 1; -+ -+ DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", -+ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt); -+ -+ if (core_if->dma_enable) { -+ if (!core_if->dma_desc_enable) { -+ dwc_write_reg32(&out_regs->doeptsiz, -+ deptsiz.d32); -+ -+ dwc_write_reg32(&(out_regs->doepdma), -+ (uint32_t) ep->dma_addr); -+ } else { -+ dma_desc = core_if->dev_if->out_desc_addr; -+ -+ /** DMA Descriptor Setup */ -+ dma_desc->status.b.bs = BS_HOST_BUSY; -+ dma_desc->status.b.l = 1; -+ dma_desc->status.b.ioc = 1; -+ dma_desc->status.b.bytes = ep->maxpacket; -+ dma_desc->buf = ep->dma_addr; -+ dma_desc->status.b.bs = BS_HOST_READY; -+ -+ /** DOEPDMA0 Register write */ -+ dwc_write_reg32(&out_regs->doepdma, -+ core_if->dev_if-> -+ dma_out_desc_addr); -+ } -+ } else { -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ } -+ -+ /* EP enable */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&(out_regs->doepctl), depctl.d32); -+ } -+} -+ -+/** -+ * This function continues control IN transfers started by -+ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a -+ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one -+ * bit for the packet count. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP0 data. -+ */ -+void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ depctl_data_t depctl; -+ deptsiz0_data_t deptsiz; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ -+ if (ep->is_in == 1) { -+ dwc_otg_dev_in_ep_regs_t *in_regs = -+ core_if->dev_if->in_ep_regs[0]; -+ gnptxsts_data_t tx_status = {.d32 = 0 }; -+ -+ tx_status.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ /** @todo Should there be check for room in the Tx -+ * Status Queue. If not remove the code above this comment. */ -+ -+ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ -+ /* Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ -+ if (core_if->dma_desc_enable == 0) { -+ deptsiz.b.xfersize = -+ (ep->total_len - ep->xfer_count) > -+ ep->maxpacket ? ep->maxpacket : (ep->total_len - -+ ep->xfer_count); -+ deptsiz.b.pktcnt = 1; -+ if (core_if->dma_enable == 0) { -+ ep->xfer_len += deptsiz.b.xfersize; -+ } else { -+ ep->xfer_len = deptsiz.b.xfersize; -+ } -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ } else { -+ ep->xfer_len = -+ (ep->total_len - ep->xfer_count) > -+ ep->maxpacket ? ep->maxpacket : (ep->total_len - -+ ep->xfer_count); -+ -+ dma_desc = core_if->dev_if->in_desc_addr; -+ -+ /** DMA Descriptor Setup */ -+ dma_desc->status.b.bs = BS_HOST_BUSY; -+ dma_desc->status.b.l = 1; -+ dma_desc->status.b.ioc = 1; -+ dma_desc->status.b.sp = -+ (ep->xfer_len == ep->maxpacket) ? 0 : 1; -+ dma_desc->status.b.bytes = ep->xfer_len; -+ dma_desc->buf = ep->dma_addr; -+ dma_desc->status.b.bs = BS_HOST_READY; -+ -+ /** DIEPDMA0 Register write */ -+ dwc_write_reg32(&in_regs->diepdma, -+ core_if->dev_if->dma_in_desc_addr); -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, -+ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", -+ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, -+ deptsiz.d32); -+ -+ /* Write the DMA register */ -+ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { -+ if (core_if->dma_desc_enable == 0) -+ dwc_write_reg32(&(in_regs->diepdma), -+ (uint32_t) ep->dma_addr); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ /** -+ * Enable the Non-Periodic Tx FIFO empty interrupt, the -+ * data will be written into the fifo by the ISR. -+ */ -+ if (!core_if->dma_enable) { -+ if (core_if->en_multiple_tx_fifo == 0) { -+ /* First clear it from GINTSTS */ -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs-> -+ gintmsk, intr_mask.d32, -+ intr_mask.d32); -+ -+ } else { -+ /* Enable the Tx FIFO Empty Interrupt for this EP */ -+ if (ep->xfer_len > 0) { -+ uint32_t fifoemptymsk = 0; -+ fifoemptymsk |= 1 << ep->num; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, -+ 0, fifoemptymsk); -+ } -+ } -+ } -+ } else { -+ dwc_otg_dev_out_ep_regs_t *out_regs = -+ core_if->dev_if->out_ep_regs[0]; -+ -+ depctl.d32 = dwc_read_reg32(&out_regs->doepctl); -+ deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz); -+ -+ /* Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ deptsiz.b.xfersize = ep->maxpacket; -+ deptsiz.b.pktcnt = 1; -+ -+ if (core_if->dma_desc_enable == 0) { -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ } else { -+ dma_desc = core_if->dev_if->out_desc_addr; -+ -+ /** DMA Descriptor Setup */ -+ dma_desc->status.b.bs = BS_HOST_BUSY; -+ dma_desc->status.b.l = 1; -+ dma_desc->status.b.ioc = 1; -+ dma_desc->status.b.bytes = ep->maxpacket; -+ dma_desc->buf = ep->dma_addr; -+ dma_desc->status.b.bs = BS_HOST_READY; -+ -+ /** DOEPDMA0 Register write */ -+ dwc_write_reg32(&out_regs->doepdma, -+ core_if->dev_if->dma_out_desc_addr); -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, -+ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", -+ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, -+ deptsiz.d32); -+ -+ /* Write the DMA register */ -+ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { -+ if (core_if->dma_desc_enable == 0) -+ dwc_write_reg32(&(out_regs->doepdma), -+ (uint32_t) ep->dma_addr); -+ } -+ -+ /* EP enable, IN data in FIFO */ -+ depctl.b.cnak = 1; -+ depctl.b.epena = 1; -+ dwc_write_reg32(&out_regs->doepctl, depctl.d32); -+ -+ } -+} -+ -+#ifdef DEBUG -+void dump_msg(const u8 * buf, unsigned int length) -+{ -+ unsigned int start, num, i; -+ char line[52], *p; -+ -+ if (length >= 512) -+ return; -+ start = 0; -+ while (length > 0) { -+ num = length < 16u ? length : 16u; -+ p = line; -+ for (i = 0; i < num; ++i) { -+ if (i == 8) -+ *p++ = ' '; -+ DWC_SPRINTF(p, " %02x", buf[i]); -+ p += 3; -+ } -+ *p = 0; -+ DWC_PRINTF("%6x: %s\n", start, line); -+ buf += num; -+ start += num; -+ length -= num; -+ } -+} -+#else -+static inline void dump_msg(const u8 * buf, unsigned int length) -+{ -+} -+#endif -+ -+/** -+ * This function writes a packet into the Tx FIFO associated with the -+ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For -+ * periodic EPs the periodic Tx FIFO associated with the EP is written -+ * with all packets for the next micro-frame. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to write packet for. -+ * @param dma Indicates if DMA is being used. -+ */ -+void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep, -+ int dma) -+{ -+ /** -+ * The buffer is padded to DWORD on a per packet basis in -+ * slave/dma mode if the MPS is not DWORD aligned. The last -+ * packet, if short, is also padded to a multiple of DWORD. -+ * -+ * ep->xfer_buff always starts DWORD aligned in memory and is a -+ * multiple of DWORD in length -+ * -+ * ep->xfer_len can be any number of bytes -+ * -+ * ep->xfer_count is a multiple of ep->maxpacket until the last -+ * packet -+ * -+ * FIFO access is DWORD */ -+ -+ uint32_t i; -+ uint32_t byte_count; -+ uint32_t dword_count; -+ uint32_t *fifo; -+ uint32_t *data_buff = (uint32_t *) ep->xfer_buff; -+ -+ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if, -+ ep); -+ if (ep->xfer_count >= ep->xfer_len) { -+ DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num); -+ return; -+ } -+ -+ /* Find the byte length of the packet either short packet or MPS */ -+ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) { -+ byte_count = ep->xfer_len - ep->xfer_count; -+ } else { -+ byte_count = ep->maxpacket; -+ } -+ -+ /* Find the DWORD length, padded by extra bytes as neccessary if MPS -+ * is not a multiple of DWORD */ -+ dword_count = (byte_count + 3) / 4; -+ -+#ifdef VERBOSE -+ dump_msg(ep->xfer_buff, byte_count); -+#endif -+ -+ /**@todo NGS Where are the Periodic Tx FIFO addresses -+ * intialized? What should this be? */ -+ -+ fifo = core_if->data_fifo[ep->num]; -+ -+ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n", -+ fifo, data_buff, *data_buff, byte_count); -+ -+ if (!dma) { -+ for (i = 0; i < dword_count; i++, data_buff++) { -+ dwc_write_reg32(fifo, *data_buff); -+ } -+ } -+ -+ ep->xfer_count += byte_count; -+ ep->xfer_buff += byte_count; -+ ep->dma_addr += byte_count; -+} -+ -+/** -+ * Set the EP STALL. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to set the stall on. -+ */ -+void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ depctl_data_t depctl; -+ volatile uint32_t *depctl_addr; -+ -+ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, -+ (ep->is_in ? "IN" : "OUT")); -+ -+ if (ep->is_in == 1) { -+ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); -+ depctl.d32 = dwc_read_reg32(depctl_addr); -+ -+ /* set the disable and stall bits */ -+ if (depctl.b.epena) { -+ depctl.b.epdis = 1; -+ } -+ depctl.b.stall = 1; -+ dwc_write_reg32(depctl_addr, depctl.d32); -+ } else { -+ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); -+ depctl.d32 = dwc_read_reg32(depctl_addr); -+ -+ /* set the stall bit */ -+ depctl.b.stall = 1; -+ dwc_write_reg32(depctl_addr, depctl.d32); -+ } -+ -+ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); -+ -+ return; -+} -+ -+/** -+ * Clear the EP STALL. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to clear stall from. -+ */ -+void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ depctl_data_t depctl; -+ volatile uint32_t *depctl_addr; -+ -+ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, -+ (ep->is_in ? "IN" : "OUT")); -+ -+ if (ep->is_in == 1) { -+ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); -+ } else { -+ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); -+ } -+ -+ depctl.d32 = dwc_read_reg32(depctl_addr); -+ -+ /* clear the stall bits */ -+ depctl.b.stall = 0; -+ -+ /* -+ * USB Spec 9.4.5: For endpoints using data toggle, regardless -+ * of whether an endpoint has the Halt feature set, a -+ * ClearFeature(ENDPOINT_HALT) request always results in the -+ * data toggle being reinitialized to DATA0. -+ */ -+ if (ep->type == DWC_OTG_EP_TYPE_INTR || -+ ep->type == DWC_OTG_EP_TYPE_BULK) { -+ depctl.b.setd0pid = 1; /* DATA0 */ -+ } -+ -+ dwc_write_reg32(depctl_addr, depctl.d32); -+ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); -+ return; -+} -+ -+/** -+ * This function reads a packet from the Rx FIFO into the destination -+ * buffer. To read SETUP data use dwc_otg_read_setup_packet. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param dest Destination buffer for the packet. -+ * @param bytes Number of bytes to copy to the destination. -+ */ -+void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, -+ uint8_t * dest, uint16_t bytes) -+{ -+ int i; -+ int word_count = (bytes + 3) / 4; -+ -+ volatile uint32_t *fifo = core_if->data_fifo[0]; -+ uint32_t *data_buff = (uint32_t *) dest; -+ -+ /** -+ * @todo Account for the case where _dest is not dword aligned. This -+ * requires reading data from the FIFO into a uint32_t temp buffer, -+ * then moving it into the data buffer. -+ */ -+ -+ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__, -+ core_if, dest, bytes); -+ -+ for (i = 0; i < word_count; i++, data_buff++) { -+ *data_buff = dwc_read_reg32(fifo); -+ } -+ -+ return; -+} -+ -+/** -+ * This functions reads the device registers and prints them -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if) -+{ -+ int i; -+ volatile uint32_t *addr; -+ -+ DWC_PRINTF("Device Global Registers\n"); -+ addr = &core_if->dev_if->dev_global_regs->dcfg; -+ DWC_PRINTF("DCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->dctl; -+ DWC_PRINTF("DCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->dsts; -+ DWC_PRINTF("DSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->diepmsk; -+ DWC_PRINTF("DIEPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->doepmsk; -+ DWC_PRINTF("DOEPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->daint; -+ DWC_PRINTF("DAINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->daintmsk; -+ DWC_PRINTF("DAINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->dtknqr1; -+ DWC_PRINTF("DTKNQR1 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ if (core_if->hwcfg2.b.dev_token_q_depth > 6) { -+ addr = &core_if->dev_if->dev_global_regs->dtknqr2; -+ DWC_PRINTF("DTKNQR2 @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ } -+ -+ addr = &core_if->dev_if->dev_global_regs->dvbusdis; -+ DWC_PRINTF("DVBUSID @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ -+ addr = &core_if->dev_if->dev_global_regs->dvbuspulse; -+ DWC_PRINTF("DVBUSPULSE @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ -+ addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; -+ DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ -+ if (core_if->hwcfg2.b.dev_token_q_depth > 22) { -+ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; -+ DWC_PRINTF("DTKNQR4 @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ } -+ -+ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; -+ DWC_PRINTF("FIFOEMPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ -+ addr = &core_if->dev_if->dev_global_regs->deachint; -+ DWC_PRINTF("DEACHINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->deachintmsk; -+ DWC_PRINTF("DEACHINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ -+ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { -+ addr = &core_if->dev_if->dev_global_regs->diepeachintmsk[i]; -+ DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08X : 0x%08X\n", i, -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ } -+ -+ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { -+ addr = &core_if->dev_if->dev_global_regs->doepeachintmsk[i]; -+ DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08X : 0x%08X\n", i, -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ } -+ -+ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { -+ DWC_PRINTF("Device IN EP %d Registers\n", i); -+ addr = &core_if->dev_if->in_ep_regs[i]->diepctl; -+ DWC_PRINTF("DIEPCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->in_ep_regs[i]->diepint; -+ DWC_PRINTF("DIEPINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; -+ DWC_PRINTF("DIETSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->in_ep_regs[i]->diepdma; -+ DWC_PRINTF("DIEPDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts; -+ DWC_PRINTF("DTXFSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->in_ep_regs[i]->diepdmab; -+ DWC_PRINTF("DIEPDMAB @0x%08X : 0x%08X\n", (uint32_t) addr, -+ 0 /*dwc_read_reg32(addr) */ ); -+ } -+ -+ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { -+ DWC_PRINTF("Device OUT EP %d Registers\n", i); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepctl; -+ DWC_PRINTF("DOEPCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepfn; -+ DWC_PRINTF("DOEPFN @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepint; -+ DWC_PRINTF("DOEPINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; -+ DWC_PRINTF("DOETSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepdma; -+ DWC_PRINTF("DOEPDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */ -+ addr = &core_if->dev_if->out_ep_regs[i]->doepdmab; -+ DWC_PRINTF("DOEPDMAB @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ } -+ -+ } -+} -+ -+/** -+ * This functions reads the SPRAM and prints its content -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if) -+{ -+ volatile uint8_t *addr, *start_addr, *end_addr; -+ -+ DWC_PRINTF("SPRAM Data:\n"); -+ start_addr = (void *)core_if->core_global_regs; -+ DWC_PRINTF("Base Address: 0x%8X\n", (uint32_t) start_addr); -+ start_addr += 0x00028000; -+ end_addr = (void *)core_if->core_global_regs; -+ end_addr += 0x000280e0; -+ -+ for (addr = start_addr; addr < end_addr; addr += 16) { -+ DWC_PRINTF -+ ("0x%8X:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", -+ (uint32_t) addr, addr[0], addr[1], addr[2], addr[3], -+ addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], -+ addr[10], addr[11], addr[12], addr[13], addr[14], addr[15] -+ ); -+ } -+ -+ return; -+} -+ -+/** -+ * This function reads the host registers and prints them -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if) -+{ -+ int i; -+ volatile uint32_t *addr; -+ -+ DWC_PRINTF("Host Global Registers\n"); -+ addr = &core_if->host_if->host_global_regs->hcfg; -+ DWC_PRINTF("HCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->hfir; -+ DWC_PRINTF("HFIR @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->hfnum; -+ DWC_PRINTF("HFNUM @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->hptxsts; -+ DWC_PRINTF("HPTXSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->haint; -+ DWC_PRINTF("HAINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->host_global_regs->haintmsk; -+ DWC_PRINTF("HAINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ if (core_if->dma_desc_enable) { -+ addr = &core_if->host_if->host_global_regs->hflbaddr; -+ DWC_PRINTF("HFLBADDR @0x%08X : 0x%08X\n",(uint32_t) addr, -+ dwc_read_reg32(addr)); -+ } -+ -+ addr = core_if->host_if->hprt0; -+ DWC_PRINTF("HPRT0 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ -+ for (i = 0; i < core_if->core_params->host_channels; i++) { -+ DWC_PRINTF("Host Channel %d Specific Registers\n", i); -+ addr = &core_if->host_if->hc_regs[i]->hcchar; -+ DWC_PRINTF("HCCHAR @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hcsplt; -+ DWC_PRINTF("HCSPLT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hcint; -+ DWC_PRINTF("HCINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hcintmsk; -+ DWC_PRINTF("HCINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hctsiz; -+ DWC_PRINTF("HCTSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->host_if->hc_regs[i]->hcdma; -+ DWC_PRINTF("HCDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ if (core_if->dma_desc_enable) { -+ addr=&core_if->host_if->hc_regs[i]->hcdmab; -+ DWC_PRINTF("HCDMAB @0x%08X : 0x%08X\n",(uint32_t) addr, dwc_read_reg32(addr)); -+ } -+ -+ } -+ return; -+} -+ -+/** -+ * This function reads the core global registers and prints them -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if) -+{ -+ int i; -+ volatile uint32_t *addr; -+ -+ DWC_PRINTF("Core Global Registers\n"); -+ addr = &core_if->core_global_regs->gotgctl; -+ DWC_PRINTF("GOTGCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gotgint; -+ DWC_PRINTF("GOTGINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gahbcfg; -+ DWC_PRINTF("GAHBCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gusbcfg; -+ DWC_PRINTF("GUSBCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->grstctl; -+ DWC_PRINTF("GRSTCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gintsts; -+ DWC_PRINTF("GINTSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gintmsk; -+ DWC_PRINTF("GINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->grxstsr; -+ DWC_PRINTF("GRXSTSR @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->grxfsiz; -+ DWC_PRINTF("GRXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gnptxfsiz; -+ DWC_PRINTF("GNPTXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gnptxsts; -+ DWC_PRINTF("GNPTXSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gi2cctl; -+ DWC_PRINTF("GI2CCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gpvndctl; -+ DWC_PRINTF("GPVNDCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ggpio; -+ DWC_PRINTF("GGPIO @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->guid; -+ DWC_PRINTF("GUID @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->gsnpsid; -+ DWC_PRINTF("GSNPSID @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ghwcfg1; -+ DWC_PRINTF("GHWCFG1 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ghwcfg2; -+ DWC_PRINTF("GHWCFG2 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ghwcfg3; -+ DWC_PRINTF("GHWCFG3 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->ghwcfg4; -+ DWC_PRINTF("GHWCFG4 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->glpmcfg; -+ DWC_PRINTF("GLPMCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->core_global_regs->hptxfsiz; -+ DWC_PRINTF("HPTXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { -+ addr = &core_if->core_global_regs->dptxfsiz_dieptxf[i]; -+ DWC_PRINTF("DPTXFSIZ[%d] @0x%08X : 0x%08X\n", i, -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ } -+ addr = core_if->pcgcctl; -+ DWC_PRINTF("PCGCCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+} -+ -+/** -+ * 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; -+ -+ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "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) { -+ DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", -+ __func__, greset.d32, -+ dwc_read_reg32(&global_regs->gnptxsts)); -+ break; -+ } -+ dwc_udelay(1); -+ } while (greset.b.txfflsh == 1); -+ -+ /* Wait for 3 PHY Clocks */ -+ dwc_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; -+ -+ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%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) { -+ DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, -+ greset.d32); -+ break; -+ } -+ dwc_udelay(1); -+ } while (greset.b.rxfflsh == 1); -+ -+ /* Wait for 3 PHY Clocks */ -+ dwc_udelay(1); -+} -+ -+/** -+ * 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; -+ -+ DWC_DEBUGPL(DBG_CILV, "%s\n", __func__); -+ /* Wait for AHB master IDLE state. */ -+ do { -+ dwc_udelay(10); -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ if (++count > 100000) { -+ DWC_WARN("%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 > 10000) { -+ DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", -+ __func__, greset.d32); -+ break; -+ } -+ dwc_udelay(1); -+ } -+ while (greset.b.csftrst == 1); -+ -+ /* Wait for 3 PHY Clocks */ -+ dwc_mdelay(100); -+} -+ -+uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if) -+{ -+ return (dwc_otg_mode(_core_if) != DWC_HOST_MODE); -+} -+ -+uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if) -+{ -+ return (dwc_otg_mode(_core_if) == DWC_HOST_MODE); -+} -+ -+/** -+ * Register HCD callbacks. The callbacks are used to start and stop -+ * the HCD for interrupt processing. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param cb the HCD callback structure. -+ * @param p pointer to be passed to callback function (usb_hcd*). -+ */ -+void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if, -+ dwc_otg_cil_callbacks_t * cb, void *p) -+{ -+ core_if->hcd_cb = cb; -+ cb->p = p; -+} -+ -+/** -+ * Register PCD callbacks. The callbacks are used to start and stop -+ * the PCD for interrupt processing. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param cb the PCD callback structure. -+ * @param p pointer to be passed to callback function (pcd*). -+ */ -+void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if, -+ dwc_otg_cil_callbacks_t * cb, void *p) -+{ -+ core_if->pcd_cb = cb; -+ cb->p = p; -+} -+ -+#ifdef DWC_EN_ISOC -+ -+/** -+ * This function writes isoc data per 1 (micro)frame into tx fifo -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ * -+ */ -+void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ dwc_otg_dev_in_ep_regs_t *ep_regs; -+ dtxfsts_data_t txstatus = {.d32 = 0 }; -+ uint32_t len = 0; -+ uint32_t dwords; -+ -+ ep->xfer_len = ep->data_per_frame; -+ ep->xfer_count = 0; -+ -+ ep_regs = core_if->dev_if->in_ep_regs[ep->num]; -+ -+ len = ep->xfer_len - ep->xfer_count; -+ -+ if (len > ep->maxpacket) { -+ len = ep->maxpacket; -+ } -+ -+ dwords = (len + 3) / 4; -+ -+ /* While there is space in the queue and space in the FIFO and -+ * More data to tranfer, Write packets to the Tx FIFO */ -+ txstatus.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); -+ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32); -+ -+ while (txstatus.b.txfspcavail > dwords && -+ ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) { -+ /* Write the FIFO */ -+ dwc_otg_ep_write_packet(core_if, ep, 0); -+ -+ len = ep->xfer_len - ep->xfer_count; -+ if (len > ep->maxpacket) { -+ len = ep->maxpacket; -+ } -+ -+ dwords = (len + 3) / 4; -+ txstatus.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ dtxfsts); -+ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num, -+ txstatus.d32); -+ } -+} -+ -+/** -+ * This function initializes a descriptor chain for Isochronous transfer -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ * -+ */ -+void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * ep) -+{ -+ deptsiz_data_t deptsiz = {.d32 = 0 }; -+ depctl_data_t depctl = {.d32 = 0 }; -+ dsts_data_t dsts = {.d32 = 0 }; -+ volatile uint32_t *addr; -+ -+ if (ep->is_in) { -+ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; -+ } else { -+ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; -+ } -+ -+ ep->xfer_len = ep->data_per_frame; -+ ep->xfer_count = 0; -+ ep->xfer_buff = ep->cur_pkt_addr; -+ ep->dma_addr = ep->cur_pkt_dma_addr; -+ -+ if (ep->is_in) { -+ /* Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ deptsiz.b.xfersize = ep->xfer_len; -+ deptsiz.b.pktcnt = -+ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; -+ deptsiz.b.mc = deptsiz.b.pktcnt; -+ dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, -+ deptsiz.d32); -+ -+ /* Write the DMA register */ -+ if (core_if->dma_enable) { -+ dwc_write_reg32(& -+ (core_if->dev_if->in_ep_regs[ep->num]-> -+ diepdma), (uint32_t) ep->dma_addr); -+ } -+ } else { -+ deptsiz.b.pktcnt = -+ (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; -+ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; -+ -+ dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> -+ doeptsiz, deptsiz.d32); -+ -+ if (core_if->dma_enable) { -+ dwc_write_reg32(& -+ (core_if->dev_if->out_ep_regs[ep->num]-> -+ doepdma), (uint32_t) ep->dma_addr); -+ } -+ } -+ -+ /** Enable endpoint, clear nak */ -+ -+ depctl.d32 = 0; -+ if (ep->bInterval == 1) { -+ dsts.d32 = -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ ep->next_frame = dsts.b.soffn + ep->bInterval; -+ -+ if (ep->next_frame & 0x1) { -+ depctl.b.setd1pid = 1; -+ } else { -+ depctl.b.setd0pid = 1; -+ } -+ } else { -+ ep->next_frame += ep->bInterval; -+ -+ if (ep->next_frame & 0x1) { -+ depctl.b.setd1pid = 1; -+ } else { -+ depctl.b.setd0pid = 1; -+ } -+ } -+ depctl.b.epena = 1; -+ depctl.b.cnak = 1; -+ -+ dwc_modify_reg32(addr, 0, depctl.d32); -+ depctl.d32 = dwc_read_reg32(addr); -+ -+ if (ep->is_in && core_if->dma_enable == 0) { -+ write_isoc_frame_data(core_if, ep); -+ } -+ -+} -+#endif /* DWC_EN_ISOC */ -+ -+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; -+} -+ -+static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if) -+{ -+ int i; -+ core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params)); -+ if (!core_if->core_params) { -+ return -DWC_E_NO_MEMORY; -+ } -+ dwc_otg_set_uninitialized((int32_t *) core_if->core_params, -+ sizeof(*core_if->core_params) / -+ sizeof(int32_t)); -+ DWC_PRINTF("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); -+ DWC_PRINTF("Finished setting default values for core params\n"); -+ return 0; -+} -+ -+uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->dma_enable; -+} -+ -+/* 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)) { -+ DWC_WARN("Wrong value for otg_cap parameter\n"); -+ DWC_WARN("otg_cap parameter must be 0,1 or 2\n"); -+ retval = -DWC_E_INVALID; -+ 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)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for opt parameter\n"); -+ return -DWC_E_INVALID; -+ } -+ 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)) { -+ DWC_WARN("Wrong value for dma enable\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) { -+ if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) { -+ DWC_ERROR -+ ("%d invalid for dma_enable paremter. Check HW configuration.\n", -+ val); -+ } -+ val = 0; -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for dma_enable\n"); -+ DWC_WARN("dma_desc_enable must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_ERROR -+ ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n", -+ val); -+ } -+ val = 0; -+ retval = -DWC_E_INVALID; -+ } -+ 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)) { -+ DWC_WARN("Wrong value for host_support_fs_low_power\n"); -+ DWC_WARN("host_support_fs_low_power must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ 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)) { -+ DWC_WARN("Wrong value for enable_dynamic_fifo\n"); -+ DWC_WARN("enable_dynamic_fifo must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->enable_dynamic_fifo)) { -+ DWC_ERROR -+ ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n", -+ val); -+ } -+ val = 0; -+ retval = -DWC_E_INVALID; -+ } -+ 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)) { -+ DWC_WARN("Wrong value for data_fifo_size\n"); -+ DWC_WARN("data_fifo_size must be 32-32768\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val > core_if->hwcfg3.b.dfifo_depth) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->data_fifo_size)) { -+ DWC_ERROR -+ ("%d invalid for data_fifo_size parameter. Check HW configuration.\n", -+ val); -+ } -+ val = core_if->hwcfg3.b.dfifo_depth; -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for dev_rx_fifo_size\n"); -+ DWC_WARN("dev_rx_fifo_size must be 16-32768\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) { -+ if(dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) { -+ DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val); -+ } -+ val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz); -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for dev_nperio_tx_fifo\n"); -+ DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for host_rx_fifo_size\n"); -+ DWC_WARN("host_rx_fifo_size must be 16-32768\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->host_rx_fifo_size)) { -+ DWC_ERROR -+ ("%d invalid for host_rx_fifo_size. Check HW configuration.\n", -+ val); -+ } -+ val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz); -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n"); -+ DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for host_perio_tx_fifo_size\n"); -+ DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for max_transfer_size\n"); -+ DWC_WARN("max_transfer_size must be 2047-524288\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->max_transfer_size)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for max_packet_count\n"); -+ DWC_WARN("max_packet_count must be 15-511\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->max_packet_count)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for host_channels\n"); -+ DWC_WARN("host_channels must be 1-16\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val > (core_if->hwcfg2.b.num_host_chan + 1)) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->host_channels)) { -+ DWC_ERROR -+ ("%d invalid for host_channels. Check HW configurations.\n", -+ val); -+ } -+ val = (core_if->hwcfg2.b.num_host_chan + 1); -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for dev_endpoints\n"); -+ DWC_WARN("dev_endpoints must be 1-15\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val > (core_if->hwcfg2.b.num_dev_ep)) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->dev_endpoints)) { -+ DWC_ERROR -+ ("%d invalid for dev_endpoints. Check HW configurations.\n", -+ val); -+ } -+ val = core_if->hwcfg2.b.num_dev_ep; -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for phy_type\n"); -+ DWC_WARN("phy_type must be 0,1 or 2\n"); -+ return -DWC_E_INVALID; -+ } -+#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)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+#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)) { -+ DWC_WARN("Wrong value for speed parameter\n"); -+ DWC_WARN("max_speed parameter must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ 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)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ 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)) { -+ DWC_WARN -+ ("Wrong value for host_ls_low_power_phy_clk parameter\n"); -+ DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for phy_ulpi_ddr\n"); -+ DWC_WARN("phy_upli_ddr must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n"); -+ DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong valaue for phy_utmi_width\n"); -+ DWC_WARN("phy_utmi_width must be 8 or 16\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong valaue for ulpi_fs_ls\n"); -+ DWC_WARN("ulpi_fs_ls must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong valaue for ts_dline\n"); -+ DWC_WARN("ts_dline must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong valaue for i2c_enable\n"); -+ DWC_WARN("i2c_enable must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+#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)) { -+ DWC_ERROR("%d invalid for i2c_enable. Check HW configuration.\n", -+ val); -+ } -+ val = 0; -+ retval = -DWC_E_INVALID; -+ } -+#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)) { -+ DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n"); -+ DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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])) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n"); -+ DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) { -+ if(dwc_otg_param_initialized(core_if->core_params->en_multiple_tx_fifo)) { -+ DWC_ERROR("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", -+ val); -+ } -+ val = 0; -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for dev_tx_fifo_size\n"); -+ DWC_WARN("dev_tx_fifo_size must be 4-768\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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])) { -+ DWC_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 = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for thr_ctl\n"); -+ DWC_WARN("thr_ctl must be 0-7\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_ERROR("%d invalid for parameter thr_ctl. Check HW configuration.\n", -+ val); -+ } -+ val = 0; -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong value for lpm_enable\n"); -+ DWC_WARN("lpm_enable must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val && !core_if->hwcfg3.b.otg_lpm_en) { -+ if(dwc_otg_param_initialized(core_if->core_params->lpm_enable)) { -+ DWC_ERROR("%d invalid for parameter lpm_enable. Check HW configuration.\n", -+ val); -+ } -+ val = 0; -+ retval = -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong valaue for tx_thr_length\n"); -+ DWC_WARN("tx_thr_length must be 8 - 128\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("Wrong valaue for rx_thr_length\n"); -+ DWC_WARN("rx_thr_length must be 8 - 128\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val); -+ return -DWC_E_INVALID; -+ } -+ 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)) { -+ DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val); -+ return -DWC_E_INVALID; -+ } -+ if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) { -+ if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) { -+ DWC_ERROR("%d invalid for parameter pti_enable. Check HW configuration.\n", -+ val); -+ } -+ retval = -DWC_E_INVALID; -+ 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)) { -+ DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val); -+ return -DWC_E_INVALID; -+ } -+ if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) { -+ if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) { -+ DWC_ERROR("%d invalid for parameter mpi_enable. Check HW configuration.\n", -+ val); -+ } -+ retval = -DWC_E_INVALID; -+ 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)) { -+ DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val); -+ DWC_WARN("ic_usb_cap must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (val && (core_if->hwcfg3.b.otg_enable_ic_usb == 0)) { -+ if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) { -+ DWC_ERROR("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", -+ val); -+ } -+ retval = -DWC_E_INVALID; -+ 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)) { -+ DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val); -+ DWC_WARN("ahb_thr_ratio must be 0 - 3\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ 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)) { -+ DWC_ERROR("%d invalid for parameter ahb_thr_ratio. Chack HW configuration.\n", val); -+ } -+ retval = -DWC_E_INVALID; -+ 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_devspeed(dwc_otg_core_if_t * core_if) -+{ -+ dcfg_data_t dcfg; -+ dcfg.d32 = -1; //GRAYG -+ DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if); -+ if (NULL == core_if) -+ DWC_ERROR("reg request with NULL core_if\n"); -+ DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__, -+ core_if, core_if->dev_if); -+ if (NULL == core_if->dev_if) -+ DWC_ERROR("reg request with NULL dev_if\n"); -+ DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->" -+ "dev_global_regs(%p)\n", __func__, -+ core_if, core_if->dev_if, -+ core_if->dev_if->dev_global_regs); -+ if (NULL == core_if->dev_if->dev_global_regs) -+ DWC_ERROR("reg request with NULL dev_global_regs\n"); -+ else { -+ DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->" -+ "dev_global_regs(%p)->dcfg = %p\n", __func__, -+ core_if, core_if->dev_if, -+ core_if->dev_if->dev_global_regs, -+ &core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ } -+ return dcfg.b.devspd; -+} -+ -+void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val) -+{ -+ dcfg_data_t dcfg; -+ dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.b.devspd = val; -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.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_enumspeed(dwc_otg_core_if_t * core_if) -+{ -+ dsts_data_t dsts; -+ dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ return dsts.b.enumspd; -+} -+ -+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, val); -+} -+ -+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, val); -+} -+ -+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, val); -+} -+ -+uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if) -+{ -+ dctl_data_t dctl; -+ dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl); -+ return dctl.b.rmtwkupsig; -+} -+ -+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); -+ -+ DWC_ASSERT(! -+ ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts), -+ "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n", -+ core_if->lx_state, lpmcfg.b.prt_sleep_sts); -+ -+ 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); -+} -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -new file mode 100644 -index 0000000..1176166 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -@@ -0,0 +1,1143 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $ -+ * $Revision: #99 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237466 $ -+ * -+ * 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. -+ * ========================================================================== */ -+ -+#if !defined(__DWC_CIL_H__) -+#define __DWC_CIL_H__ -+ -+//#define HW2937_WORKAROUND -+#define DBG_HW2937 0x400 -+ -+#include "dwc_os.h" -+#include "dwc_list.h" -+#include "dwc_otg_dbg.h" -+#include "dwc_otg_regs.h" -+ -+#include "dwc_otg_core_if.h" -+ -+/** -+ * @file -+ * This file contains the interface to the Core Interface Layer. -+ */ -+ -+#ifdef DWC_UTE_CFI -+ -+#define MAX_DMA_DESCS_PER_EP 256 -+ -+/** -+ * Enumeration for the data buffer mode -+ */ -+typedef enum _data_buffer_mode { -+ BM_STANDARD = 0, /* data buffer is in normal mode */ -+ BM_SG = 1, /* data buffer uses the scatter/gather mode */ -+ BM_CONCAT = 2, /* data buffer uses the concatenation mode */ -+ BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */ -+ BM_ALIGN = 4 /* data buffer is in buffer alignment mode */ -+} data_buffer_mode_e; -+#endif //DWC_UTE_CFI -+ -+/** 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 -+ -+/** -+ * Information for each ISOC packet. -+ */ -+typedef struct iso_pkt_info { -+ uint32_t offset; -+ uint32_t length; -+ int32_t status; -+} iso_pkt_info_t; -+ -+/** -+ * The dwc_ep structure represents the state of a single -+ * endpoint when acting in device mode. It contains the data items -+ * needed for an endpoint to be activated and transfer packets. -+ */ -+typedef struct dwc_ep { -+ /** EP number used for register address lookup */ -+ uint8_t num; -+ /** EP direction 0 = OUT */ -+ unsigned is_in:1; -+ /** EP active. */ -+ unsigned active:1; -+ -+ /** Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic Tx FIFO -+ If dedicated Tx FIFOs are enabled for all IN Eps - Tx FIFO # FOR IN EPs*/ -+ unsigned tx_fifo_num:4; -+ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ -+ unsigned type:2; -+#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 -+ -+ /** DATA start PID for INTR and BULK EP */ -+ unsigned data_pid_start:1; -+ /** Frame (even/odd) for ISOC EP */ -+ unsigned even_odd_frame:1; -+ /** Max Packet bytes */ -+ unsigned maxpacket:11; -+ -+ /** Max Transfer size */ -+ uint32_t maxxfer; -+ -+ /** @name Transfer state */ -+ /** @{ */ -+ -+ /** -+ * Pointer to the beginning of the transfer buffer -- do not modify -+ * during transfer. -+ */ -+ -+ dwc_dma_t dma_addr; -+ -+ dwc_dma_t dma_desc_addr; -+ dwc_otg_dev_dma_desc_t *desc_addr; -+ -+ uint8_t *start_xfer_buff; -+ /** pointer to the transfer buffer */ -+ uint8_t *xfer_buff; -+ /** Number of bytes to transfer */ -+ unsigned xfer_len:19; -+ /** Number of bytes transferred. */ -+ unsigned xfer_count:19; -+ /** Sent ZLP */ -+ unsigned sent_zlp:1; -+ /** Total len for control transfer */ -+ unsigned total_len:19; -+ -+ /** stall clear flag */ -+ unsigned stall_clear_flag:1; -+ -+#ifdef DWC_UTE_CFI -+ /* The buffer mode */ -+ data_buffer_mode_e buff_mode; -+ -+ /* The chain of DMA descriptors. -+ * MAX_DMA_DESCS_PER_EP will be allocated for each active EP. -+ */ -+ dwc_otg_dma_desc_t *descs; -+ -+ /* The DMA address of the descriptors chain start */ -+ dma_addr_t descs_dma_addr; -+ /** This variable stores the length of the last enqueued request */ -+ uint32_t cfi_req_len; -+#endif //DWC_UTE_CFI -+ -+ /** Allocated DMA Desc count */ -+ uint32_t desc_cnt; -+ -+#ifdef DWC_EN_ISOC -+ /** -+ * Variables specific for ISOC EPs -+ * -+ */ -+ /** DMA addresses of ISOC buffers */ -+ dwc_dma_t dma_addr0; -+ dwc_dma_t dma_addr1; -+ -+ dwc_dma_t iso_dma_desc_addr; -+ dwc_otg_dev_dma_desc_t *iso_desc_addr; -+ -+ /** pointer to the transfer buffers */ -+ uint8_t *xfer_buff0; -+ uint8_t *xfer_buff1; -+ -+ /** number of ISOC Buffer is processing */ -+ uint32_t proc_buf_num; -+ /** Interval of ISOC Buffer processing */ -+ uint32_t buf_proc_intrvl; -+ /** Data size for regular frame */ -+ uint32_t data_per_frame; -+ -+ /* todo - pattern data support is to be implemented in the future */ -+ /** Data size for pattern frame */ -+ uint32_t data_pattern_frame; -+ /** Frame number of pattern data */ -+ uint32_t sync_frame; -+ -+ /** bInterval */ -+ uint32_t bInterval; -+ /** ISO Packet number per frame */ -+ uint32_t pkt_per_frm; -+ /** Next frame num for which will be setup DMA Desc */ -+ uint32_t next_frame; -+ /** Number of packets per buffer processing */ -+ uint32_t pkt_cnt; -+ /** Info for all isoc packets */ -+ iso_pkt_info_t *pkt_info; -+ /** current pkt number */ -+ uint32_t cur_pkt; -+ /** current pkt number */ -+ uint8_t *cur_pkt_addr; -+ /** current pkt number */ -+ uint32_t cur_pkt_dma_addr; -+#endif /* DWC_EN_ISOC */ -+ -+/** @} */ -+} dwc_ep_t; -+ -+/* -+ * Reasons for halting a host channel. -+ */ -+typedef enum dwc_otg_halt_status { -+ DWC_OTG_HC_XFER_NO_HALT_STATUS, -+ DWC_OTG_HC_XFER_COMPLETE, -+ DWC_OTG_HC_XFER_URB_COMPLETE, -+ DWC_OTG_HC_XFER_ACK, -+ DWC_OTG_HC_XFER_NAK, -+ DWC_OTG_HC_XFER_NYET, -+ DWC_OTG_HC_XFER_STALL, -+ DWC_OTG_HC_XFER_XACT_ERR, -+ DWC_OTG_HC_XFER_FRAME_OVERRUN, -+ DWC_OTG_HC_XFER_BABBLE_ERR, -+ DWC_OTG_HC_XFER_DATA_TOGGLE_ERR, -+ DWC_OTG_HC_XFER_AHB_ERR, -+ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE, -+ DWC_OTG_HC_XFER_URB_DEQUEUE -+#ifdef HW2937_WORKAROUND -+ , DWC_OTG_HC_XFER_PAUSE_IN -+#endif -+} dwc_otg_halt_status_e; -+ -+/** -+ * Host channel descriptor. This structure represents the state of a single -+ * host channel when acting in host mode. It contains the data items needed to -+ * transfer packets to an endpoint via a host channel. -+ */ -+typedef struct dwc_hc { -+ /** Host channel number used for register address lookup */ -+ uint8_t hc_num; -+ -+ /** Device to access */ -+ unsigned dev_addr:7; -+ -+ /** EP to access */ -+ unsigned ep_num:4; -+ -+ /** EP direction. 0: OUT, 1: IN */ -+ unsigned ep_is_in:1; -+ -+ /** -+ * EP speed. -+ * One of the following values: -+ * - DWC_OTG_EP_SPEED_LOW -+ * - DWC_OTG_EP_SPEED_FULL -+ * - DWC_OTG_EP_SPEED_HIGH -+ */ -+ unsigned speed:2; -+#define DWC_OTG_EP_SPEED_LOW 0 -+#define DWC_OTG_EP_SPEED_FULL 1 -+#define DWC_OTG_EP_SPEED_HIGH 2 -+ -+ /** -+ * Endpoint type. -+ * One of the following values: -+ * - DWC_OTG_EP_TYPE_CONTROL: 0 -+ * - DWC_OTG_EP_TYPE_ISOC: 1 -+ * - DWC_OTG_EP_TYPE_BULK: 2 -+ * - DWC_OTG_EP_TYPE_INTR: 3 -+ */ -+ unsigned ep_type:2; -+ -+ /** Max packet size in bytes */ -+ unsigned max_packet:11; -+ -+ /** -+ * PID for initial transaction. -+ * 0: DATA0,
-+ * 1: DATA2,
-+ * 2: DATA1,
-+ * 3: MDATA (non-Control EP), -+ * SETUP (Control EP) -+ */ -+ unsigned data_pid_start:2; -+#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 -+ -+ /** Number of periodic transactions per (micro)frame */ -+ unsigned multi_count:2; -+ -+ /** @name Transfer State */ -+ /** @{ */ -+ -+ /** Pointer to the current transfer buffer position. */ -+ uint8_t *xfer_buff; -+ /** -+ * In Buffer DMA mode this buffer will be used -+ * if xfer_buff is not DWORD aligned. -+ */ -+ dwc_dma_t align_buff; -+ /** Total number of bytes to transfer. */ -+ uint32_t xfer_len; -+ /** Number of bytes transferred so far. */ -+ uint32_t xfer_count; -+ /** Packet count at start of transfer.*/ -+ uint16_t start_pkt_count; -+ -+ /** -+ * Flag to indicate whether the transfer has been started. Set to 1 if -+ * it has been started, 0 otherwise. -+ */ -+ uint8_t xfer_started; -+ -+ /** -+ * Set to 1 to indicate that a PING request should be issued on this -+ * channel. If 0, process normally. -+ */ -+ uint8_t do_ping; -+ -+ /** -+ * Set to 1 to indicate that the error count for this transaction is -+ * non-zero. Set to 0 if the error count is 0. -+ */ -+ uint8_t error_state; -+ -+ /** -+ * Set to 1 to indicate that this channel should be halted the next -+ * time a request is queued for the channel. This is necessary in -+ * slave mode if no request queue space is available when an attempt -+ * is made to halt the channel. -+ */ -+ uint8_t halt_on_queue; -+ -+ /** -+ * Set to 1 if the host channel has been halted, but the core is not -+ * finished flushing queued requests. Otherwise 0. -+ */ -+ uint8_t halt_pending; -+ -+ /** -+ * Reason for halting the host channel. -+ */ -+ dwc_otg_halt_status_e halt_status; -+ -+ /* -+ * Split settings for the host channel -+ */ -+ uint8_t do_split; /**< Enable split for the channel */ -+ uint8_t complete_split; /**< Enable complete split */ -+ uint8_t hub_addr; /**< Address of high speed hub */ -+ -+ uint8_t port_addr; /**< Port of the low/full speed device */ -+ /** Split transaction position -+ * One of the following values: -+ * - DWC_HCSPLIT_XACTPOS_MID -+ * - DWC_HCSPLIT_XACTPOS_BEGIN -+ * - DWC_HCSPLIT_XACTPOS_END -+ * - DWC_HCSPLIT_XACTPOS_ALL */ -+ uint8_t xact_pos; -+ -+ /** Set when the host channel does a short read. */ -+ uint8_t short_read; -+ -+ /** -+ * Number of requests issued for this channel since it was assigned to -+ * the current transfer (not counting PINGs). -+ */ -+ uint8_t requests; -+ -+ /** -+ * Queue Head for the transfer being processed by this channel. -+ */ -+ struct dwc_otg_qh *qh; -+ -+ /** @} */ -+ -+ /** Entry in list of host channels. */ -+ DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry; -+ -+ /** @name Descriptor DMA support */ -+ /** @{ */ -+ -+ /** Number of Transfer Descriptors */ -+ uint16_t ntd; -+ -+ /** Descriptor List DMA address */ -+ dwc_dma_t desc_list_addr; -+ -+ /** Scheduling micro-frame bitmap. */ -+ uint8_t schinfo; -+ -+ /** @} */ -+} dwc_hc_t; -+ -+/** -+ * 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 65,535 (default 65,535) -+ */ -+ 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; -+ -+#ifdef DEBUG -+struct dwc_otg_core_if; -+typedef struct hc_xfer_info { -+ struct dwc_otg_core_if *core_if; -+ dwc_hc_t *hc; -+} hc_xfer_info_t; -+#endif -+/* -+ * Device States -+ */ -+typedef enum dwc_otg_lx_state { -+ /** On state */ -+ DWC_OTG_L0, -+ /** LPM sleep state*/ -+ DWC_OTG_L1, -+ /** USB suspend state*/ -+ DWC_OTG_L2, -+ /** Off state*/ -+ DWC_OTG_L3 -+} dwc_otg_lx_state_e; -+ -+/** -+ * The dwc_otg_core_if 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; -+ -+ /** Device-specific information */ -+ dwc_otg_dev_if_t *dev_if; -+ /** 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; -+ -+ /* -+ * SRP Success flag, set by srp success interrupt in FS I2C mode -+ */ -+ uint8_t srp_success; -+ uint8_t srp_timer_started; -+ -+ /* 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; -+ dcfg_data_t dcfg; -+ -+ /** 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) -+ -+ /** HCD callbacks */ -+ struct dwc_otg_cil_callbacks *hcd_cb; -+ /** PCD callbacks */ -+ struct dwc_otg_cil_callbacks *pcd_cb; -+ -+ /** Device mode Periodic Tx FIFO Mask */ -+ uint32_t p_tx_msk; -+ /** Device mode Periodic Tx FIFO Mask */ -+ uint32_t tx_msk; -+ -+ /** Workqueue object used for handling several interrupts */ -+ dwc_workq_t *wq_otg; -+ -+ /** Timer object used for handling "Wakeup Detected" Interrupt */ -+ dwc_timer_t *wkp_timer; -+ -+#ifdef DEBUG -+ uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; -+ -+ hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS]; -+ dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS]; -+ -+ uint32_t hfnum_7_samples; -+ uint64_t hfnum_7_frrem_accum; -+ uint32_t hfnum_0_samples; -+ uint64_t hfnum_0_frrem_accum; -+ uint32_t hfnum_other_samples; -+ uint64_t hfnum_other_frrem_accum; -+#endif -+ -+#ifdef DWC_UTE_CFI -+ uint16_t pwron_rxfsiz; -+ uint16_t pwron_gnptxfsiz; -+ uint16_t pwron_txfsiz[15]; -+ -+ uint16_t init_rxfsiz; -+ uint16_t init_gnptxfsiz; -+ uint16_t init_txfsiz[15]; -+#endif -+ -+ /** Lx state of device */ -+ dwc_otg_lx_state_e lx_state; -+ -+}; -+ -+#ifdef DEBUG -+/* -+ * This function is called when transfer is timed out. -+ */ -+extern void hc_xfer_timeout(void *ptr); -+#endif -+ -+/* -+ * The following functions are functions for works -+ * using during handling some interrupts -+ */ -+extern void w_conn_id_status_change(void *p); -+ -+extern void w_wakeup_detected(void *p); -+ -+/* -+ * The following functions support initialization of the CIL driver component -+ * and the DWC_otg controller. -+ */ -+extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if); -+extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if); -+ -+/** @name Device CIL Functions -+ * The following functions support managing the DWC_otg controller in device -+ * mode. -+ */ -+/**@{*/ -+extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if); -+extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if, -+ uint32_t * _dest); -+extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if); -+extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); -+extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); -+extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); -+extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if, -+ dwc_ep_t * _ep); -+extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if, -+ dwc_ep_t * _ep); -+extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if, -+ dwc_ep_t * _ep); -+extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if, -+ dwc_ep_t * _ep); -+extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if, -+ dwc_ep_t * _ep, int _dma); -+extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); -+extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if, -+ dwc_ep_t * _ep); -+extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if); -+ -+#ifdef DWC_EN_ISOC -+extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * ep); -+extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * ep); -+#endif /* DWC_EN_ISOC */ -+/**@}*/ -+ -+/** @name Host CIL Functions -+ * The following functions support managing the DWC_otg controller in host -+ * mode. -+ */ -+/**@{*/ -+extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); -+extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if, -+ dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status); -+extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); -+extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if, -+ dwc_hc_t * _hc); -+extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if, -+ dwc_hc_t * _hc); -+extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); -+extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if, -+ dwc_hc_t * _hc); -+extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if); -+extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if); -+ -+extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc); -+ -+/* Macro used to clear one channel interrupt */ -+#define clear_hc_int(_hc_regs_, _intr_) \ -+do { \ -+ hcint_data_t hcint_clear = {.d32 = 0}; \ -+ hcint_clear.b._intr_ = 1; \ -+ dwc_write_reg32(&(_hc_regs_)->hcint, hcint_clear.d32); \ -+} while (0) -+ -+/* -+ * Macro used to disable one channel interrupt. Channel interrupts are -+ * disabled when the channel is halted or released by the interrupt handler. -+ * There is no need to handle further interrupts of that type until the -+ * channel is re-assigned. In fact, subsequent handling may cause crashes -+ * because the channel structures are cleaned up when the channel is released. -+ */ -+#define disable_hc_int(_hc_regs_, _intr_) \ -+do { \ -+ hcintmsk_data_t hcintmsk = {.d32 = 0}; \ -+ hcintmsk.b._intr_ = 1; \ -+ dwc_modify_reg32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \ -+} while (0) -+ -+/** -+ * 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 -+ */ -+static inline 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; -+} -+ -+/**@}*/ -+ -+/** @name Common CIL Functions -+ * The following functions support managing the DWC_otg controller in either -+ * device or host mode. -+ */ -+/**@{*/ -+ -+extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, -+ uint8_t * dest, uint16_t bytes); -+ -+extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num); -+extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if); -+extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if); -+ -+/** -+ * This function returns the Core Interrupt register. -+ */ -+static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if) -+{ -+ return (dwc_read_reg32(&core_if->core_global_regs->gintsts) & -+ dwc_read_reg32(&core_if->core_global_regs->gintmsk)); -+} -+ -+/** -+ * This function returns the OTG Interrupt register. -+ */ -+static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if) -+{ -+ return (dwc_read_reg32(&core_if->core_global_regs->gotgint)); -+} -+ -+/** -+ * This function reads the Device All Endpoints Interrupt register and -+ * returns the IN endpoint interrupt bits. -+ */ -+static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t * -+ core_if) -+{ -+ -+ uint32_t v; -+ -+ if (core_if->multiproc_int_enable) { -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ deachint) & dwc_read_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ deachintmsk); -+ } else { -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); -+ } -+ return (v & 0xffff); -+} -+ -+/** -+ * This function reads the Device All Endpoints Interrupt register and -+ * returns the OUT endpoint interrupt bits. -+ */ -+static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t * -+ core_if) -+{ -+ uint32_t v; -+ -+ if (core_if->multiproc_int_enable) { -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ deachint) & dwc_read_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ deachintmsk); -+ } else { -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); -+ } -+ -+ return ((v & 0xffff0000) >> 16); -+} -+ -+/** -+ * This function returns the Device IN EP Interrupt register -+ */ -+static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * ep) -+{ -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ uint32_t v, msk, emp; -+ -+ if (core_if->multiproc_int_enable) { -+ msk = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ diepeachintmsk[ep->num]); -+ emp = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ dtknqr4_fifoemptymsk); -+ msk |= ((emp >> ep->num) & 0x1) << 7; -+ v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; -+ } else { -+ msk = dwc_read_reg32(&dev_if->dev_global_regs->diepmsk); -+ emp = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ dtknqr4_fifoemptymsk); -+ msk |= ((emp >> ep->num) & 0x1) << 7; -+ v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; -+ } -+ -+ return v; -+} -+ -+/** -+ * This function returns the Device OUT EP Interrupt register -+ */ -+static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t * -+ _core_if, dwc_ep_t * _ep) -+{ -+ dwc_otg_dev_if_t *dev_if = _core_if->dev_if; -+ uint32_t v; -+ doepmsk_data_t msk = {.d32 = 0 }; -+ -+ if (_core_if->multiproc_int_enable) { -+ msk.d32 = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ doepeachintmsk[_ep->num]); -+ if (_core_if->pti_enh_enable) { -+ msk.b.pktdrpsts = 1; -+ } -+ v = dwc_read_reg32(&dev_if->out_ep_regs[_ep->num]-> -+ doepint) & msk.d32; -+ } else { -+ msk.d32 = dwc_read_reg32(&dev_if->dev_global_regs->doepmsk); -+ if (_core_if->pti_enh_enable) { -+ msk.b.pktdrpsts = 1; -+ } -+ v = dwc_read_reg32(&dev_if->out_ep_regs[_ep->num]-> -+ doepint) & msk.d32; -+ } -+ return v; -+} -+ -+/** -+ * 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, dwc_hc_t * _hc) -+{ -+ return (dwc_read_reg32 -+ (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint)); -+} -+ -+/** -+ * 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); -+} -+ -+/**@}*/ -+ -+/** -+ * DWC_otg CIL callback structure. This structure allows the HCD and -+ * PCD to register functions used for starting and stopping the PCD -+ * and HCD for role change on for a DRD. -+ */ -+typedef struct dwc_otg_cil_callbacks { -+ /** Start function for role change */ -+ int (*start) (void *_p); -+ /** Stop Function for role change */ -+ int (*stop) (void *_p); -+ /** Disconnect Function for role change */ -+ int (*disconnect) (void *_p); -+ /** Resume/Remote wakeup Function */ -+ int (*resume_wakeup) (void *_p); -+ /** Suspend function */ -+ int (*suspend) (void *_p); -+ /** Session Start (SRP) */ -+ int (*session_start) (void *_p); -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ /** Sleep (switch to L0 state) */ -+ int (*sleep) (void *_p); -+#endif -+ /** Pointer passed to start() and stop() */ -+ void *p; -+} dwc_otg_cil_callbacks_t; -+ -+extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if, -+ dwc_otg_cil_callbacks_t * _cb, -+ void *_p); -+extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if, -+ dwc_otg_cil_callbacks_t * _cb, -+ void *_p); -+ -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -new file mode 100644 -index 0000000..b8b2740 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -@@ -0,0 +1,846 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ -+ * $Revision: #15 $ -+ * $Date: 2009/04/15 $ -+ * $Change: 1234129 $ -+ * -+ * 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. -+ * ========================================================================== */ -+ -+/** @file -+ * -+ * The Core Interface Layer provides basic services for accessing and -+ * managing the DWC_otg hardware. These services are used by both the -+ * Host Controller Driver and the Peripheral Controller Driver. -+ * -+ * This file contains the Common Interrupt handlers. -+ */ -+#include "dwc_os.h" -+#include "dwc_otg_regs.h" -+#include "dwc_otg_cil.h" -+ -+#ifdef DEBUG -+inline const char *op_state_str(dwc_otg_core_if_t * core_if) -+{ -+ return (core_if->op_state == A_HOST ? "a_host" : -+ (core_if->op_state == A_SUSPEND ? "a_suspend" : -+ (core_if->op_state == A_PERIPHERAL ? "a_peripheral" : -+ (core_if->op_state == B_PERIPHERAL ? "b_peripheral" : -+ (core_if->op_state == B_HOST ? "b_host" : "unknown"))))); -+} -+#endif -+ -+/** This function will log a debug message -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if) -+{ -+ gintsts_data_t gintsts; -+ DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n", -+ dwc_otg_mode(core_if) ? "Host" : "Device"); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.modemismatch = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ return 1; -+} -+ -+/** Start the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void hcd_start(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->start) { -+ core_if->hcd_cb->start(core_if->hcd_cb->p); -+ } -+} -+ -+/** Stop the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void hcd_stop(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->stop) { -+ core_if->hcd_cb->stop(core_if->hcd_cb->p); -+ } -+} -+ -+/** Disconnect the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void hcd_disconnect(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->disconnect) { -+ core_if->hcd_cb->disconnect(core_if->hcd_cb->p); -+ } -+} -+ -+/** Inform the HCD the a New Session has begun. Helper function for -+ * using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void hcd_session_start(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->session_start) { -+ core_if->hcd_cb->session_start(core_if->hcd_cb->p); -+ } -+} -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+/** -+ * Inform the HCD about LPM sleep. -+ * Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void hcd_sleep(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->sleep) { -+ core_if->hcd_cb->sleep(core_if->hcd_cb->p); -+ } -+} -+#endif -+ -+/** Resume the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void hcd_resume(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { -+ core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); -+ } -+} -+ -+/** Start the PCD. Helper function for using the PCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void pcd_start(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->start) { -+ core_if->pcd_cb->start(core_if->pcd_cb->p); -+ } -+} -+ -+/** Stop the PCD. Helper function for using the PCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void pcd_stop(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->stop) { -+ core_if->pcd_cb->stop(core_if->pcd_cb->p); -+ } -+} -+ -+/** Suspend the PCD. Helper function for using the PCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void pcd_suspend(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->suspend) { -+ core_if->pcd_cb->suspend(core_if->pcd_cb->p); -+ } -+} -+ -+/** Resume the PCD. Helper function for using the PCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void pcd_resume(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); -+ } -+} -+ -+/** -+ * This function handles the OTG Interrupts. It reads the OTG -+ * Interrupt Register (GOTGINT) to determine what interrupt has -+ * occurred. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) -+{ -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ gotgint_data_t gotgint; -+ gotgctl_data_t gotgctl; -+ gintmsk_data_t gintmsk; -+ -+ gotgint.d32 = dwc_read_reg32(&global_regs->gotgint); -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, -+ op_state_str(core_if)); -+ -+ if (gotgint.b.sesenddet) { -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " -+ "Session End Detected++ (%s)\n", -+ op_state_str(core_if)); -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ -+ if (core_if->op_state == B_HOST) { -+ pcd_start(core_if); -+ core_if->op_state = B_PERIPHERAL; -+ } else { -+ /* If not B_HOST and Device HNP still set. HNP -+ * Did not succeed!*/ -+ if (gotgctl.b.devhnpen) { -+ DWC_DEBUGPL(DBG_ANY, "Session End Detected\n"); -+ __DWC_ERROR("Device Not Connected/Responding!\n"); -+ } -+ -+ /* If Session End Detected the B-Cable has -+ * been disconnected. */ -+ /* Reset PCD and Gadget driver to a -+ * clean state. */ -+ core_if->lx_state = DWC_OTG_L0; -+ pcd_stop(core_if); -+ } -+ gotgctl.d32 = 0; -+ gotgctl.b.devhnpen = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); -+ } -+ if (gotgint.b.sesreqsucstschng) { -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " -+ "Session Reqeust Success Status Change++\n"); -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ if (gotgctl.b.sesreqscs) { -+ if ((core_if->core_params->phy_type == -+ DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) { -+ core_if->srp_success = 1; -+ } else { -+ pcd_resume(core_if); -+ /* Clear Session Request */ -+ gotgctl.d32 = 0; -+ gotgctl.b.sesreq = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, -+ gotgctl.d32, 0); -+ } -+ } -+ } -+ if (gotgint.b.hstnegsucstschng) { -+ /* Print statements during the HNP interrupt handling -+ * can cause it to fail.*/ -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ if (gotgctl.b.hstnegscs) { -+ if (dwc_otg_is_host_mode(core_if)) { -+ core_if->op_state = B_HOST; -+ /* -+ * Need to disable SOF interrupt immediately. -+ * When switching from device to host, the PCD -+ * interrupt handler won't handle the -+ * interrupt if host mode is already set. The -+ * HCD interrupt handler won't get called if -+ * the HCD state is HALT. This means that the -+ * interrupt does not get handled and Linux -+ * complains loudly. -+ */ -+ gintmsk.d32 = 0; -+ gintmsk.b.sofintr = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, -+ gintmsk.d32, 0); -+ pcd_stop(core_if); -+ /* -+ * Initialize the Core for Host mode. -+ */ -+ hcd_start(core_if); -+ core_if->op_state = B_HOST; -+ } -+ } else { -+ gotgctl.d32 = 0; -+ gotgctl.b.hnpreq = 1; -+ gotgctl.b.devhnpen = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); -+ DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); -+ __DWC_ERROR("Device Not Connected/Responding\n"); -+ } -+ } -+ if (gotgint.b.hstnegdet) { -+ /* The disconnect interrupt is set at the same time as -+ * Host Negotiation Detected. During the mode -+ * switch all interrupts are cleared so the disconnect -+ * interrupt handler will not get executed. -+ */ -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " -+ "Host Negotiation Detected++ (%s)\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : -+ "Device")); -+ if (dwc_otg_is_device_mode(core_if)) { -+ DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", -+ core_if->op_state); -+ hcd_disconnect(core_if); -+ pcd_start(core_if); -+ core_if->op_state = A_PERIPHERAL; -+ } else { -+ /* -+ * Need to disable SOF interrupt immediately. When -+ * switching from device to host, the PCD interrupt -+ * handler won't handle the interrupt if host mode is -+ * already set. The HCD interrupt handler won't get -+ * called if the HCD state is HALT. This means that -+ * the interrupt does not get handled and Linux -+ * complains loudly. -+ */ -+ gintmsk.d32 = 0; -+ gintmsk.b.sofintr = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, gintmsk.d32, 0); -+ pcd_stop(core_if); -+ hcd_start(core_if); -+ core_if->op_state = A_HOST; -+ } -+ } -+ if (gotgint.b.adevtoutchng) { -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " -+ "A-Device Timeout Change++\n"); -+ } -+ if (gotgint.b.debdone) { -+ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n"); -+ } -+ -+ /* Clear GOTGINT */ -+ dwc_write_reg32(&core_if->core_global_regs->gotgint, gotgint.d32); -+ -+ return 1; -+} -+ -+void w_conn_id_status_change(void *p) -+{ -+ dwc_otg_core_if_t *core_if = p; -+ uint32_t count = 0; -+ gotgctl_data_t gotgctl = {.d32 = 0 }; -+ -+ gotgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); -+ DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); -+ DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); -+ -+ /* B-Device connector (Device Mode) */ -+ if (gotgctl.b.conidsts) { -+ /* Wait for switch to device mode. */ -+ while (!dwc_otg_is_device_mode(core_if)) { -+ DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : -+ "Peripheral")); -+ dwc_mdelay(100); -+ if (++count > 10000) -+ break; -+ } -+ DWC_ASSERT(++count < 10000, -+ "Connection id status change timed out"); -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ pcd_start(core_if); -+ } else { -+ /* A-Device connector (Host Mode) */ -+ while (!dwc_otg_is_host_mode(core_if)) { -+ DWC_PRINTF("Waiting for Host Mode, Mode=%s\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : -+ "Peripheral")); -+ dwc_mdelay(100); -+ if (++count > 10000) -+ break; -+ } -+ DWC_ASSERT(++count < 10000, -+ "Connection id status change timed out"); -+ core_if->op_state = A_HOST; -+ /* -+ * Initialize the Core for Host mode. -+ */ -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ hcd_start(core_if); -+ } -+} -+ -+/** -+ * This function handles the Connector ID Status Change Interrupt. It -+ * reads the OTG Interrupt Register (GOTCTL) to determine whether this -+ * is a Device to Host Mode transition or a Host Mode to Device -+ * Transition. -+ * -+ * This only occurs when the cable is connected/removed from the PHY -+ * connector. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if) -+{ -+ -+ /* -+ * Need to disable SOF interrupt immediately. If switching from device -+ * to host, the PCD interrupt handler won't handle the interrupt if -+ * host mode is already set. The HCD interrupt handler won't get -+ * called if the HCD state is HALT. This means that the interrupt does -+ * not get handled and Linux complains loudly. -+ */ -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ gintsts_data_t gintsts = {.d32 = 0 }; -+ -+ gintmsk.b.sofintr = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); -+ -+ DWC_DEBUGPL(DBG_CIL, -+ " ++Connector ID Status Change Interrupt++ (%s)\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device")); -+ -+ /* -+ * Need to schedule a work, as there are possible DELAY function calls -+ */ -+ DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change, -+ core_if, "connection id status change"); -+ -+ /* Set flag and clear interrupt */ -+ gintsts.b.conidstschng = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that a device is initiating the Session -+ * Request Protocol to request the host to turn on bus power so a new -+ * session can begin. The handler responds by turning on bus power. If -+ * the DWC_otg controller is in low power mode, the handler brings the -+ * controller out of low power mode before turning on bus power. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if) -+{ -+ hprt0_data_t hprt0; -+ gintsts_data_t gintsts; -+ -+#ifndef DWC_HOST_ONLY -+ DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n"); -+ -+ if (dwc_otg_is_device_mode(core_if)) { -+ DWC_PRINTF("SRP: Device mode\n"); -+ } else { -+ DWC_PRINTF("SRP: Host mode\n"); -+ -+ /* Turn on the port power bit. */ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtpwr = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ -+ /* Start the Connection timer. So a message can be displayed -+ * if connect does not occur within 10 seconds. */ -+ hcd_session_start(core_if); -+ } -+#endif -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.sessreqintr = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+void w_wakeup_detected(void *p) -+{ -+ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p; -+ /* -+ * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms -+ * so that OPT tests pass with all PHYs). -+ */ -+ hprt0_data_t hprt0 = {.d32 = 0 }; -+#if 0 -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ /* Restart the Phy Clock */ -+ pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); -+ dwc_udelay(10); -+#endif //0 -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); -+// dwc_mdelay(70); -+ hprt0.b.prtres = 0; /* Resume */ -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n", -+ dwc_read_reg32(core_if->host_if->hprt0)); -+ -+ hcd_resume(core_if); -+ -+ /** Change to L0 state*/ -+ core_if->lx_state = DWC_OTG_L0; -+ -+} -+ -+/** -+ * This interrupt indicates that the DWC_otg controller has detected a -+ * resume or remote wakeup sequence. If the DWC_otg controller is in -+ * low power mode, the handler must brings the controller out of low -+ * power mode. The controller automatically begins resume -+ * signaling. The handler schedules a time to stop resume signaling. -+ */ -+int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) -+{ -+ gintsts_data_t gintsts; -+ -+ DWC_DEBUGPL(DBG_ANY, -+ "++Resume and Remote Wakeup Detected Interrupt++\n"); -+ -+ DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state); -+ -+ if (dwc_otg_is_device_mode(core_if)) { -+ dctl_data_t dctl = {.d32 = 0 }; -+ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ dsts)); -+ if (core_if->lx_state == DWC_OTG_L2) { -+#ifdef PARTIAL_POWER_DOWN -+ if (core_if->hwcfg4.b.power_optimiz) { -+ pcgcctl_data_t power = {.d32 = 0 }; -+ -+ power.d32 = dwc_read_reg32(core_if->pcgcctl); -+ DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", -+ power.d32); -+ -+ power.b.stoppclk = 0; -+ dwc_write_reg32(core_if->pcgcctl, power.d32); -+ -+ power.b.pwrclmp = 0; -+ dwc_write_reg32(core_if->pcgcctl, power.d32); -+ -+ power.b.rstpdwnmodule = 0; -+ dwc_write_reg32(core_if->pcgcctl, power.d32); -+ } -+#endif -+ /* Clear the Remote Wakeup Signalling */ -+ dctl.b.rmtwkupsig = 1; -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ dctl, dctl.d32, 0); -+ -+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb-> -+ p); -+ } -+ } else { -+ glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ lpmcfg.b.hird_thres &= (~(1 << 4)); -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, -+ lpmcfg.d32); -+ } -+ /** Change to L0 state*/ -+ core_if->lx_state = DWC_OTG_L0; -+ } else { -+ if (core_if->lx_state != DWC_OTG_L1) { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ -+ /* Restart the Phy Clock */ -+ pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); -+ -+ DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71); -+ } else { -+ /** Change to L0 state*/ -+ core_if->lx_state = DWC_OTG_L0; -+ } -+ } -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.wkupintr = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that a device has been disconnected from -+ * the root port. -+ */ -+int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) -+{ -+ gintsts_data_t gintsts; -+ -+ DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n", -+ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"), -+ op_state_str(core_if)); -+ -+/** @todo Consolidate this if statement. */ -+#ifndef DWC_HOST_ONLY -+ if (core_if->op_state == B_HOST) { -+ /* If in device mode Disconnect and stop the HCD, then -+ * start the PCD. */ -+ hcd_disconnect(core_if); -+ pcd_start(core_if); -+ core_if->op_state = B_PERIPHERAL; -+ } else if (dwc_otg_is_device_mode(core_if)) { -+ gotgctl_data_t gotgctl = {.d32 = 0 }; -+ gotgctl.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gotgctl); -+ if (gotgctl.b.hstsethnpen == 1) { -+ /* Do nothing, if HNP in process the OTG -+ * interrupt "Host Negotiation Detected" -+ * interrupt will do the mode switch. -+ */ -+ } else if (gotgctl.b.devhnpen == 0) { -+ /* If in device mode Disconnect and stop the HCD, then -+ * start the PCD. */ -+ hcd_disconnect(core_if); -+ pcd_start(core_if); -+ core_if->op_state = B_PERIPHERAL; -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); -+ } -+ } else { -+ if (core_if->op_state == A_HOST) { -+ /* A-Cable still connected but device disconnected. */ -+ hcd_disconnect(core_if); -+ } -+ } -+#endif -+ /* Change to L3(OFF) state */ -+ core_if->lx_state = DWC_OTG_L3; -+ -+ gintsts.d32 = 0; -+ gintsts.b.disconnect = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that SUSPEND state has been detected on -+ * the USB. -+ * -+ * For HNP the USB Suspend interrupt signals the change from -+ * "a_peripheral" to "a_host". -+ * -+ * When power management is enabled the core will be put in low power -+ * mode. -+ */ -+int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) -+{ -+ dsts_data_t dsts; -+ gintsts_data_t gintsts; -+ -+ DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); -+ -+ if (dwc_otg_is_device_mode(core_if)) { -+ /* Check the Device status register to determine if the Suspend -+ * state is active. */ -+ dsts.d32 = -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); -+ DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " -+ "HWCFG4.power Optimize=%d\n", -+ dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz); -+ -+#ifdef PARTIAL_POWER_DOWN -+/** @todo Add a module parameter for power management. */ -+ -+ if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) { -+ pcgcctl_data_t power = {.d32 = 0 }; -+ DWC_DEBUGPL(DBG_CIL, "suspend\n"); -+ -+ power.b.pwrclmp = 1; -+ dwc_write_reg32(core_if->pcgcctl, power.d32); -+ -+ power.b.rstpdwnmodule = 1; -+ dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); -+ -+ power.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); -+ -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "disconnect?\n"); -+ } -+#endif -+ /* PCD callback for suspend. */ -+ pcd_suspend(core_if); -+ } else { -+ if (core_if->op_state == A_PERIPHERAL) { -+ DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); -+ /* Clear the a_peripheral flag, back to a_host. */ -+ pcd_stop(core_if); -+ hcd_start(core_if); -+ core_if->op_state = A_HOST; -+ } -+ } -+ -+ /* Change to L2(suspend) state */ -+ core_if->lx_state = DWC_OTG_L2; -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.usbsuspend = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+/** -+ * This function hadles LPM transaction received interrupt. -+ */ -+static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) -+{ -+ glpmcfg_data_t lpmcfg; -+ gintsts_data_t gintsts; -+ -+ if (!core_if->core_params->lpm_enable) { -+ DWC_PRINTF("Unexpected LPM interrupt\n"); -+ } -+ -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32); -+ -+ if (dwc_otg_is_host_mode(core_if)) { -+ hcd_sleep(core_if); -+ } else { -+ lpmcfg.b.hird_thres |= (1 << 4); -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, -+ lpmcfg.d32); -+ } -+ -+ /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ -+ dwc_udelay(10); -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ if (lpmcfg.b.prt_sleep_sts) { -+ /* Save the current state */ -+ core_if->lx_state = DWC_OTG_L1; -+ } -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.lpmtranrcvd = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ return 1; -+} -+#endif /* CONFIG_USB_DWC_OTG_LPM */ -+ -+/** -+ * This function returns the Core Interrupt register. -+ */ -+static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) -+{ -+ gintsts_data_t gintsts; -+ gintmsk_data_t gintmsk; -+ gintmsk_data_t gintmsk_common = {.d32 = 0 }; -+ gintmsk_common.b.wkupintr = 1; -+ gintmsk_common.b.sessreqintr = 1; -+ gintmsk_common.b.conidstschng = 1; -+ gintmsk_common.b.otgintr = 1; -+ gintmsk_common.b.modemismatch = 1; -+ gintmsk_common.b.disconnect = 1; -+ gintmsk_common.b.usbsuspend = 1; -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ gintmsk_common.b.lpmtranrcvd = 1; -+#endif -+ /** @todo: The port interrupt occurs while in device -+ * mode. Added code to CIL to clear the interrupt for now! -+ */ -+ gintmsk_common.b.portintr = 1; -+ -+ gintsts.d32 = dwc_read_reg32(&core_if->core_global_regs->gintsts); -+ gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk); -+#ifdef DEBUG -+ /* if any common interrupts set */ -+ if (gintsts.d32 & gintmsk_common.d32) { -+ DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", -+ gintsts.d32, gintmsk.d32); -+ } -+#endif -+ -+ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); -+ -+} -+ -+/** -+ * Common interrupt handler. -+ * -+ * The common interrupts are those that occur in both Host and Device mode. -+ * This handler handles the following interrupts: -+ * - Mode Mismatch Interrupt -+ * - Disconnect Interrupt -+ * - OTG Interrupt -+ * - Connector ID Status Change Interrupt -+ * - Session Request Interrupt. -+ * - Resume / Remote Wakeup Detected Interrupt. -+ * - LPM Transaction Received Interrutp -+ * -+ */ -+int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t * core_if) -+{ -+ int retval = 0; -+ gintsts_data_t gintsts; -+ -+ gintsts.d32 = dwc_otg_read_common_intr(core_if); -+ -+ if (gintsts.b.modemismatch) { -+ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); -+ } -+ if (gintsts.b.otgintr) { -+ retval |= dwc_otg_handle_otg_intr(core_if); -+ } -+ if (gintsts.b.conidstschng) { -+ retval |= dwc_otg_handle_conn_id_status_change_intr(core_if); -+ } -+ if (gintsts.b.disconnect) { -+ retval |= dwc_otg_handle_disconnect_intr(core_if); -+ } -+ if (gintsts.b.sessreqintr) { -+ retval |= dwc_otg_handle_session_req_intr(core_if); -+ } -+ if (gintsts.b.wkupintr) { -+ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); -+ } -+ if (gintsts.b.usbsuspend) { -+ retval |= dwc_otg_handle_usb_suspend_intr(core_if); -+ } -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ if (gintsts.b.lpmtranrcvd) { -+ retval |= dwc_otg_handle_lpm_intr(core_if); -+ } -+#endif -+ -+ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { -+ /* The port interrupt occurs while in device mode with HPRT0 -+ * Port Enable/Disable. -+ */ -+ gintsts.d32 = 0; -+ gintsts.b.portintr = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, -+ gintsts.d32); -+ retval |= 1; -+ -+ } -+ return retval; -+} -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -new file mode 100644 -index 0000000..4a78b03 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -@@ -0,0 +1,641 @@ -+/* ========================================================================== -+ * $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. -+ * ========================================================================== */ -+#if !defined(__DWC_CORE_IF_H__) -+#define __DWC_CORE_IF_H__ -+ -+#include "dwc_os.h" -+ -+/** @file -+ * This file defines DWC_OTG Core API -+ */ -+ -+struct dwc_otg_core_if; -+typedef struct dwc_otg_core_if dwc_otg_core_if_t; -+ -+/** 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 -+ -+extern dwc_otg_core_if_t *dwc_otg_cil_init(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); -+ -+/** @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 1 -+#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 8192 -+#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 1024 -+#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 1024 -+#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 1024 -+#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708 -+ -+/** The maximum transfer size supported in bytes. -+ * 2047 to 65,535 (default 65,535) -+ */ -+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 16 -+#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 1 -+ -+/** -+ * 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); -+ -+/** -+ * GHPTXFSIZE -+ */ -+extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if); -+ -+/** @} */ -+ -+#endif /* __DWC_CORE_IF_H__ */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h -new file mode 100644 -index 0000000..e81d093 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h -@@ -0,0 +1,113 @@ -+/* ========================================================================== -+ * -+ * 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_DBG_H__ -+#define __DWC_OTG_DBG_H__ -+ -+/** @file -+ * This file defines debug levels. -+ * Debugging support vanishes in non-debug builds. -+ */ -+ -+/** -+ * The Debug Level bit-mask variable. -+ */ -+extern uint32_t g_dbg_lvl; -+/** -+ * Set the Debug Level variable. -+ */ -+static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new) -+{ -+ uint32_t old = g_dbg_lvl; -+ g_dbg_lvl = new; -+ return old; -+} -+ -+/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */ -+#define DBG_CIL (0x2) -+/** When debug level has the DBG_CILV bit set, display CIL Verbose debug -+ * messages */ -+#define DBG_CILV (0x20) -+/** When debug level has the DBG_PCD bit set, display PCD (Device) debug -+ * messages */ -+#define DBG_PCD (0x4) -+/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug -+ * messages */ -+#define DBG_PCDV (0x40) -+/** When debug level has the DBG_HCD bit set, display Host debug messages */ -+#define DBG_HCD (0x8) -+/** When debug level has the DBG_HCDV bit set, display Verbose Host debug -+ * messages */ -+#define DBG_HCDV (0x80) -+/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host -+ * mode. */ -+#define DBG_HCD_URB (0x800) -+ -+/** When debug level has any bit set, display debug messages */ -+#define DBG_ANY (0xFF) -+ -+/** All debug messages off */ -+#define DBG_OFF 0 -+ -+/** Prefix string for DWC_DEBUG print macros. */ -+#define USB_DWC "DWC_otg: " -+ -+/** -+ * Print a debug message when the Global debug level variable contains -+ * the bit defined in lvl. -+ * -+ * @param[in] lvl - Debug level, use one of the DBG_ constants above. -+ * @param[in] x - like printf -+ * -+ * Example:

-+ * -+ * DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr); -+ * -+ *
-+ * results in:
-+ * -+ * usb-DWC_otg: dwc_otg_cil_init(ca867000) -+ * -+ */ -+#ifdef DEBUG -+ -+# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0) -+# define DWC_DEBUGP(x...) DWC_DEBUGPL(DBG_ANY, x ) -+ -+# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl) -+ -+#else -+ -+# define DWC_DEBUGPL(lvl, x...) do{}while(0) -+# define DWC_DEBUGP(x...) -+ -+# define CHK_DEBUG_LEVEL(level) (0) -+ -+#endif /*DEBUG*/ -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -new file mode 100644 -index 0000000..0e22013 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -0,0 +1,1577 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ -+ * $Revision: #76 $ -+ * $Date: 2009/05/03 $ -+ * $Change: 1245589 $ -+ * -+ * 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. -+ * ========================================================================== */ -+ -+/** @file -+ * The dwc_otg_driver module provides the initialization and cleanup entry -+ * points for the DWC_otg driver. This module will be dynamically installed -+ * after Linux is booted using the insmod command. When the module is -+ * installed, the dwc_otg_driver_init function is called. When the module is -+ * removed (using rmmod), the dwc_otg_driver_cleanup function is called. -+ * -+ * This module also defines a data structure for the dwc_otg_driver, which is -+ * used in conjunction with the standard ARM lm_device structure. These -+ * structures allow the OTG driver to comply with the standard Linux driver -+ * model in which devices and drivers are registered with a bus driver. This -+ * has the benefit that Linux can expose attributes of the driver and device -+ * in its special sysfs file system. Users can then read or write files in -+ * this file system to perform diagnostics on the driver components or the -+ * device. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* permission constants */ -+#include -+#include -+ -+#ifdef LM_INTERFACE -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#include -+#else -+/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - -+ here we use definitions stolen from arm-integrator headers -+*/ -+#include -+#include -+#endif -+#include -+#include -+ -+#elif defined(PLATFORM_INTERFACE) -+ -+#include -+#include -+ -+#endif -+ -+# include -+ -+#include -+ -+ -+#include "dwc_os.h" -+#include "dwc_otg_dbg.h" -+#include "dwc_otg_driver.h" -+#include "dwc_otg_attr.h" -+#include "dwc_otg_core_if.h" -+#include "dwc_otg_pcd_if.h" -+#include "dwc_otg_hcd_if.h" -+ -+#define DWC_DRIVER_VERSION "2.90b 6-MAY-2010" -+#define DWC_DRIVER_DESC "HS OTG USB Controller driver" -+ -+static const char dwc_driver_name[] = "dwc_otg"; -+ -+extern int pcd_init( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *dev -+#endif -+ ); -+extern int hcd_init( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *dev -+#endif -+ ); -+ -+extern int pcd_remove( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ); -+ -+extern void hcd_remove( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ); -+ -+/*-------------------------------------------------------------------------*/ -+/* Encapsulate the module parameter settings */ -+ -+struct dwc_otg_driver_module_params { -+ int32_t opt; -+ int32_t otg_cap; -+ int32_t dma_enable; -+ int32_t dma_desc_enable; -+ int32_t dma_burst_size; -+ int32_t speed; -+ int32_t host_support_fs_ls_low_power; -+ int32_t host_ls_low_power_phy_clk; -+ int32_t enable_dynamic_fifo; -+ int32_t data_fifo_size; -+ int32_t dev_rx_fifo_size; -+ int32_t dev_nperio_tx_fifo_size; -+ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; -+ int32_t host_rx_fifo_size; -+ int32_t host_nperio_tx_fifo_size; -+ int32_t host_perio_tx_fifo_size; -+ int32_t max_transfer_size; -+ int32_t max_packet_count; -+ int32_t host_channels; -+ int32_t dev_endpoints; -+ int32_t phy_type; -+ int32_t phy_utmi_width; -+ int32_t phy_ulpi_ddr; -+ int32_t phy_ulpi_ext_vbus; -+ int32_t i2c_enable; -+ int32_t ulpi_fs_ls; -+ int32_t ts_dline; -+ int32_t en_multiple_tx_fifo; -+ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; -+ uint32_t thr_ctl; -+ uint32_t tx_thr_length; -+ uint32_t rx_thr_length; -+ int32_t pti_enable; -+ int32_t mpi_enable; -+ int32_t lpm_enable; -+ int32_t ic_usb_cap; -+ int32_t ahb_thr_ratio; -+}; -+ -+static struct dwc_otg_driver_module_params dwc_otg_module_params = { -+ .opt = -1, -+ .otg_cap = -1, -+ .dma_enable = -1, -+ .dma_desc_enable = -1, -+ .dma_burst_size = -1, -+ .speed = -1, -+ .host_support_fs_ls_low_power = -1, -+ .host_ls_low_power_phy_clk = -1, -+ .enable_dynamic_fifo = -1, -+ .data_fifo_size = -1, -+ .dev_rx_fifo_size = -1, -+ .dev_nperio_tx_fifo_size = -1, -+ .dev_perio_tx_fifo_size = { -+ /* dev_perio_tx_fifo_size_1 */ -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1 -+ /* 15 */ -+ }, -+ .host_rx_fifo_size = -1, -+ .host_nperio_tx_fifo_size = -1, -+ .host_perio_tx_fifo_size = -1, -+ .max_transfer_size = -1, -+ .max_packet_count = -1, -+ .host_channels = -1, -+ .dev_endpoints = -1, -+ .phy_type = -1, -+ .phy_utmi_width = -1, -+ .phy_ulpi_ddr = -1, -+ .phy_ulpi_ext_vbus = -1, -+ .i2c_enable = -1, -+ .ulpi_fs_ls = -1, -+ .ts_dline = -1, -+ .en_multiple_tx_fifo = -1, -+ .dev_tx_fifo_size = { -+ /* dev_tx_fifo_size */ -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1, -+ -1 -+ /* 15 */ -+ }, -+ .thr_ctl = -1, -+ .tx_thr_length = -1, -+ .rx_thr_length = -1, -+ .pti_enable = -1, -+ .mpi_enable = -1, -+ .lpm_enable = -1, -+ .ic_usb_cap = -1, -+ .ahb_thr_ratio = -1, -+}; -+ -+/** -+ * This function shows the Driver Version. -+ */ -+static ssize_t version_show(struct device_driver *dev, char *buf) -+{ -+ return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n", -+ DWC_DRIVER_VERSION); -+} -+ -+static DRIVER_ATTR(version, S_IRUGO, version_show, NULL); -+ -+/** -+ * Global Debug Level Mask. -+ */ -+uint32_t g_dbg_lvl = 0; /* OFF */ -+ -+/** -+ * This function shows the driver Debug Level. -+ */ -+static ssize_t dbg_level_show(struct device_driver *drv, char *buf) -+{ -+ return sprintf(buf, "0x%0x\n", g_dbg_lvl); -+} -+ -+/** -+ * This function stores the driver Debug Level. -+ */ -+static ssize_t dbg_level_store(struct device_driver *drv, const char *buf, -+ size_t count) -+{ -+ g_dbg_lvl = simple_strtoul(buf, NULL, 16); -+ return count; -+} -+ -+static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show, -+ dbg_level_store); -+ -+/** -+ * This function is called during module intialization -+ * to pass module parameters to the DWC_OTG CORE. -+ */ -+static int set_parameters(dwc_otg_core_if_t * core_if) -+{ -+ int retval = 0; -+ int i; -+ -+ if (dwc_otg_module_params.otg_cap != -1) { -+ retval += -+ dwc_otg_set_param_otg_cap(core_if, -+ dwc_otg_module_params.otg_cap); -+ } -+ if (dwc_otg_module_params.dma_enable != -1) { -+ retval += -+ dwc_otg_set_param_dma_enable(core_if, -+ dwc_otg_module_params. -+ dma_enable); -+ } -+ if (dwc_otg_module_params.dma_desc_enable != -1) { -+ retval += -+ dwc_otg_set_param_dma_desc_enable(core_if, -+ dwc_otg_module_params. -+ dma_desc_enable); -+ } -+ if (dwc_otg_module_params.opt != -1) { -+ retval += -+ dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt); -+ } -+ if (dwc_otg_module_params.dma_burst_size != -1) { -+ retval += -+ dwc_otg_set_param_dma_burst_size(core_if, -+ dwc_otg_module_params. -+ dma_burst_size); -+ } -+ if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) { -+ retval += -+ dwc_otg_set_param_host_support_fs_ls_low_power(core_if, -+ dwc_otg_module_params. -+ host_support_fs_ls_low_power); -+ } -+ if (dwc_otg_module_params.enable_dynamic_fifo != -1) { -+ retval += -+ dwc_otg_set_param_enable_dynamic_fifo(core_if, -+ dwc_otg_module_params. -+ enable_dynamic_fifo); -+ } -+ if (dwc_otg_module_params.data_fifo_size != -1) { -+ retval += -+ dwc_otg_set_param_data_fifo_size(core_if, -+ dwc_otg_module_params. -+ data_fifo_size); -+ } -+ if (dwc_otg_module_params.dev_rx_fifo_size != -1) { -+ retval += -+ dwc_otg_set_param_dev_rx_fifo_size(core_if, -+ dwc_otg_module_params. -+ dev_rx_fifo_size); -+ } -+ if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) { -+ retval += -+ dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if, -+ dwc_otg_module_params. -+ dev_nperio_tx_fifo_size); -+ } -+ if (dwc_otg_module_params.host_rx_fifo_size != -1) { -+ retval += -+ dwc_otg_set_param_host_rx_fifo_size(core_if, -+ dwc_otg_module_params.host_rx_fifo_size); -+ } -+ if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) { -+ retval += -+ dwc_otg_set_param_host_nperio_tx_fifo_size(core_if, -+ dwc_otg_module_params. -+ host_nperio_tx_fifo_size); -+ } -+ if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) { -+ retval += -+ dwc_otg_set_param_host_perio_tx_fifo_size(core_if, -+ dwc_otg_module_params. -+ host_perio_tx_fifo_size); -+ } -+ if (dwc_otg_module_params.max_transfer_size != -1) { -+ retval += -+ dwc_otg_set_param_max_transfer_size(core_if, -+ dwc_otg_module_params. -+ max_transfer_size); -+ } -+ if (dwc_otg_module_params.max_packet_count != -1) { -+ retval += -+ dwc_otg_set_param_max_packet_count(core_if, -+ dwc_otg_module_params. -+ max_packet_count); -+ } -+ if (dwc_otg_module_params.host_channels != -1) { -+ retval += -+ dwc_otg_set_param_host_channels(core_if, -+ dwc_otg_module_params. -+ host_channels); -+ } -+ if (dwc_otg_module_params.dev_endpoints != -1) { -+ retval += -+ dwc_otg_set_param_dev_endpoints(core_if, -+ dwc_otg_module_params. -+ dev_endpoints); -+ } -+ if (dwc_otg_module_params.phy_type != -1) { -+ retval += -+ dwc_otg_set_param_phy_type(core_if, -+ dwc_otg_module_params.phy_type); -+ } -+ if (dwc_otg_module_params.speed != -1) { -+ retval += -+ dwc_otg_set_param_speed(core_if, -+ dwc_otg_module_params.speed); -+ } -+ if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) { -+ retval += -+ dwc_otg_set_param_host_ls_low_power_phy_clk(core_if, -+ dwc_otg_module_params. -+ host_ls_low_power_phy_clk); -+ } -+ if (dwc_otg_module_params.phy_ulpi_ddr != -1) { -+ retval += -+ dwc_otg_set_param_phy_ulpi_ddr(core_if, -+ dwc_otg_module_params. -+ phy_ulpi_ddr); -+ } -+ if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) { -+ retval += -+ dwc_otg_set_param_phy_ulpi_ext_vbus(core_if, -+ dwc_otg_module_params. -+ phy_ulpi_ext_vbus); -+ } -+ if (dwc_otg_module_params.phy_utmi_width != -1) { -+ retval += -+ dwc_otg_set_param_phy_utmi_width(core_if, -+ dwc_otg_module_params. -+ phy_utmi_width); -+ } -+ if (dwc_otg_module_params.ulpi_fs_ls != -1) { -+ retval += -+ dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_otg_module_params.ulpi_fs_ls); -+ } -+ if (dwc_otg_module_params.ts_dline != -1) { -+ retval += -+ dwc_otg_set_param_ts_dline(core_if, -+ dwc_otg_module_params.ts_dline); -+ } -+ if (dwc_otg_module_params.i2c_enable != -1) { -+ retval += -+ dwc_otg_set_param_i2c_enable(core_if, -+ dwc_otg_module_params. -+ i2c_enable); -+ } -+ if (dwc_otg_module_params.en_multiple_tx_fifo != -1) { -+ retval += -+ dwc_otg_set_param_en_multiple_tx_fifo(core_if, -+ dwc_otg_module_params. -+ en_multiple_tx_fifo); -+ } -+ for (i = 0; i < 15; i++) { -+ if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) { -+ retval += -+ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if, -+ dwc_otg_module_params. -+ dev_perio_tx_fifo_size -+ [i], i); -+ } -+ } -+ -+ for (i = 0; i < 15; i++) { -+ if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) { -+ retval += dwc_otg_set_param_dev_tx_fifo_size(core_if, -+ dwc_otg_module_params. -+ dev_tx_fifo_size -+ [i], i); -+ } -+ } -+ if (dwc_otg_module_params.thr_ctl != -1) { -+ retval += -+ dwc_otg_set_param_thr_ctl(core_if, -+ dwc_otg_module_params.thr_ctl); -+ } -+ if (dwc_otg_module_params.mpi_enable != -1) { -+ retval += -+ dwc_otg_set_param_mpi_enable(core_if, -+ dwc_otg_module_params. -+ mpi_enable); -+ } -+ if (dwc_otg_module_params.pti_enable != -1) { -+ retval += -+ dwc_otg_set_param_pti_enable(core_if, -+ dwc_otg_module_params. -+ pti_enable); -+ } -+ if (dwc_otg_module_params.lpm_enable != -1) { -+ retval += -+ dwc_otg_set_param_lpm_enable(core_if, -+ dwc_otg_module_params. -+ lpm_enable); -+ } -+ if (dwc_otg_module_params.ic_usb_cap != -1) { -+ retval += -+ dwc_otg_set_param_ic_usb_cap(core_if, -+ dwc_otg_module_params. -+ ic_usb_cap); -+ } -+ if (dwc_otg_module_params.tx_thr_length != -1) { -+ retval += -+ dwc_otg_set_param_tx_thr_length(core_if, -+ dwc_otg_module_params.tx_thr_length); -+ } -+ if (dwc_otg_module_params.rx_thr_length != -1) { -+ retval += -+ dwc_otg_set_param_rx_thr_length(core_if, -+ dwc_otg_module_params. -+ rx_thr_length); -+ } -+ if(dwc_otg_module_params.ahb_thr_ratio != -1) { -+ retval += -+ dwc_otg_set_param_ahb_thr_ratio(core_if, dwc_otg_module_params.ahb_thr_ratio); -+ } -+ return retval; -+} -+ -+/** -+ * This function is the top level interrupt handler for the Common -+ * (Device and host modes) interrupts. -+ */ -+static irqreturn_t dwc_otg_common_irq(int irq, void *dev) -+{ -+ dwc_otg_device_t *otg_dev = dev; -+ int32_t retval = IRQ_NONE; -+ -+ retval = dwc_otg_handle_common_intr(otg_dev->core_if); -+ if (retval != 0) { -+ S3C2410X_CLEAR_EINTPEND(); -+ } -+ return IRQ_RETVAL(retval); -+} -+ -+/** -+ * This function is called when a lm_device is unregistered with the -+ * dwc_otg_driver. This happens, for example, when the rmmod command is -+ * executed. The device may or may not be electrically present. If it is -+ * present, the driver stops device processing. Any resources used on behalf -+ * of this device are freed. -+ * -+ * @param _dev -+ */ -+#ifdef LM_INTERFACE -+static void dwc_otg_driver_remove( -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+static void dwc_otg_driver_remove( -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+static int dwc_otg_driver_remove( -+ struct platform_device *_dev -+#endif -+) -+ -+{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ -+ -+ DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev); -+ -+ if (!otg_dev) { -+ /* Memory allocation for the dwc_otg_device failed. */ -+ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); -+#ifdef PLATFORM_INTERFACE -+ return -ENOMEM; -+#else -+ return; -+#endif -+ } -+#ifndef DWC_DEVICE_ONLY -+ if (otg_dev->hcd) { -+ hcd_remove(_dev); -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); -+#ifdef PLATFORM_INTERFACE -+ return -EINVAL; -+#else -+ return; -+#endif -+ } -+#endif -+ -+#ifndef DWC_HOST_ONLY -+ if (otg_dev->pcd) { -+ pcd_remove(_dev); -+ } -+#endif -+ /* -+ * Free the IRQ -+ */ -+ if (otg_dev->common_irq_installed) { -+#ifdef PLATFORM_INTERFACE -+ free_irq(platform_get_irq(_dev, 0), otg_dev); -+#else -+ free_irq(_dev->irq, otg_dev); -+#endif -+ } -+ -+ if (otg_dev->core_if) { -+ dwc_otg_cil_remove(otg_dev->core_if); -+ } -+ -+ /* -+ * Remove the device attributes -+ */ -+ dwc_otg_attr_remove(_dev); -+ -+ /* -+ * Return the memory. -+ */ -+ if (otg_dev->base) { -+ iounmap(otg_dev->base); -+ } -+ dwc_free(otg_dev); -+ -+ /* -+ * Clear the drvdata pointer. -+ */ -+#ifdef LM_INTERFACE -+ lm_set_drvdata(_dev, 0); -+#elif defined(PCI_INTERFACE) -+ release_mem_region(otg_dev->rsrc_start, otg_dev->rsrc_len); -+ pci_set_drvdata(_dev, 0); -+#elif defined(PLATFORM_INTERFACE) -+ platform_set_drvdata(_dev, 0); -+ return 0; -+#endif -+} -+ -+/** -+ * This function is called when an lm_device is bound to a -+ * dwc_otg_driver. It creates the driver components required to -+ * control the device (CIL, HCD, and PCD) and it initializes the -+ * device. The driver components are stored in a dwc_otg_device -+ * structure. A reference to the dwc_otg_device is saved in the -+ * lm_device. This allows the driver to access the dwc_otg_device -+ * structure on subsequent calls to driver methods for this device. -+ * -+ * @param _dev Bus device -+ */ -+static int dwc_otg_driver_probe( -+#ifdef LM_INTERFACE -+struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+struct pci_dev *_dev, const struct pci_device_id *id -+#elif defined(PLATFORM_INTERFACE) -+struct platform_device *_dev -+#endif -+) -+{ -+ int retval = 0; -+ dwc_otg_device_t *dwc_otg_device; -+ int devirq; -+ -+ dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev); -+#ifdef LM_INTERFACE -+ dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start); -+#elif defined(PCI_INTERFACE) -+ if (!id) { -+ DWC_ERROR("Invalid pci_device_id %p", id); -+ return -EINVAL; -+ } -+ -+ if (!_dev || (pci_enable_device(_dev) < 0)) { -+ DWC_ERROR("Invalid pci_device %p", _dev); -+ return -ENODEV; -+ } -+ dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0)); -+ /* other stuff needed as well? */ -+ -+#elif defined(PLATFORM_INTERFACE) -+ dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n", -+ (unsigned)_dev->resource->start, -+ (unsigned)(_dev->resource->end - _dev->resource->start)); -+#endif -+ -+ -+ dwc_otg_device = dwc_alloc(sizeof(dwc_otg_device_t)); -+ -+ if (!dwc_otg_device) { -+ dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n"); -+ retval = -ENOMEM; -+ goto fail; -+ } -+ -+ memset(dwc_otg_device, 0, sizeof(*dwc_otg_device)); -+ dwc_otg_device->reg_offset = 0xFFFFFFFF; -+ -+ /* -+ * Map the DWC_otg Core memory into virtual address space. -+ */ -+#ifdef LM_INTERFACE -+#if 1 -+ dwc_otg_device->base = ioremap(_dev->resource.start, SZ_256K); -+#else -+ struct map_desc desc = { -+ .virtual = IO_ADDRESS((unsigned)_dev->resource.start), -+ .pfn = __phys_to_pfn((unsigned)_dev->resource.start), -+ .length = SZ_128K, -+ .type = MT_DEVICE -+ }; -+ iotable_init(&desc, 1); -+ dwc_otg_device->base = (void *)desc.virtual; -+#endif -+ -+ if (!dwc_otg_device->base) { -+ dev_err(&_dev->dev, "ioremap() failed\n"); -+ retval = -ENOMEM; -+ goto fail; -+ } -+ dev_dbg(&_dev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base); -+#elif defined(PCI_INTERFACE) -+ _dev->current_state = PCI_D0; -+ _dev->dev.power.power_state = PMSG_ON; -+ -+ if (!_dev->irq) { -+ DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!", pci_name(_dev)); -+ retval = -ENODEV; -+ goto fail; -+ } -+ -+ dwc_otg_device->rsrc_start = pci_resource_start(_dev,0); -+ dwc_otg_device->rsrc_len = pci_resource_len(_dev,0); -+ DWC_DEBUGPL(DBG_ANY,"PCI resource: start=%08x, len=%08x\n", -+ dwc_otg_device->rsrc_start, -+ dwc_otg_device->rsrc_len); -+ if (!request_mem_region(dwc_otg_device->rsrc_start, dwc_otg_device->rsrc_len, "dwc_otg")) { -+ dev_dbg(&_dev->dev, "error mapping memory\n"); -+ retval = -EFAULT; -+ goto fail; -+ } -+ -+ dwc_otg_device->base = ioremap_nocache(dwc_otg_device->rsrc_start, dwc_otg_device->rsrc_len); -+ if (dwc_otg_device->base == NULL) { -+ dev_dbg(&_dev->dev, "error mapping memory\n"); -+ retval = -EFAULT; -+ goto fail; -+ } -+ dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n", dwc_otg_device->base); -+ dwc_otg_device->base = (char *)dwc_otg_device->base; -+ dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n", dwc_otg_device->base); -+ dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__, -+ (unsigned)dwc_otg_device->rsrc_start, dwc_otg_device->base); -+ // -+ pci_set_drvdata(_dev, dwc_otg_device); -+ pci_set_master(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n", -+ _dev->resource->start, -+ _dev->resource->end - _dev->resource->start + 1); -+#if 1 -+ if (!request_mem_region(_dev->resource->start, -+ _dev->resource->end - _dev->resource->start + 1, -+ "dwc_otg")) { -+ dev_dbg(&_dev->dev, "error reserving mapped memory\n"); -+ retval = -EFAULT; -+ goto fail; -+ } -+ -+ dwc_otg_device->base = ioremap_nocache(_dev->resource->start, -+ _dev->resource->end - -+ _dev->resource->start + 1); -+#else -+ { -+ struct map_desc desc = { -+ .virtual = IO_ADDRESS((unsigned)_dev->resource->start), -+ .pfn = __phys_to_pfn((unsigned)_dev->resource->start), -+ .length = SZ_128K, -+ .type = MT_DEVICE -+ }; -+ iotable_init(&desc, 1); -+ dwc_otg_device->base = (void *)desc.virtual; -+ } -+#endif -+ if (!dwc_otg_device->base) { -+ dev_err(&_dev->dev, "ioremap() failed\n"); -+ retval = -ENOMEM; -+ goto fail; -+ } -+ dev_dbg(&_dev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base); -+#endif -+ -+ /* -+ * Initialize driver data to point to the global DWC_otg -+ * Device structure. -+ */ -+#ifdef LM_INTERFACE -+ lm_set_drvdata(_dev, dwc_otg_device); -+#elif defined(PLATFORM_INTERFACE) -+ platform_set_drvdata(_dev, dwc_otg_device); -+#endif -+ dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device); -+ -+ dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->base); -+ DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n", -+ dwc_otg_device, dwc_otg_device->core_if);//GRAYG -+ -+ if (!dwc_otg_device->core_if) { -+ dev_err(&_dev->dev, "CIL initialization failed!\n"); -+ retval = -ENOMEM; -+ goto fail; -+ } -+ -+ dev_dbg(&_dev->dev, "Calling get_gsnpsid\n"); -+ /* -+ * Attempt to ensure this device is really a DWC_otg Controller. -+ * Read and verify the SNPSID register contents. The value should be -+ * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX". -+ */ -+ -+ if ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != -+ 0x4F542000) { -+ dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n", -+ dwc_otg_get_gsnpsid(dwc_otg_device->core_if)); -+ dwc_otg_cil_remove(dwc_otg_device->core_if); -+ dwc_free(dwc_otg_device); -+ retval = -EINVAL; -+ goto fail; -+ } -+ -+ /* -+ * Validate parameter values. -+ */ -+ dev_dbg(&_dev->dev, "Calling set_parameters\n"); -+ if (set_parameters(dwc_otg_device->core_if)) { -+ dwc_otg_cil_remove(dwc_otg_device->core_if); -+ retval = -EINVAL; -+ goto fail; -+ } -+ -+ /* -+ * Create Device Attributes in sysfs -+ */ -+ dev_dbg(&_dev->dev, "Calling attr_create\n"); -+ dwc_otg_attr_create(_dev); -+ -+ /* -+ * Disable the global interrupt until all the interrupt -+ * handlers are installed. -+ */ -+ dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n"); -+ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); -+ -+ /* -+ * Install the interrupt handler for the common interrupts before -+ * enabling common interrupts in core_init below. -+ */ -+#if defined(PLATFORM_INTERFACE) -+ devirq = platform_get_irq(_dev, 0); -+#else -+ devirq = _dev->irq; -+#endif -+ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", -+ devirq); -+ dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq); -+ retval = request_irq(devirq, dwc_otg_common_irq, -+ IRQF_SHARED, -+ "dwc_otg", dwc_otg_device); -+ if (retval) { -+ DWC_ERROR("request of irq%d failed\n", devirq); -+ retval = -EBUSY; -+ goto fail; -+ } else { -+ dwc_otg_device->common_irq_installed = 1; -+ } -+ -+#ifndef IRQF_TRIGGER_LOW -+#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE) -+ dev_dbg(&_dev->dev, "Calling set_irq_type\n"); -+ set_irq_type(devirq, -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ IRQT_LOW -+#else -+ IRQ_TYPE_LEVEL_LOW -+#endif -+ ); -+#endif -+#endif /*IRQF_TRIGGER_LOW*/ -+ -+ /* -+ * Initialize the DWC_otg core. -+ */ -+ dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n"); -+ dwc_otg_core_init(dwc_otg_device->core_if); -+ -+#ifndef DWC_HOST_ONLY -+ /* -+ * Initialize the PCD -+ */ -+ dev_dbg(&_dev->dev, "Calling pcd_init\n"); -+ retval = pcd_init(_dev); -+ if (retval != 0) { -+ DWC_ERROR("pcd_init failed\n"); -+ dwc_otg_device->pcd = NULL; -+ goto fail; -+ } -+#endif -+#ifndef DWC_DEVICE_ONLY -+ /* -+ * Initialize the HCD -+ */ -+ dev_dbg(&_dev->dev, "Calling hcd_init\n"); -+ retval = hcd_init(_dev); -+ if (retval != 0) { -+ DWC_ERROR("hcd_init failed\n"); -+ dwc_otg_device->hcd = NULL; -+ goto fail; -+ } -+#endif -+ /* Recover from drvdata having been overwritten by hcd_init() */ -+#ifdef LM_INTERFACE -+ lm_set_drvdata(_dev, dwc_otg_device); -+#elif defined(PLATFORM_INTERFACE) -+ platform_set_drvdata(_dev, dwc_otg_device); -+#elif defined(PCI_INTERFACE) -+ pci_set_drvdata(_dev, dwc_otg_device); -+#endif -+ -+ /* -+ * Enable the global interrupt after all the interrupt -+ * handlers are installed. -+ */ -+ dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n"); -+ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); -+ dev_dbg(&_dev->dev, "Done\n"); -+ -+ return 0; -+ -+ fail: -+ dwc_otg_driver_remove(_dev); -+ return retval; -+} -+ -+/** -+ * This structure defines the methods to be called by a bus driver -+ * during the lifecycle of a device on that bus. Both drivers and -+ * devices are registered with a bus driver. The bus driver matches -+ * devices to drivers based on information in the device and driver -+ * structures. -+ * -+ * The probe function is called when the bus driver matches a device -+ * to this driver. The remove function is called when a device is -+ * unregistered with the bus driver. -+ */ -+#ifdef LM_INTERFACE -+static struct lm_driver dwc_otg_driver = { -+ .drv = { -+ .name = (char *)dwc_driver_name, -+ }, -+ .probe = dwc_otg_driver_probe, -+ .remove = dwc_otg_driver_remove, -+ // 'suspend' and 'resume' absent -+}; -+#elif defined(PCI_INTERFACE) -+static const struct pci_device_id pci_ids[] = { { -+ PCI_DEVICE(0x16c3, 0xabcd), -+ .driver_data = (unsigned long) 0xdeadbeef, -+ }, { /* end: all zeroes */ } -+}; -+MODULE_DEVICE_TABLE(pci, pci_ids); -+ -+/* pci driver glue; this is a "new style" PCI driver module */ -+static struct pci_driver dwc_otg_driver = { -+ .name = "dwc_otg", -+ .id_table = pci_ids, -+ -+ .probe = dwc_otg_driver_probe, -+ .remove = dwc_otg_driver_remove, -+ -+ .driver = { -+ .name = (char*)dwc_driver_name, -+ }, -+}; -+#elif defined(PLATFORM_INTERFACE) -+static struct platform_device_id platform_ids[] = { -+ { -+ .name = "bcm2708_usb", -+ .driver_data = (kernel_ulong_t) 0xdeadbeef, -+ }, -+ { /* end: all zeroes */ } -+}; -+MODULE_DEVICE_TABLE(platform, platform_ids); -+ -+static struct platform_driver dwc_otg_driver = { -+ .driver = { -+ .name = (char *)dwc_driver_name, -+ }, -+ .id_table = platform_ids, -+ -+ .probe = dwc_otg_driver_probe, -+ .remove = dwc_otg_driver_remove, -+ // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early' -+}; -+#endif -+ -+ -+/** -+ * This function is called when the dwc_otg_driver is installed with the -+ * insmod command. It registers the dwc_otg_driver structure with the -+ * appropriate bus driver. This will cause the dwc_otg_driver_probe function -+ * to be called. In addition, the bus driver will automatically expose -+ * attributes defined for the device and driver in the special sysfs file -+ * system. -+ * -+ * @return -+ */ -+static int __init dwc_otg_driver_init(void) -+{ -+ int retval = 0; -+ int error; -+ printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name, -+ DWC_DRIVER_VERSION, -+#ifdef LM_INTERFACE -+ "logicmodule"); -+ retval = lm_driver_register(&dwc_otg_driver); -+#elif defined(PCI_INTERFACE) -+ "pci"); -+ retval = pci_register_driver(&dwc_otg_driver); -+#elif defined(PLATFORM_INTERFACE) -+ "platform"); -+ retval = platform_driver_register(&dwc_otg_driver); -+#endif -+ if (retval < 0) { -+ printk(KERN_ERR "%s retval=%d\n", __func__, retval); -+ return retval; -+ } -+#ifdef LM_INTERFACE -+ error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_version); -+ error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_debuglevel); -+#elif defined(PCI_INTERFACE) -+ error = driver_create_file(&dwc_otg_driver.driver, -+ &driver_attr_version); -+ error = driver_create_file(&dwc_otg_driver.driver, -+ &driver_attr_debuglevel); -+#elif defined(PLATFORM_INTERFACE) -+ error = driver_create_file(&dwc_otg_driver.driver, -+ &driver_attr_version); -+ error = driver_create_file(&dwc_otg_driver.driver, -+ &driver_attr_debuglevel); -+#endif -+ return retval; -+} -+ -+module_init(dwc_otg_driver_init); -+ -+/** -+ * This function is called when the driver is removed from the kernel -+ * with the rmmod command. The driver unregisters itself with its bus -+ * driver. -+ * -+ */ -+static void __exit dwc_otg_driver_cleanup(void) -+{ -+ printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n"); -+ -+#ifdef LM_INTERFACE -+ driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel); -+ driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version); -+ lm_driver_unregister(&dwc_otg_driver); -+#elif defined(PCI_INTERFACE) -+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel); -+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version); -+ pci_unregister_driver(&dwc_otg_driver); -+#elif defined(PLATFORM_INTERFACE) -+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel); -+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version); -+ platform_driver_unregister(&dwc_otg_driver); -+#endif -+ -+ printk(KERN_INFO "%s module removed\n", dwc_driver_name); -+} -+module_exit(dwc_otg_driver_cleanup); -+ -+MODULE_DESCRIPTION(DWC_DRIVER_DESC); -+MODULE_AUTHOR("Synopsys Inc."); -+MODULE_LICENSE("GPL"); -+ -+module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444); -+MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None"); -+module_param_named(opt, dwc_otg_module_params.opt, int, 0444); -+MODULE_PARM_DESC(opt, "OPT Mode"); -+module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444); -+MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled"); -+ -+module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int, -+ 0444); -+MODULE_PARM_DESC(dma_desc_enable, -+ "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled"); -+ -+module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int, -+ 0444); -+MODULE_PARM_DESC(dma_burst_size, -+ "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256"); -+module_param_named(speed, dwc_otg_module_params.speed, int, 0444); -+MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed"); -+module_param_named(host_support_fs_ls_low_power, -+ dwc_otg_module_params.host_support_fs_ls_low_power, int, -+ 0444); -+MODULE_PARM_DESC(host_support_fs_ls_low_power, -+ "Support Low Power w/FS or LS 0=Support 1=Don't Support"); -+module_param_named(host_ls_low_power_phy_clk, -+ dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444); -+MODULE_PARM_DESC(host_ls_low_power_phy_clk, -+ "Low Speed Low Power Clock 0=48Mhz 1=6Mhz"); -+module_param_named(enable_dynamic_fifo, -+ dwc_otg_module_params.enable_dynamic_fifo, int, 0444); -+MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing"); -+module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int, -+ 0444); -+MODULE_PARM_DESC(data_fifo_size, -+ "Total number of words in the data FIFO memory 32-32768"); -+module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size, -+ int, 0444); -+MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); -+module_param_named(dev_nperio_tx_fifo_size, -+ dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444); -+MODULE_PARM_DESC(dev_nperio_tx_fifo_size, -+ "Number of words in the non-periodic Tx FIFO 16-32768"); -+module_param_named(dev_perio_tx_fifo_size_1, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_1, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_2, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_2, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_3, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_3, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_4, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_4, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_5, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_5, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_6, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_6, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_7, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_7, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_8, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_8, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_9, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_9, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_10, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_10, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_11, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_11, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_12, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_12, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_13, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_13, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_14, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_14, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(dev_perio_tx_fifo_size_15, -+ dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444); -+MODULE_PARM_DESC(dev_perio_tx_fifo_size_15, -+ "Number of words in the periodic Tx FIFO 4-768"); -+module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size, -+ int, 0444); -+MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); -+module_param_named(host_nperio_tx_fifo_size, -+ dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444); -+MODULE_PARM_DESC(host_nperio_tx_fifo_size, -+ "Number of words in the non-periodic Tx FIFO 16-32768"); -+module_param_named(host_perio_tx_fifo_size, -+ dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444); -+MODULE_PARM_DESC(host_perio_tx_fifo_size, -+ "Number of words in the host periodic Tx FIFO 16-32768"); -+module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size, -+ int, 0444); -+/** @todo Set the max to 512K, modify checks */ -+MODULE_PARM_DESC(max_transfer_size, -+ "The maximum transfer size supported in bytes 2047-65535"); -+module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count, -+ int, 0444); -+MODULE_PARM_DESC(max_packet_count, -+ "The maximum number of packets in a transfer 15-511"); -+module_param_named(host_channels, dwc_otg_module_params.host_channels, int, -+ 0444); -+MODULE_PARM_DESC(host_channels, -+ "The number of host channel registers to use 1-16"); -+module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int, -+ 0444); -+MODULE_PARM_DESC(dev_endpoints, -+ "The number of endpoints in addition to EP0 available for device mode 1-15"); -+module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444); -+MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI"); -+module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int, -+ 0444); -+MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits"); -+module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444); -+MODULE_PARM_DESC(phy_ulpi_ddr, -+ "ULPI at double or single data rate 0=Single 1=Double"); -+module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus, -+ int, 0444); -+MODULE_PARM_DESC(phy_ulpi_ext_vbus, -+ "ULPI PHY using internal or external vbus 0=Internal"); -+module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444); -+MODULE_PARM_DESC(i2c_enable, "FS PHY Interface"); -+module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444); -+MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only"); -+module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444); -+MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs"); -+module_param_named(debug, g_dbg_lvl, int, 0444); -+MODULE_PARM_DESC(debug, ""); -+ -+module_param_named(en_multiple_tx_fifo, -+ dwc_otg_module_params.en_multiple_tx_fifo, int, 0444); -+MODULE_PARM_DESC(en_multiple_tx_fifo, -+ "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled"); -+module_param_named(dev_tx_fifo_size_1, -+ dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_2, -+ dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_3, -+ dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_4, -+ dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_5, -+ dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_6, -+ dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_7, -+ dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_8, -+ dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_9, -+ dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_10, -+ dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_11, -+ dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_12, -+ dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_13, -+ dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_14, -+ dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768"); -+module_param_named(dev_tx_fifo_size_15, -+ dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444); -+MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768"); -+ -+module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444); -+MODULE_PARM_DESC(thr_ctl, -+ "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled"); -+module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int, -+ 0444); -+MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs"); -+module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int, -+ 0444); -+MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs"); -+ -+module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444); -+module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444); -+module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444); -+MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled"); -+module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444); -+MODULE_PARM_DESC(ic_usb_cap, -+ "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled"); -+module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int, 0444); -+MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio"); -+ -+/** @page "Module Parameters" -+ * -+ * The following parameters may be specified when starting the module. -+ * These parameters define how the DWC_otg controller should be -+ * configured. Parameter values are passed to the CIL initialization -+ * function dwc_otg_cil_init -+ * -+ * Example: modprobe dwc_otg speed=1 otg_cap=1 -+ * -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+*/ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.h b/drivers/usb/host/dwc_otg/dwc_otg_driver.h -new file mode 100644 -index 0000000..f37d3ac ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h -@@ -0,0 +1,101 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $ -+ * $Revision: #16 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225160 $ -+ * -+ * 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_DRIVER_H__ -+#define __DWC_OTG_DRIVER_H__ -+ -+/** @file -+ * This file contains the interface to the Linux driver. -+ */ -+#include "dwc_otg_core_if.h" -+ -+/* Type declarations */ -+struct dwc_otg_pcd; -+struct dwc_otg_hcd; -+ -+#ifdef PCI_INTERFACE -+#include -+#endif -+ -+ -+ -+/** -+ * This structure is a wrapper that encapsulates the driver components used to -+ * manage a single DWC_otg controller. -+ */ -+typedef struct dwc_otg_device { -+ /** Base address returned from ioremap() */ -+ void *base; -+ -+#ifdef LM_INTERFACE -+ struct lm_device *lmdev; -+#elif defined(PCI_INTERFACE) -+ int rsrc_start; -+ int rsrc_len; -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platformdev; -+#endif -+ -+ /** Pointer to the core interface structure. */ -+ dwc_otg_core_if_t *core_if; -+ -+ /** Register offset for Diagnostic API. */ -+ uint32_t reg_offset; -+ -+ /** Pointer to the PCD structure. */ -+ struct dwc_otg_pcd *pcd; -+ -+ /** Pointer to the HCD structure. */ -+ struct dwc_otg_hcd *hcd; -+ -+ /** Flag to indicate whether the common IRQ handler is installed. */ -+ uint8_t common_irq_installed; -+ -+} dwc_otg_device_t; -+ -+/*We must clear S3C24XX_EINTPEND external interrupt register -+ * because after clearing in this register trigerred IRQ from -+ * H/W core in kernel interrupt can be occured again before OTG -+ * handlers clear all IRQ sources of Core registers because of -+ * timing latencies and Low Level IRQ Type. -+ */ -+#ifdef CONFIG_MACH_IPMATE -+#define S3C2410X_CLEAR_EINTPEND() \ -+do { \ -+ __raw_writel(1UL << 11,S3C24XX_EINTPEND); \ -+} while (0) -+#else -+#define S3C2410X_CLEAR_EINTPEND() do { } while (0) -+#endif -+ -+#endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -new file mode 100644 -index 0000000..223d879 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -0,0 +1,3330 @@ -+ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ -+ * $Revision: #87 $ -+ * $Date: 2009/04/23 $ -+ * $Change: 1239143 $ -+ * -+ * 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_DEVICE_ONLY -+ -+/** @file -+ * This file implements HCD Core. All code in this file is portable and don't -+ * use any OS specific functions. -+ * Interface provided by HCD Core is defined in -+ * header file. -+ */ -+ -+#include "dwc_otg_hcd.h" -+#include "dwc_otg_regs.h" -+ -+#ifdef HW2937_WORKAROUND -+//#include -+#include -+#endif -+ -+dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) -+{ -+ return dwc_alloc(sizeof(dwc_otg_hcd_t)); -+} -+ -+/** -+ * Connection timeout function. An OTG host is required to display a -+ * message if the device does not connect within 10 seconds. -+ */ -+void dwc_otg_hcd_connect_timeout(void *ptr) -+{ -+ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr); -+ DWC_PRINTF("Connect Timeout\n"); -+ __DWC_ERROR("Device Not Connected/Responding\n"); -+} -+ -+#ifdef DEBUG -+static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ if (qh->channel != NULL) { -+ dwc_hc_t *hc = qh->channel; -+ dwc_list_link_t *item; -+ dwc_otg_qh_t *qh_item; -+ int num_channels = hcd->core_if->core_params->host_channels; -+ int i; -+ -+ dwc_otg_hc_regs_t *hc_regs; -+ hcchar_data_t hcchar; -+ hcsplt_data_t hcsplt; -+ hctsiz_data_t hctsiz; -+ uint32_t hcdma; -+ -+ hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hcdma = dwc_read_reg32(&hc_regs->hcdma); -+ -+ DWC_PRINTF(" Assigned to channel %p:\n", hc); -+ DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, -+ hcsplt.d32); -+ DWC_PRINTF(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, -+ hcdma); -+ DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", -+ hc->dev_addr, hc->ep_num, hc->ep_is_in); -+ DWC_PRINTF(" ep_type: %d\n", hc->ep_type); -+ DWC_PRINTF(" max_packet: %d\n", hc->max_packet); -+ DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); -+ DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started); -+ DWC_PRINTF(" halt_status: %d\n", hc->halt_status); -+ DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); -+ DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len); -+ DWC_PRINTF(" qh: %p\n", hc->qh); -+ DWC_PRINTF(" NP inactive sched:\n"); -+ DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) { -+ qh_item = -+ DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); -+ DWC_PRINTF(" %p\n", qh_item); -+ } -+ DWC_PRINTF(" NP active sched:\n"); -+ DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) { -+ qh_item = -+ DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); -+ DWC_PRINTF(" %p\n", qh_item); -+ } -+ DWC_PRINTF(" Channels: \n"); -+ for (i = 0; i < num_channels; i++) { -+ dwc_hc_t *hc = hcd->hc_ptr_array[i]; -+ DWC_PRINTF(" %2d: %p\n", i, hc); -+ } -+ } -+} -+#endif /* DEBUG */ -+ -+/** -+ * Work queue function for starting the HCD when A-Cable is connected. -+ * The hcd_start() must be called in a process context. -+ */ -+static void hcd_start_func(void *_vp) -+{ -+ dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp; -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd); -+ if (hcd) { -+ hcd->fops->start(hcd); -+ } -+} -+ -+static void del_xfer_timers(dwc_otg_hcd_t * hcd) -+{ -+#ifdef DEBUG -+ int i; -+ int num_channels = hcd->core_if->core_params->host_channels; -+ for (i = 0; i < num_channels; i++) { -+ DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]); -+ } -+#endif -+} -+ -+static void del_timers(dwc_otg_hcd_t * hcd) -+{ -+ del_xfer_timers(hcd); -+ DWC_TIMER_CANCEL(hcd->conn_timer); -+} -+ -+/** -+ * Processes all the URBs in a single list of QHs. Completes them with -+ * -ETIMEDOUT and frees the QTD. -+ */ -+static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) -+{ -+ dwc_list_link_t *qh_item; -+ dwc_otg_qh_t *qh; -+ dwc_otg_qtd_t *qtd, *qtd_tmp; -+ -+ DWC_LIST_FOREACH(qh_item, qh_list) { -+ qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry); -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, -+ &qh->qtd_list, qtd_list_entry) { -+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -+ if (qtd->urb != NULL) { -+ hcd->fops->complete(hcd, qtd->urb->priv, -+ qtd->urb, -+ -DWC_E_TIMEOUT); -+ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -+ } -+ -+ } -+ } -+} -+ -+/** -+ * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic -+ * and periodic schedules. The QTD associated with each URB is removed from -+ * the schedule and freed. This function may be called when a disconnect is -+ * detected or when the HCD is being stopped. -+ */ -+static void kill_all_urbs(dwc_otg_hcd_t * hcd) -+{ -+ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive); -+ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active); -+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive); -+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready); -+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned); -+ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued); -+} -+ -+/** -+ * Start the connection timer. An OTG host is required to display a -+ * message if the device does not connect within 10 seconds. The -+ * timer is deleted if a port connect interrupt occurs before the -+ * timer expires. -+ */ -+static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd) -+{ -+ DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ ); -+} -+ -+/** -+ * HCD Callback function for disconnect of the HCD. -+ * -+ * @param p void pointer to the struct usb_hcd -+ */ -+static int32_t dwc_otg_hcd_session_start_cb(void *p) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd; -+ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); -+ dwc_otg_hcd = p; -+ dwc_otg_hcd_start_connect_timer(dwc_otg_hcd); -+ return 1; -+} -+ -+/** -+ * HCD Callback function for starting the HCD when A-Cable is -+ * connected. -+ * -+ * @param p void pointer to the struct usb_hcd -+ */ -+static int32_t dwc_otg_hcd_start_cb(void *p) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = p; -+ dwc_otg_core_if_t *core_if; -+ hprt0_data_t hprt0; -+ -+ core_if = dwc_otg_hcd->core_if; -+ -+ if (core_if->op_state == B_HOST) { -+ /* -+ * Reset the port. During a HNP mode switch the reset -+ * needs to occur within 1ms and have a duration of at -+ * least 50ms. -+ */ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ } -+ DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, -+ hcd_start_func, dwc_otg_hcd, 50, -+ "start hcd"); -+ -+ return 1; -+} -+ -+/** -+ * HCD Callback function for disconnect of the HCD. -+ * -+ * @param p void pointer to the struct usb_hcd -+ */ -+static int32_t dwc_otg_hcd_disconnect_cb(void *p) -+{ -+ gintsts_data_t intr; -+ dwc_otg_hcd_t *dwc_otg_hcd = p; -+ -+ /* -+ * Set status flags for the hub driver. -+ */ -+ dwc_otg_hcd->flags.b.port_connect_status_change = 1; -+ dwc_otg_hcd->flags.b.port_connect_status = 0; -+ -+ /* -+ * Shutdown any transfers in process by clearing the Tx FIFO Empty -+ * interrupt mask and status bits and disabling subsequent host -+ * channel interrupts. -+ */ -+ intr.d32 = 0; -+ intr.b.nptxfempty = 1; -+ intr.b.ptxfempty = 1; -+ intr.b.hcintr = 1; -+ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, -+ intr.d32, 0); -+ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, -+ intr.d32, 0); -+ -+ del_timers(dwc_otg_hcd); -+ -+ /* -+ * Turn off the vbus power only if the core has transitioned to device -+ * mode. If still in host mode, need to keep power on to detect a -+ * reconnection. -+ */ -+ if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) { -+ if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) { -+ hprt0_data_t hprt0 = {.d32 = 0 }; -+ DWC_PRINTF("Disconnect: PortPower off\n"); -+ hprt0.b.prtpwr = 0; -+ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, -+ hprt0.d32); -+ } -+ -+ dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); -+ } -+ -+ /* Respond with an error status to all URBs in the schedule. */ -+ kill_all_urbs(dwc_otg_hcd); -+ -+ if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) { -+ /* Clean up any host channels that were in use. */ -+ int num_channels; -+ int i; -+ dwc_hc_t *channel; -+ dwc_otg_hc_regs_t *hc_regs; -+ hcchar_data_t hcchar; -+ -+ num_channels = dwc_otg_hcd->core_if->core_params->host_channels; -+ -+ if (!dwc_otg_hcd->core_if->dma_enable) { -+ /* Flush out any channel requests in slave mode. */ -+ for (i = 0; i < num_channels; i++) { -+ channel = dwc_otg_hcd->hc_ptr_array[i]; -+ if (DWC_CIRCLEQ_EMPTY_ENTRY -+ (channel, hc_list_entry)) { -+ hc_regs = -+ dwc_otg_hcd->core_if->host_if-> -+ hc_regs[i]; -+ hcchar.d32 = -+ dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ hcchar.b.chen = 0; -+ hcchar.b.chdis = 1; -+ hcchar.b.epdir = 0; -+ dwc_write_reg32(&hc_regs-> -+ hcchar, -+ hcchar.d32); -+ } -+ } -+ } -+ } -+ -+ for (i = 0; i < num_channels; i++) { -+ channel = dwc_otg_hcd->hc_ptr_array[i]; -+ if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) { -+ hc_regs = -+ dwc_otg_hcd->core_if->host_if->hc_regs[i]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ /* Halt the channel. */ -+ hcchar.b.chdis = 1; -+ dwc_write_reg32(&hc_regs->hcchar, -+ hcchar.d32); -+ } -+ -+ dwc_otg_hc_cleanup(dwc_otg_hcd->core_if, -+ channel); -+ DWC_CIRCLEQ_INSERT_TAIL(&dwc_otg_hcd-> -+ free_hc_list, channel, -+ hc_list_entry); -+ /* -+ * Added for Descriptor DMA to prevent channel double cleanup -+ * in release_channel_ddma(). Which called from ep_disable -+ * when device disconnect. -+ */ -+ channel->qh = NULL; -+ } -+ } -+ } -+ -+ if (dwc_otg_hcd->fops->disconnect) { -+ dwc_otg_hcd->fops->disconnect(dwc_otg_hcd); -+ } -+ -+ return 1; -+} -+ -+/** -+ * HCD Callback function for stopping the HCD. -+ * -+ * @param p void pointer to the struct usb_hcd -+ */ -+static int32_t dwc_otg_hcd_stop_cb(void *p) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = p; -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); -+ dwc_otg_hcd_stop(dwc_otg_hcd); -+ return 1; -+} -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+/** -+ * HCD Callback function for sleep of HCD. -+ * -+ * @param p void pointer to the struct usb_hcd -+ */ -+static int dwc_otg_hcd_sleep_cb(void *p) -+{ -+ dwc_otg_hcd_t *hcd = p; -+ -+ dwc_otg_hcd_free_hc_from_lpm(hcd); -+ -+ return 0; -+} -+#endif -+ -+/** -+ * HCD Callback function for Remote Wakeup. -+ * -+ * @param p void pointer to the struct usb_hcd -+ */ -+static int dwc_otg_hcd_rem_wakeup_cb(void *p) -+{ -+ dwc_otg_hcd_t *hcd = p; -+ -+ if (hcd->core_if->lx_state == DWC_OTG_L2) { -+ hcd->flags.b.port_suspend_change = 1; -+ } -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ else { -+ hcd->flags.b.port_l1_change = 1; -+ } -+#endif -+ return 0; -+} -+ -+/** -+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are -+ * stopped. -+ */ -+void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd) -+{ -+ hprt0_data_t hprt0 = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n"); -+ -+ /* -+ * The root hub should be disconnected before this function is called. -+ * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue) -+ * and the QH lists (via ..._hcd_endpoint_disable). -+ */ -+ -+ /* Turn off all host-specific interrupts. */ -+ dwc_otg_disable_host_interrupts(hcd->core_if); -+ -+ /* Turn off the vbus power */ -+ DWC_PRINTF("PortPower off\n"); -+ hprt0.b.prtpwr = 0; -+ dwc_write_reg32(hcd->core_if->host_if->hprt0, hprt0.d32); -+ dwc_mdelay(1); -+} -+ -+int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, -+ dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle) -+{ -+ uint64_t flags; -+ int retval = 0; -+ dwc_otg_qtd_t *qtd; -+ -+ if (NULL == hcd->core_if) { //GRAYG -+ DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n"); -+ /* No longer connected. */ -+ return -DWC_E_INVALID; -+ } -+ -+ if (!hcd->flags.b.port_connect_status) { -+ /* No longer connected. */ -+ return -DWC_E_NO_DEVICE; -+ } -+ -+ qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb); -+ if (qtd == NULL) { -+ DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); -+ return -DWC_E_NO_MEMORY; -+ } -+ if (qtd->urb == NULL) { //GRAYG -+ DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n"); -+ return -DWC_E_NO_MEMORY; -+ } -+ if (qtd->urb->priv == NULL) { //GRAYG -+ DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n"); -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ retval = -+ dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle); -+ // creates a new queue in ep_handle if it doesn't exist already -+ if (retval < 0) { -+ DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " -+ "Error status %d\n", retval); -+ dwc_otg_hcd_qtd_free(qtd); -+ } else { -+ qtd->qh = *ep_handle; -+ } -+ -+ if (hcd->core_if->dma_desc_enable && retval == 0) { -+ dwc_otg_transaction_type_e tr_type; -+ if ((qtd->qh->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { -+ /* Do not schedule SG transcations until qtd has URB_GIVEBACK_ASAP set */ -+ return 0; -+ } -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ tr_type = dwc_otg_hcd_select_transactions(hcd); -+ if (tr_type != DWC_OTG_TRANSACTION_NONE) { -+ dwc_otg_hcd_queue_transactions(hcd, tr_type); -+ } -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ } -+ -+ return retval; -+} -+ -+int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, -+ dwc_otg_hcd_urb_t * dwc_otg_urb) -+{ -+ uint64_t flags; -+ -+ dwc_otg_qh_t *qh; -+ dwc_otg_qtd_t *urb_qtd; -+ -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ -+ if (hcd == NULL) { //GRAYG -+ DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n"); -+ return -DWC_E_INVALID; -+ } -+ if (dwc_otg_urb == NULL) { //GRAYG -+ DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n"); -+ return -DWC_E_INVALID; -+ } -+ if (dwc_otg_urb->qtd == NULL) { //GRAYG -+ DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n"); -+ return -DWC_E_INVALID; -+ } -+ urb_qtd = dwc_otg_urb->qtd; -+ if (urb_qtd->qh == NULL) { //GRAYG -+ DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n"); -+ return -DWC_E_INVALID; -+ } -+ qh = urb_qtd->qh; -+#ifdef DEBUG -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ if (urb_qtd->in_process) { -+ dump_channel_info(hcd, qh); -+ } -+ } -+#endif -+ if (hcd->core_if == NULL) { //GRAYG -+ DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n"); -+ return -DWC_E_INVALID; -+ } -+ if (urb_qtd->in_process && qh->channel) { -+ /* The QTD is in process (it has been assigned to a channel). */ -+ if (hcd->flags.b.port_connect_status) { -+ /* -+ * If still connected (i.e. in host mode), halt the -+ * channel so it can be used for other transfers. If -+ * no longer connected, the host registers can't be -+ * written to halt the channel since the core is in -+ * device mode. -+ */ -+ dwc_otg_hc_halt(hcd->core_if, qh->channel, -+ DWC_OTG_HC_XFER_URB_DEQUEUE); -+ } -+ } -+ -+ /* -+ * Free the QTD and clean up the associated QH. Leave the QH in the -+ * schedule if it has any remaining QTDs. -+ */ -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - " -+ "delete %sQueue handler\n", -+ hcd->core_if->dma_desc_enable?"DMA ":""); //GRAYG -+ if (!hcd->core_if->dma_desc_enable) { -+ uint8_t b = urb_qtd->in_process; -+ dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); -+ if (b) { -+ dwc_otg_hcd_qh_deactivate(hcd, qh, 0); -+ qh->channel = NULL; -+ } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ } -+ } -+ else { -+ dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ -+ return 0; -+} -+ -+int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, -+ int retry) -+{ -+ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; -+ int retval = 0; -+ uint64_t flags; -+ -+ if (retry < 0) { -+ retval = -DWC_E_INVALID; -+ goto done; -+ } -+ -+ if (!qh) { -+ goto done; -+ } -+ -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ -+ while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) { -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ retry--; -+ dwc_msleep(5); -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ } -+ -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ /* -+ * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove -+ * and qh_free to prevent stack dump on dwc_dma_free() with -+ * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() -+ * and dwc_otg_hcd_frame_list_alloc(). -+ */ -+ dwc_otg_hcd_qh_free(hcd, qh); -+ -+ done: -+ return retval; -+} -+ -+/** -+ * HCD Callback structure for handling mode switching. -+ */ -+static dwc_otg_cil_callbacks_t hcd_cil_callbacks = { -+ .start = dwc_otg_hcd_start_cb, -+ .stop = dwc_otg_hcd_stop_cb, -+ .disconnect = dwc_otg_hcd_disconnect_cb, -+ .session_start = dwc_otg_hcd_session_start_cb, -+ .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb, -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ .sleep = dwc_otg_hcd_sleep_cb, -+#endif -+ .p = 0, -+}; -+ -+/** -+ * Reset tasklet function -+ */ -+static void reset_tasklet_func(void *data) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data; -+ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; -+ hprt0_data_t hprt0; -+ -+ DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n"); -+ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ dwc_mdelay(60); -+ -+ hprt0.b.prtrst = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ dwc_otg_hcd->flags.b.port_reset_change = 1; -+} -+ -+static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) -+{ -+ dwc_list_link_t *item; -+ dwc_otg_qh_t *qh; -+ -+ if (!qh_list->next) { -+ /* The list hasn't been initialized yet. */ -+ return; -+ } -+ -+ /* Ensure there are no QTDs or URBs left. */ -+ kill_urbs_in_qh_list(hcd, qh_list); -+ -+ DWC_LIST_FOREACH(item, qh_list) { -+ qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); -+ dwc_otg_hcd_qh_remove_and_free(hcd, qh); -+ } -+} -+ -+/** -+ * Frees secondary storage associated with the dwc_otg_hcd structure contained -+ * in the struct usb_hcd field. -+ */ -+static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ int i; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); -+ -+ del_timers(dwc_otg_hcd); -+ -+ /* Free memory for QH/QTD lists */ -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned); -+ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued); -+ -+ /* Free memory for the host channels. */ -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i]; -+ -+#ifdef DEBUG -+ if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) { -+ DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]); -+ } -+#endif -+ if (hc != NULL) { -+ DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", -+ i, hc); -+ dwc_free(hc); -+ } -+ } -+ -+ if (dwc_otg_hcd->core_if->dma_enable) { -+ if (dwc_otg_hcd->status_buf_dma) { -+ dwc_dma_free(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ dwc_otg_hcd->status_buf, -+ dwc_otg_hcd->status_buf_dma); -+ } -+ } else if (dwc_otg_hcd->status_buf != NULL) { -+ dwc_free(dwc_otg_hcd->status_buf); -+ } -+ DWC_SPINLOCK_FREE(dwc_otg_hcd->lock); -+ DWC_TIMER_FREE(dwc_otg_hcd->conn_timer); -+ DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet); -+ dwc_free(dwc_otg_hcd); -+} -+ -+int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) -+{ -+ int retval = 0; -+ int num_channels; -+ int i; -+ dwc_hc_t *channel; -+ -+ hcd->lock = DWC_SPINLOCK_ALLOC(); -+ -+ DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n", -+ hcd, core_if);//GRAYG -+ -+ hcd->core_if = core_if; -+ /* Register the HCD CIL Callbacks */ -+ dwc_otg_cil_register_hcd_callbacks(hcd->core_if, -+ &hcd_cil_callbacks, hcd); -+ -+ /* Initialize the non-periodic schedule. */ -+ DWC_LIST_INIT(&hcd->non_periodic_sched_inactive); -+ DWC_LIST_INIT(&hcd->non_periodic_sched_active); -+ -+ /* Initialize the periodic schedule. */ -+ DWC_LIST_INIT(&hcd->periodic_sched_inactive); -+ DWC_LIST_INIT(&hcd->periodic_sched_ready); -+ DWC_LIST_INIT(&hcd->periodic_sched_assigned); -+ DWC_LIST_INIT(&hcd->periodic_sched_queued); -+ -+ /* -+ * Create a host channel descriptor for each host channel implemented -+ * in the controller. Initialize the channel descriptor array. -+ */ -+ DWC_CIRCLEQ_INIT(&hcd->free_hc_list); -+ num_channels = hcd->core_if->core_params->host_channels; -+ DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array)); -+ for (i = 0; i < num_channels; i++) { -+ channel = dwc_alloc(sizeof(dwc_hc_t)); -+ if (channel == NULL) { -+ retval = -DWC_E_NO_MEMORY; -+ DWC_ERROR("%s: host channel allocation failed\n", -+ __func__); -+ dwc_otg_hcd_free(hcd); -+ goto out; -+ } -+ channel->hc_num = i; -+ hcd->hc_ptr_array[i] = channel; -+#ifdef DEBUG -+ hcd->core_if->hc_xfer_timer[i] = -+ DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout, -+ &hcd->core_if->hc_xfer_info[i]); -+#endif -+ DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, -+ channel); -+ } -+ -+ /* Initialize the Connection timeout timer. */ -+ hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer", -+ dwc_otg_hcd_connect_timeout, 0); -+ -+ /* Initialize reset tasklet. */ -+ hcd->reset_tasklet = DWC_TASK_ALLOC(reset_tasklet_func, hcd); -+ -+ /* -+ * Allocate space for storing data on status transactions. Normally no -+ * data is sent, but this space acts as a bit bucket. This must be -+ * done after usb_add_hcd since that function allocates the DMA buffer -+ * pool. -+ */ -+ if (hcd->core_if->dma_enable) { -+ hcd->status_buf = -+ dwc_dma_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ &hcd->status_buf_dma); -+ } else { -+ hcd->status_buf = dwc_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE); -+ } -+ if (!hcd->status_buf) { -+ retval = -DWC_E_NO_MEMORY; -+ DWC_ERROR("%s: status_buf allocation failed\n", __func__); -+ dwc_otg_hcd_free(hcd); -+ goto out; -+ } -+ -+ hcd->otg_port = 1; -+ hcd->frame_list = NULL; -+ hcd->frame_list_dma = 0; -+ -+#ifdef HW2937_WORKAROUND -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IDLE; -+ hcd->hw2937_assigned_channels = 0; -+#endif -+ -+out: -+ return retval; -+} -+ -+void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd) -+{ -+ /* Turn off all host-specific interrupts. */ -+ dwc_otg_disable_host_interrupts(hcd->core_if); -+ -+ dwc_otg_hcd_free(hcd); -+} -+ -+/** -+ * Initializes dynamic portions of the DWC_otg HCD state. -+ */ -+static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd) -+{ -+ int num_channels; -+ int i; -+ dwc_hc_t *channel; -+ dwc_hc_t *channel_tmp; -+ -+ hcd->flags.d32 = 0; -+ -+ hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; -+ hcd->non_periodic_channels = 0; -+ hcd->periodic_channels = 0; -+ -+ /* -+ * Put all channels in the free channel list and clean up channel -+ * states. -+ */ -+ DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp, -+ &hcd->free_hc_list, hc_list_entry) { -+ DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry); -+ } -+ -+ num_channels = hcd->core_if->core_params->host_channels; -+ for (i = 0; i < num_channels; i++) { -+ channel = hcd->hc_ptr_array[i]; -+ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel, -+ hc_list_entry); -+ dwc_otg_hc_cleanup(hcd->core_if, channel); -+ } -+ -+ /* Initialize the DWC core for host mode operation. */ -+ dwc_otg_core_host_init(hcd->core_if); -+} -+ -+/** -+ * Assigns transactions from a QTD to a free host channel and initializes the -+ * host channel to perform the transactions. The host channel is removed from -+ * the free list. -+ * -+ * @param hcd The HCD state structure. -+ * @param qh Transactions from the first QTD for this QH are selected and -+ * assigned to a free host channel. -+ */ -+#ifdef HW2937_WORKAROUND -+static int assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+#else -+static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+#endif -+{ -+ dwc_hc_t *hc; -+ dwc_otg_qtd_t *qtd; -+ dwc_otg_hcd_urb_t *urb; -+ void* ptr = NULL; -+#ifdef HW2937_WORKAROUND -+ int ep_is_in; -+#endif -+ -+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -+ -+ urb = qtd->urb; -+ -+ DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length); -+ -+#ifdef HW2937_WORKAROUND -+ ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); -+ if (ep_is_in && ((hcd->hw2937_xfer_mode == HW2937_XFER_MODE_OUT) || -+ (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_PAUSEIN))) -+ return 0; -+#endif -+ -+ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); -+ -+ /* Remove the host channel from the free list. */ -+ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); -+ qh->channel = hc; -+ -+ qtd->in_process = 1; -+ -+ /* -+ * Use usb_pipedevice to determine device address. This address is -+ * 0 before the SET_ADDRESS command and the correct address afterward. -+ */ -+ hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info); -+ hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info); -+ hc->speed = qh->dev_speed; -+ hc->max_packet = dwc_max_packet(qh->maxp); -+ -+ hc->xfer_started = 0; -+ hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS; -+ hc->error_state = (qtd->error_count > 0); -+ hc->halt_on_queue = 0; -+ hc->halt_pending = 0; -+ hc->requests = 0; -+ -+ /* -+ * The following values may be modified in the transfer type section -+ * below. The xfer_len value may be reduced when the transfer is -+ * started to accommodate the max widths of the XferSize and PktCnt -+ * fields in the HCTSIZn register. -+ */ -+ hc->do_ping = qh->ping_state; -+#ifdef HW2937_WORKAROUND -+ hc->ep_is_in = ep_is_in; -+#else -+ hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); -+#endif -+ hc->data_pid_start = qh->data_toggle; -+ hc->multi_count = 1; -+ -+ if (hcd->core_if->dma_enable) { -+ hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length; -+ -+ /* For non-dword aligned case */ -+ if (((uint32_t)hc->xfer_buff & 0x3) && !hcd->core_if->dma_desc_enable) { -+ ptr = (uint8_t *) urb->buf + urb->actual_length; -+ } -+ } else { -+ hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length; -+ } -+ hc->xfer_len = urb->length - urb->actual_length; -+ hc->xfer_count = 0; -+ -+ /* -+ * Set the split attributes -+ */ -+ hc->do_split = 0; -+ if (qh->do_split) { -+ uint32_t hub_addr, port_addr; -+ hc->do_split = 1; -+ hc->xact_pos = qtd->isoc_split_pos; -+ hc->complete_split = qtd->complete_split; -+ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr); -+ hc->hub_addr = (uint8_t) hub_addr; -+ hc->port_addr = (uint8_t) port_addr; -+ } -+ -+ switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { -+ case UE_CONTROL: -+ hc->ep_type = DWC_OTG_EP_TYPE_CONTROL; -+ switch (qtd->control_phase) { -+ case DWC_OTG_CONTROL_SETUP: -+ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n"); -+ hc->do_ping = 0; -+ hc->ep_is_in = 0; -+ hc->data_pid_start = DWC_OTG_HC_PID_SETUP; -+ if (hcd->core_if->dma_enable) { -+ hc->xfer_buff = (uint8_t *) urb->setup_dma; -+ } else { -+ hc->xfer_buff = (uint8_t *) urb->setup_packet; -+ } -+ hc->xfer_len = 8; -+ ptr = NULL; -+ break; -+ case DWC_OTG_CONTROL_DATA: -+ DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n"); -+ hc->data_pid_start = qtd->data_toggle; -+ break; -+ case DWC_OTG_CONTROL_STATUS: -+ /* -+ * Direction is opposite of data direction or IN if no -+ * data. -+ */ -+ DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n"); -+ if (urb->length == 0) { -+ hc->ep_is_in = 1; -+ } else { -+ hc->ep_is_in = -+ dwc_otg_hcd_is_pipe_out(&urb->pipe_info); -+ } -+ if (hc->ep_is_in) { -+ hc->do_ping = 0; -+ } -+ -+ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; -+ -+ hc->xfer_len = 0; -+ if (hcd->core_if->dma_enable) { -+ hc->xfer_buff = (uint8_t *) hcd->status_buf_dma; -+ } else { -+ hc->xfer_buff = (uint8_t *) hcd->status_buf; -+ } -+ ptr = NULL; -+ break; -+ } -+ break; -+ case UE_BULK: -+ hc->ep_type = DWC_OTG_EP_TYPE_BULK; -+ break; -+ case UE_INTERRUPT: -+ hc->ep_type = DWC_OTG_EP_TYPE_INTR; -+ break; -+ case UE_ISOCHRONOUS: -+ { -+ struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ -+ hc->ep_type = DWC_OTG_EP_TYPE_ISOC; -+ -+ if (hcd->core_if->dma_desc_enable) -+ break; -+ -+ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; -+ -+ frame_desc->status = 0; -+ -+ if (hcd->core_if->dma_enable) { -+ hc->xfer_buff = (uint8_t *) urb->dma; -+ } else { -+ hc->xfer_buff = (uint8_t *) urb->buf; -+ } -+ hc->xfer_buff += -+ frame_desc->offset + qtd->isoc_split_offset; -+ hc->xfer_len = -+ frame_desc->length - qtd->isoc_split_offset; -+ -+ /* For non-dword aligned buffers */ -+ if (((uint32_t)hc->xfer_buff & 0x3) && hcd->core_if->dma_enable) { -+ ptr = (uint8_t *) urb->buf + frame_desc->offset + qtd->isoc_split_offset; -+ } -+ else -+ ptr = NULL; -+ -+ if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) { -+ if (hc->xfer_len <= 188) { -+ hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL; -+ } else { -+ hc->xact_pos = -+ DWC_HCSPLIT_XACTPOS_BEGIN; -+ } -+ } -+ } -+ break; -+ } -+ /* non DWORD-aligned buffer case */ -+ if (ptr) { -+ uint32_t buf_size; -+ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { -+ buf_size = hcd->core_if->core_params->max_transfer_size; -+ } else { -+ buf_size = 4096; -+ } -+ if (!qh->dw_align_buf) { -+ qh->dw_align_buf = -+ dwc_dma_alloc_atomic(buf_size, -+ &qh->dw_align_buf_dma); -+ if (!qh->dw_align_buf) { -+ DWC_ERROR("%s: Failed to allocate memory to handle " -+ "non-dword aligned buffer case\n", __func__); -+#ifdef HW2937_WORKAROUND -+ return 0; -+#else -+ return; -+#endif -+ } -+ } -+ if (!hc->ep_is_in) { -+ dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len); -+ } -+ hc->align_buff = qh->dw_align_buf_dma; -+ } -+ else { -+ hc->align_buff = 0; -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * This value may be modified when the transfer is started to -+ * reflect the actual transfer length. -+ */ -+ hc->multi_count = dwc_hb_mult(qh->maxp); -+ } -+ -+ if (hcd->core_if->dma_desc_enable) -+ hc->desc_list_addr = qh->desc_list_dma; -+ -+ dwc_otg_hc_init(hcd->core_if, hc); -+ hc->qh = qh; -+#ifdef HW2937_WORKAROUND -+ hcd->hw2937_assigned_channels |= (1 << hc->hc_num); -+ DWC_DEBUGPL(DBG_HW2937, " assign %d -> hw2937_ac %x\n", hc->hc_num, hcd->hw2937_assigned_channels); -+ return 1; -+#endif -+} -+ -+#ifdef HW2937_WORKAROUND -+ -+void debug_halt(void) -+{ -+ spinlock_t mr_lock = SPIN_LOCK_UNLOCKED; -+ unsigned long flags; -+ extern void v6_flush_kern_cache_all(void); -+ -+ spin_lock_irqsave(&mr_lock, flags); -+#ifdef CONFIG_MACH_BCM2708 -+ v6_flush_kern_cache_all(); -+#endif -+ while (1) continue; -+} -+ -+static -+void dwc_otg_hcd_disable_in_channels(dwc_otg_hcd_t * hcd) -+{ -+ int num_channels = hcd->core_if->core_params->host_channels; -+ static int stall_count = 0; -+ static int max_stall_count = 1; -+ static int last_stalled = 0; -+ int stalled = 0; -+ int i; -+ -+ DWC_DEBUGPL(DBG_HW2937, " Disable In Channels(%x)\n", hcd->hw2937_assigned_channels); -+ -+ for (i = 0; i < num_channels; i++) { -+ if (hcd->hw2937_assigned_channels & (1 << i)) { -+ dwc_hc_t *hc = hcd->hc_ptr_array[i]; -+ if (!hc->halt_pending) { -+ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -+ hctsiz_data_t hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ DWC_DEBUGPL(DBG_HW2937, "pktcnt %d, xfersize %x, xfer_len %x\n", hctsiz.b.pktcnt, hctsiz.b.xfersize, hc->xfer_len); -+ if (hctsiz.b.pktcnt == hc->start_pkt_count) -+ { -+ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_PAUSE_IN); -+ } -+ else -+ { -+ /* Unless a receive is in progress */ -+ stalled |= (1< max_stall_count) -+ { -+ max_stall_count = stall_count; -+ DWC_PRINTF( "stall (%x) count -> %d\n", stalled, stall_count); -+ if (stall_count == 10) -+ { -+ debug_halt(); -+ } -+ } -+ } -+ else -+ { -+ stall_count = 0; -+ last_stalled = stalled; -+ } -+} -+ -+static -+int dwc_otg_hcd_update_transaction_mode(dwc_otg_hcd_t * hcd) -+{ -+ dwc_list_link_t *qh_ptr; -+ dwc_otg_qh_t *qh; -+ dwc_otg_qtd_t *qtd; -+ dwc_otg_hcd_urb_t *urb; -+ int found_in = 0; -+ -+ /* If there are any existing out transactions, stay in OUT mode */ -+ if (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_OUT) -+ { -+ return 1; -+ } -+ -+ /* Scan entries in the periodic ready list. */ -+ qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); -+ -+ while (qh_ptr != &hcd->periodic_sched_ready) { -+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -+ urb = qtd->urb; -+ if (!dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) { -+ /* Switch to OUT mode */ -+ switch (hcd->hw2937_xfer_mode) -+ { -+ case HW2937_XFER_MODE_IDLE: -+ DWC_DEBUGPL(DBG_HW2937, "utm -> OUT\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_OUT; -+ /* Drop through... */ -+ case HW2937_XFER_MODE_OUT: -+ return 1; -+ case HW2937_XFER_MODE_IN: -+ DWC_DEBUGPL(DBG_HW2937, "utm - halting %x INs\n", hcd->hw2937_assigned_channels); -+ /* Disable the channels with outstanding INs */ -+ dwc_otg_hcd_disable_in_channels(hcd); -+ -+ DWC_DEBUGPL(DBG_HW2937, "utm -> PAUSEIN\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_PAUSEIN; -+ /* Drop through... */ -+ case HW2937_XFER_MODE_PAUSEIN: -+ /* Delay until the halt completes */ -+ return 0; -+ } -+ } -+ found_in = 1; -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ } -+ -+ /* -+ * Scan entries in the inactive portion of the non-periodic -+ * schedule. -+ */ -+ qh_ptr = hcd->non_periodic_sched_inactive.next; -+ while (qh_ptr != &hcd->non_periodic_sched_inactive) { -+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -+ urb = qtd->urb; -+ if (!dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) { -+ /* Switch to OUT mode */ -+ switch (hcd->hw2937_xfer_mode) -+ { -+ case HW2937_XFER_MODE_IDLE: -+ DWC_DEBUGPL(DBG_HW2937, "utm -> OUT\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_OUT; -+ /* Drop through... */ -+ case HW2937_XFER_MODE_OUT: -+ return 1; -+ case HW2937_XFER_MODE_IN: -+ DWC_DEBUGPL(DBG_HW2937, "utm - halting %x INs\n", hcd->hw2937_assigned_channels); -+ /* Disable the channels with outstanding INs */ -+ dwc_otg_hcd_disable_in_channels(hcd); -+ -+ DWC_DEBUGPL(DBG_HW2937, "utm -> PAUSEIN\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_PAUSEIN; -+ /* Drop through... */ -+ case HW2937_XFER_MODE_PAUSEIN: -+ /* Delay until the halt completes */ -+ return 0; -+ } -+ } -+ found_in = 1; -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ } -+ -+ if (found_in && (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_IDLE)) -+ { -+ DWC_DEBUGPL(DBG_HW2937, "utm -> IN\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IN; -+ } -+ return 1; -+} -+ -+#endif /* HW2937_WORKAROUND */ -+ -+/** -+ * This function selects transactions from the HCD transfer schedule and -+ * assigns them to available host channels. It is called from HCD interrupt -+ * handler functions. -+ * -+ * @param hcd The HCD state structure. -+ * -+ * @return The types of new transactions that were assigned to host channels. -+ */ -+dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) -+{ -+ dwc_list_link_t *qh_ptr; -+ dwc_otg_qh_t *qh; -+ int num_channels; -+ dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE; -+ -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); -+#endif -+ -+#ifdef HW2937_WORKAROUND -+ if (!dwc_otg_hcd_update_transaction_mode(hcd)) -+ { -+ return ret_val; -+ } -+#endif -+ -+ /* Process entries in the periodic ready list. */ -+ qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); -+ -+ while (qh_ptr != &hcd->periodic_sched_ready && -+ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { -+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+#ifdef HW2937_WORKAROUND -+ if (assign_and_init_hc(hcd, qh)) { -+#else -+ assign_and_init_hc(hcd, qh); -+#endif -+ -+ /* -+ * Move the QH from the periodic ready schedule to the -+ * periodic assigned schedule. -+ */ -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, -+ &qh->qh_list_entry); -+ -+ ret_val = DWC_OTG_TRANSACTION_PERIODIC; -+#ifdef HW2937_WORKAROUND -+ } else { -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ } -+#endif -+ } -+ -+ /* -+ * Process entries in the inactive portion of the non-periodic -+ * schedule. Some free host channels may not be used if they are -+ * reserved for periodic transfers. -+ */ -+ qh_ptr = hcd->non_periodic_sched_inactive.next; -+ num_channels = hcd->core_if->core_params->host_channels; -+ while (qh_ptr != &hcd->non_periodic_sched_inactive && -+ (hcd->non_periodic_channels < -+ num_channels - hcd->periodic_channels) && -+ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { -+ -+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+ -+#ifdef HW2937_WORKAROUND -+ if (assign_and_init_hc(hcd, qh)) { -+#else -+ assign_and_init_hc(hcd, qh); -+#endif -+ -+ /* -+ * Move the QH from the non-periodic inactive schedule to the -+ * non-periodic active schedule. -+ */ -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active, -+ &qh->qh_list_entry); -+ -+ if (ret_val == DWC_OTG_TRANSACTION_NONE) { -+ ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; -+ } else { -+ ret_val = DWC_OTG_TRANSACTION_ALL; -+ } -+ -+ hcd->non_periodic_channels++; -+#ifdef HW2937_WORKAROUND -+ } else { -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ } -+#endif -+ } -+ -+ return ret_val; -+} -+/** -+ * Attempts to queue a single transaction request for a host channel -+ * associated with either a periodic or non-periodic transfer. This function -+ * assumes that there is space available in the appropriate request queue. For -+ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space -+ * is available in the appropriate Tx FIFO. -+ * -+ * @param hcd The HCD state structure. -+ * @param hc Host channel descriptor associated with either a periodic or -+ * non-periodic transfer. -+ * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx -+ * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic -+ * transfers. -+ * -+ * @return 1 if a request is queued and more requests may be needed to -+ * complete the transfer, 0 if no more requests are required for this -+ * transfer, -1 if there is insufficient space in the Tx FIFO. -+ */ -+static int queue_transaction(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, uint16_t fifo_dwords_avail) -+{ -+ int retval; -+ -+ if (hcd->core_if->dma_enable) { -+ if (hcd->core_if->dma_desc_enable) { -+ if (!hc->xfer_started || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { -+ dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh); -+ hc->qh->ping_state = 0; -+ } -+ } -+ else if (!hc->xfer_started) { -+ dwc_otg_hc_start_transfer(hcd->core_if, hc); -+ hc->qh->ping_state = 0; -+ } -+ retval = 0; -+ } else if (hc->halt_pending) { -+ /* Don't queue a request if the channel has been halted. */ -+ retval = 0; -+ } else if (hc->halt_on_queue) { -+ dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status); -+ retval = 0; -+ } else if (hc->do_ping) { -+ if (!hc->xfer_started) { -+ dwc_otg_hc_start_transfer(hcd->core_if, hc); -+ } -+ retval = 0; -+ } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { -+ if ((fifo_dwords_avail * 4) >= hc->max_packet) { -+ if (!hc->xfer_started) { -+ dwc_otg_hc_start_transfer(hcd->core_if, hc); -+ retval = 1; -+ } else { -+ retval = -+ dwc_otg_hc_continue_transfer(hcd->core_if, -+ hc); -+ } -+ } else { -+ retval = -1; -+ } -+ } else { -+ if (!hc->xfer_started) { -+ dwc_otg_hc_start_transfer(hcd->core_if, hc); -+ retval = 1; -+ } else { -+ retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc); -+ } -+ } -+ -+ return retval; -+} -+ -+/** -+ * Processes periodic channels for the next frame and queues transactions for -+ * these channels to the DWC_otg controller. After queueing transactions, the -+ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions -+ * to queue as Periodic Tx FIFO or request queue space becomes available. -+ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. -+ */ -+static void process_periodic_channels(dwc_otg_hcd_t * hcd) -+{ -+ hptxsts_data_t tx_status; -+ dwc_list_link_t *qh_ptr; -+ dwc_otg_qh_t *qh; -+ int status; -+ int no_queue_space = 0; -+ int no_fifo_space = 0; -+ -+ dwc_otg_host_global_regs_t *host_regs; -+ host_regs = hcd->core_if->host_if->host_global_regs; -+ -+ DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); -+#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ DWC_DEBUGPL(DBG_HCDV, -+ " P Tx Req Queue Space Avail (before queue): %d\n", -+ tx_status.b.ptxqspcavail); -+ DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n", -+ tx_status.b.ptxfspcavail); -+#endif -+ -+ qh_ptr = hcd->periodic_sched_assigned.next; -+ while (qh_ptr != &hcd->periodic_sched_assigned) { -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ if (tx_status.b.ptxqspcavail == 0) { -+ no_queue_space = 1; -+ break; -+ } -+ -+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+ -+ /* -+ * Set a flag if we're queuing high-bandwidth in slave mode. -+ * The flag prevents any halts to get into the request queue in -+ * the middle of multiple high-bandwidth packets getting queued. -+ */ -+ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) { -+ hcd->core_if->queuing_high_bandwidth = 1; -+ } -+ status = -+ queue_transaction(hcd, qh->channel, -+ tx_status.b.ptxfspcavail); -+ if (status < 0) { -+ no_fifo_space = 1; -+ break; -+ } -+ -+ /* -+ * In Slave mode, stay on the current transfer until there is -+ * nothing more to do or the high-bandwidth request count is -+ * reached. In DMA mode, only need to queue one request. The -+ * controller automatically handles multiple packets for -+ * high-bandwidth transfers. -+ */ -+ if (hcd->core_if->dma_enable || status == 0 || -+ qh->channel->requests == qh->channel->multi_count) { -+ qh_ptr = qh_ptr->next; -+ /* -+ * Move the QH from the periodic assigned schedule to -+ * the periodic queued schedule. -+ */ -+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued, -+ &qh->qh_list_entry); -+ -+ /* done queuing high bandwidth */ -+ hcd->core_if->queuing_high_bandwidth = 0; -+ } -+ } -+ -+ if (!hcd->core_if->dma_enable) { -+ dwc_otg_core_global_regs_t *global_regs; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ global_regs = hcd->core_if->core_global_regs; -+ intr_mask.b.ptxfempty = 1; -+#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ DWC_DEBUGPL(DBG_HCDV, -+ " P Tx Req Queue Space Avail (after queue): %d\n", -+ tx_status.b.ptxqspcavail); -+ DWC_DEBUGPL(DBG_HCDV, -+ " P Tx FIFO Space Avail (after queue): %d\n", -+ tx_status.b.ptxfspcavail); -+#endif -+ if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) || -+ no_queue_space || no_fifo_space) { -+ /* -+ * May need to queue more transactions as the request -+ * queue or Tx FIFO empties. Enable the periodic Tx -+ * FIFO empty interrupt. (Always use the half-empty -+ * level to ensure that new requests are loaded as -+ * soon as possible.) -+ */ -+ dwc_modify_reg32(&global_regs->gintmsk, 0, -+ intr_mask.d32); -+ } else { -+ /* -+ * Disable the Tx FIFO empty interrupt since there are -+ * no more transactions that need to be queued right -+ * now. This function is called from interrupt -+ * handlers to queue more transactions as transfer -+ * states change. -+ */ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, -+ 0); -+ } -+ } -+} -+ -+/** -+ * Processes active non-periodic channels and queues transactions for these -+ * channels to the DWC_otg controller. After queueing transactions, the NP Tx -+ * FIFO Empty interrupt is enabled if there are more transactions to queue as -+ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx -+ * FIFO Empty interrupt is disabled. -+ */ -+static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) -+{ -+ gnptxsts_data_t tx_status; -+ dwc_list_link_t *orig_qh_ptr; -+ dwc_otg_qh_t *qh; -+ int status; -+ int no_queue_space = 0; -+ int no_fifo_space = 0; -+ int more_to_do = 0; -+ -+ dwc_otg_core_global_regs_t *global_regs = -+ hcd->core_if->core_global_regs; -+ -+ DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); -+#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ DWC_DEBUGPL(DBG_HCDV, -+ " NP Tx Req Queue Space Avail (before queue): %d\n", -+ tx_status.b.nptxqspcavail); -+ DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n", -+ tx_status.b.nptxfspcavail); -+#endif -+ /* -+ * Keep track of the starting point. Skip over the start-of-list -+ * entry. -+ */ -+ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { -+ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; -+ } -+ orig_qh_ptr = hcd->non_periodic_qh_ptr; -+ -+ /* -+ * Process once through the active list or until no more space is -+ * available in the request queue or the Tx FIFO. -+ */ -+ do { -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { -+ no_queue_space = 1; -+ break; -+ } -+ -+ qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t, -+ qh_list_entry); -+ status = -+ queue_transaction(hcd, qh->channel, -+ tx_status.b.nptxfspcavail); -+ -+ if (status > 0) { -+ more_to_do = 1; -+ } else if (status < 0) { -+ no_fifo_space = 1; -+ break; -+ } -+ -+ /* Advance to next QH, skipping start-of-list entry. */ -+ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; -+ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { -+ hcd->non_periodic_qh_ptr = -+ hcd->non_periodic_qh_ptr->next; -+ } -+ -+ } while (hcd->non_periodic_qh_ptr != orig_qh_ptr); -+ -+ if (!hcd->core_if->dma_enable) { -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ intr_mask.b.nptxfempty = 1; -+ -+#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ DWC_DEBUGPL(DBG_HCDV, -+ " NP Tx Req Queue Space Avail (after queue): %d\n", -+ tx_status.b.nptxqspcavail); -+ DWC_DEBUGPL(DBG_HCDV, -+ " NP Tx FIFO Space Avail (after queue): %d\n", -+ tx_status.b.nptxfspcavail); -+#endif -+ if (more_to_do || no_queue_space || no_fifo_space) { -+ /* -+ * May need to queue more transactions as the request -+ * queue or Tx FIFO empties. Enable the non-periodic -+ * Tx FIFO empty interrupt. (Always use the half-empty -+ * level to ensure that new requests are loaded as -+ * soon as possible.) -+ */ -+ dwc_modify_reg32(&global_regs->gintmsk, 0, -+ intr_mask.d32); -+ } else { -+ /* -+ * Disable the Tx FIFO empty interrupt since there are -+ * no more transactions that need to be queued right -+ * now. This function is called from interrupt -+ * handlers to queue more transactions as transfer -+ * states change. -+ */ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, -+ 0); -+ } -+ } -+} -+ -+/** -+ * This function processes the currently active host channels and queues -+ * transactions for these channels to the DWC_otg controller. It is called -+ * from HCD interrupt handler functions. -+ * -+ * @param hcd The HCD state structure. -+ * @param tr_type The type(s) of transactions to queue (non-periodic, -+ * periodic, or both). -+ */ -+void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, -+ dwc_otg_transaction_type_e tr_type) -+{ -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); -+#endif -+ /* Process host channels associated with periodic transfers. */ -+ if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC || -+ tr_type == DWC_OTG_TRANSACTION_ALL) && -+ !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) { -+ -+ process_periodic_channels(hcd); -+ } -+ -+ /* Process host channels associated with non-periodic transfers. */ -+ if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC || -+ tr_type == DWC_OTG_TRANSACTION_ALL) { -+ if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) { -+ process_non_periodic_channels(hcd); -+ } else { -+ /* -+ * Ensure NP Tx FIFO empty interrupt is disabled when -+ * there are no non-periodic transfers to process. -+ */ -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ gintmsk.b.nptxfempty = 1; -+ dwc_modify_reg32(&hcd->core_if->core_global_regs-> -+ gintmsk, gintmsk.d32, 0); -+ } -+ } -+} -+ -+#ifdef DWC_HS_ELECT_TST -+/* -+ * Quick and dirty hack to implement the HS Electrical Test -+ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature. -+ * -+ * This code was copied from our userspace app "hset". It sends a -+ * Get Device Descriptor control sequence in two parts, first the -+ * Setup packet by itself, followed some time later by the In and -+ * Ack packets. Rather than trying to figure out how to add this -+ * functionality to the normal driver code, we just hijack the -+ * hardware, using these two function to drive the hardware -+ * directly. -+ */ -+ -+static dwc_otg_core_global_regs_t *global_regs; -+static dwc_otg_host_global_regs_t *hc_global_regs; -+static dwc_otg_hc_regs_t *hc_regs; -+static uint32_t *data_fifo; -+ -+static void do_setup(void) -+{ -+ gintsts_data_t gintsts; -+ hctsiz_data_t hctsiz; -+ hcchar_data_t hcchar; -+ haint_data_t haint; -+ hcint_data_t hcint; -+ -+ /* Enable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); -+ -+ /* Enable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* -+ * Send Setup packet (Get Device Descriptor) -+ */ -+ -+ /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ hcchar.b.chdis = 1; -+// hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ //sleep(1); -+ dwc_mdelay(1000); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ } -+ -+ /* Set HCTSIZ */ -+ 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); -+ -+ /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; -+ hcchar.b.epdir = 0; -+ hcchar.b.epnum = 0; -+ hcchar.b.mps = 8; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ /* Fill FIFO with Setup data for Get Device Descriptor */ -+ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); -+ dwc_write_reg32(data_fifo++, 0x01000680); -+ dwc_write_reg32(data_fifo++, 0x00080000); -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for host channel interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.hcintr == 0); -+ -+ -+ /* Disable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); -+ -+ /* Disable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+} -+ -+static void do_in_ack(void) -+{ -+ gintsts_data_t gintsts; -+ hctsiz_data_t hctsiz; -+ hcchar_data_t hcchar; -+ haint_data_t haint; -+ hcint_data_t hcint; -+ host_grxsts_data_t grxsts; -+ -+ /* Enable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); -+ -+ /* Enable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* -+ * Receive Control In packet -+ */ -+ -+ /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ hcchar.b.chdis = 1; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ //sleep(1); -+ dwc_mdelay(1000); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ } -+ -+ /* Set HCTSIZ */ -+ hctsiz.d32 = 0; -+ hctsiz.b.xfersize = 8; -+ hctsiz.b.pktcnt = 1; -+ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ -+ /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; -+ hcchar.b.epdir = 1; -+ hcchar.b.epnum = 0; -+ hcchar.b.mps = 8; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for receive status queue interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.rxstsqlvl == 0); -+ -+ -+ /* Read RXSTS */ -+ grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); -+ -+ /* Clear RXSTSQLVL in GINTSTS */ -+ gintsts.d32 = 0; -+ gintsts.b.rxstsqlvl = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ switch (grxsts.b.pktsts) { -+ case DWC_GRXSTS_PKTSTS_IN: -+ /* Read the data into the host buffer */ -+ if (grxsts.b.bcnt > 0) { -+ int i; -+ int word_count = (grxsts.b.bcnt + 3) / 4; -+ -+ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); -+ -+ for (i = 0; i < word_count; i++) { -+ (void)dwc_read_reg32(data_fifo++); -+ } -+ } -+ break; -+ -+ default: -+ break; -+ } -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for receive status queue interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.rxstsqlvl == 0); -+ -+ -+ /* Read RXSTS */ -+ grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); -+ -+ /* Clear RXSTSQLVL in GINTSTS */ -+ gintsts.d32 = 0; -+ gintsts.b.rxstsqlvl = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ switch (grxsts.b.pktsts) { -+ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: -+ break; -+ -+ default: -+ break; -+ } -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for host channel interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.hcintr == 0); -+ -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+// usleep(100000); -+// mdelay(100); -+ dwc_mdelay(1); -+ -+ /* -+ * Send handshake packet -+ */ -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chen) { -+ hcchar.b.chdis = 1; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ //sleep(1); -+ dwc_mdelay(1000); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ } -+ -+ /* Set HCTSIZ */ -+ 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); -+ -+ /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; -+ hcchar.b.epdir = 0; -+ hcchar.b.epnum = 0; -+ hcchar.b.mps = 8; -+ hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ -+ /* Wait for host channel interrupt */ -+ do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ } while (gintsts.b.hcintr == 0); -+ -+ -+ /* Disable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); -+ -+ /* Disable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); -+ -+ /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ -+ /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ -+ /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ -+ /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ -+ /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ -+ /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+} -+#endif -+ -+/** Handles hub class-specific requests. */ -+int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, -+ uint16_t typeReq, -+ uint16_t wValue, -+ uint16_t wIndex, uint8_t * buf, uint16_t wLength) -+{ -+ int retval = 0; -+ -+ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; -+ usb_hub_descriptor_t *hub_desc; -+ hprt0_data_t hprt0 = {.d32 = 0 }; -+ -+ uint32_t port_status; -+ -+ switch (typeReq) { -+ case UCR_CLEAR_HUB_FEATURE: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearHubFeature 0x%x\n", wValue); -+ switch (wValue) { -+ case UHF_C_HUB_LOCAL_POWER: -+ case UHF_C_HUB_OVER_CURRENT: -+ /* Nothing required here */ -+ break; -+ default: -+ retval = -DWC_E_INVALID; -+ DWC_ERROR("DWC OTG HCD - " -+ "ClearHubFeature request %xh unknown\n", -+ wValue); -+ } -+ break; -+ case UCR_CLEAR_PORT_FEATURE: -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ if (wValue != UHF_PORT_L1) -+#endif -+ if (!wIndex || wIndex > 1) -+ goto error; -+ -+ switch (wValue) { -+ case UHF_PORT_ENABLE: -+ DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtena = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+ case UHF_PORT_SUSPEND: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); -+ -+ dwc_write_reg32(core_if->pcgcctl, 0); -+ dwc_mdelay(5); -+ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtres = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ hprt0.b.prtsusp = 0; -+ /* Clear Resume bit */ -+ dwc_mdelay(100); -+ hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ case UHF_PORT_L1: -+ { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ glpmcfg_data_t lpmcfg = {.d32 = 0 }; -+ -+ lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ glpmcfg); -+ lpmcfg.b.en_utmi_sleep = 0; -+ lpmcfg.b.hird_thres &= (~(1 << 4)); -+ lpmcfg.b.prt_sleep_sts = 1; -+ dwc_write_reg32(&core_if->core_global_regs-> -+ glpmcfg, lpmcfg.d32); -+ -+ /* Clear Enbl_L1Gating bit. */ -+ pcgcctl.b.enbl_sleep_gating = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, -+ 0); -+ -+ dwc_mdelay(5); -+ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtres = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); -+ /* This bit will be cleared in wakeup interrupt handle */ -+ break; -+ } -+#endif -+ case UHF_PORT_POWER: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_POWER\n"); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtpwr = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+ case UHF_PORT_INDICATOR: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); -+ /* Port inidicator not supported */ -+ break; -+ case UHF_C_PORT_CONNECTION: -+ /* Clears drivers internal connect status change -+ * flag */ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); -+ dwc_otg_hcd->flags.b.port_connect_status_change = 0; -+ break; -+ case UHF_C_PORT_RESET: -+ /* Clears the driver's internal Port Reset Change -+ * flag */ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); -+ dwc_otg_hcd->flags.b.port_reset_change = 0; -+ break; -+ case UHF_C_PORT_ENABLE: -+ /* Clears the driver's internal Port -+ * Enable/Disable Change flag */ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); -+ dwc_otg_hcd->flags.b.port_enable_change = 0; -+ break; -+ case UHF_C_PORT_SUSPEND: -+ /* Clears the driver's internal Port Suspend -+ * Change flag, which is set when resume signaling on -+ * the host port is complete */ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); -+ dwc_otg_hcd->flags.b.port_suspend_change = 0; -+ break; -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ case UHF_C_PORT_L1: -+ dwc_otg_hcd->flags.b.port_l1_change = 0; -+ break; -+#endif -+ case UHF_C_PORT_OVER_CURRENT: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); -+ dwc_otg_hcd->flags.b.port_over_current_change = 0; -+ break; -+ default: -+ retval = -DWC_E_INVALID; -+ DWC_ERROR("DWC OTG HCD - " -+ "ClearPortFeature request %xh " -+ "unknown or unsupported\n", wValue); -+ } -+ break; -+ case UCR_GET_HUB_DESCRIPTOR: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "GetHubDescriptor\n"); -+ hub_desc = (usb_hub_descriptor_t *) buf; -+ hub_desc->bDescLength = 9; -+ hub_desc->bDescriptorType = 0x29; -+ hub_desc->bNbrPorts = 1; -+ USETW(hub_desc->wHubCharacteristics, 0x08); -+ hub_desc->bPwrOn2PwrGood = 1; -+ hub_desc->bHubContrCurrent = 0; -+ hub_desc->DeviceRemovable[0] = 0; -+ hub_desc->DeviceRemovable[1] = 0xff; -+ break; -+ case UCR_GET_HUB_STATUS: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "GetHubStatus\n"); -+ DWC_MEMSET(buf, 0, 4); -+ break; -+ case UCR_GET_PORT_STATUS: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "GetPortStatus\n"); -+ if (!wIndex || wIndex > 1) -+ goto error; -+ -+ port_status = 0; -+ -+ if (dwc_otg_hcd->flags.b.port_connect_status_change) -+ port_status |= (1 << UHF_C_PORT_CONNECTION); -+ -+ if (dwc_otg_hcd->flags.b.port_enable_change) -+ port_status |= (1 << UHF_C_PORT_ENABLE); -+ -+ if (dwc_otg_hcd->flags.b.port_suspend_change) -+ port_status |= (1 << UHF_C_PORT_SUSPEND); -+ -+ if (dwc_otg_hcd->flags.b.port_l1_change) -+ port_status |= (1 << UHF_C_PORT_L1); -+ -+ if (dwc_otg_hcd->flags.b.port_reset_change) { -+ port_status |= (1 << UHF_C_PORT_RESET); -+ } -+ -+ if (dwc_otg_hcd->flags.b.port_over_current_change) { -+ DWC_ERROR("Device Not Supported\n"); -+ port_status |= (1 << UHF_C_PORT_OVER_CURRENT); -+ } -+ -+ if (!dwc_otg_hcd->flags.b.port_connect_status) { -+ /* -+ * The port is disconnected, which means the core is -+ * either in device mode or it soon will be. Just -+ * return 0's for the remainder of the port status -+ * since the port register can't be read if the core -+ * is in device mode. -+ */ -+ *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); -+ break; -+ } -+ -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); -+ DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); -+ -+ if (hprt0.b.prtconnsts) -+ port_status |= (1 << UHF_PORT_CONNECTION); -+ -+ if (hprt0.b.prtena) -+ port_status |= (1 << UHF_PORT_ENABLE); -+ -+ if (hprt0.b.prtsusp) -+ port_status |= (1 << UHF_PORT_SUSPEND); -+ -+ if (hprt0.b.prtovrcurract) -+ port_status |= (1 << UHF_PORT_OVER_CURRENT); -+ -+ if (hprt0.b.prtrst) -+ port_status |= (1 << UHF_PORT_RESET); -+ -+ if (hprt0.b.prtpwr) -+ port_status |= (1 << UHF_PORT_POWER); -+ -+ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) -+ port_status |= (1 << UHF_PORT_HIGH_SPEED); -+ else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) -+ port_status |= (1 << UHF_PORT_LOW_SPEED); -+ -+ if (hprt0.b.prttstctl) -+ port_status |= (1 << UHF_PORT_TEST); -+ if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) { -+ port_status |= (1 << UHF_PORT_L1); -+ } -+ -+ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ -+ -+ *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); -+ -+ break; -+ case UCR_SET_HUB_FEATURE: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetHubFeature\n"); -+ /* No HUB features supported */ -+ break; -+ case UCR_SET_PORT_FEATURE: -+ if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1)) -+ goto error; -+ -+ if (!dwc_otg_hcd->flags.b.port_connect_status) { -+ /* -+ * The port is disconnected, which means the core is -+ * either in device mode or it soon will be. Just -+ * return without doing anything since the port -+ * register can't be written if the core is in device -+ * mode. -+ */ -+ break; -+ } -+ -+ switch (wValue) { -+ case UHF_PORT_SUSPEND: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); -+ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex && -+ dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { -+ gotgctl_data_t gotgctl = {.d32 = 0 }; -+ gotgctl.b.hstsethnpen = 1; -+ dwc_modify_reg32(&core_if->core_global_regs-> -+ gotgctl, 0, gotgctl.d32); -+ core_if->op_state = A_SUSPEND; -+ } -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtsusp = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ { -+ uint64_t flags; -+ /* Update lx_state */ -+ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); -+ core_if->lx_state = DWC_OTG_L2; -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); -+ } -+ /* Suspend the Phy Clock */ -+ { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, 0, -+ pcgcctl.d32); -+ } -+ -+ /* For HNP the bus must be suspended for at least 200ms. */ -+ if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { -+ dwc_mdelay(200); -+ } -+ break; -+ case UHF_PORT_POWER: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_POWER\n"); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtpwr = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ break; -+ case UHF_PORT_RESET: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_RESET\n"); -+ { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ pcgcctl.b.enbl_sleep_gating = 1; -+ pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, -+ 0); -+ dwc_write_reg32(core_if->pcgcctl, 0); -+ } -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ { -+ glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ glpmcfg); -+ if (lpmcfg.b.prt_sleep_sts) { -+ lpmcfg.b.en_utmi_sleep = 0; -+ lpmcfg.b.hird_thres &= (~(1 << 4)); -+ dwc_write_reg32(&core_if-> -+ core_global_regs-> -+ glpmcfg, lpmcfg.d32); -+ dwc_mdelay(1); -+ } -+ } -+#endif -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ /* When B-Host the Port reset bit is set in -+ * the Start HCD Callback function, so that -+ * the reset is started within 1ms of the HNP -+ * success interrupt. */ -+ if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) { -+ hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); -+ } -+ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ -+ dwc_mdelay(60); -+ hprt0.b.prtrst = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */ -+ break; -+#ifdef DWC_HS_ELECT_TST -+ case UHF_PORT_TEST: -+ { -+ uint32_t t; -+ gintmsk_data_t gintmsk; -+ -+ t = (wIndex >> 8); /* MSB wIndex USB */ -+ DWC_DEBUGPL(DBG_HCD, -+ "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_TEST %d\n", -+ t); -+ DWC_WARN("USB_PORT_FEAT_TEST %d\n", t); -+ if (t < 6) { -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prttstctl = t; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); -+ } else { -+ /* Setup global vars with reg addresses (quick and -+ * dirty hack, should be cleaned up) -+ */ -+ global_regs = core_if->core_global_regs; -+ hc_global_regs = -+ core_if->host_if->host_global_regs; -+ hc_regs = -+ (dwc_otg_hc_regs_t *) ((char *) -+ global_regs + -+ 0x500); -+ data_fifo = -+ (uint32_t *) ((char *)global_regs + -+ 0x1000); -+ -+ if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ -+ /* Save current interrupt mask */ -+ gintmsk.d32 = -+ dwc_read_reg32 -+ (&global_regs->gintmsk); -+ -+ /* Disable all interrupts while we muck with -+ * the hardware directly -+ */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, 0); -+ -+ /* 15 second delay per the test spec */ -+ dwc_mdelay(15000); -+ -+ /* Drive suspend on the root port */ -+ hprt0.d32 = -+ dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtsusp = 1; -+ hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if-> -+ host_if->hprt0, -+ hprt0.d32); -+ -+ /* 15 second delay per the test spec */ -+ dwc_mdelay(15000); -+ -+ /* Drive resume on the root port */ -+ hprt0.d32 = -+ dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtsusp = 0; -+ hprt0.b.prtres = 1; -+ dwc_write_reg32(core_if-> -+ host_if->hprt0, -+ hprt0.d32); -+ dwc_mdelay(100); -+ -+ /* Clear the resume bit */ -+ hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if-> -+ host_if->hprt0, -+ hprt0.d32); -+ -+ /* Restore interrupts */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, -+ gintmsk.d32); -+ } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ -+ /* Save current interrupt mask */ -+ gintmsk.d32 = -+ dwc_read_reg32 -+ (&global_regs->gintmsk); -+ -+ /* Disable all interrupts while we muck with -+ * the hardware directly -+ */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, 0); -+ -+ /* 15 second delay per the test spec */ -+ dwc_mdelay(15000); -+ -+ /* Send the Setup packet */ -+ do_setup(); -+ -+ /* 15 second delay so nothing else happens for awhile */ -+ dwc_mdelay(15000); -+ -+ /* Restore interrupts */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, -+ gintmsk.d32); -+ } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ -+ /* Save current interrupt mask */ -+ gintmsk.d32 = -+ dwc_read_reg32 -+ (&global_regs->gintmsk); -+ -+ /* Disable all interrupts while we muck with -+ * the hardware directly -+ */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, 0); -+ -+ /* Send the Setup packet */ -+ do_setup(); -+ -+ /* 15 second delay so nothing else happens for awhile */ -+ dwc_mdelay(15000); -+ -+ /* Send the In and Ack packets */ -+ do_in_ack(); -+ -+ /* 15 second delay so nothing else happens for awhile */ -+ dwc_mdelay(15000); -+ -+ /* Restore interrupts */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, -+ gintmsk.d32); -+ } -+ } -+ break; -+ } -+#endif /* DWC_HS_ELECT_TST */ -+ -+ case UHF_PORT_INDICATOR: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); -+ /* Not supported */ -+ break; -+ default: -+ retval = -DWC_E_INVALID; -+ DWC_ERROR("DWC OTG HCD - " -+ "SetPortFeature request %xh " -+ "unknown or unsupported\n", wValue); -+ break; -+ } -+ break; -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ case UCR_SET_AND_TEST_PORT_FEATURE: -+ if (wValue != UHF_PORT_L1) { -+ goto error; -+ } -+ { -+ int portnum, hird, devaddr, remwake; -+ glpmcfg_data_t lpmcfg; -+ uint32_t time_usecs; -+ gintsts_data_t gintsts; -+ gintmsk_data_t gintmsk; -+ -+ if (!dwc_otg_get_param_lpm_enable(core_if)) { -+ goto error; -+ } -+ if (wValue != UHF_PORT_L1 || wLength != 1) { -+ goto error; -+ } -+ /* Check if the port currently is in SLEEP state */ -+ lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ if (lpmcfg.b.prt_sleep_sts) { -+ DWC_INFO("Port is already in sleep mode\n"); -+ buf[0] = 0; /* Return success */ -+ break; -+ } -+ -+ portnum = wIndex & 0xf; -+ hird = (wIndex >> 4) & 0xf; -+ devaddr = (wIndex >> 8) & 0x7f; -+ remwake = (wIndex >> 15); -+ -+ if (portnum != 1) { -+ retval = -DWC_E_INVALID; -+ DWC_WARN -+ ("Wrong port number(%d) in SetandTestPortFeature request\n", -+ portnum); -+ break; -+ } -+ -+ DWC_PRINTF -+ ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n", -+ portnum, hird, devaddr, remwake); -+ /* Disable LPM interrupt */ -+ gintmsk.d32 = 0; -+ gintmsk.b.lpmtranrcvd = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, -+ gintmsk.d32, 0); -+ -+ if (dwc_otg_hcd_send_lpm -+ (dwc_otg_hcd, devaddr, hird, remwake)) { -+ retval = -DWC_E_INVALID; -+ break; -+ } -+ -+ time_usecs = 10 * (lpmcfg.b.retry_count + 1); -+ /* We will consider timeout if time_usecs microseconds pass, -+ * and we don't receive LPM transaction status. -+ * After receiving non-error responce(ACK/NYET/STALL) from device, -+ * core will set lpmtranrcvd bit. -+ */ -+ do { -+ gintsts.d32 = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ gintsts); -+ if (gintsts.b.lpmtranrcvd) { -+ break; -+ } -+ dwc_udelay(1); -+ } while (--time_usecs); -+ /* lpm_int bit will be cleared in LPM interrupt handler */ -+ -+ /* Now fill status -+ * 0x00 - Success -+ * 0x10 - NYET -+ * 0x11 - Timeout -+ */ -+ if (!gintsts.b.lpmtranrcvd) { -+ buf[0] = 0x3; /* Completion code is Timeout */ -+ dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd); -+ } else { -+ lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ glpmcfg); -+ if (lpmcfg.b.lpm_resp == 0x3) { -+ /* ACK responce from the device */ -+ buf[0] = 0x00; /* Success */ -+ } else if (lpmcfg.b.lpm_resp == 0x2) { -+ /* NYET responce from the device */ -+ buf[0] = 0x2; -+ } else { -+ /* Otherwise responce with Timeout */ -+ buf[0] = 0x3; -+ } -+ } -+ DWC_PRINTF("Device responce to LPM trans is %x\n", -+ lpmcfg.b.lpm_resp); -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, -+ gintmsk.d32); -+ -+ break; -+ } -+#endif /* CONFIG_USB_DWC_OTG_LPM */ -+ default: -+ error: -+ retval = -DWC_E_INVALID; -+ DWC_WARN("DWC OTG HCD - " -+ "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", -+ typeReq, wIndex, wValue); -+ break; -+ } -+ -+ return retval; -+} -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+/** Returns index of host channel to perform LPM transaction. */ -+int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr) -+{ -+ dwc_otg_core_if_t *core_if = hcd->core_if; -+ dwc_hc_t *hc; -+ hcchar_data_t hcchar; -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ -+ if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { -+ DWC_PRINTF("No free channel to select for LPM transaction\n"); -+ return -1; -+ } -+ -+ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); -+ -+ /* Mask host channel interrupts. */ -+ gintmsk.b.hcintr = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); -+ -+ /* Fill fields that core needs for LPM transaction */ -+ hcchar.b.devaddr = devaddr; -+ hcchar.b.epnum = 0; -+ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; -+ hcchar.b.mps = 64; -+ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); -+ hcchar.b.epdir = 0; /* OUT */ -+ dwc_write_reg32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, -+ hcchar.d32); -+ -+ /* Remove the host channel from the free list. */ -+ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); -+ -+ DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr); -+ -+ return hc->hc_num; -+} -+ -+/** Release hc after performing LPM transaction */ -+void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd) -+{ -+ dwc_hc_t *hc; -+ glpmcfg_data_t lpmcfg; -+ uint8_t hc_num; -+ -+ lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg); -+ hc_num = lpmcfg.b.lpm_chan_index; -+ -+ hc = hcd->hc_ptr_array[hc_num]; -+ -+ DWC_PRINTF("Freeing channel %d after LPM\n", hc_num); -+ /* Return host channel to free list */ -+ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); -+} -+ -+int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird, -+ uint8_t bRemoteWake) -+{ -+ glpmcfg_data_t lpmcfg; -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ int channel; -+ -+ channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr); -+ if (channel < 0) { -+ return channel; -+ } -+ -+ pcgcctl.b.enbl_sleep_gating = 1; -+ dwc_modify_reg32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); -+ -+ /* Read LPM config register */ -+ lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg); -+ -+ /* Program LPM transaction fields */ -+ lpmcfg.b.rem_wkup_en = bRemoteWake; -+ lpmcfg.b.hird = hird; -+ lpmcfg.b.hird_thres = 0x1c; -+ lpmcfg.b.lpm_chan_index = channel; -+ lpmcfg.b.en_utmi_sleep = 1; -+ /* Program LPM config register */ -+ dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); -+ -+ /* Send LPM transaction */ -+ lpmcfg.b.send_lpm = 1; -+ dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); -+ -+ return 0; -+} -+ -+#endif /* CONFIG_USB_DWC_OTG_LPM */ -+ -+int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port) -+{ -+ int retval; -+ -+ if (port != 1) { -+ return -DWC_E_INVALID; -+ } -+ -+ retval = (hcd->flags.b.port_connect_status_change || -+ hcd->flags.b.port_reset_change || -+ hcd->flags.b.port_enable_change || -+ hcd->flags.b.port_suspend_change || -+ hcd->flags.b.port_over_current_change); -+#ifdef DEBUG -+ if (retval) { -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:" -+ " Root port status changed\n"); -+ DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n", -+ hcd->flags.b.port_connect_status_change); -+ DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n", -+ hcd->flags.b.port_reset_change); -+ DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n", -+ hcd->flags.b.port_enable_change); -+ DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n", -+ hcd->flags.b.port_suspend_change); -+ DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n", -+ hcd->flags.b.port_over_current_change); -+ } -+#endif -+ return retval; -+} -+ -+int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ hfnum_data_t hfnum; -+ hfnum.d32 = dwc_read_reg32(&dwc_otg_hcd->core_if-> -+ host_if->host_global_regs->hfnum); -+ -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", -+ hfnum.b.frnum); -+#endif -+ return hfnum.b.frnum; -+} -+ -+int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, -+ struct dwc_otg_hcd_function_ops *fops) -+{ -+ int retval = 0; -+ -+ hcd->fops = fops; -+ if (!dwc_otg_is_device_mode(hcd->core_if)) { -+ dwc_otg_hcd_reinit(hcd); -+ } else { -+ retval = -DWC_E_NO_DEVICE; -+ } -+ -+ return retval; -+} -+ -+void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd) -+{ -+ return hcd->priv; -+} -+ -+void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data) -+{ -+ hcd->priv = priv_data; -+} -+ -+uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd) -+{ -+ return hcd->otg_port; -+} -+ -+uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd) -+{ -+ uint32_t is_b_host; -+ if (hcd->core_if->op_state == B_HOST) { -+ is_b_host = 1; -+ } else { -+ is_b_host = 0; -+ } -+ -+ return is_b_host; -+} -+ -+dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, -+ int iso_desc_count, int atomic_alloc) -+{ -+ dwc_otg_hcd_urb_t *dwc_otg_urb; -+ uint32_t size; -+ -+ size = -+ sizeof(*dwc_otg_urb) + -+ iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc); -+ if (atomic_alloc) { -+ dwc_otg_urb = dwc_alloc_atomic(size); -+ } else { -+ dwc_otg_urb = dwc_alloc(size); -+ } -+ dwc_otg_urb->packet_count = iso_desc_count; -+ -+ return dwc_otg_urb; -+} -+ -+void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb, -+ uint8_t dev_addr, uint8_t ep_num, -+ uint8_t ep_type, uint8_t ep_dir, uint16_t mps) -+{ -+ dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num, -+ ep_type, ep_dir, mps); -+#if 0 -+ DWC_PRINTF -+ ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n", -+ dev_addr, ep_num, ep_dir, ep_type, mps); -+#endif -+} -+ -+void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb, -+ void *urb_handle, void *buf, dwc_dma_t dma, -+ uint32_t buflen, void *setup_packet, -+ dwc_dma_t setup_dma, uint32_t flags, -+ uint16_t interval) -+{ -+ dwc_otg_urb->priv = urb_handle; -+ dwc_otg_urb->buf = buf; -+ dwc_otg_urb->dma = dma; -+ dwc_otg_urb->length = buflen; -+ dwc_otg_urb->setup_packet = setup_packet; -+ dwc_otg_urb->setup_dma = setup_dma; -+ dwc_otg_urb->flags = flags; -+ dwc_otg_urb->interval = interval; -+ dwc_otg_urb->status = -DWC_E_IN_PROGRESS; -+} -+ -+uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb) -+{ -+ return dwc_otg_urb->status; -+} -+ -+uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb) -+{ -+ return dwc_otg_urb->actual_length; -+} -+ -+uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb) -+{ -+ return dwc_otg_urb->error_count; -+} -+ -+void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb, -+ int desc_num, uint32_t offset, -+ uint32_t length) -+{ -+ dwc_otg_urb->iso_descs[desc_num].offset = offset; -+ dwc_otg_urb->iso_descs[desc_num].length = length; -+} -+ -+uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb, -+ int desc_num) -+{ -+ return dwc_otg_urb->iso_descs[desc_num].status; -+} -+ -+uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * -+ dwc_otg_urb, int desc_num) -+{ -+ return dwc_otg_urb->iso_descs[desc_num].actual_length; -+} -+ -+int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle) -+{ -+ int allocated = 0; -+ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; -+ -+ if (qh) { -+ if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { -+ allocated = 1; -+ } -+ } -+ return allocated; -+} -+ -+int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle) -+{ -+ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; -+ int freed = 0; -+ DWC_ASSERT(qh, "qh is not allocated\n"); -+ -+ if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { -+ freed = 1; -+ } -+ -+ return freed; -+} -+ -+uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle) -+{ -+ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; -+ DWC_ASSERT(qh, "qh is not allocated\n"); -+ return qh->usecs; -+} -+ -+void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd) -+{ -+#ifdef DEBUG -+ int num_channels; -+ int i; -+ gnptxsts_data_t np_tx_status; -+ hptxsts_data_t p_tx_status; -+ -+ num_channels = hcd->core_if->core_params->host_channels; -+ DWC_PRINTF("\n"); -+ DWC_PRINTF -+ ("************************************************************\n"); -+ DWC_PRINTF("HCD State:\n"); -+ DWC_PRINTF(" Num channels: %d\n", num_channels); -+ for (i = 0; i < num_channels; i++) { -+ dwc_hc_t *hc = hcd->hc_ptr_array[i]; -+ DWC_PRINTF(" Channel %d:\n", i); -+ DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", -+ hc->dev_addr, hc->ep_num, hc->ep_is_in); -+ DWC_PRINTF(" speed: %d\n", hc->speed); -+ DWC_PRINTF(" ep_type: %d\n", hc->ep_type); -+ DWC_PRINTF(" max_packet: %d\n", hc->max_packet); -+ DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); -+ DWC_PRINTF(" multi_count: %d\n", hc->multi_count); -+ DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started); -+ DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); -+ DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len); -+ DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count); -+ DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue); -+ DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending); -+ DWC_PRINTF(" halt_status: %d\n", hc->halt_status); -+ DWC_PRINTF(" do_split: %d\n", hc->do_split); -+ DWC_PRINTF(" complete_split: %d\n", hc->complete_split); -+ DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr); -+ DWC_PRINTF(" port_addr: %d\n", hc->port_addr); -+ DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos); -+ DWC_PRINTF(" requests: %d\n", hc->requests); -+ DWC_PRINTF(" qh: %p\n", hc->qh); -+ if (hc->xfer_started) { -+ hfnum_data_t hfnum; -+ hcchar_data_t hcchar; -+ hctsiz_data_t hctsiz; -+ hcint_data_t hcint; -+ hcintmsk_data_t hcintmsk; -+ hfnum.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if-> -+ host_global_regs->hfnum); -+ hcchar.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -+ hcchar); -+ hctsiz.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -+ hctsiz); -+ hcint.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -+ hcint); -+ hcintmsk.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -+ hcintmsk); -+ DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32); -+ DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32); -+ DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32); -+ DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32); -+ DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32); -+ } -+ if (hc->xfer_started && hc->qh) { -+ dwc_otg_qtd_t *qtd; -+ dwc_otg_hcd_urb_t *urb; -+ -+ DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) { -+ if(!qtd->in_process) -+ break; -+ -+ urb = qtd->urb; -+ DWC_PRINTF(" URB Info:\n"); -+ DWC_PRINTF(" qtd: %p, urb: %p\n", qtd, urb); -+ if (urb) { -+ DWC_PRINTF(" Dev: %d, EP: %d %s\n", -+ dwc_otg_hcd_get_dev_addr(&urb-> -+ pipe_info), -+ dwc_otg_hcd_get_ep_num(&urb-> -+ pipe_info), -+ dwc_otg_hcd_is_pipe_in(&urb-> -+ pipe_info) ? -+ "IN" : "OUT"); -+ DWC_PRINTF(" Max packet size: %d\n", -+ dwc_otg_hcd_get_mps(&urb-> -+ pipe_info)); -+ DWC_PRINTF(" transfer_buffer: %p\n", -+ urb->buf); -+ DWC_PRINTF(" transfer_dma: %p\n", -+ (void *)urb->dma); -+ DWC_PRINTF(" transfer_buffer_length: %d\n", -+ urb->length); -+ DWC_PRINTF(" actual_length: %d\n", -+ urb->actual_length); -+ } -+ } -+ } -+ } -+ DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels); -+ DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels); -+ DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs); -+ np_tx_status.d32 = -+ dwc_read_reg32(&hcd->core_if->core_global_regs->gnptxsts); -+ DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n", -+ np_tx_status.b.nptxqspcavail); -+ DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n", -+ np_tx_status.b.nptxfspcavail); -+ p_tx_status.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hptxsts); -+ DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n", -+ p_tx_status.b.ptxqspcavail); -+ DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); -+ dwc_otg_hcd_dump_frrem(hcd); -+ dwc_otg_dump_global_registers(hcd->core_if); -+ dwc_otg_dump_host_registers(hcd->core_if); -+ DWC_PRINTF -+ ("************************************************************\n"); -+ DWC_PRINTF("\n"); -+#endif -+} -+ -+#ifdef DEBUG -+void dwc_print_setup_data(uint8_t * setup) -+{ -+ int i; -+ if (CHK_DEBUG_LEVEL(DBG_HCD)) { -+ DWC_PRINTF("Setup Data = MSB "); -+ for (i = 7; i >= 0; i--) -+ DWC_PRINTF("%02x ", setup[i]); -+ DWC_PRINTF("\n"); -+ DWC_PRINTF(" bmRequestType Tranfer = %s\n", -+ (setup[0] & 0x80) ? "Device-to-Host" : -+ "Host-to-Device"); -+ DWC_PRINTF(" bmRequestType Type = "); -+ switch ((setup[0] & 0x60) >> 5) { -+ case 0: -+ DWC_PRINTF("Standard\n"); -+ break; -+ case 1: -+ DWC_PRINTF("Class\n"); -+ break; -+ case 2: -+ DWC_PRINTF("Vendor\n"); -+ break; -+ case 3: -+ DWC_PRINTF("Reserved\n"); -+ break; -+ } -+ DWC_PRINTF(" bmRequestType Recipient = "); -+ switch (setup[0] & 0x1f) { -+ case 0: -+ DWC_PRINTF("Device\n"); -+ break; -+ case 1: -+ DWC_PRINTF("Interface\n"); -+ break; -+ case 2: -+ DWC_PRINTF("Endpoint\n"); -+ break; -+ case 3: -+ DWC_PRINTF("Other\n"); -+ break; -+ default: -+ DWC_PRINTF("Reserved\n"); -+ break; -+ } -+ DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]); -+ DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *) & setup[2])); -+ DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *) & setup[4])); -+ DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *) & setup[6])); -+ } -+} -+#endif -+ -+void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd) -+{ -+#if 0 -+ DWC_PRINTF("Frame remaining at SOF:\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->frrem_samples, hcd->frrem_accum, -+ (hcd->frrem_samples > 0) ? -+ hcd->frrem_accum / hcd->frrem_samples : 0); -+ -+ DWC_PRINTF("\n"); -+ DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->core_if->hfnum_7_samples, -+ hcd->core_if->hfnum_7_frrem_accum, -+ (hcd->core_if->hfnum_7_samples > -+ 0) ? hcd->core_if->hfnum_7_frrem_accum / -+ hcd->core_if->hfnum_7_samples : 0); -+ DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->core_if->hfnum_0_samples, -+ hcd->core_if->hfnum_0_frrem_accum, -+ (hcd->core_if->hfnum_0_samples > -+ 0) ? hcd->core_if->hfnum_0_frrem_accum / -+ hcd->core_if->hfnum_0_samples : 0); -+ DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->core_if->hfnum_other_samples, -+ hcd->core_if->hfnum_other_frrem_accum, -+ (hcd->core_if->hfnum_other_samples > -+ 0) ? hcd->core_if->hfnum_other_frrem_accum / -+ hcd->core_if->hfnum_other_samples : 0); -+ -+ DWC_PRINTF("\n"); -+ DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a, -+ (hcd->hfnum_7_samples_a > 0) ? -+ hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0); -+ DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a, -+ (hcd->hfnum_0_samples_a > 0) ? -+ hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0); -+ DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a, -+ (hcd->hfnum_other_samples_a > 0) ? -+ hcd->hfnum_other_frrem_accum_a / -+ hcd->hfnum_other_samples_a : 0); -+ -+ DWC_PRINTF("\n"); -+ DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b, -+ (hcd->hfnum_7_samples_b > 0) ? -+ hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0); -+ DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b, -+ (hcd->hfnum_0_samples_b > 0) ? -+ hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0); -+ DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n"); -+ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", -+ hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b, -+ (hcd->hfnum_other_samples_b > 0) ? -+ hcd->hfnum_other_frrem_accum_b / -+ hcd->hfnum_other_samples_b : 0); -+#endif -+} -+ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -new file mode 100644 -index 0000000..9459c4c ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -0,0 +1,804 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ -+ * $Revision: #52 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237472 $ -+ * -+ * 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_DEVICE_ONLY -+#ifndef __DWC_HCD_H__ -+#define __DWC_HCD_H__ -+ -+#include -+#include "dwc_otg_hcd_if.h" -+#include "dwc_otg_core_if.h" -+#include "dwc_list.h" -+#include "dwc_otg_cil.h" -+ -+/** -+ * @file -+ * -+ * This file contains the structures, constants, and interfaces for -+ * the Host Contoller Driver (HCD). -+ * -+ * The Host Controller Driver (HCD) is responsible for translating requests -+ * from the USB Driver into the appropriate actions on the DWC_otg controller. -+ * It isolates the USBD from the specifics of the controller by providing an -+ * API to the USBD. -+ */ -+ -+struct dwc_otg_hcd_pipe_info { -+ uint8_t dev_addr; -+ uint8_t ep_num; -+ uint8_t pipe_type; -+ uint8_t pipe_dir; -+ uint16_t mps; -+}; -+ -+struct dwc_otg_hcd_iso_packet_desc { -+ uint32_t offset; -+ uint32_t length; -+ uint32_t actual_length; -+ uint32_t status; -+}; -+ -+struct dwc_otg_qtd; -+ -+struct dwc_otg_hcd_urb { -+ void *priv; -+ struct dwc_otg_qtd *qtd; -+ void *buf; -+ dwc_dma_t dma; -+ void *setup_packet; -+ dwc_dma_t setup_dma; -+ uint32_t length; -+ uint32_t actual_length; -+ uint32_t status; -+ uint32_t error_count; -+ uint32_t packet_count; -+ uint32_t flags; -+ uint16_t interval; -+ struct dwc_otg_hcd_pipe_info pipe_info; -+ struct dwc_otg_hcd_iso_packet_desc iso_descs[0]; -+}; -+ -+static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe) -+{ -+ return pipe->ep_num; -+} -+ -+static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info -+ *pipe) -+{ -+ return pipe->pipe_type; -+} -+ -+static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe) -+{ -+ return pipe->mps; -+} -+ -+static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info -+ *pipe) -+{ -+ return pipe->dev_addr; -+} -+ -+static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info -+ *pipe) -+{ -+ return (pipe->pipe_type == UE_ISOCHRONOUS); -+} -+ -+static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info -+ *pipe) -+{ -+ return (pipe->pipe_type == UE_INTERRUPT); -+} -+ -+static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info -+ *pipe) -+{ -+ return (pipe->pipe_type == UE_BULK); -+} -+ -+static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info -+ *pipe) -+{ -+ return (pipe->pipe_type == UE_CONTROL); -+} -+ -+static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe) -+{ -+ return (pipe->pipe_dir == UE_DIR_IN); -+} -+ -+static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info -+ *pipe) -+{ -+ return (!dwc_otg_hcd_is_pipe_in(pipe)); -+} -+ -+static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, -+ uint8_t devaddr, uint8_t ep_num, -+ uint8_t pipe_type, uint8_t pipe_dir, -+ uint16_t mps) -+{ -+ pipe->dev_addr = devaddr; -+ pipe->ep_num = ep_num; -+ pipe->pipe_type = pipe_type; -+ pipe->pipe_dir = pipe_dir; -+ pipe->mps = mps; -+} -+ -+/** -+ * Phases for control transfers. -+ */ -+typedef enum dwc_otg_control_phase { -+ DWC_OTG_CONTROL_SETUP, -+ DWC_OTG_CONTROL_DATA, -+ DWC_OTG_CONTROL_STATUS -+} dwc_otg_control_phase_e; -+ -+/** Transaction types. */ -+typedef enum dwc_otg_transaction_type { -+ DWC_OTG_TRANSACTION_NONE, -+ DWC_OTG_TRANSACTION_PERIODIC, -+ DWC_OTG_TRANSACTION_NON_PERIODIC, -+ DWC_OTG_TRANSACTION_ALL -+} dwc_otg_transaction_type_e; -+ -+struct dwc_otg_qh; -+ -+/** -+ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, -+ * interrupt, or isochronous transfer. A single QTD is created for each URB -+ * (of one of these types) submitted to the HCD. The transfer associated with -+ * a QTD may require one or multiple transactions. -+ * -+ * A QTD is linked to a Queue Head, which is entered in either the -+ * non-periodic or periodic schedule for execution. When a QTD is chosen for -+ * execution, some or all of its transactions may be executed. After -+ * execution, the state of the QTD is updated. The QTD may be retired if all -+ * its transactions are complete or if an error occurred. Otherwise, it -+ * remains in the schedule so more transactions can be executed later. -+ */ -+typedef struct dwc_otg_qtd { -+ /** -+ * Determines the PID of the next data packet for the data phase of -+ * control transfers. Ignored for other transfer types.
-+ * One of the following values: -+ * - DWC_OTG_HC_PID_DATA0 -+ * - DWC_OTG_HC_PID_DATA1 -+ */ -+ uint8_t data_toggle; -+ -+ /** Current phase for control transfers (Setup, Data, or Status). */ -+ dwc_otg_control_phase_e control_phase; -+ -+ /** Keep track of the current split type -+ * for FS/LS endpoints on a HS Hub */ -+ uint8_t complete_split; -+ -+ /** How many bytes transferred during SSPLIT OUT */ -+ uint32_t ssplit_out_xfer_count; -+ -+ /** -+ * Holds the number of bus errors that have occurred for a transaction -+ * within this transfer. -+ */ -+ uint8_t error_count; -+ -+ /** -+ * Index of the next frame descriptor for an isochronous transfer. A -+ * frame descriptor describes the buffer position and length of the -+ * data to be transferred in the next scheduled (micro)frame of an -+ * isochronous transfer. It also holds status for that transaction. -+ * The frame index starts at 0. -+ */ -+ uint16_t isoc_frame_index; -+ -+ /** Position of the ISOC split on full/low speed */ -+ uint8_t isoc_split_pos; -+ -+ /** Position of the ISOC split in the buffer for the current frame */ -+ uint16_t isoc_split_offset; -+ -+ /** URB for this transfer */ -+ struct dwc_otg_hcd_urb *urb; -+ -+ struct dwc_otg_qh *qh; -+ -+ /** This list of QTDs */ -+ DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry; -+ -+ /** Indicates if this QTD is currently processed by HW. */ -+ uint8_t in_process; -+ -+ /** Number of DMA descriptors for this QTD */ -+ uint8_t n_desc; -+ -+ /** -+ * Last activated frame(packet) index. -+ * Used in Descriptor DMA mode only. -+ */ -+ uint16_t isoc_frame_index_last; -+ -+} dwc_otg_qtd_t; -+ -+DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd); -+ -+/** -+ * A Queue Head (QH) holds the static characteristics of an endpoint and -+ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may -+ * be entered in either the non-periodic or periodic schedule. -+ */ -+typedef struct dwc_otg_qh { -+ /** -+ * Endpoint type. -+ * One of the following values: -+ * - UE_CONTROL -+ * - UE_BULK -+ * - UE_INTERRUPT -+ * - UE_ISOCHRONOUS -+ */ -+ uint8_t ep_type; -+ uint8_t ep_is_in; -+ -+ /** wMaxPacketSize Field of Endpoint Descriptor. */ -+ uint16_t maxp; -+ -+ /** -+ * Device speed. -+ * One of the following values: -+ * - DWC_OTG_EP_SPEED_LOW -+ * - DWC_OTG_EP_SPEED_FULL -+ * - DWC_OTG_EP_SPEED_HIGH -+ */ -+ uint8_t dev_speed; -+ -+ /** -+ * Determines the PID of the next data packet for non-control -+ * transfers. Ignored for control transfers.
-+ * One of the following values: -+ * - DWC_OTG_HC_PID_DATA0 -+ * - DWC_OTG_HC_PID_DATA1 -+ */ -+ uint8_t data_toggle; -+ -+ /** Ping state if 1. */ -+ uint8_t ping_state; -+ -+ /** -+ * List of QTDs for this QH. -+ */ -+ struct dwc_otg_qtd_list qtd_list; -+ -+ /** Host channel currently processing transfers for this QH. */ -+ struct dwc_hc *channel; -+ -+ /** Full/low speed endpoint on high-speed hub requires split. */ -+ uint8_t do_split; -+ -+ /** @name Periodic schedule information */ -+ /** @{ */ -+ -+ /** Bandwidth in microseconds per (micro)frame. */ -+ uint16_t usecs; -+ -+ /** Interval between transfers in (micro)frames. */ -+ uint16_t interval; -+ -+ /** -+ * (micro)frame to initialize a periodic transfer. The transfer -+ * executes in the following (micro)frame. -+ */ -+ uint16_t sched_frame; -+ -+ /** (micro)frame at which last start split was initialized. */ -+ uint16_t start_split_frame; -+ -+ /** @} */ -+ -+ /** -+ * Used instead of original buffer if -+ * it(physical address) is not dword-aligned. -+ */ -+ uint8_t *dw_align_buf; -+ dwc_dma_t dw_align_buf_dma; -+ -+ /** Entry for QH in either the periodic or non-periodic schedule. */ -+ dwc_list_link_t qh_list_entry; -+ -+ /** @name Descriptor DMA support */ -+ /** @{ */ -+ -+ /** Descriptor List. */ -+ dwc_otg_host_dma_desc_t *desc_list; -+ -+ /** Descriptor List physical address. */ -+ dwc_dma_t desc_list_dma; -+ -+ /** -+ * Xfer Bytes array. -+ * Each element corresponds to a descriptor and indicates -+ * original XferSize size value for the descriptor. -+ */ -+ uint32_t *n_bytes; -+ -+ /** Actual number of transfer descriptors in a list. */ -+ uint16_t ntd; -+ -+ /** First activated isochronous transfer descriptor index. */ -+ uint8_t td_first; -+ /** Last activated isochronous transfer descriptor index. */ -+ uint8_t td_last; -+ -+ /** @} */ -+ -+} dwc_otg_qh_t; -+ -+DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); -+ -+#ifdef HW2937_WORKAROUND -+ -+typedef enum { -+ HW2937_XFER_MODE_IDLE, -+ HW2937_XFER_MODE_IN, -+ HW2937_XFER_MODE_OUT, -+ HW2937_XFER_MODE_PAUSEIN /* Transitioning from IN to IDLE */ -+} hw2937_xfer_mode_t; -+#endif -+ -+/** -+ * This structure holds the state of the HCD, including the non-periodic and -+ * periodic schedules. -+ */ -+struct dwc_otg_hcd { -+ /** DWC OTG Core Interface Layer */ -+ dwc_otg_core_if_t *core_if; -+ -+ /** Function HCD driver callbacks */ -+ struct dwc_otg_hcd_function_ops *fops; -+ -+ /** Internal DWC HCD Flags */ -+ volatile union dwc_otg_hcd_internal_flags { -+ uint32_t d32; -+ struct { -+ unsigned port_connect_status_change:1; -+ unsigned port_connect_status:1; -+ unsigned port_reset_change:1; -+ unsigned port_enable_change:1; -+ unsigned port_suspend_change:1; -+ unsigned port_over_current_change:1; -+ unsigned port_l1_change:1; -+ unsigned reserved:26; -+ } b; -+ } flags; -+ -+ /** -+ * Inactive items in the non-periodic schedule. This is a list of -+ * Queue Heads. Transfers associated with these Queue Heads are not -+ * currently assigned to a host channel. -+ */ -+ dwc_list_link_t non_periodic_sched_inactive; -+ -+ /** -+ * Active items in the non-periodic schedule. This is a list of -+ * Queue Heads. Transfers associated with these Queue Heads are -+ * currently assigned to a host channel. -+ */ -+ dwc_list_link_t non_periodic_sched_active; -+ -+ /** -+ * Pointer to the next Queue Head to process in the active -+ * non-periodic schedule. -+ */ -+ dwc_list_link_t *non_periodic_qh_ptr; -+ -+ /** -+ * Inactive items in the periodic schedule. This is a list of QHs for -+ * periodic transfers that are _not_ scheduled for the next frame. -+ * Each QH in the list has an interval counter that determines when it -+ * needs to be scheduled for execution. This scheduling mechanism -+ * allows only a simple calculation for periodic bandwidth used (i.e. -+ * must assume that all periodic transfers may need to execute in the -+ * same frame). However, it greatly simplifies scheduling and should -+ * be sufficient for the vast majority of OTG hosts, which need to -+ * connect to a small number of peripherals at one time. -+ * -+ * Items move from this list to periodic_sched_ready when the QH -+ * interval counter is 0 at SOF. -+ */ -+ dwc_list_link_t periodic_sched_inactive; -+ -+ /** -+ * List of periodic QHs that are ready for execution in the next -+ * frame, but have not yet been assigned to host channels. -+ * -+ * Items move from this list to periodic_sched_assigned as host -+ * channels become available during the current frame. -+ */ -+ dwc_list_link_t periodic_sched_ready; -+ -+ /** -+ * List of periodic QHs to be executed in the next frame that are -+ * assigned to host channels. -+ * -+ * Items move from this list to periodic_sched_queued as the -+ * transactions for the QH are queued to the DWC_otg controller. -+ */ -+ dwc_list_link_t periodic_sched_assigned; -+ -+ /** -+ * List of periodic QHs that have been queued for execution. -+ * -+ * Items move from this list to either periodic_sched_inactive or -+ * periodic_sched_ready when the channel associated with the transfer -+ * is released. If the interval for the QH is 1, the item moves to -+ * periodic_sched_ready because it must be rescheduled for the next -+ * frame. Otherwise, the item moves to periodic_sched_inactive. -+ */ -+ dwc_list_link_t periodic_sched_queued; -+ -+ /** -+ * Total bandwidth claimed so far for periodic transfers. This value -+ * is in microseconds per (micro)frame. The assumption is that all -+ * periodic transfers may occur in the same (micro)frame. -+ */ -+ uint16_t periodic_usecs; -+ -+ /** -+ * Frame number read from the core at SOF. The value ranges from 0 to -+ * DWC_HFNUM_MAX_FRNUM. -+ */ -+ uint16_t frame_number; -+ -+ /** -+ * Free host channels in the controller. This is a list of -+ * dwc_hc_t items. -+ */ -+ struct hc_list free_hc_list; -+ /** -+ * Number of host channels assigned to periodic transfers. Currently -+ * assuming that there is a dedicated host channel for each periodic -+ * transaction and at least one host channel available for -+ * non-periodic transactions. -+ */ -+ int periodic_channels; -+ -+ /** -+ * Number of host channels assigned to non-periodic transfers. -+ */ -+ int non_periodic_channels; -+ -+ /** -+ * Array of pointers to the host channel descriptors. Allows accessing -+ * a host channel descriptor given the host channel number. This is -+ * useful in interrupt handlers. -+ */ -+ struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS]; -+ -+ /** -+ * Buffer to use for any data received during the status phase of a -+ * control transfer. Normally no data is transferred during the status -+ * phase. This buffer is used as a bit bucket. -+ */ -+ uint8_t *status_buf; -+ -+ /** -+ * DMA address for status_buf. -+ */ -+ dma_addr_t status_buf_dma; -+#define DWC_OTG_HCD_STATUS_BUF_SIZE 64 -+ -+ /** -+ * Connection timer. An OTG host must display a message if the device -+ * does not connect. Started when the VBus power is turned on via -+ * sysfs attribute "buspower". -+ */ -+ dwc_timer_t *conn_timer; -+ -+ /* Tasket to do a reset */ -+ dwc_tasklet_t *reset_tasklet; -+ -+ /* */ -+ dwc_spinlock_t *lock; -+ -+ /** -+ * Private data that could be used by OS wrapper. -+ */ -+ void *priv; -+ -+ uint8_t otg_port; -+ -+ /** Frame List */ -+ uint32_t *frame_list; -+ -+ /** Frame List DMA address */ -+ dma_addr_t frame_list_dma; -+ -+#ifdef HW2937_WORKAROUND -+ /** Current transfer mode (IN, OUT, or IDLE) */ -+ hw2937_xfer_mode_t hw2937_xfer_mode; -+ -+ /** Mask of channels assigned to the current mode */ -+ uint32_t hw2937_assigned_channels; -+#endif -+ -+#ifdef DEBUG -+ uint32_t frrem_samples; -+ uint64_t frrem_accum; -+ -+ uint32_t hfnum_7_samples_a; -+ uint64_t hfnum_7_frrem_accum_a; -+ uint32_t hfnum_0_samples_a; -+ uint64_t hfnum_0_frrem_accum_a; -+ uint32_t hfnum_other_samples_a; -+ uint64_t hfnum_other_frrem_accum_a; -+ -+ uint32_t hfnum_7_samples_b; -+ uint64_t hfnum_7_frrem_accum_b; -+ uint32_t hfnum_0_samples_b; -+ uint64_t hfnum_0_frrem_accum_b; -+ uint32_t hfnum_other_samples_b; -+ uint64_t hfnum_other_frrem_accum_b; -+#endif -+}; -+ -+/** @name Transaction Execution Functions */ -+/** @{ */ -+extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t -+ * hcd); -+extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, -+ dwc_otg_transaction_type_e tr_type); -+ -+/** @} */ -+ -+/** @name Interrupt Handler Functions */ -+/** @{ */ -+extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * -+ dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * -+ dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * -+ dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t * -+ dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t * -+ dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, -+ uint32_t num); -+extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd); -+extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t * -+ dwc_otg_hcd); -+/** @} */ -+ -+/** @name Schedule Queue Functions */ -+/** @{ */ -+ -+/* Implemented in dwc_otg_hcd_queue.c */ -+extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, -+ dwc_otg_hcd_urb_t * urb); -+extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); -+extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); -+extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); -+extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, -+ int sched_csplit); -+ -+/** Remove and free a QH */ -+static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd, -+ dwc_otg_qh_t * qh) -+{ -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ dwc_otg_hcd_qh_free(hcd, qh); -+} -+ -+/** Allocates memory for a QH structure. -+ * @return Returns the memory allocate or NULL on error. */ -+static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(void) -+{ -+ return (dwc_otg_qh_t *) dwc_alloc(sizeof(dwc_otg_qh_t)); -+} -+ -+extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb); -+extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb); -+extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd, -+ dwc_otg_qh_t ** qh); -+ -+/** Allocates memory for a QTD structure. -+ * @return Returns the memory allocate or NULL on error. */ -+static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void) -+{ -+ return (dwc_otg_qtd_t *) dwc_alloc(sizeof(dwc_otg_qtd_t)); -+} -+ -+/** Frees the memory for a QTD structure. QTD should already be removed from -+ * list. -+ * @param qtd QTD to free.*/ -+static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd) -+{ -+ dwc_free(qtd); -+} -+ -+/** Removes a QTD from list. -+ * @param hcd HCD instance. -+ * @param qtd QTD to remove from list. -+ * @param qh QTD belongs to. -+ */ -+static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_qh_t * qh) -+{ -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+} -+ -+/** Remove and free a QTD */ -+static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_qh_t * qh) -+{ -+ dwc_otg_hcd_qtd_remove(hcd, qtd, qh); -+ dwc_otg_hcd_qtd_free(qtd); -+} -+ -+/** @} */ -+ -+/** @name Descriptor DMA Supporting Functions */ -+/** @{ */ -+ -+extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); -+extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_halt_status_e halt_status); -+ -+extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); -+extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); -+ -+/** @} */ -+ -+/** @name Internal Functions */ -+/** @{ */ -+dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb); -+/** @} */ -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, -+ uint8_t devaddr); -+extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd); -+#endif -+ -+/** Gets the QH that contains the list_head */ -+#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry) -+ -+/** Gets the QTD that contains the list_head */ -+#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry) -+ -+/** Check if QH is non-periodic */ -+#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \ -+ (_qh_ptr_->ep_type == UE_CONTROL)) -+ -+/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ -+#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -+ -+/** Packet size for any kind of endpoint descriptor */ -+#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) -+ -+/** -+ * Returns true if _frame1 is less than or equal to _frame2. The comparison is -+ * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the -+ * frame number when the max frame number is reached. -+ */ -+static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2) -+{ -+ return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <= -+ (DWC_HFNUM_MAX_FRNUM >> 1); -+} -+ -+/** -+ * Returns true if _frame1 is greater than _frame2. The comparison is done -+ * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame -+ * number when the max frame number is reached. -+ */ -+static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2) -+{ -+ return (frame1 != frame2) && -+ (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) < -+ (DWC_HFNUM_MAX_FRNUM >> 1)); -+} -+ -+/** -+ * Increments _frame by the amount specified by _inc. The addition is done -+ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value. -+ */ -+static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc) -+{ -+ return (frame + inc) & DWC_HFNUM_MAX_FRNUM; -+} -+ -+static inline uint16_t dwc_full_frame_num(uint16_t frame) -+{ -+ return (frame & DWC_HFNUM_MAX_FRNUM) >> 3; -+} -+ -+static inline uint16_t dwc_micro_frame_num(uint16_t frame) -+{ -+ return frame & 0x7; -+} -+ -+void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd); -+ -+#ifdef DEBUG -+/** -+ * Macro to sample the remaining PHY clocks left in the current frame. This -+ * may be used during debugging to determine the average time it takes to -+ * execute sections of code. There are two possible sample points, "a" and -+ * "b", so the _letter argument must be one of these values. -+ * -+ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For -+ * example, "cat /sys/devices/lm0/hcd_frrem". -+ */ -+#define dwc_sample_frrem(_hcd, _qh, _letter) \ -+{ \ -+ hfnum_data_t hfnum; \ -+ dwc_otg_qtd_t *qtd; \ -+ qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \ -+ if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \ -+ hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ -+ switch (hfnum.b.frnum & 0x7) { \ -+ case 7: \ -+ _hcd->hfnum_7_samples_##_letter++; \ -+ _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \ -+ break; \ -+ case 0: \ -+ _hcd->hfnum_0_samples_##_letter++; \ -+ _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \ -+ break; \ -+ default: \ -+ _hcd->hfnum_other_samples_##_letter++; \ -+ _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \ -+ break; \ -+ } \ -+ } \ -+} -+#else -+#define dwc_sample_frrem(_hcd, _qh, _letter) -+#endif -+#endif -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -new file mode 100644 -index 0000000..21d1ab1 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -@@ -0,0 +1,1106 @@ -+/*========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ -+ * $Revision: #2 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237473 $ -+ * -+ * 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_DEVICE_ONLY -+ -+/** @file -+ * This file contains Descriptor DMA support implementation for host mode. -+ */ -+ -+#include "dwc_otg_hcd.h" -+#include "dwc_otg_regs.h" -+ -+ -+static inline uint8_t frame_list_idx(uint16_t frame) -+{ -+ return (frame & (MAX_FRLIST_EN_NUM - 1)); -+} -+ -+static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed) -+{ -+ return (idx + inc) & -+ (((speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1); -+} -+ -+static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed) -+{ -+ return (idx - inc) & -+ (((speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1); -+} -+ -+static inline uint16_t max_desc_num(dwc_otg_qh_t * qh) -+{ -+ return (((qh->ep_type == UE_ISOCHRONOUS) && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) -+ ? -+ MAX_DMA_DESC_NUM_HS_ISOC -+ : -+ MAX_DMA_DESC_NUM_GENERIC); -+} -+static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) -+{ -+ return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) -+ ? ((qh->interval + 8 - 1) / 8) -+ : -+ qh->interval); -+} -+ -+static int desc_list_alloc(dwc_otg_qh_t * qh) -+{ -+ int retval = 0; -+ -+ qh->desc_list = (dwc_otg_host_dma_desc_t *) -+ dwc_dma_alloc(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), -+ &qh->desc_list_dma -+ ); -+ -+ if (!qh->desc_list) { -+ retval = -DWC_E_NO_MEMORY; -+ DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__); -+ -+ } -+ -+ dwc_memset(qh->desc_list, 0x00, sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); -+ -+ -+ qh->n_bytes = (uint32_t *) dwc_alloc(sizeof(uint32_t) * max_desc_num(qh)); -+ -+ if (!qh->n_bytes) { -+ retval = -DWC_E_NO_MEMORY; -+ DWC_ERROR("%s: Failed to allocate array for descriptors' size actual values\n", -+ __func__); -+ -+ } -+ return retval; -+ -+} -+ -+static void desc_list_free(dwc_otg_qh_t * qh) -+{ -+ if(qh->desc_list) { -+ dwc_dma_free(max_desc_num(qh), qh->desc_list, qh->desc_list_dma); -+ qh->desc_list = NULL; -+ } -+ -+ if (qh->n_bytes) { -+ dwc_free(qh->n_bytes); -+ qh->n_bytes = NULL; -+ } -+} -+ -+static int frame_list_alloc(dwc_otg_hcd_t * hcd) -+{ -+ int retval = 0; -+ if (hcd->frame_list) -+ return 0; -+ -+ hcd->frame_list = dwc_dma_alloc(4 * MAX_FRLIST_EN_NUM, -+ &hcd->frame_list_dma -+ ); -+ if (!hcd->frame_list) { -+ retval = -DWC_E_NO_MEMORY; -+ DWC_ERROR("%s: Frame List allocation failed\n", __func__); -+ } -+ -+ dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM); -+ -+ return retval; -+} -+ -+static void frame_list_free(dwc_otg_hcd_t * hcd) -+{ -+ if (!hcd->frame_list) -+ return; -+ -+ dwc_dma_free(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); -+ hcd->frame_list = NULL; -+} -+ -+static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en) -+{ -+ -+ hcfg_data_t hcfg; -+ -+ hcfg.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hcfg); -+ -+ if (hcfg.b.perschedstat) { -+ /* already enabled*/ -+ return; -+ } -+ -+ dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hflbaddr, hcd->frame_list_dma); -+ -+ switch(fr_list_en) { -+ case 64: -+ hcfg.b.frlisten = 3; -+ break; -+ case 32: -+ hcfg.b.frlisten = 2; -+ break; -+ case 16: -+ hcfg.b.frlisten = 1; -+ case 8: -+ hcfg.b.frlisten = 0; -+ default: -+ break; -+ } -+ -+ hcfg.b.perschedena = 1; -+ -+ DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n"); -+ dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); -+ -+} -+ -+static void per_sched_disable(dwc_otg_hcd_t * hcd) -+{ -+ hcfg_data_t hcfg; -+ -+ hcfg.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hcfg); -+ -+ if (!hcfg.b.perschedstat) { -+ /* already disabled */ -+ return; -+ } -+ hcfg.b.perschedena = 0; -+ -+ DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n"); -+ dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); -+} -+ -+/* -+ * Activates/Deactivates FrameList entries for the channel -+ * based on endpoint servicing period. -+ */ -+void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable) -+{ -+ uint16_t i, j, inc; -+ dwc_hc_t *hc = qh->channel; -+ -+ inc = frame_incr_val(qh); -+ -+ if (qh->ep_type == UE_ISOCHRONOUS) -+ i = frame_list_idx(qh->sched_frame); -+ else -+ i = 0; -+ -+ j = i; -+ do { -+ if (enable) -+ hcd->frame_list[j] |= (1 << hc->hc_num); -+ else -+ hcd->frame_list[j] &= ~(1 << hc->hc_num); -+ j = (j + inc) & (MAX_FRLIST_EN_NUM - 1); -+ } -+ while (j != i); -+ -+ if (!enable) -+ return; -+ -+ hc->schinfo = 0; -+ if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) { -+ j = 1; -+ for (i = 0 ; i < 8 / qh->interval; i++) { -+ hc->schinfo |= j; -+ j = j << qh->interval; -+ } -+ } -+ else { -+ hc->schinfo = 0xff; -+ } -+} -+#if 1 -+void dump_frame_list(dwc_otg_hcd_t * hcd) -+{ -+ int i = 0; -+ DWC_PRINTF("--FRAME LIST (hex) --\n"); -+ for (i = 0; i < MAX_FRLIST_EN_NUM; i++) { -+ DWC_PRINTF("%x\t",hcd->frame_list[i]); -+ if (!(i % 8) && i) -+ DWC_PRINTF("\n"); -+ } -+ DWC_PRINTF("\n----\n"); -+ -+} -+#endif -+ -+static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ dwc_hc_t *hc = qh->channel; -+ if (dwc_qh_is_non_per(qh)) { -+ hcd->non_periodic_channels--; -+ } -+ else { -+ update_frame_list(hcd, qh, 0); -+ } -+ /* -+ * The condition is added to prevent double cleanup try in case of device -+ * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb(). -+ */ -+ if (hc->qh) { -+ dwc_otg_hc_cleanup(hcd->core_if, hc); -+ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); -+ hc->qh = NULL; -+ } -+ -+ qh->channel = NULL; -+ qh->ntd = 0; -+ -+ if (qh->desc_list) { -+ dwc_memset(qh->desc_list, 0x00, -+ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); -+ } -+} -+ -+/** -+ * Initializes a QH structure's Descriptor DMA related members. -+ * Allocates memory for descriptor list. -+ * On first periodic QH, allocates memory for FrameList -+ * and enables periodic scheduling. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh The QH to init. -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ int retval = 0; -+ -+ if (qh->do_split) { -+ DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n"); -+ return -1; -+ } -+ -+ retval = desc_list_alloc(qh); -+ -+ if ((retval == 0) && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { -+ if(!hcd->frame_list) { -+ retval = frame_list_alloc(hcd); -+ /* Enable periodic schedule on first periodic QH */ -+ if (retval == 0) -+ per_sched_enable(hcd, MAX_FRLIST_EN_NUM); -+ } -+ } -+ -+ qh->ntd = 0; -+ -+ return retval; -+} -+ -+/** -+ * Frees descriptor list memory associated with the QH. -+ * If QH is periodic and the last, frees FrameList memory -+ * and disables periodic scheduling. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh The QH to init. -+ */ -+void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ desc_list_free(qh); -+ -+ /* -+ * Channel still assigned due to some reasons. -+ * Seen on Isoc URB dequeue. Channel halted but no subsequent -+ * ChHalted interrupt to release the channel. Afterwards -+ * when it comes here from endpoint disable routine -+ * channel remains assigned. -+ */ -+ if (qh->channel) -+ release_channel_ddma(hcd, qh); -+ -+ if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) -+ && !hcd->periodic_channels && hcd->frame_list) { -+ -+ per_sched_disable(hcd); -+ frame_list_free(hcd); -+ } -+} -+ -+static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx) -+{ -+ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { -+ /* -+ * Descriptor set(8 descriptors) index -+ * which is 8-aligned. -+ */ -+ return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; -+ } -+ else { -+ return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1)); -+ } -+} -+ -+/* -+ * Determine starting frame for Isochronous transfer. -+ * Few frames skipped to prevent race condition with HC. -+ */ -+static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t* skip_frames) -+{ -+ uint16_t frame = 0; -+ hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd); -+ -+ /* sched_frame is always frame number(not uFrame) both in FS and HS !! */ -+ -+ /* -+ * skip_frames is used to limit activated descriptors number -+ * to avoid the situation when HC services the last activated -+ * descriptor firstly. -+ * Example for FS: -+ * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor -+ * corresponding to curr_frame+1, the descriptor corresponding to frame 2 -+ * will be fetched. If the number of descriptors is max=64 (or greather) the list will -+ * be fully programmed with Active descriptors and it is possible case(rare) that the latest -+ * descriptor(considering rollback) corresponding to frame 2 will be serviced first. -+ * HS case is more probable because, in fact, up to 11 uframes(16 in the code) -+ * may be skipped. -+ */ -+ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { -+ /* -+ * Consider uframe counter also, to start xfer asap. -+ * If half of the frame elapsed skip 2 frames otherwise -+ * just 1 frame. -+ * Starting descriptor index must be 8-aligned, so -+ * if the current frame is near to complete the next one -+ * is skipped as well. -+ */ -+ -+ if (dwc_micro_frame_num(hcd->frame_number) >= 5) { -+ *skip_frames = 2 * 8; -+ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); -+ } -+ else { -+ *skip_frames = 1 * 8; -+ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); -+ } -+ -+ frame = dwc_full_frame_num(frame); -+ } else { -+ /* -+ * Two frames are skipped for FS - the current and the next. -+ * But for descriptor programming, 1 frame(descriptor) is enough, -+ * see example above. -+ */ -+ *skip_frames = 1; -+ frame = dwc_frame_num_inc(hcd->frame_number, 2); -+ } -+ -+ return frame; -+} -+/* -+ * Calculate initial descriptor index for isochronous transfer -+ * based on scheduled frame. -+ */ -+static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ uint16_t frame = 0, fr_idx, fr_idx_tmp; -+ uint8_t skip_frames = 0 ; -+ /* -+ * With current ISOC processing algorithm the channel is being -+ * released when no more QTDs in the list(qh->ntd == 0). -+ * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. -+ * -+ * So qh->channel != NULL branch is not used and just not removed from the -+ * source file. It is required for another possible approach which is, -+ * do not disable and release the channel when ISOC session completed, -+ * just move QH to inactive schedule until new QTD arrives. -+ * On new QTD, the QH moved back to 'ready' schedule, -+ * starting frame and therefore starting desc_index are recalculated. -+ * In this case channel is released only on ep_disable. -+ */ -+ -+ /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */ -+ if (qh->channel) { -+ frame = calc_starting_frame(hcd, qh, &skip_frames); -+ /* -+ * Calculate initial descriptor index based on FrameList current bitmap -+ * and servicing period. -+ */ -+ fr_idx_tmp = frame_list_idx(frame); -+ fr_idx = (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - fr_idx_tmp) -+ % frame_incr_val(qh); -+ fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM; -+ } -+ else { -+ qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); -+ fr_idx = frame_list_idx(qh->sched_frame); -+ } -+ -+ qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); -+ -+ return skip_frames; -+} -+ -+#define ISOC_URB_GIVEBACK_ASAP -+ -+#define MAX_ISOC_XFER_SIZE_FS 1023 -+#define MAX_ISOC_XFER_SIZE_HS 3072 -+#define DESCNUM_THRESHOLD 4 -+ -+static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t skip_frames) -+{ -+ struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ dwc_otg_qtd_t *qtd; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ uint16_t idx, inc, n_desc, ntd_max, max_xfer_size; -+ -+ idx = qh->td_last; -+ inc = qh->interval; -+ n_desc = 0; -+ -+ ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval; -+ if (skip_frames && !qh->channel) -+ ntd_max = ntd_max - skip_frames / qh->interval; -+ -+ max_xfer_size = (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS -+ : MAX_ISOC_XFER_SIZE_FS; -+ -+ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { -+ while ((qh->ntd < ntd_max) && (qtd->isoc_frame_index_last < qtd->urb->packet_count)) { -+ -+ dma_desc = &qh->desc_list[idx]; -+ dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t)); -+ -+ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; -+ -+ if (frame_desc->length > max_xfer_size) -+ qh->n_bytes[idx] = max_xfer_size; -+ else -+ qh->n_bytes[idx] = frame_desc->length; -+ dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx]; -+ dma_desc->status.b_isoc.a = 1; -+ -+ dma_desc->buf = qtd->urb->dma + frame_desc->offset; -+ -+ qh->ntd++; -+ -+ qtd->isoc_frame_index_last++; -+ -+ #ifdef ISOC_URB_GIVEBACK_ASAP -+ /* -+ * Set IOC for each descriptor corresponding to the -+ * last frame of the URB. -+ */ -+ if (qtd->isoc_frame_index_last == qtd->urb->packet_count) -+ dma_desc->status.b_isoc.ioc = 1; -+ -+ #endif -+ idx = desclist_idx_inc(idx, inc, qh->dev_speed); -+ n_desc++; -+ -+ } -+ qtd->in_process = 1; -+ } -+ -+ qh->td_last = idx; -+ -+#ifdef ISOC_URB_GIVEBACK_ASAP -+ /* Set IOC for the last descriptor if descriptor list is full */ -+ if (qh->ntd == ntd_max) { -+ idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed); -+ qh->desc_list[idx].status.b_isoc.ioc = 1; -+ } -+#else -+ /* -+ * Set IOC bit only for one descriptor. -+ * Always try to be ahead of HW processing, -+ * i.e. on IOC generation driver activates next descriptors but -+ * core continues to process descriptors followed the one with IOC set. -+ */ -+ -+ if (n_desc > DESCNUM_THRESHOLD) { -+ /* -+ * Move IOC "up". Required even if there is only one QTD -+ * in the list, cause QTDs migth continue to be queued, -+ * but during the activation it was only one queued. -+ * Actually more than one QTD might be in the list if this function called -+ * from XferCompletion - QTDs was queued during HW processing of the previous -+ * descriptor chunk. -+ */ -+ idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed); -+ } -+ else { -+ /* -+ * Set the IOC for the latest descriptor -+ * if either number of descriptor is not greather than threshold -+ * or no more new descriptors activated. -+ */ -+ idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); -+ } -+ -+ qh->desc_list[idx].status.b_isoc.ioc = 1; -+#endif -+} -+ -+ -+static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ -+ dwc_hc_t *hc; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ dwc_otg_qtd_t *qtd; -+ int num_packets, len, n_desc = 0; -+ -+ hc = qh->channel; -+ -+ /* -+ * Start with hc->xfer_buff initialized in -+ * assign_and_init_hc(), then if SG transfer consists of multiple URBs, -+ * this pointer re-assigned to the buffer of the currently processed QTD. -+ * For non-SG request there is always one QTD active. -+ */ -+ -+ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { -+ -+ if (n_desc) { -+ /* SG request - more than 1 QTDs */ -+ hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length; -+ hc->xfer_len = qtd->urb->length - qtd->urb->actual_length; -+ } -+ -+ qtd->n_desc = 0; -+ -+ do { -+ dma_desc = &qh->desc_list[n_desc]; -+ len = hc->xfer_len; -+ -+ -+ if (len > MAX_DMA_DESC_SIZE) -+ len = MAX_DMA_DESC_SIZE - hc->max_packet + 1; -+ -+ if (hc->ep_is_in) { -+ if (len > 0) { -+ num_packets = (len + hc->max_packet - 1) / hc->max_packet; -+ } -+ else { -+ /* Need 1 packet for transfer length of 0. */ -+ num_packets = 1; -+ } -+ /* Always program an integral # of max packets for IN transfers. */ -+ len = num_packets * hc->max_packet; -+ } -+ -+ dma_desc->status.b.n_bytes = len; -+ -+ qh->n_bytes[n_desc] = len; -+ -+ -+ if ((qh->ep_type == UE_CONTROL) && (qtd->control_phase == DWC_OTG_CONTROL_SETUP)) -+ dma_desc->status.b.sup = 1; /* Setup Packet */ -+ -+ dma_desc->status.b.a = 1; /* Active descriptor */ -+ -+ dma_desc->buf = (uint32_t) hc->xfer_buff; -+ -+ /* -+ * Last descriptor(or single) of IN transfer -+ * with actual size less than MaxPacket. -+ */ -+ if (len > hc->xfer_len) { -+ hc->xfer_len = 0; -+ } -+ else { -+ hc->xfer_buff += len; -+ hc->xfer_len -= len; -+ } -+ -+ qtd->n_desc++; -+ n_desc++; -+ } -+ while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC)); -+ -+ -+ qtd->in_process = 1; -+ -+ if (n_desc == MAX_DMA_DESC_NUM_GENERIC) -+ break; -+ } -+ -+ if (n_desc) { -+ /* Request Transfer Complete interrupt for the last descriptor */ -+ qh->desc_list[n_desc-1].status.b.ioc = 1; -+ /* End of List indicator */ -+ qh->desc_list[n_desc-1].status.b.eol = 1; -+ -+ hc->ntd = n_desc; -+ } -+} -+ -+/** -+ * For Control and Bulk endpoints initializes descriptor list -+ * and starts the transfer. -+ * -+ * For Interrupt and Isochronous endpoints initializes descriptor list -+ * then updates FrameList, marking appropriate entries as active. -+ * In case of Isochronous, the starting descriptor index is calculated based -+ * on the scheduled frame, but only on the first transfer descriptor within a session. -+ * Then starts the transfer via enabling the channel. -+ * For Isochronous endpoint the channel is not halted on XferComplete -+ * interrupt so remains assigned to the endpoint(QH) until session is done. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh The QH to init. -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ /* Channel is already assigned */ -+ dwc_hc_t *hc = qh->channel; -+ uint8_t skip_frames = 0; -+ -+ switch (hc->ep_type) { -+ case DWC_OTG_EP_TYPE_CONTROL: -+ case DWC_OTG_EP_TYPE_BULK: -+ init_non_isoc_dma_desc(hcd, qh); -+ -+ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); -+ break; -+ case DWC_OTG_EP_TYPE_INTR: -+ init_non_isoc_dma_desc(hcd, qh); -+ -+ update_frame_list(hcd, qh, 1); -+ -+ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); -+ break; -+ case DWC_OTG_EP_TYPE_ISOC: -+ -+ if(!qh->ntd) -+ skip_frames = recalc_initial_desc_idx(hcd, qh); -+ -+ init_isoc_dma_desc(hcd, qh, skip_frames); -+ -+ if (!hc->xfer_started) { -+ -+ update_frame_list(hcd, qh, 1); -+ -+ /* -+ * Always set to max, instead of actual size. -+ * Otherwise ntd will be changed with -+ * channel being enabled. Not recommended. -+ * -+ */ -+ hc->ntd = max_desc_num(qh); -+ /* Enable channel only once for ISOC */ -+ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); -+ } -+ -+ break; -+ default: -+ -+ break; -+ } -+} -+ -+static void complete_isoc_xfer_ddma(dwc_otg_hcd_t *hcd, -+ dwc_hc_t *hc, -+ dwc_otg_hc_regs_t *hc_regs, -+ dwc_otg_halt_status_e halt_status) -+{ -+ struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ dwc_otg_qtd_t *qtd, *qtd_tmp; -+ dwc_otg_qh_t *qh; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ uint16_t idx, remain; -+ uint8_t urb_compl; -+ -+ qh = hc->qh; -+ idx = qh->td_first; -+ -+ -+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) -+ qtd->in_process = 0; -+ return; -+ } -+ else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || -+ (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) { -+ /* -+ * Channel is halted in these error cases. -+ * Considered as serious issues. -+ * Complete all URBs marking all frames as failed, -+ * irrespective whether some of the descriptors(frames) succeeded or no. -+ * Pass error code to completion routine as well, to -+ * update urb->status, some of class drivers might use it to stop -+ * queing transfer requests. -+ */ -+ int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) -+ ? (-DWC_E_IO) -+ : (-DWC_E_OVERFLOW); -+ -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { -+ for(idx = 0; idx < qtd->urb->packet_count; idx++) { -+ frame_desc = &qtd->urb->iso_descs[idx]; -+ frame_desc->status = err; -+ } -+ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err); -+ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -+ } -+ return; -+ } -+ -+ -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { -+ -+ if (!qtd->in_process) -+ break; -+ -+ urb_compl = 0; -+ -+ do { -+ -+ dma_desc = &qh->desc_list[idx]; -+ -+ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; -+ remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0; -+ -+ if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) { -+ /* -+ * XactError or, unable to complete all the transactions -+ * in the scheduled micro-frame/frame, -+ * both indicated by DMA_DESC_STS_PKTERR. -+ */ -+ qtd->urb->error_count++; -+ frame_desc->actual_length = qh->n_bytes[idx] - remain; -+ frame_desc->status = -DWC_E_PROTOCOL; -+ } -+ else { -+ /* Success */ -+ -+ frame_desc->actual_length = qh->n_bytes[idx] - remain; -+ frame_desc->status = 0; -+ } -+ -+ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { -+ /* -+ * urb->status is not used for isoc transfers here. -+ * The individual frame_desc status are used instead. -+ */ -+ -+ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); -+ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -+ -+ /* -+ * This check is necessary because urb_dequeue can be called -+ * from urb complete callback(sound driver example). -+ * All pending URBs are dequeued there, so no need for -+ * further processing. -+ */ -+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { -+ return; -+ } -+ -+ urb_compl = 1; -+ -+ } -+ -+ qh->ntd--; -+ -+ /* Stop if IOC requested descriptor reached */ -+ if (dma_desc->status.b_isoc.ioc) { -+ idx = desclist_idx_inc(idx, qh->interval, hc->speed); -+ goto stop_scan; -+ } -+ -+ idx = desclist_idx_inc(idx, qh->interval, hc->speed); -+ -+ if (urb_compl) -+ break; -+ } -+ while(idx != qh->td_first); -+ } -+stop_scan: -+ qh->td_first = idx; -+} -+ -+uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_host_dma_desc_t * dma_desc, -+ dwc_otg_halt_status_e halt_status, -+ uint32_t n_bytes, -+ uint8_t *xfer_done) -+{ -+ -+ uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0; -+ dwc_otg_hcd_urb_t *urb = qtd->urb; -+ -+ -+ if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) { -+ urb->status = -DWC_E_IO; -+ return 1; -+ } -+ if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) { -+ switch (halt_status) { -+ case DWC_OTG_HC_XFER_STALL: -+ urb->status = -DWC_E_PIPE; -+ break; -+ case DWC_OTG_HC_XFER_BABBLE_ERR: -+ urb->status = -DWC_E_OVERFLOW; -+ break; -+ case DWC_OTG_HC_XFER_XACT_ERR: -+ urb->status = -DWC_E_PROTOCOL; -+ break; -+ default: -+ DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__, -+ halt_status); -+ break; -+ } -+ return 1; -+ } -+ -+ if (dma_desc->status.b.a == 1) { -+ DWC_DEBUGPL(DBG_HCDV, "Active descriptor encountered on channel %d\n", hc->hc_num); -+ return 0; -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) { -+ if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { -+ urb->actual_length += n_bytes - remain; -+ if (remain || urb->actual_length == urb->length) { -+ /* -+ * For Control Data stage do not set urb->status=0 to prevent -+ * URB callback. Set it when Status phase done. See below. -+ */ -+ *xfer_done = 1; -+ } -+ -+ } -+ else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) { -+ urb->status = 0; -+ *xfer_done = 1; -+ } -+ /* No handling for SETUP stage */ -+ -+ } -+ else { -+ /* BULK and INTR */ -+ urb->actual_length += n_bytes - remain; -+ if (remain || urb->actual_length == urb->length) { -+ urb->status = 0; -+ *xfer_done = 1; -+ } -+ } -+ -+ return 0; -+} -+ -+static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_halt_status_e halt_status) -+{ -+ dwc_otg_hcd_urb_t *urb = NULL; -+ dwc_otg_qtd_t *qtd, *qtd_tmp; -+ dwc_otg_qh_t *qh; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ uint32_t n_bytes, n_desc, i; -+ uint8_t failed = 0, xfer_done; -+ -+ n_desc = 0; -+ -+ qh = hc->qh; -+ -+ -+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { -+ qtd->in_process = 0; -+ } -+ return; -+ } -+ -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { -+ -+ urb = qtd->urb; -+ -+ n_bytes = 0; -+ xfer_done = 0; -+ -+ for (i = 0; i < qtd->n_desc; i++) { -+ dma_desc = &qh->desc_list[n_desc]; -+ -+ n_bytes = qh->n_bytes[n_desc]; -+ -+ -+ failed = update_non_isoc_urb_state_ddma(hcd, hc, qtd, dma_desc, -+ halt_status, n_bytes, &xfer_done); -+ -+ if (failed || (xfer_done && (urb->status != -DWC_E_IN_PROGRESS))) { -+ -+ hcd->fops->complete(hcd, urb->priv, urb, urb->status); -+ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -+ -+ if (failed) -+ goto stop_scan; -+ } -+ else if (qh->ep_type == UE_CONTROL) { -+ if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) { -+ if (urb->length > 0) { -+ qtd->control_phase = DWC_OTG_CONTROL_DATA; -+ } else { -+ qtd->control_phase = DWC_OTG_CONTROL_STATUS; -+ } -+ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); -+ } -+ else if(qtd->control_phase == DWC_OTG_CONTROL_DATA) { -+ if (xfer_done) { -+ qtd->control_phase = DWC_OTG_CONTROL_STATUS; -+ DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); -+ } else if (i+1 == qtd->n_desc){ -+ /* -+ * Last descriptor for Control data stage which is -+ * not completed yet. -+ */ -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ } -+ } -+ } -+ -+ n_desc++; -+ } -+ -+ } -+ -+stop_scan: -+ -+ if (qh->ep_type != UE_CONTROL) { -+ /* -+ * Resetting the data toggle for bulk -+ * and interrupt endpoints in case of stall. See handle_hc_stall_intr() -+ */ -+ if (halt_status == DWC_OTG_HC_XFER_STALL) { -+ qh->data_toggle = DWC_OTG_HC_PID_DATA0; -+ } -+ else { -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ } -+ } -+ -+ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { -+ hcint_data_t hcint; -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ if (hcint.b.nyet) { -+ /* -+ * Got a NYET on the last transaction of the transfer. It -+ * means that the endpoint should be in the PING state at the -+ * beginning of the next transfer. -+ */ -+ qh->ping_state = 1; -+ clear_hc_int(hc_regs, nyet); -+ } -+ -+ } -+ -+} -+ -+/** -+ * This function is called from interrupt handlers. -+ * Scans the descriptor list, updates URB's status and -+ * calls completion routine for the URB if it's done. -+ * Releases the channel to be used by other transfers. -+ * In case of Isochronous endpoint the channel is not halted until -+ * the end of the session, i.e. QTD list is empty. -+ * If periodic channel released the FrameList is updated accordingly. -+ * -+ * Calls transaction selection routines to activate pending transfers. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param hc Host channel, the transfer is completed on. -+ * @param hc_regs Host channel registers. -+ * @param halt_status Reason the channel is being halted, -+ * or just XferComplete for isochronous transfer -+ */ -+void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t *hcd, -+ dwc_hc_t *hc, -+ dwc_otg_hc_regs_t *hc_regs, -+ dwc_otg_halt_status_e halt_status) -+{ -+ uint8_t continue_isoc_xfer = 0; -+ dwc_otg_transaction_type_e tr_type; -+ dwc_otg_qh_t *qh = hc->qh; -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ -+ complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); -+ -+ /* Release the channel if halted or session completed */ -+ if (halt_status != DWC_OTG_HC_XFER_COMPLETE || -+ DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -+ -+ /* Halt the channel if session completed */ -+ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { -+ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); -+ } -+ -+ release_channel_ddma(hcd, qh); -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ } -+ else { -+ /* Keep in assigned schedule to continue transfer */ -+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, -+ &qh->qh_list_entry); -+ continue_isoc_xfer = 1; -+ -+ } -+ /** @todo Consider the case when period exceeds FrameList size. -+ * Frame Rollover interrupt should be used. -+ */ -+ } -+ else { -+ /* Scan descriptor list to complete the URB(s), then release the channel */ -+ complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); -+ -+ release_channel_ddma(hcd, qh); -+ -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ -+ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -+ /* Add back to inactive non-periodic schedule on normal completion */ -+ dwc_otg_hcd_qh_add(hcd, qh); -+ } -+ -+ -+ } -+ tr_type = dwc_otg_hcd_select_transactions(hcd); -+ if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) { -+ if (continue_isoc_xfer) { -+ if (tr_type == DWC_OTG_TRANSACTION_NONE) { -+ tr_type = DWC_OTG_TRANSACTION_PERIODIC; -+ } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) { -+ tr_type = DWC_OTG_TRANSACTION_ALL; -+ } -+ } -+ dwc_otg_hcd_queue_transactions(hcd, tr_type); -+ } -+} -+ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -new file mode 100644 -index 0000000..d5a903b ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -@@ -0,0 +1,393 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $ -+ * $Revision: #6 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237474 $ -+ * -+ * 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_DEVICE_ONLY -+#ifndef __DWC_HCD_IF_H__ -+#define __DWC_HCD_IF_H__ -+ -+#include "dwc_otg_core_if.h" -+ -+/** @file -+ * This file defines DWC_OTG HCD Core API. -+ */ -+ -+struct dwc_otg_hcd; -+typedef struct dwc_otg_hcd dwc_otg_hcd_t; -+ -+struct dwc_otg_hcd_urb; -+typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t; -+ -+/** @name HCD Function Driver Callbacks */ -+/** @{ */ -+ -+/** This function is called whenever core switches to host mode. */ -+typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd); -+ -+/** This function is called when device has been disconnected */ -+typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd); -+ -+/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */ -+typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd, -+ void *urb_handle, -+ uint32_t * hub_addr, -+ uint32_t * port_addr); -+/** Via this function HCD core gets device speed */ -+typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd, -+ void *urb_handle); -+ -+/** This function is called when urb is completed */ -+typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd, -+ void *urb_handle, -+ dwc_otg_hcd_urb_t * dwc_otg_urb, -+ int32_t status); -+ -+/** Via this function HCD core gets b_hnp_enable parameter */ -+typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd); -+ -+struct dwc_otg_hcd_function_ops { -+ dwc_otg_hcd_start_cb_t start; -+ dwc_otg_hcd_disconnect_cb_t disconnect; -+ dwc_otg_hcd_hub_info_from_urb_cb_t hub_info; -+ dwc_otg_hcd_speed_from_urb_cb_t speed; -+ dwc_otg_hcd_complete_urb_cb_t complete; -+ dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable; -+}; -+/** @} */ -+ -+/** @name HCD Core API */ -+/** @{ */ -+/** This function allocates dwc_otg_hcd structure and returns pointer on it. */ -+extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void); -+ -+/** This function should be called to initiate HCD Core. -+ * -+ * @param hcd The HCD -+ * @param core_if The DWC_OTG Core -+ * -+ * Returns -DWC_E_NO_MEMORY if no enough memory. -+ * Returns 0 on success -+ */ -+extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if); -+ -+/** Frees HCD -+ * -+ * @param hcd The HCD -+ */ -+extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd); -+ -+/** This function should be called on every hardware interrupt. -+ * -+ * @param dwc_otg_hcd The HCD -+ * -+ * Returns non zero if interrupt is handled -+ * Return 0 if interrupt is not handled -+ */ -+extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); -+ -+/** -+ * Returns private data set by -+ * dwc_otg_hcd_set_priv_data function. -+ * -+ * @param hcd The HCD -+ */ -+extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd); -+ -+/** -+ * Set private data. -+ * -+ * @param hcd The HCD -+ * @param priv_data pointer to be stored in private data -+ */ -+extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data); -+ -+/** -+ * This function initializes the HCD Core. -+ * -+ * @param hcd The HCD -+ * @param fops The Function Driver Operations data structure containing pointers to all callbacks. -+ * -+ * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode. -+ * Returns 0 on success -+ */ -+extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, -+ struct dwc_otg_hcd_function_ops *fops); -+ -+/** -+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are -+ * stopped. -+ * -+ * @param hcd The HCD -+ */ -+extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd); -+ -+/** -+ * Handles hub class-specific requests. -+ * -+ * @param dwc_otg_hcd The HCD -+ * @param typeReq Request Type -+ * @param wValue wValue from control request -+ * @param wIndex wIndex from control request -+ * @param buf data buffer -+ * @param wLength data buffer length -+ * -+ * Returns -DWC_E_INVALID if invalid argument is passed -+ * Returns 0 on success -+ */ -+extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, -+ uint16_t typeReq, uint16_t wValue, -+ uint16_t wIndex, uint8_t * buf, -+ uint16_t wLength); -+ -+/** -+ * Returns otg port number. -+ * -+ * @param hcd The HCD -+ */ -+extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd); -+ -+/** -+ * Returns 1 if currently core is acting as B host, and 0 otherwise. -+ * -+ * @param hcd The HCD -+ */ -+extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd); -+ -+/** -+ * Returns current frame number. -+ * -+ * @param hcd The HCD -+ */ -+extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd); -+ -+/** -+ * Dumps hcd state. -+ * -+ * @param hcd The HCD -+ */ -+extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd); -+ -+/** -+ * Dump the average frame remaining at SOF. This can be used to -+ * determine average interrupt latency. Frame remaining is also shown for -+ * start transfer and two additional sample points. -+ * Currently this function is not implemented. -+ * -+ * @param hcd The HCD -+ */ -+extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd); -+ -+/** -+ * Sends LPM transaction to the local device. -+ * -+ * @param hcd The HCD -+ * @param devaddr Device Address -+ * @param hird Host initiated resume duration -+ * @param bRemoteWake Value of bRemoteWake field in LPM transaction -+ * -+ * Returns negative value if sending LPM transaction was not succeeded. -+ * Returns 0 on success. -+ */ -+extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, -+ uint8_t hird, uint8_t bRemoteWake); -+ -+/* URB interface */ -+ -+/** -+ * Allocates memory for dwc_otg_hcd_urb structure. -+ * Allocated memory should be freed by call dwc_free function. -+ * -+ * @param hcd The HCD -+ * @param iso_desc_count Count of ISOC descriptors -+ * @param atomic_alloc Specefies whether to perform atomic allocation. -+ */ -+extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, -+ int iso_desc_count, -+ int atomic_alloc); -+ -+/** -+ * Set pipe information in URB. -+ * -+ * @param hcd_urb DWC_OTG URB -+ * @param devaddr Device Address -+ * @param ep_num Endpoint Number -+ * @param ep_type Endpoint Type -+ * @param ep_dir Endpoint Direction -+ * @param mps Max Packet Size -+ */ -+extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb, -+ uint8_t devaddr, uint8_t ep_num, -+ uint8_t ep_type, uint8_t ep_dir, -+ uint16_t mps); -+ -+/* Transfer flags */ -+#define URB_GIVEBACK_ASAP 0x1 -+#define URB_SEND_ZERO_PACKET 0x2 -+ -+/** -+ * Sets dwc_otg_hcd_urb parameters. -+ * -+ * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function. -+ * @param urb_handle Unique handle for request, this will be passed back -+ * to function driver in completion callback. -+ * @param buf The buffer for the data -+ * @param dma The DMA buffer for the data -+ * @param buflen Transfer length -+ * @param sp Buffer for setup data -+ * @param sp_dma DMA address of setup data buffer -+ * @param flags Transfer flags -+ * @param interval Polling interval for interrupt or isochronous transfers. -+ */ -+extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb, -+ void *urb_handle, void *buf, -+ dwc_dma_t dma, uint32_t buflen, void *sp, -+ dwc_dma_t sp_dma, uint32_t flags, -+ uint16_t interval); -+ -+/** Gets status from dwc_otg_hcd_urb -+ * -+ * @param dwc_otg_urb DWC_OTG URB -+ */ -+extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb); -+ -+/** Gets actual length from dwc_otg_hcd_urb -+ * -+ * @param dwc_otg_urb DWC_OTG URB -+ */ -+extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * -+ dwc_otg_urb); -+ -+/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs -+ * -+ * @param dwc_otg_urb DWC_OTG URB -+ */ -+extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * -+ dwc_otg_urb); -+ -+/** Set ISOC descriptor offset and length -+ * -+ * @param dwc_otg_urb DWC_OTG URB -+ * @param desc_num ISOC descriptor number -+ * @param offset Offset from beginig of buffer. -+ * @param length Transaction length -+ */ -+extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb, -+ int desc_num, uint32_t offset, -+ uint32_t length); -+ -+/** Get status of ISOC descriptor, specified by desc_num -+ * -+ * @param dwc_otg_urb DWC_OTG URB -+ * @param desc_num ISOC descriptor number -+ */ -+extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * -+ dwc_otg_urb, int desc_num); -+ -+/** Get actual length of ISOC descriptor, specified by desc_num -+ * -+ * @param dwc_otg_urb DWC_OTG URB -+ * @param desc_num ISOC descriptor number -+ */ -+extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * -+ dwc_otg_urb, -+ int desc_num); -+ -+/** Queue URB. After transfer is completes, the complete callback will be called with the URB status -+ * -+ * @param dwc_otg_hcd The HCD -+ * @param dwc_otg_urb DWC_OTG URB -+ * @param ep_handle Out parameter for returning endpoint handle -+ * -+ * Returns -DWC_E_NO_DEVICE if no device is connected. -+ * Returns -DWC_E_NO_MEMORY if there is no enough memory. -+ * Returns 0 on success. -+ */ -+extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd, -+ dwc_otg_hcd_urb_t * dwc_otg_urb, -+ void **ep_handle); -+ -+/** De-queue the specified URB -+ * -+ * @param dwc_otg_hcd The HCD -+ * @param dwc_otg_urb DWC_OTG URB -+ */ -+extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd, -+ dwc_otg_hcd_urb_t * dwc_otg_urb); -+ -+/** Frees resources in the DWC_otg controller related to a given endpoint. -+ * Any URBs for the endpoint must already be dequeued. -+ * -+ * @param hcd The HCD -+ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function -+ * @param retry Number of retries if there are queued transfers. -+ * -+ * Returns -DWC_E_INVALID if invalid arguments are passed. -+ * Returns 0 on success -+ */ -+extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, -+ int retry); -+ -+/** Returns 1 if status of specified port is changed and 0 otherwise. -+ * -+ * @param hcd The HCD -+ * @param port Port number -+ */ -+extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port); -+ -+/** Call this function to check if bandwidth was allocated for specified endpoint. -+ * Only for ISOC and INTERRUPT endpoints. -+ * -+ * @param hcd The HCD -+ * @param ep_handle Endpoint handle -+ */ -+extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, -+ void *ep_handle); -+ -+/** Call this function to check if bandwidth was freed for specified endpoint. -+ * -+ * @param hcd The HCD -+ * @param ep_handle Endpoint handle -+ */ -+extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle); -+ -+/** Returns bandwidth allocated for specified endpoint in microseconds. -+ * Only for ISOC and INTERRUPT endpoints. -+ * -+ * @param hcd The HCD -+ * @param ep_handle Endpoint handle -+ */ -+extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, -+ void *ep_handle); -+ -+/** @} */ -+ -+#endif /* __DWC_HCD_IF_H__ */ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -new file mode 100644 -index 0000000..6e4bc60 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -@@ -0,0 +1,2065 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ -+ * $Revision: #77 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237475 $ -+ * -+ * 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_DEVICE_ONLY -+ -+#include "dwc_otg_hcd.h" -+#include "dwc_otg_regs.h" -+ -+/** @file -+ * This file contains the implementation of the HCD Interrupt handlers. -+ */ -+ -+/** This function handles interrupts for the HCD. */ -+int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ int retval = 0; -+ -+ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; -+ gintsts_data_t gintsts; -+#ifdef DEBUG -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ -+ //GRAYG: debugging -+ if (NULL == global_regs) { -+ DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p " -+ "core_if=%p\n", -+ dwc_otg_hcd, global_regs); -+ return retval; -+ } -+#endif -+ -+ /* Check if HOST Mode */ -+ if (dwc_otg_is_host_mode(core_if)) { -+ gintsts.d32 = dwc_otg_read_core_intr(core_if); -+ if (!gintsts.d32) { -+ return 0; -+ } -+#ifdef DEBUG -+ /* Don't print debug message in the interrupt handler on SOF */ -+#ifndef DEBUG_SOF -+ if (gintsts.d32 != DWC_SOF_INTR_MASK) -+#endif -+ DWC_DEBUGPL(DBG_HCD, "\n"); -+#endif -+ -+#ifdef DEBUG -+#ifndef DEBUG_SOF -+ if (gintsts.d32 != DWC_SOF_INTR_MASK) -+#endif -+ DWC_DEBUGPL(DBG_HCD, -+ "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n", -+ gintsts.d32, core_if); -+#endif -+ -+ if (gintsts.b.sofintr) { -+ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); -+ } -+ if (gintsts.b.rxstsqlvl) { -+ retval |= -+ dwc_otg_hcd_handle_rx_status_q_level_intr -+ (dwc_otg_hcd); -+ } -+ if (gintsts.b.nptxfempty) { -+ retval |= -+ dwc_otg_hcd_handle_np_tx_fifo_empty_intr -+ (dwc_otg_hcd); -+ } -+ if (gintsts.b.i2cintr) { -+ /** @todo Implement i2cintr handler. */ -+ } -+ if (gintsts.b.portintr) { -+ retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); -+ } -+ if (gintsts.b.hcintr) { -+ retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); -+ } -+ if (gintsts.b.ptxfempty) { -+ retval |= -+ dwc_otg_hcd_handle_perio_tx_fifo_empty_intr -+ (dwc_otg_hcd); -+ } -+#ifdef DEBUG -+#ifndef DEBUG_SOF -+ if (gintsts.d32 != DWC_SOF_INTR_MASK) -+#endif -+ { -+ DWC_DEBUGPL(DBG_HCD, -+ "DWC OTG HCD Finished Servicing Interrupts\n"); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n", -+ dwc_read_reg32(&global_regs->gintsts)); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n", -+ dwc_read_reg32(&global_regs->gintmsk)); -+ } -+#endif -+ -+#ifdef DEBUG -+#ifndef DEBUG_SOF -+ if (gintsts.d32 != DWC_SOF_INTR_MASK) -+#endif -+ DWC_DEBUGPL(DBG_HCD, "\n"); -+#endif -+ -+ } -+ -+ return retval; -+} -+ -+#ifdef DWC_TRACK_MISSED_SOFS -+#warning Compiling code to track missed SOFs -+#define FRAME_NUM_ARRAY_SIZE 1000 -+/** -+ * This function is for debug only. -+ */ -+static inline void track_missed_sofs(uint16_t curr_frame_number) -+{ -+ static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE]; -+ static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE]; -+ static int frame_num_idx = 0; -+ static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM; -+ static int dumped_frame_num_array = 0; -+ -+ if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) { -+ if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) != -+ curr_frame_number) { -+ frame_num_array[frame_num_idx] = curr_frame_number; -+ last_frame_num_array[frame_num_idx++] = last_frame_num; -+ } -+ } else if (!dumped_frame_num_array) { -+ int i; -+ DWC_PRINTF("Frame Last Frame\n"); -+ DWC_PRINTF("----- ----------\n"); -+ for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) { -+ DWC_PRINTF("0x%04x 0x%04x\n", -+ frame_num_array[i], last_frame_num_array[i]); -+ } -+ dumped_frame_num_array = 1; -+ } -+ last_frame_num = curr_frame_number; -+} -+#endif -+ -+/** -+ * Handles the start-of-frame interrupt in host mode. Non-periodic -+ * transactions may be queued to the DWC_otg controller for the current -+ * (micro)frame. Periodic transactions may be queued to the controller for the -+ * next (micro)frame. -+ */ -+int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) -+{ -+ hfnum_data_t hfnum; -+ dwc_list_link_t *qh_entry; -+ dwc_otg_qh_t *qh; -+ dwc_otg_transaction_type_e tr_type; -+ gintsts_data_t gintsts = {.d32 = 0 }; -+ -+ hfnum.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum); -+ -+#ifdef DEBUG_SOF -+ DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); -+#endif -+ hcd->frame_number = hfnum.b.frnum; -+ -+#ifdef DEBUG -+ hcd->frrem_accum += hfnum.b.frrem; -+ hcd->frrem_samples++; -+#endif -+ -+#ifdef DWC_TRACK_MISSED_SOFS -+ track_missed_sofs(hcd->frame_number); -+#endif -+ /* Determine whether any periodic QHs should be executed. */ -+ qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive); -+ while (qh_entry != &hcd->periodic_sched_inactive) { -+ qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry); -+ qh_entry = qh_entry->next; -+ if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { -+ /* -+ * Move QH to the ready list to be executed next -+ * (micro)frame. -+ */ -+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, -+ &qh->qh_list_entry); -+ } -+ } -+ tr_type = dwc_otg_hcd_select_transactions(hcd); -+ if (tr_type != DWC_OTG_TRANSACTION_NONE) { -+ dwc_otg_hcd_queue_transactions(hcd, tr_type); -+ } -+ -+ /* Clear interrupt */ -+ gintsts.b.sofintr = 1; -+ dwc_write_reg32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at -+ * least one packet in the Rx FIFO. The packets are moved from the FIFO to -+ * memory if the DWC_otg controller is operating in Slave mode. */ -+int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ host_grxsts_data_t grxsts; -+ dwc_hc_t *hc = NULL; -+ -+ DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); -+ -+ grxsts.d32 = -+ dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); -+ -+ hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; -+ -+ /* Packet Status */ -+ DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); -+ DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt); -+ DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid, -+ hc->data_pid_start); -+ DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts); -+ -+ switch (grxsts.b.pktsts) { -+ case DWC_GRXSTS_PKTSTS_IN: -+ /* Read the data into the host buffer. */ -+ if (grxsts.b.bcnt > 0) { -+ dwc_otg_read_packet(dwc_otg_hcd->core_if, -+ hc->xfer_buff, grxsts.b.bcnt); -+ -+ /* Update the HC fields for the next packet received. */ -+ hc->xfer_count += grxsts.b.bcnt; -+ hc->xfer_buff += grxsts.b.bcnt; -+ } -+ -+ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: -+ case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: -+ case DWC_GRXSTS_PKTSTS_CH_HALTED: -+ /* Handled in interrupt, just ignore data */ -+ break; -+ default: -+ DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n", -+ grxsts.b.pktsts); -+ break; -+ } -+ -+ return 1; -+} -+ -+/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More -+ * data packets may be written to the FIFO for OUT transfers. More requests -+ * may be written to the non-periodic request queue for IN transfers. This -+ * interrupt is enabled only in Slave mode. */ -+int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n"); -+ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, -+ DWC_OTG_TRANSACTION_NON_PERIODIC); -+ return 1; -+} -+ -+/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data -+ * packets may be written to the FIFO for OUT transfers. More requests may be -+ * written to the periodic request queue for IN transfers. This interrupt is -+ * enabled only in Slave mode. */ -+int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); -+ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, -+ DWC_OTG_TRANSACTION_PERIODIC); -+ return 1; -+} -+ -+/** There are multiple conditions that can cause a port interrupt. This function -+ * determines which interrupt conditions have occurred and handles them -+ * appropriately. */ -+int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ int retval = 0; -+ hprt0_data_t hprt0; -+ hprt0_data_t hprt0_modify; -+ -+ hprt0.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); -+ hprt0_modify.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); -+ -+ /* Clear appropriate bits in HPRT0 to clear the interrupt bit in -+ * GINTSTS */ -+ -+ hprt0_modify.b.prtena = 0; -+ hprt0_modify.b.prtconndet = 0; -+ hprt0_modify.b.prtenchng = 0; -+ hprt0_modify.b.prtovrcurrchng = 0; -+ -+ /* Port Connect Detected -+ * Set flag and clear if detected */ -+ if (hprt0.b.prtconndet) { -+ DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " -+ "Port Connect Detected--\n", hprt0.d32); -+ dwc_otg_hcd->flags.b.port_connect_status_change = 1; -+ dwc_otg_hcd->flags.b.port_connect_status = 1; -+ hprt0_modify.b.prtconndet = 1; -+ -+ /* B-Device has connected, Delete the connection timer. */ -+ DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer); -+ -+ /* The Hub driver asserts a reset when it sees port connect -+ * status change flag */ -+ retval |= 1; -+ } -+ -+ /* Port Enable Changed -+ * Clear if detected - Set internal flag if disabled */ -+ if (hprt0.b.prtenchng) { -+ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " -+ "Port Enable Changed--\n", hprt0.d32); -+ hprt0_modify.b.prtenchng = 1; -+ if (hprt0.b.prtena == 1) { -+ int do_reset = 0; -+ dwc_otg_core_params_t *params = -+ dwc_otg_hcd->core_if->core_params; -+ dwc_otg_core_global_regs_t *global_regs = -+ dwc_otg_hcd->core_if->core_global_regs; -+ dwc_otg_host_if_t *host_if = -+ dwc_otg_hcd->core_if->host_if; -+ -+ /* Check if we need to adjust the PHY clock speed for -+ * low power and adjust it */ -+ if (params->host_support_fs_ls_low_power) { -+ gusbcfg_data_t usbcfg; -+ -+ usbcfg.d32 = -+ dwc_read_reg32(&global_regs->gusbcfg); -+ -+ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED -+ || hprt0.b.prtspd == -+ DWC_HPRT0_PRTSPD_FULL_SPEED) { -+ /* -+ * Low power -+ */ -+ hcfg_data_t hcfg; -+ if (usbcfg.b.phylpwrclksel == 0) { -+ /* Set PHY low power clock select for FS/LS devices */ -+ usbcfg.b.phylpwrclksel = 1; -+ dwc_write_reg32(&global_regs-> -+ gusbcfg, -+ usbcfg.d32); -+ do_reset = 1; -+ } -+ -+ hcfg.d32 = -+ dwc_read_reg32(&host_if-> -+ host_global_regs->hcfg); -+ -+ if (hprt0.b.prtspd == -+ DWC_HPRT0_PRTSPD_LOW_SPEED -+ && params-> -+ host_ls_low_power_phy_clk == -+ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) -+ { -+ /* 6 MHZ */ -+ DWC_DEBUGPL(DBG_CIL, -+ "FS_PHY programming HCFG to 6 MHz (Low Power)\n"); -+ if (hcfg.b.fslspclksel != -+ DWC_HCFG_6_MHZ) { -+ hcfg.b.fslspclksel = -+ DWC_HCFG_6_MHZ; -+ dwc_write_reg32 -+ (&host_if-> -+ host_global_regs-> -+ hcfg, hcfg.d32); -+ do_reset = 1; -+ } -+ } else { -+ /* 48 MHZ */ -+ DWC_DEBUGPL(DBG_CIL, -+ "FS_PHY programming HCFG to 48 MHz ()\n"); -+ if (hcfg.b.fslspclksel != -+ DWC_HCFG_48_MHZ) { -+ hcfg.b.fslspclksel = -+ DWC_HCFG_48_MHZ; -+ dwc_write_reg32 -+ (&host_if-> -+ host_global_regs-> -+ hcfg, hcfg.d32); -+ do_reset = 1; -+ } -+ } -+ } else { -+ /* -+ * Not low power -+ */ -+ if (usbcfg.b.phylpwrclksel == 1) { -+ usbcfg.b.phylpwrclksel = 0; -+ dwc_write_reg32(&global_regs-> -+ gusbcfg, -+ usbcfg.d32); -+ do_reset = 1; -+ } -+ } -+ -+ if (do_reset) { -+ DWC_TASK_SCHEDULE(dwc_otg_hcd-> -+ reset_tasklet); -+ } -+ } -+ -+ if (!do_reset) { -+ /* Port has been enabled set the reset change flag */ -+ dwc_otg_hcd->flags.b.port_reset_change = 1; -+ } -+ } else { -+ dwc_otg_hcd->flags.b.port_enable_change = 1; -+ } -+ retval |= 1; -+ } -+ -+ /** Overcurrent Change Interrupt */ -+ if (hprt0.b.prtovrcurrchng) { -+ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " -+ "Port Overcurrent Changed--\n", hprt0.d32); -+ dwc_otg_hcd->flags.b.port_over_current_change = 1; -+ hprt0_modify.b.prtovrcurrchng = 1; -+ retval |= 1; -+ } -+ -+ /* Clear Port Interrupts */ -+ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); -+ -+ return retval; -+} -+ -+/** This interrupt indicates that one or more host channels has a pending -+ * interrupt. There are multiple conditions that can cause each host channel -+ * interrupt. This function determines which conditions have occurred for each -+ * host channel interrupt and handles them appropriately. */ -+int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ int i; -+ int retval = 0; -+ haint_data_t haint; -+ -+ /* Clear appropriate bits in HCINTn to clear the interrupt bit in -+ * GINTSTS */ -+ -+ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); -+ -+ for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { -+ if (haint.b2.chint & (1 << i)) { -+ retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); -+ } -+ } -+ -+ return retval; -+} -+ -+ -+ -+/** -+ * Gets the actual length of a transfer after the transfer halts. _halt_status -+ * holds the reason for the halt. -+ * -+ * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE, -+ * *short_read is set to 1 upon return if less than the requested -+ * number of bytes were transferred. Otherwise, *short_read is set to 0 upon -+ * return. short_read may also be NULL on entry, in which case it remains -+ * unchanged. -+ */ -+static uint32_t get_actual_xfer_length(dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_halt_status_e halt_status, -+ int *short_read) -+{ -+ hctsiz_data_t hctsiz; -+ uint32_t length; -+ -+ if (short_read != NULL) { -+ *short_read = 0; -+ } -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ -+ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { -+ if (hc->ep_is_in) { -+ length = hc->xfer_len - hctsiz.b.xfersize; -+ if (short_read != NULL) { -+ *short_read = (hctsiz.b.xfersize != 0); -+ } -+ } else if (hc->qh->do_split) { -+ length = qtd->ssplit_out_xfer_count; -+ } else { -+ length = hc->xfer_len; -+ } -+ } else { -+ /* -+ * Must use the hctsiz.pktcnt field to determine how much data -+ * has been transferred. This field reflects the number of -+ * packets that have been transferred via the USB. This is -+ * always an integral number of packets if the transfer was -+ * halted before its normal completion. (Can't use the -+ * hctsiz.xfersize field because that reflects the number of -+ * bytes transferred via the AHB, not the USB). -+ */ -+ length = -+ (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet; -+ } -+ -+ return length; -+} -+ -+/** -+ * Updates the state of the URB after a Transfer Complete interrupt on the -+ * host channel. Updates the actual_length field of the URB based on the -+ * number of bytes transferred via the host channel. Sets the URB status -+ * if the data transfer is finished. -+ * -+ * @return 1 if the data transfer specified by the URB is completely finished, -+ * 0 otherwise. -+ */ -+static int update_urb_state_xfer_comp(dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_hcd_urb_t * urb, -+ dwc_otg_qtd_t * qtd) -+{ -+ int xfer_done = 0; -+ int short_read = 0; -+ -+ int xfer_length; -+ -+ xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_COMPLETE, -+ &short_read); -+ -+ -+ /* non DWORD-aligned buffer case handling. */ -+ if (hc->align_buff && xfer_length && hc->ep_is_in) { -+ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, xfer_length); -+ } -+ -+ urb->actual_length += xfer_length; -+ -+ if(xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) && -+ (urb->flags & URB_SEND_ZERO_PACKET) && (urb->actual_length == urb->length) && -+ !(urb->length % hc->max_packet)) { -+ xfer_done = 0; -+ } else if (short_read || urb->actual_length == urb->length) { -+ xfer_done = 1; -+ urb->status = 0; -+ } -+ -+#ifdef DEBUG -+ { -+ hctsiz_data_t hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", -+ __func__, (hc->ep_is_in ? "IN" : "OUT"), -+ hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len); -+ DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", -+ hctsiz.b.xfersize); -+ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", -+ urb->length); -+ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", -+ urb->actual_length); -+ DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n", -+ short_read, xfer_done); -+ } -+#endif -+ -+ return xfer_done; -+} -+ -+/* -+ * Save the starting data toggle for the next transfer. The data toggle is -+ * saved in the QH for non-control transfers and it's saved in the QTD for -+ * control transfers. -+ */ -+void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd) -+{ -+ hctsiz_data_t hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ -+ if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { -+ dwc_otg_qh_t *qh = hc->qh; -+ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { -+ qh->data_toggle = DWC_OTG_HC_PID_DATA0; -+ } else { -+ qh->data_toggle = DWC_OTG_HC_PID_DATA1; -+ } -+ } else { -+ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { -+ qtd->data_toggle = DWC_OTG_HC_PID_DATA0; -+ } else { -+ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; -+ } -+ } -+} -+ -+/** -+ * Updates the state of an Isochronous URB when the transfer is stopped for -+ * any reason. The fields of the current entry in the frame descriptor array -+ * are set based on the transfer state and the input _halt_status. Completes -+ * the Isochronous URB if all the URB frames have been completed. -+ * -+ * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be -+ * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE. -+ */ -+static dwc_otg_halt_status_e -+update_isoc_urb_state(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) -+{ -+ dwc_otg_hcd_urb_t *urb = qtd->urb; -+ dwc_otg_halt_status_e ret_val = halt_status; -+ struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ -+ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; -+ switch (halt_status) { -+ case DWC_OTG_HC_XFER_COMPLETE: -+ frame_desc->status = 0; -+ frame_desc->actual_length = -+ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); -+ -+ /* non DWORD-aligned buffer case handling. */ -+ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { -+ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, -+ hc->qh->dw_align_buf, frame_desc->actual_length); -+ } -+ -+ break; -+ case DWC_OTG_HC_XFER_FRAME_OVERRUN: -+ urb->error_count++; -+ if (hc->ep_is_in) { -+ frame_desc->status = -DWC_E_NO_STREAM_RES; -+ } else { -+ frame_desc->status = -DWC_E_COMMUNICATION; -+ } -+ frame_desc->actual_length = 0; -+ break; -+ case DWC_OTG_HC_XFER_BABBLE_ERR: -+ urb->error_count++; -+ frame_desc->status = -DWC_E_OVERFLOW; -+ /* Don't need to update actual_length in this case. */ -+ break; -+ case DWC_OTG_HC_XFER_XACT_ERR: -+ urb->error_count++; -+ frame_desc->status = -DWC_E_PROTOCOL; -+ frame_desc->actual_length = -+ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); -+ -+ /* non DWORD-aligned buffer case handling. */ -+ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { -+ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, -+ hc->qh->dw_align_buf, frame_desc->actual_length); -+ } -+ /* Skip whole frame */ -+ if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && -+ hc->ep_is_in && hcd->core_if->dma_enable) { -+ qtd->complete_split = 0; -+ qtd->isoc_split_offset = 0; -+ } -+ -+ break; -+ default: -+ DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status); -+ break; -+ } -+ if (++qtd->isoc_frame_index == urb->packet_count) { -+ /* -+ * urb->status is not used for isoc transfers. -+ * The individual frame_desc statuses are used instead. -+ */ -+ hcd->fops->complete(hcd, urb->priv, urb, 0); -+ ret_val = DWC_OTG_HC_XFER_URB_COMPLETE; -+ } else { -+ ret_val = DWC_OTG_HC_XFER_COMPLETE; -+ } -+ return ret_val; -+} -+ -+/** -+ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic -+ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are -+ * still linked to the QH, the QH is added to the end of the inactive -+ * non-periodic schedule. For periodic QHs, removes the QH from the periodic -+ * schedule if no more QTDs are linked to the QH. -+ */ -+static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd) -+{ -+ int continue_split = 0; -+ dwc_otg_qtd_t *qtd; -+ -+ DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); -+ -+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -+ -+ if (qtd->complete_split) { -+ continue_split = 1; -+ } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID || -+ qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) { -+ continue_split = 1; -+ } -+ -+ if (free_qtd) { -+ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -+ continue_split = 0; -+ } -+ -+ qh->channel = NULL; -+ dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split); -+} -+ -+/** -+ * Releases a host channel for use by other transfers. Attempts to select and -+ * queue more transactions since at least one host channel is available. -+ * -+ * @param hcd The HCD state structure. -+ * @param hc The host channel to release. -+ * @param qtd The QTD associated with the host channel. This QTD may be freed -+ * if the transfer is complete or an error has occurred. -+ * @param halt_status Reason the channel is being released. This status -+ * determines the actions taken by this function. -+ */ -+static void release_channel(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_halt_status_e halt_status) -+{ -+ dwc_otg_transaction_type_e tr_type; -+ int free_qtd; -+ -+ DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", -+ __func__, hc->hc_num, halt_status, hc->xfer_len); -+ -+#ifdef HW2937_WORKAROUND -+ if (hcd->hw2937_assigned_channels & (1<hc_num)) -+ { -+ if ((hcd->hw2937_assigned_channels &= ~(1<hc_num)) == 0) -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IDLE; -+ DWC_DEBUGPL(DBG_HW2937, " release %d, hw2937_ac -> %x\n", hc->hc_num, hcd->hw2937_assigned_channels); -+ } -+ else -+ { -+ DWC_DEBUGPL(DBG_ANY, " Unexpected release %d (hw2937_ac = %x)\n", hc->hc_num, hcd->hw2937_assigned_channels); -+ } -+#endif -+ -+ switch (halt_status) { -+ case DWC_OTG_HC_XFER_URB_COMPLETE: -+ free_qtd = 1; -+ break; -+ case DWC_OTG_HC_XFER_AHB_ERR: -+ case DWC_OTG_HC_XFER_STALL: -+ case DWC_OTG_HC_XFER_BABBLE_ERR: -+ free_qtd = 1; -+ break; -+ case DWC_OTG_HC_XFER_XACT_ERR: -+ if (qtd->error_count >= 3) { -+ DWC_DEBUGPL(DBG_HCDV, -+ " Complete URB with transaction error\n"); -+ free_qtd = 1; -+ qtd->urb->status = -DWC_E_PROTOCOL; -+ hcd->fops->complete(hcd, qtd->urb->priv, -+ qtd->urb, -DWC_E_PROTOCOL); -+ } else { -+ free_qtd = 0; -+ } -+ break; -+ case DWC_OTG_HC_XFER_URB_DEQUEUE: -+ /* -+ * The QTD has already been removed and the QH has been -+ * deactivated. Don't want to do anything except release the -+ * host channel and try to queue more transfers. -+ */ -+ goto cleanup; -+ case DWC_OTG_HC_XFER_NO_HALT_STATUS: -+ free_qtd = 0; -+ break; -+ default: -+ free_qtd = 0; -+ break; -+ } -+ -+ deactivate_qh(hcd, hc->qh, free_qtd); -+ -+ cleanup: -+ /* -+ * Release the host channel for use by other transfers. The cleanup -+ * function clears the channel interrupt enables and conditions, so -+ * there's no need to clear the Channel Halted interrupt separately. -+ */ -+ dwc_otg_hc_cleanup(hcd->core_if, hc); -+ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); -+ -+ switch (hc->ep_type) { -+ case DWC_OTG_EP_TYPE_CONTROL: -+ case DWC_OTG_EP_TYPE_BULK: -+ hcd->non_periodic_channels--; -+ break; -+ -+ default: -+ /* -+ * Don't release reservations for periodic channels here. -+ * That's done when a periodic transfer is descheduled (i.e. -+ * when the QH is removed from the periodic schedule). -+ */ -+ break; -+ } -+ -+ /* Try to queue more transfers now that there's a free channel. */ -+ tr_type = dwc_otg_hcd_select_transactions(hcd); -+ if (tr_type != DWC_OTG_TRANSACTION_NONE) { -+ dwc_otg_hcd_queue_transactions(hcd, tr_type); -+ } -+} -+ -+ -+/** -+ * Halts a host channel. If the channel cannot be halted immediately because -+ * the request queue is full, this function ensures that the FIFO empty -+ * interrupt for the appropriate queue is enabled so that the halt request can -+ * be queued when there is space in the request queue. -+ * -+ * This function may also be called in DMA mode. In that case, the channel is -+ * simply released since the core always halts the channel automatically in -+ * DMA mode. -+ */ -+static void halt_channel(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) -+{ -+ if (hcd->core_if->dma_enable) { -+ release_channel(hcd, hc, qtd, halt_status); -+ return; -+ } -+ -+ /* Slave mode processing... */ -+ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); -+ -+ if (hc->halt_on_queue) { -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ dwc_otg_core_global_regs_t *global_regs; -+ global_regs = hcd->core_if->core_global_regs; -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || -+ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { -+ /* -+ * Make sure the Non-periodic Tx FIFO empty interrupt -+ * is enabled so that the non-periodic schedule will -+ * be processed. -+ */ -+ gintmsk.b.nptxfempty = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); -+ } else { -+ /* -+ * Move the QH from the periodic queued schedule to -+ * the periodic assigned schedule. This allows the -+ * halt to be queued when the periodic schedule is -+ * processed. -+ */ -+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, -+ &hc->qh->qh_list_entry); -+ -+ /* -+ * Make sure the Periodic Tx FIFO Empty interrupt is -+ * enabled so that the periodic schedule will be -+ * processed. -+ */ -+ gintmsk.b.ptxfempty = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); -+ } -+ } -+} -+ -+/** -+ * Performs common cleanup for non-periodic transfers after a Transfer -+ * Complete interrupt. This function should be called after any endpoint type -+ * specific handling is finished to release the host channel. -+ */ -+static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_halt_status_e halt_status) -+{ -+ hcint_data_t hcint; -+ -+ qtd->error_count = 0; -+ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ if (hcint.b.nyet) { -+ /* -+ * Got a NYET on the last transaction of the transfer. This -+ * means that the endpoint should be in the PING state at the -+ * beginning of the next transfer. -+ */ -+ hc->qh->ping_state = 1; -+ clear_hc_int(hc_regs, nyet); -+ } -+ -+ /* -+ * Always halt and release the host channel to make it available for -+ * more transfers. There may still be more phases for a control -+ * transfer or more data packets for a bulk transfer at this point, -+ * but the host channel is still halted. A channel will be reassigned -+ * to the transfer when the non-periodic schedule is processed after -+ * the channel is released. This allows transactions to be queued -+ * properly via dwc_otg_hcd_queue_transactions, which also enables the -+ * Tx FIFO Empty interrupt if necessary. -+ */ -+ if (hc->ep_is_in) { -+ /* -+ * IN transfers in Slave mode require an explicit disable to -+ * halt the channel. (In DMA mode, this call simply releases -+ * the channel.) -+ */ -+ halt_channel(hcd, hc, qtd, halt_status); -+ } else { -+ /* -+ * The channel is automatically disabled by the core for OUT -+ * transfers in Slave mode. -+ */ -+ release_channel(hcd, hc, qtd, halt_status); -+ } -+} -+ -+/** -+ * Performs common cleanup for periodic transfers after a Transfer Complete -+ * interrupt. This function should be called after any endpoint type specific -+ * handling is finished to release the host channel. -+ */ -+static void complete_periodic_xfer(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_halt_status_e halt_status) -+{ -+ hctsiz_data_t hctsiz; -+ qtd->error_count = 0; -+ -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { -+ /* Core halts channel in these cases. */ -+ release_channel(hcd, hc, qtd, halt_status); -+ } else { -+ /* Flush any outstanding requests from the Tx queue. */ -+ halt_channel(hcd, hc, qtd, halt_status); -+ } -+} -+ -+static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ uint32_t len; -+ struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; -+ -+ len = get_actual_xfer_length(hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_COMPLETE, -+ NULL); -+ -+ if (!len) { -+ qtd->complete_split = 0; -+ qtd->isoc_split_offset = 0; -+ return 0; -+ } -+ frame_desc->actual_length += len; -+ -+ if (hc->align_buff && len) -+ dwc_memcpy(qtd->urb->buf + frame_desc->offset + qtd->isoc_split_offset, -+ hc->qh->dw_align_buf, -+ len); -+ qtd->isoc_split_offset += len; -+ -+ if (frame_desc->length == frame_desc->actual_length) { -+ frame_desc->status = 0; -+ qtd->isoc_frame_index++; -+ qtd->complete_split = 0; -+ qtd->isoc_split_offset = 0; -+ } -+ -+ if (qtd->isoc_frame_index == qtd->urb->packet_count) { -+ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); -+ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); -+ } else { -+ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); -+ } -+ -+ return 1; /* Indicates that channel released */ -+} -+/** -+ * Handles a host channel Transfer Complete interrupt. This handler may be -+ * called in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ int urb_xfer_done; -+ dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ dwc_otg_hcd_urb_t *urb = qtd->urb; -+ int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); -+ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Transfer Complete--\n", hc->hc_num); -+ -+ if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status); -+ if (pipe_type == UE_ISOCHRONOUS) { -+ /* Do not disable the interrupt, just clear it */ -+ clear_hc_int(hc_regs, xfercomp); -+ return 1; -+ } -+ goto handle_xfercomp_done; -+ } -+ -+ /* -+ * Handle xfer complete on CSPLIT. -+ */ -+ -+ if (hc->qh->do_split) { -+ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in && hcd->core_if->dma_enable) { -+ if (qtd->complete_split && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, qtd)) -+ goto handle_xfercomp_done; -+ } -+ else { -+ qtd->complete_split = 0; -+ } -+ } -+ -+ /* Update the QTD and URB states. */ -+ switch (pipe_type) { -+ case UE_CONTROL: -+ switch (qtd->control_phase) { -+ case DWC_OTG_CONTROL_SETUP: -+ if (urb->length > 0) { -+ qtd->control_phase = DWC_OTG_CONTROL_DATA; -+ } else { -+ qtd->control_phase = DWC_OTG_CONTROL_STATUS; -+ } -+ DWC_DEBUGPL(DBG_HCDV, -+ " Control setup transaction done\n"); -+ halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ break; -+ case DWC_OTG_CONTROL_DATA:{ -+ urb_xfer_done = -+ update_urb_state_xfer_comp(hc, hc_regs, urb, -+ qtd); -+ if (urb_xfer_done) { -+ qtd->control_phase = -+ DWC_OTG_CONTROL_STATUS; -+ DWC_DEBUGPL(DBG_HCDV, -+ " Control data transfer done\n"); -+ } else { -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ } -+ halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ break; -+ } -+ case DWC_OTG_CONTROL_STATUS: -+ DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n"); -+ if (urb->status == -DWC_E_IN_PROGRESS) { -+ urb->status = 0; -+ } -+ hcd->fops->complete(hcd, urb->priv, urb, urb->status); -+ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; -+ break; -+ } -+ -+ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); -+ break; -+ case UE_BULK: -+ DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n"); -+ urb_xfer_done = -+ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); -+ if (urb_xfer_done) { -+ hcd->fops->complete(hcd, urb->priv, urb, urb->status); -+ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; -+ } else { -+ halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ } -+ -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); -+ break; -+ case UE_INTERRUPT: -+ DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); -+ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); -+ -+ /* -+ * Interrupt URB is done on the first transfer complete -+ * interrupt. -+ */ -+ hcd->fops->complete(hcd, urb->priv, urb, urb->status); -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ complete_periodic_xfer(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_URB_COMPLETE); -+ break; -+ case UE_ISOCHRONOUS: -+ DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); -+ if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) { -+ halt_status = -+ update_isoc_urb_state(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_COMPLETE); -+ } -+ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); -+ break; -+ } -+ -+handle_xfercomp_done: -+ disable_hc_int(hc_regs, xfercompl); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel STALL interrupt. This handler may be called in -+ * either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ dwc_otg_hcd_urb_t *urb = qtd->urb; -+ int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); -+ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "STALL Received--\n", hc->hc_num); -+ -+ if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL); -+ goto handle_stall_done; -+ } -+ -+ if (pipe_type == UE_CONTROL) { -+ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE); -+ } -+ -+ if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) { -+ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE); -+ /* -+ * USB protocol requires resetting the data toggle for bulk -+ * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) -+ * setup command is issued to the endpoint. Anticipate the -+ * CLEAR_FEATURE command since a STALL has occurred and reset -+ * the data toggle now. -+ */ -+ hc->qh->data_toggle = 0; -+ } -+ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL); -+ -+handle_stall_done: -+ disable_hc_int(hc_regs, stall); -+ -+ return 1; -+} -+ -+/* -+ * Updates the state of the URB when a transfer has been stopped due to an -+ * abnormal condition before the transfer completes. Modifies the -+ * actual_length field of the URB to reflect the number of bytes that have -+ * actually been transferred via the host channel. -+ */ -+static void update_urb_state_xfer_intr(dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_hcd_urb_t * urb, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_halt_status_e halt_status) -+{ -+ uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd, -+ halt_status, NULL); -+ /* non DWORD-aligned buffer case handling. */ -+ if (hc->align_buff && bytes_transferred && hc->ep_is_in) { -+ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, bytes_transferred); -+ } -+ -+ urb->actual_length += bytes_transferred; -+ -+#ifdef DEBUG -+ { -+ hctsiz_data_t hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", -+ __func__, (hc->ep_is_in ? "IN" : "OUT"), -+ hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n", -+ hc->start_pkt_count); -+ DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt); -+ DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet); -+ DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n", -+ bytes_transferred); -+ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", -+ urb->actual_length); -+ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", -+ urb->length); -+ } -+#endif -+} -+ -+/** -+ * Handles a host channel NAK interrupt. This handler may be called in either -+ * DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "NAK Received--\n", hc->hc_num); -+ -+ /* -+ * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and -+ * interrupt. Re-start the SSPLIT transfer. -+ */ -+ if (hc->do_split) { -+ if (hc->complete_split) { -+ qtd->error_count = 0; -+ } -+ qtd->complete_split = 0; -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ goto handle_nak_done; -+ } -+ -+ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { -+ case UE_CONTROL: -+ case UE_BULK: -+ if (hcd->core_if->dma_enable && hc->ep_is_in) { -+#ifdef HW2937_WORKAROUND -+ if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ } -+#endif -+ /* -+ * NAK interrupts are enabled on bulk/control IN -+ * transfers in DMA mode for the sole purpose of -+ * resetting the error count after a transaction error -+ * occurs. The core will continue transferring data. -+ */ -+ qtd->error_count = 0; -+ goto handle_nak_done; -+ } -+ -+ /* -+ * NAK interrupts normally occur during OUT transfers in DMA -+ * or Slave mode. For IN transfers, more requests will be -+ * queued as request queue space is available. -+ */ -+ qtd->error_count = 0; -+ -+ if (!hc->qh->ping_state) { -+ update_urb_state_xfer_intr(hc, hc_regs, -+ qtd->urb, qtd, -+ DWC_OTG_HC_XFER_NAK); -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ -+ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) -+ hc->qh->ping_state = 1; -+ } -+ -+ /* -+ * Halt the channel so the transfer can be re-started from -+ * the appropriate point or the PING protocol will -+ * start/continue. -+ */ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ break; -+ case UE_INTERRUPT: -+ qtd->error_count = 0; -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ break; -+ case UE_ISOCHRONOUS: -+#ifdef HW2937_WORKAROUND -+ if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ break; -+ } -+#endif -+ /* Should never get called for isochronous transfers. */ -+ DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n"); -+ break; -+ } -+ -+ handle_nak_done: -+ disable_hc_int(hc_regs, nak); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel ACK interrupt. This interrupt is enabled when -+ * performing the PING protocol in Slave mode, when errors occur during -+ * either Slave mode or DMA mode, and during Start Split transactions. -+ */ -+static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "ACK Received--\n", hc->hc_num); -+ -+ if (hc->do_split) { -+ /* -+ * Handle ACK on SSPLIT. -+ * ACK should not occur in CSPLIT. -+ */ -+ if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) { -+ qtd->ssplit_out_xfer_count = hc->xfer_len; -+ } -+ if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) { -+ /* Don't need complete for isochronous out transfers. */ -+ qtd->complete_split = 1; -+ } -+ -+ /* ISOC OUT */ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { -+ switch (hc->xact_pos) { -+ case DWC_HCSPLIT_XACTPOS_ALL: -+ break; -+ case DWC_HCSPLIT_XACTPOS_END: -+ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; -+ qtd->isoc_split_offset = 0; -+ break; -+ case DWC_HCSPLIT_XACTPOS_BEGIN: -+ case DWC_HCSPLIT_XACTPOS_MID: -+ /* -+ * For BEGIN or MID, calculate the length for -+ * the next microframe to determine the correct -+ * SSPLIT token, either MID or END. -+ */ -+ { -+ struct dwc_otg_hcd_iso_packet_desc -+ *frame_desc; -+ -+ frame_desc = -+ &qtd->urb->iso_descs[qtd-> -+ isoc_frame_index]; -+ qtd->isoc_split_offset += 188; -+ -+ if ((frame_desc->length - -+ qtd->isoc_split_offset) <= 188) { -+ qtd->isoc_split_pos = -+ DWC_HCSPLIT_XACTPOS_END; -+ } else { -+ qtd->isoc_split_pos = -+ DWC_HCSPLIT_XACTPOS_MID; -+ } -+ -+ } -+ break; -+ } -+ } else { -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); -+ } -+ } else { -+ qtd->error_count = 0; -+ -+ if (hc->qh->ping_state) { -+ hc->qh->ping_state = 0; -+ /* -+ * Halt the channel so the transfer can be re-started -+ * from the appropriate point. This only happens in -+ * Slave mode. In DMA mode, the ping_state is cleared -+ * when the transfer is started because the core -+ * automatically executes the PING, then the transfer. -+ */ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); -+ } -+#ifdef HW2937_WORKAROUND -+ else if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -+ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -+ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, DWC_OTG_HC_XFER_PAUSE_IN); -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_PAUSE_IN); -+ } -+#endif -+ } -+ -+ /* -+ * If the ACK occurred when _not_ in the PING state, let the channel -+ * continue transferring data after clearing the error count. -+ */ -+ -+ disable_hc_int(hc_regs, ack); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel NYET interrupt. This interrupt should only occur on -+ * Bulk and Control OUT endpoints and for complete split transactions. If a -+ * NYET occurs at the same time as a Transfer Complete interrupt, it is -+ * handled in the xfercomp interrupt handler, not here. This handler may be -+ * called in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "NYET Received--\n", hc->hc_num); -+ -+ /* -+ * NYET on CSPLIT -+ * re-do the CSPLIT immediately on non-periodic -+ */ -+ if (hc->do_split && hc->complete_split) { -+ if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hcd->core_if->dma_enable) { -+ qtd->complete_split = 0; -+ qtd->isoc_split_offset = 0; -+ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { -+ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); -+ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); -+ } -+ else -+ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); -+ goto handle_nyet_done; -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ int frnum = dwc_otg_hcd_get_frame_number(hcd); -+ -+ if (dwc_full_frame_num(frnum) != -+ dwc_full_frame_num(hc->qh->sched_frame)) { -+ /* -+ * No longer in the same full speed frame. -+ * Treat this as a transaction error. -+ */ -+#if 0 -+ /** @todo Fix system performance so this can -+ * be treated as an error. Right now complete -+ * splits cannot be scheduled precisely enough -+ * due to other system activity, so this error -+ * occurs regularly in Slave mode. -+ */ -+ qtd->error_count++; -+#endif -+ qtd->complete_split = 0; -+ halt_channel(hcd, hc, qtd, -+ DWC_OTG_HC_XFER_XACT_ERR); -+ /** @todo add support for isoc release */ -+ goto handle_nyet_done; -+ } -+ } -+ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); -+ goto handle_nyet_done; -+ } -+ -+ hc->qh->ping_state = 1; -+ qtd->error_count = 0; -+ -+ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, -+ DWC_OTG_HC_XFER_NYET); -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ -+ /* -+ * Halt the channel and re-start the transfer so the PING -+ * protocol will start. -+ */ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); -+ -+ handle_nyet_done: -+ disable_hc_int(hc_regs, nyet); -+ return 1; -+} -+ -+/** -+ * Handles a host channel babble interrupt. This handler may be called in -+ * either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Babble Error--\n", hc->hc_num); -+ -+ if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_BABBLE_ERR); -+ goto handle_babble_done; -+ } -+ -+ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { -+ hcd->fops->complete(hcd, qtd->urb->priv, -+ qtd->urb, -DWC_E_OVERFLOW); -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR); -+ } else { -+ dwc_otg_halt_status_e halt_status; -+ halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_BABBLE_ERR); -+ halt_channel(hcd, hc, qtd, halt_status); -+ } -+ -+handle_babble_done: -+ disable_hc_int(hc_regs, bblerr); -+ return 1; -+} -+ -+/** -+ * Handles a host channel AHB error interrupt. This handler is only called in -+ * DMA mode. -+ */ -+static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ hcchar_data_t hcchar; -+ hcsplt_data_t hcsplt; -+ hctsiz_data_t hctsiz; -+ uint32_t hcdma; -+ char *pipetype, *speed; -+ -+ dwc_otg_hcd_urb_t *urb = qtd->urb; -+ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "AHB Error--\n", hc->hc_num); -+ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hcdma = dwc_read_reg32(&hc_regs->hcdma); -+ -+ DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); -+ DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); -+ DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma); -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n"); -+ DWC_ERROR(" Device address: %d\n", -+ dwc_otg_hcd_get_dev_addr(&urb->pipe_info)); -+ DWC_ERROR(" Endpoint: %d, %s\n", -+ dwc_otg_hcd_get_ep_num(&urb->pipe_info), -+ (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT")); -+ -+ -+ switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { -+case UE_CONTROL: -+ pipetype = "CONTROL"; -+ break; -+ case UE_BULK: -+ pipetype = "BULK"; -+ break; -+ case UE_INTERRUPT: -+ pipetype = "INTERRUPT"; -+ break; -+ case UE_ISOCHRONOUS: -+ pipetype = "ISOCHRONOUS"; -+ break; -+ default: -+ pipetype = "UNKNOWN"; -+ break; -+ } -+ -+ DWC_ERROR(" Endpoint type: %s\n", pipetype); -+ -+ switch (hc->speed) { -+ case DWC_OTG_EP_SPEED_HIGH: -+ speed = "HIGH"; -+ break; -+ case DWC_OTG_EP_SPEED_FULL: -+ speed = "FULL"; -+ break; -+ case DWC_OTG_EP_SPEED_LOW: -+ speed = "LOW"; -+ break; -+ default: -+ speed = "UNKNOWN"; -+ break; -+ }; -+ -+ DWC_ERROR(" Speed: %s\n", speed); -+ -+ DWC_ERROR(" Max packet size: %d\n", -+ dwc_otg_hcd_get_mps(&urb->pipe_info)); -+ DWC_ERROR(" Data buffer length: %d\n", urb->length); -+ DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n", -+ urb->buf, (void *)urb->dma); -+ DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n", -+ urb->setup_packet, (void *)urb->setup_dma); -+ DWC_ERROR(" Interval: %d\n", urb->interval); -+ -+ /* Core haltes the channel for Descriptor DMA mode */ -+ if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_AHB_ERR); -+ goto handle_ahberr_done; -+ } -+ -+ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO); -+ -+ /* -+ * Force a channel halt. Don't call halt_channel because that won't -+ * write to the HCCHARn register in DMA mode to force the halt. -+ */ -+ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR); -+handle_ahberr_done: -+ disable_hc_int(hc_regs, ahberr); -+ return 1; -+} -+ -+/** -+ * Handles a host channel transaction error interrupt. This handler may be -+ * called in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Transaction Error--\n", hc->hc_num); -+ -+ if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_XACT_ERR); -+ goto handle_xacterr_done; -+ } -+ -+ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { -+ case UE_CONTROL: -+ case UE_BULK: -+ qtd->error_count++; -+ if (!hc->qh->ping_state) { -+ -+ update_urb_state_xfer_intr(hc, hc_regs, -+ qtd->urb, qtd, -+ DWC_OTG_HC_XFER_XACT_ERR); -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) { -+ hc->qh->ping_state = 1; -+ } -+ } -+ -+ /* -+ * Halt the channel so the transfer can be re-started from -+ * the appropriate point or the PING protocol will start. -+ */ -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); -+ break; -+ case UE_INTERRUPT: -+ qtd->error_count++; -+ if (hc->do_split && hc->complete_split) { -+ qtd->complete_split = 0; -+ } -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); -+ break; -+ case UE_ISOCHRONOUS: -+ { -+ dwc_otg_halt_status_e halt_status; -+ halt_status = -+ update_isoc_urb_state(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_XACT_ERR); -+ -+ halt_channel(hcd, hc, qtd, halt_status); -+ } -+ break; -+ } -+handle_xacterr_done: -+ disable_hc_int(hc_regs, xacterr); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel frame overrun interrupt. This handler may be called -+ * in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Frame Overrun--\n", hc->hc_num); -+ -+ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { -+ case UE_CONTROL: -+ case UE_BULK: -+ break; -+ case UE_INTERRUPT: -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); -+ break; -+ case UE_ISOCHRONOUS: -+ { -+ dwc_otg_halt_status_e halt_status; -+ halt_status = -+ update_isoc_urb_state(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_FRAME_OVERRUN); -+ -+ halt_channel(hcd, hc, qtd, halt_status); -+ } -+ break; -+ } -+ -+ disable_hc_int(hc_regs, frmovrun); -+ -+ return 1; -+} -+ -+/** -+ * Handles a host channel data toggle error interrupt. This handler may be -+ * called in either DMA mode or Slave mode. -+ */ -+static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Data Toggle Error--\n", hc->hc_num); -+ -+ if (hc->ep_is_in) { -+ qtd->error_count = 0; -+ } else { -+ DWC_ERROR("Data Toggle Error on OUT transfer," -+ "channel %d\n", hc->hc_num); -+ } -+ -+ disable_hc_int(hc_regs, datatglerr); -+ -+ return 1; -+} -+ -+#ifdef DEBUG -+/** -+ * This function is for debug only. It checks that a valid halt status is set -+ * and that HCCHARn.chdis is clear. If there's a problem, corrective action is -+ * taken and a warning is issued. -+ * @return 1 if halt status is ok, 0 otherwise. -+ */ -+static inline int halt_status_ok(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ hcchar_data_t hcchar; -+ hctsiz_data_t hctsiz; -+ hcint_data_t hcint; -+ hcintmsk_data_t hcintmsk; -+ hcsplt_data_t hcsplt; -+ -+ if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) { -+ /* -+ * This code is here only as a check. This condition should -+ * never happen. Ignore the halt if it does occur. -+ */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ DWC_WARN -+ ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, " -+ "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " -+ "hcint 0x%08x, hcintmsk 0x%08x, " -+ "hcsplt 0x%08x, qtd->complete_split %d\n", __func__, -+ hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32, -+ hcintmsk.d32, hcsplt.d32, qtd->complete_split); -+ -+ DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n", -+ __func__, hc->hc_num); -+ DWC_WARN("\n"); -+ clear_hc_int(hc_regs, chhltd); -+ return 0; -+ } -+ -+ /* -+ * This code is here only as a check. hcchar.chdis should -+ * never be set when the halt interrupt occurs. Halt the -+ * channel again if it does occur. -+ */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ if (hcchar.b.chdis) { -+ DWC_WARN("%s: hcchar.chdis set unexpectedly, " -+ "hcchar 0x%08x, trying to halt again\n", -+ __func__, hcchar.d32); -+ clear_hc_int(hc_regs, chhltd); -+ hc->halt_pending = 0; -+ halt_channel(hcd, hc, qtd, hc->halt_status); -+ return 0; -+ } -+ -+ return 1; -+} -+#endif -+ -+/** -+ * Handles a host Channel Halted interrupt in DMA mode. This handler -+ * determines the reason the channel halted and proceeds accordingly. -+ */ -+static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ hcint_data_t hcint; -+ hcintmsk_data_t hcintmsk; -+ int out_nak_enh = 0; -+ -+ /* For core with OUT NAK enhancement, the flow for high- -+ * speed CONTROL/BULK OUT is handled a little differently. -+ */ -+ if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) { -+ if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in && -+ (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || -+ hc->ep_type == DWC_OTG_EP_TYPE_BULK)) { -+ out_nak_enh = 1; -+ } -+ } -+ -+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || -+ (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR && !hcd->core_if->dma_desc_enable)) { -+ /* -+ * Just release the channel. A dequeue can happen on a -+ * transfer timeout. In the case of an AHB Error, the channel -+ * was forced to halt because there's no way to gracefully -+ * recover. -+ */ -+ if (hcd->core_if->dma_desc_enable) -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, hc->halt_status); -+ else -+ release_channel(hcd, hc, qtd, hc->halt_status); -+ return; -+ } -+ -+ /* Read the HCINTn register to determine the cause for the halt. */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -+ -+ if (hcint.b.xfercomp) { -+ /** @todo This is here because of a possible hardware bug. Spec -+ * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT -+ * interrupt w/ACK bit set should occur, but I only see the -+ * XFERCOMP bit, even with it masked out. This is a workaround -+ * for that behavior. Should fix this when hardware is fixed. -+ */ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { -+ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); -+ } -+ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.stall) { -+ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) { -+ if (out_nak_enh) { -+ if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) { -+ DWC_DEBUG("XactErr with NYET/NAK/ACK\n"); -+ qtd->error_count = 0; -+ } else { -+ DWC_DEBUG("XactErr without NYET/NAK/ACK\n"); -+ } -+ } -+ -+ /* -+ * Must handle xacterr before nak or ack. Could get a xacterr -+ * at the same time as either of these on a BULK/CONTROL OUT -+ * that started with a PING. The xacterr takes precedence. -+ */ -+ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) { -+ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { -+ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.bblerr) { -+ handle_hc_babble_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.frmovrun) { -+ handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd); -+ } else if (!out_nak_enh) { -+ if (hcint.b.nyet) { -+ /* -+ * Must handle nyet before nak or ack. Could get a nyet at the -+ * same time as either of those on a BULK/CONTROL OUT that -+ * started with a PING. The nyet takes precedence. -+ */ -+ handle_hc_nyet_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.nak && !hcintmsk.b.nak) { -+ /* -+ * If nak is not masked, it's because a non-split IN transfer -+ * is in an error state. In that case, the nak is handled by -+ * the nak interrupt handler, not here. Handle nak here for -+ * BULK/CONTROL OUT transfers, which halt on a NAK to allow -+ * rewinding the buffer pointer. -+ */ -+ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.ack && !hcintmsk.b.ack) { -+ /* -+ * If ack is not masked, it's because a non-split IN transfer -+ * is in an error state. In that case, the ack is handled by -+ * the ack interrupt handler, not here. Handle ack here for -+ * split transfers. Start splits halt on ACK. -+ */ -+ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); -+ } else { -+ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || -+ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * A periodic transfer halted with no other channel -+ * interrupts set. Assume it was halted by the core -+ * because it could not be completed in its scheduled -+ * (micro)frame. -+ */ -+#ifdef DEBUG -+ DWC_PRINTF -+ ("%s: Halt channel %d (assume incomplete periodic transfer)\n", -+ __func__, hc->hc_num); -+#endif -+ halt_channel(hcd, hc, qtd, -+ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE); -+ } else { -+ DWC_ERROR -+ ("%s: Channel %d, DMA Mode -- ChHltd set, but reason " -+ "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n", -+ __func__, hc->hc_num, hcint.d32, -+ dwc_read_reg32(&hcd->core_if-> -+ core_global_regs->gintsts)); -+ } -+ -+ } -+ } else { -+ DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n", -+ hcint.d32); -+ } -+} -+ -+/** -+ * Handles a host channel Channel Halted interrupt. -+ * -+ * In slave mode, this handler is called only when the driver specifically -+ * requests a halt. This occurs during handling other host channel interrupts -+ * (e.g. nak, xacterr, stall, nyet, etc.). -+ * -+ * In DMA mode, this is the interrupt that occurs when the core has finished -+ * processing a transfer on a channel. Other host channel interrupts (except -+ * ahberr) are disabled in DMA mode. -+ */ -+static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) -+{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ "Channel Halted--\n", hc->hc_num); -+ -+ if (hcd->core_if->dma_enable) { -+ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); -+ } else { -+#ifdef DEBUG -+ if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { -+ return 1; -+ } -+#endif -+ release_channel(hcd, hc, qtd, hc->halt_status); -+ } -+ -+ return 1; -+} -+ -+/** Handles interrupt for a specific Host Channel */ -+int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) -+{ -+ int retval = 0; -+ hcint_data_t hcint; -+ hcintmsk_data_t hcintmsk; -+ dwc_hc_t *hc; -+ dwc_otg_hc_regs_t *hc_regs; -+ dwc_otg_qtd_t *qtd; -+ -+ DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num); -+ -+ hc = dwc_otg_hcd->hc_ptr_array[num]; -+ hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num]; -+ qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); -+ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -+ DWC_DEBUGPL(DBG_HCDV, -+ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", -+ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); -+ hcint.d32 = hcint.d32 & hcintmsk.d32; -+ -+ if (!dwc_otg_hcd->core_if->dma_enable) { -+ if (hcint.b.chhltd && hcint.d32 != 0x2) { -+ hcint.b.chhltd = 0; -+ } -+ } -+ -+ if (hcint.b.xfercomp) { -+ retval |= -+ handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ /* -+ * If NYET occurred at same time as Xfer Complete, the NYET is -+ * handled by the Xfer Complete interrupt handler. Don't want -+ * to call the NYET interrupt handler in this case. -+ */ -+ hcint.b.nyet = 0; -+ } -+ if (hcint.b.chhltd) { -+ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.ahberr) { -+ retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.stall) { -+ retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.nak) { -+ retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.ack) { -+ retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.nyet) { -+ retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.xacterr) { -+ retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.bblerr) { -+ retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.frmovrun) { -+ retval |= -+ handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ if (hcint.b.datatglerr) { -+ retval |= -+ handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd); -+ } -+ -+ return retval; -+} -+ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -new file mode 100644 -index 0000000..a5f8546 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -0,0 +1,840 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ -+ * $Revision: #11 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237476 $ -+ * -+ * 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_DEVICE_ONLY -+ -+/** -+ * @file -+ * -+ * This file contains the implementation of the HCD. In Linux, the HCD -+ * implements the hc_driver API. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef LM_INTERFACE -+//#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#include -+#else -+#include -+#include -+#endif -+#elif defined(PLATFORM_INTERFACE) -+#include -+#endif -+ -+#include -+#include -+ -+#include "dwc_otg_hcd_if.h" -+#include "dwc_otg_dbg.h" -+#include "dwc_otg_driver.h" -+ -+/** -+ * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is -+ * qualified with its direction (possible 32 endpoints per device). -+ */ -+#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ -+ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) -+ -+static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; -+ -+/** @name Linux HC Driver API Functions */ -+/** @{ */ -+/* manage i/o requests, device state */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+static int urb_enqueue(struct usb_hcd *hcd, -+ struct usb_host_endpoint *ep, -+ struct urb *urb, gfp_t mem_flags); -+ -+static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb); -+#else -+static int urb_enqueue(struct usb_hcd *hcd, -+ struct urb *urb, gfp_t mem_flags); -+ -+static int urb_dequeue(struct usb_hcd *hcd, -+ struct urb *urb, int status); -+#endif -+ -+static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep); -+ -+static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); -+extern int hcd_start(struct usb_hcd *hcd); -+extern void hcd_stop(struct usb_hcd *hcd); -+static int get_frame_number(struct usb_hcd *hcd); -+extern int hub_status_data(struct usb_hcd *hcd, char *buf); -+extern int hub_control(struct usb_hcd *hcd, -+ u16 typeReq, -+ u16 wValue, u16 wIndex, char *buf, u16 wLength); -+ -+struct wrapper_priv_data { -+ dwc_otg_hcd_t *dwc_otg_hcd; -+}; -+ -+/** @} */ -+ -+static struct hc_driver dwc_otg_hc_driver = { -+ -+ .description = dwc_otg_hcd_name, -+ .product_desc = "DWC OTG Controller", -+ .hcd_priv_size = sizeof(struct wrapper_priv_data), -+ -+ .irq = dwc_otg_hcd_irq, -+ -+ .flags = HCD_MEMORY | HCD_USB2, -+ -+ //.reset = -+ .start = hcd_start, -+ //.suspend = -+ //.resume = -+ .stop = hcd_stop, -+ -+ .urb_enqueue = urb_enqueue, -+ .urb_dequeue = urb_dequeue, -+ .endpoint_disable = endpoint_disable, -+ -+ .get_frame_number = get_frame_number, -+ -+ .hub_status_data = hub_status_data, -+ .hub_control = hub_control, -+ //.bus_suspend = -+ //.bus_resume = -+}; -+ -+/** Gets the dwc_otg_hcd from a struct usb_hcd */ -+static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd) -+{ -+ struct wrapper_priv_data *p; -+ p = (struct wrapper_priv_data *)(hcd->hcd_priv); -+ return p->dwc_otg_hcd; -+} -+ -+/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */ -+static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd) -+{ -+ return dwc_otg_hcd_get_priv_data(dwc_otg_hcd); -+} -+ -+/** Gets the usb_host_endpoint associated with an URB. */ -+inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb) -+{ -+ struct usb_device *dev = urb->dev; -+ int ep_num = usb_pipeendpoint(urb->pipe); -+ -+ if (usb_pipein(urb->pipe)) -+ return dev->ep_in[ep_num]; -+ else -+ return dev->ep_out[ep_num]; -+} -+ -+static int _disconnect(dwc_otg_hcd_t * hcd) -+{ -+ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); -+ -+ usb_hcd->self.is_b_host = 0; -+ return 0; -+} -+ -+static int _start(dwc_otg_hcd_t * hcd) -+{ -+ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); -+ -+ usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd); -+ hcd_start(usb_hcd); -+ -+ return 0; -+} -+ -+static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr, -+ uint32_t * port_addr) -+{ -+ struct urb *urb = (struct urb *)urb_handle; -+#if 1 //GRAYG - temporary -+ if (NULL == urb_handle) -+ DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG -+ if (NULL == urb->dev) -+ DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG -+ if (NULL == port_addr) -+ DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG -+#endif -+ if (urb->dev->tt) { -+ if (NULL == urb->dev->tt->hub) { -+ DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n", -+ __func__); //GRAYG -+ //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG -+ *hub_addr = 0; //GRAYG -+ // we probably shouldn't have a transaction translator if -+ // there's no associated hub? -+ } else -+ *hub_addr = urb->dev->tt->hub->devnum; -+ } else { -+ *hub_addr = 0; -+ } -+ *port_addr = urb->dev->ttport; -+ return 0; -+} -+ -+static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle) -+{ -+ struct urb *urb = (struct urb *)urb_handle; -+ return urb->dev->speed; -+} -+ -+static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd) -+{ -+ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); -+ return usb_hcd->self.b_hnp_enable; -+} -+ -+static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, -+ struct urb *urb) -+{ -+ hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval; -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ hcd_to_bus(hcd)->bandwidth_isoc_reqs++; -+ } else { -+ hcd_to_bus(hcd)->bandwidth_int_reqs++; -+ } -+} -+ -+static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, -+ struct urb *urb) -+{ -+ hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval; -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ hcd_to_bus(hcd)->bandwidth_isoc_reqs--; -+ } else { -+ hcd_to_bus(hcd)->bandwidth_int_reqs--; -+ } -+} -+ -+/** -+ * Sets the final status of an URB and returns it to the device driver. Any -+ * required cleanup of the URB is performed. -+ */ -+static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, -+ dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status) -+{ -+ struct urb *urb = (struct urb *)urb_handle; -+#ifdef DEBUG -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n", -+ __func__, urb, usb_pipedevice(urb->pipe), -+ usb_pipeendpoint(urb->pipe), -+ usb_pipein(urb->pipe) ? "IN" : "OUT", status); -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ int i; -+ for (i = 0; i < urb->number_of_packets; i++) { -+ DWC_PRINTF(" ISO Desc %d status: %d\n", -+ i, urb->iso_frame_desc[i].status); -+ } -+ } -+ } -+#endif -+ -+ urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb); -+ /* Convert status value. */ -+ switch (status) { -+ case -DWC_E_PROTOCOL: -+ status = -EPROTO; -+ break; -+ case -DWC_E_IN_PROGRESS: -+ status = -EINPROGRESS; -+ break; -+ case -DWC_E_PIPE: -+ status = -EPIPE; -+ break; -+ case -DWC_E_IO: -+ status = -EIO; -+ break; -+ case -DWC_E_TIMEOUT: -+ status = -ETIMEDOUT; -+ break; -+ case -DWC_E_OVERFLOW: -+ status = -EOVERFLOW; -+ break; -+ default: -+ if (status) { -+ DWC_PRINTF("Uknown urb status %d\n", status); -+ -+ } -+ } -+ -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ int i; -+ -+ urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb); -+ for (i = 0; i < urb->number_of_packets; ++i) { -+ urb->iso_frame_desc[i].actual_length = -+ dwc_otg_hcd_urb_get_iso_desc_actual_length -+ (dwc_otg_urb, i); -+ urb->iso_frame_desc[i].status = -+ dwc_otg_hcd_urb_get_iso_desc_status -+ (dwc_otg_urb, i); -+ } -+ } -+ -+ urb->status = status; -+ urb->hcpriv = NULL; -+ if (!status) { -+ if ((urb->transfer_flags & URB_SHORT_NOT_OK) && -+ (urb->actual_length < urb->transfer_buffer_length)) { -+ urb->status = -EREMOTEIO; -+ } -+ } -+ -+ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) || -+ (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { -+ struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb); -+ if (ep) { -+ free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd), -+ dwc_otg_hcd_get_ep_bandwidth(hcd, -+ ep-> -+ hcpriv), -+ urb); -+ } -+ } -+ -+ dwc_free(dwc_otg_urb); -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); -+#else -+ usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb); -+ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); -+#endif -+ return 0; -+} -+ -+static struct dwc_otg_hcd_function_ops hcd_fops = { -+ .start = _start, -+ .disconnect = _disconnect, -+ .hub_info = _hub_info, -+ .speed = _speed, -+ .complete = _complete, -+ .get_b_hnp_enable = _get_b_hnp_enable, -+}; -+ -+/** -+ * Initializes the HCD. This function allocates memory for and initializes the -+ * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the -+ * USB bus with the core and calls the hc_driver->start() function. It returns -+ * a negative error on failure. -+ */ -+int hcd_init( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) -+{ -+ struct usb_hcd *hcd = NULL; -+ dwc_otg_hcd_t *dwc_otg_hcd = NULL; -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ -+ int retval = 0; -+ u64 dmamask; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev); -+ -+ /* Set device flags indicating whether the HCD supports DMA. */ -+ if (dwc_otg_is_dma_enable(otg_dev->core_if)) -+ dmamask = DMA_BIT_MASK(32); -+ else -+ dmamask = 0; -+ -+#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE) -+ dma_set_mask(&_dev->dev, dmamask); -+ dma_set_coherent_mask(&_dev->dev, dmamask); -+#elif defined(PCI_INTERFACE) -+ pci_set_dma_mask(_dev, dmamask); -+ pci_set_consistent_dma_mask(_dev, dmamask); -+#endif -+ -+ /* -+ * Allocate memory for the base HCD plus the DWC OTG HCD. -+ * Initialize the base HCD. -+ */ -+ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ _dev->dev.bus_id); -+#else -+ dev_name(&_dev->dev)); -+#endif -+ if (!hcd) { -+ retval = -ENOMEM; -+ goto error1; -+ } -+ -+ hcd->regs = otg_dev->base; -+ -+ /* Initialize the DWC OTG HCD. */ -+ dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); -+ if (!dwc_otg_hcd) { -+ goto error2; -+ } -+ ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd = -+ dwc_otg_hcd; -+ otg_dev->hcd = dwc_otg_hcd; -+ -+ if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { -+ goto error2; -+ } -+ -+ hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); -+ -+ /* -+ * Finish generic HCD initialization and start the HCD. This function -+ * allocates the DMA buffer pool, registers the USB bus, requests the -+ * IRQ line, and calls hcd_start method. -+ */ -+#ifdef PLATFORM_INTERFACE -+ retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED); -+#else -+ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED); -+#endif -+ if (retval < 0) { -+ goto error2; -+ } -+ -+ dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd); -+ return 0; -+ -+ error2: -+ usb_put_hcd(hcd); -+ error1: -+ return retval; -+} -+ -+/** -+ * Removes the HCD. -+ * Frees memory and resources associated with the HCD and deregisters the bus. -+ */ -+void hcd_remove( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) -+{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ -+ dwc_otg_hcd_t *dwc_otg_hcd; -+ struct usb_hcd *hcd; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev); -+ -+ if (!otg_dev) { -+ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); -+ return; -+ } -+ -+ dwc_otg_hcd = otg_dev->hcd; -+ -+ if (!dwc_otg_hcd) { -+ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); -+ return; -+ } -+ -+ hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd); -+ -+ if (!hcd) { -+ DWC_DEBUGPL(DBG_ANY, -+ "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n", -+ __func__); -+ return; -+ } -+ usb_remove_hcd(hcd); -+ dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL); -+ dwc_otg_hcd_remove(dwc_otg_hcd); -+ usb_put_hcd(hcd); -+} -+ -+/* ========================================================================= -+ * Linux HC Driver Functions -+ * ========================================================================= */ -+ -+/** Initializes the DWC_otg controller and its root hub and prepares it for host -+ * mode operation. Activates the root port. Returns 0 on success and a negative -+ * error code on failure. */ -+int hcd_start(struct usb_hcd *hcd) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ struct usb_bus *bus; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n"); -+ bus = hcd_to_bus(hcd); -+ -+ hcd->state = HC_STATE_RUNNING; -+ if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) { -+ return 0; -+ } -+ -+ /* Initialize and connect root hub if one is not already attached */ -+ if (bus->root_hub) { -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n"); -+ /* Inform the HUB driver to resume. */ -+ usb_hcd_resume_root_hub(hcd); -+ } -+ -+ return 0; -+} -+ -+/** -+ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are -+ * stopped. -+ */ -+void hcd_stop(struct usb_hcd *hcd) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ dwc_otg_hcd_stop(dwc_otg_hcd); -+} -+ -+/** Returns the current frame number. */ -+static int get_frame_number(struct usb_hcd *hcd) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd); -+} -+ -+#ifdef DEBUG -+static void dump_urb_info(struct urb *urb, char *fn_name) -+{ -+ DWC_PRINTF("%s, urb %p\n", fn_name, urb); -+ DWC_PRINTF(" Device address: %d\n", usb_pipedevice(urb->pipe)); -+ DWC_PRINTF(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), -+ (usb_pipein(urb->pipe) ? "IN" : "OUT")); -+ DWC_PRINTF(" Endpoint type: %s\n", ( { -+ char *pipetype; -+ switch (usb_pipetype(urb->pipe)) { -+case PIPE_CONTROL: -+pipetype = "CONTROL"; break; case PIPE_BULK: -+pipetype = "BULK"; break; case PIPE_INTERRUPT: -+pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS: -+pipetype = "ISOCHRONOUS"; break; default: -+ pipetype = "UNKNOWN"; break;}; -+ pipetype;} -+ )) ; -+ DWC_PRINTF(" Speed: %s\n", ( { -+ char *speed; switch (urb->dev->speed) { -+case USB_SPEED_HIGH: -+speed = "HIGH"; break; case USB_SPEED_FULL: -+speed = "FULL"; break; case USB_SPEED_LOW: -+speed = "LOW"; break; default: -+ speed = "UNKNOWN"; break;}; -+ speed;} -+ )) ; -+ DWC_PRINTF(" Max packet size: %d\n", -+ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); -+ DWC_PRINTF(" Data buffer length: %d\n", urb->transfer_buffer_length); -+ DWC_PRINTF(" Transfer buffer: %p, Transfer DMA: %p\n", -+ urb->transfer_buffer, (void *)urb->transfer_dma); -+ DWC_PRINTF(" Setup buffer: %p, Setup DMA: %p\n", -+ urb->setup_packet, (void *)urb->setup_dma); -+ DWC_PRINTF(" Interval: %d\n", urb->interval); -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ int i; -+ for (i = 0; i < urb->number_of_packets; i++) { -+ DWC_PRINTF(" ISO Desc %d:\n", i); -+ DWC_PRINTF(" offset: %d, length %d\n", -+ urb->iso_frame_desc[i].offset, -+ urb->iso_frame_desc[i].length); -+ } -+ } -+} -+ -+#endif -+ -+/** Starts processing a USB transfer request specified by a USB Request Block -+ * (URB). mem_flags indicates the type of memory allocation to use while -+ * processing this URB. */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+static int urb_enqueue(struct usb_hcd *hcd, -+ struct usb_host_endpoint *ep, -+ struct urb *urb, gfp_t mem_flags) -+{ -+#else -+static int urb_enqueue(struct usb_hcd *hcd, -+ struct urb *urb, -+ gfp_t mem_flags) -+{ -+ struct usb_host_endpoint *ep = urb->ep; -+#endif -+ void **ref_ep_hcpriv = &ep->hcpriv; -+ int retval = 0; -+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ dwc_otg_hcd_urb_t *dwc_otg_urb; -+ int i; -+ int alloc_bandwidth = 0; -+ uint8_t ep_type = 0; -+ uint32_t flags = 0; -+ void *buf; -+ -+#ifdef DEBUG -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ dump_urb_info(urb, "urb_enqueue"); -+ } -+#endif -+ -+ if (!urb->transfer_buffer && urb->transfer_buffer_length) -+ return -EINVAL; -+ -+ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) -+ || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { -+ if (!dwc_otg_hcd_is_bandwidth_allocated -+ (dwc_otg_hcd, ref_ep_hcpriv)) { -+ alloc_bandwidth = 1; -+ } -+ } -+ -+ switch (usb_pipetype(urb->pipe)) { -+ case PIPE_CONTROL: -+ ep_type = USB_ENDPOINT_XFER_CONTROL; -+ break; -+ case PIPE_ISOCHRONOUS: -+ ep_type = USB_ENDPOINT_XFER_ISOC; -+ break; -+ case PIPE_BULK: -+ ep_type = USB_ENDPOINT_XFER_BULK; -+ break; -+ case PIPE_INTERRUPT: -+ ep_type = USB_ENDPOINT_XFER_INT; -+ break; -+ default: -+ DWC_WARN("Wrong ep type\n"); -+ } -+ -+ dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd, -+ urb->number_of_packets, -+ mem_flags == GFP_ATOMIC ? 1 : 0); -+ -+ urb->hcpriv = dwc_otg_urb; -+ -+ dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe), -+ usb_pipeendpoint(urb->pipe), ep_type, -+ usb_pipein(urb->pipe), -+ usb_maxpacket(urb->dev, urb->pipe, -+ !(usb_pipein(urb->pipe)))); -+ -+ buf = urb->transfer_buffer; -+ if (hcd->self.uses_dma) { -+ /* -+ * Calculate virtual address from physical address, -+ * because some class driver may not fill transfer_buffer. -+ * In Buffer DMA mode virual address is used, -+ * when handling non DWORD aligned buffers. -+ */ -+ //buf = phys_to_virt(urb->transfer_dma); -+ // DMA addresses are bus addresses not physical addresses! -+ buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma); -+ } -+ -+ if (!(urb->transfer_flags & URB_NO_INTERRUPT)) -+ flags |= URB_GIVEBACK_ASAP; -+ if (urb->transfer_flags & URB_ZERO_PACKET) -+ flags |= URB_SEND_ZERO_PACKET; -+ -+ dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf, -+ urb->transfer_dma, -+ urb->transfer_buffer_length, -+ urb->setup_packet, -+ urb->setup_dma, -+ flags, -+ urb->interval); -+ -+ for (i = 0; i < urb->number_of_packets; ++i) { -+ dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i, -+ urb->iso_frame_desc[i]. -+ offset, -+ urb->iso_frame_desc[i]. -+ length); -+ } -+ -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) -+ retval = usb_hcd_link_urb_to_ep(hcd, urb); -+ if (0 == retval) -+#endif -+ { -+ retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, -+ /*(dwc_otg_qh_t **)*/ -+ ref_ep_hcpriv); -+ if (0 == retval) { -+ if (alloc_bandwidth) { -+ allocate_bus_bandwidth(hcd, -+ dwc_otg_hcd_get_ep_bandwidth( -+ dwc_otg_hcd, *ref_ep_hcpriv), -+ urb); -+ } -+ } else { -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) -+ usb_hcd_unlink_urb_from_ep(hcd, urb); -+#endif -+ if (retval == -DWC_E_NO_DEVICE) { -+ retval = -ENODEV; -+ } -+ } -+ } -+ return retval; -+} -+ -+/** Aborts/cancels a USB transfer request. Always returns 0 to indicate -+ * success. */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -+#else -+static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -+#endif -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd; -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); -+ -+ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+#ifdef DEBUG -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ dump_urb_info(urb, "urb_dequeue"); -+ } -+#endif -+ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv); -+ -+ dwc_free(urb->hcpriv); -+ urb->hcpriv = NULL; -+ -+ /* Higher layer software sets URB status. */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ usb_hcd_giveback_urb(hcd, urb); -+#else -+ usb_hcd_unlink_urb_from_ep(hcd, urb); -+ usb_hcd_giveback_urb(hcd, urb, status); -+#endif -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ DWC_PRINTF("Called usb_hcd_giveback_urb()\n"); -+ DWC_PRINTF(" urb->status = %d\n", urb->status); -+ } -+ -+ return 0; -+} -+ -+/* Frees resources in the DWC_otg controller related to a given endpoint. Also -+ * clears state in the HCD related to the endpoint. Any URBs for the endpoint -+ * must already be dequeued. */ -+static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ DWC_DEBUGPL(DBG_HCD, -+ "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " -+ "endpoint=%d\n", ep->desc.bEndpointAddress, -+ dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress)); -+ dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250); -+ ep->hcpriv = NULL; -+} -+ -+/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if -+ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid -+ * interrupt. -+ * -+ * This function is called by the USB core when an interrupt occurs */ -+static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd); -+ if (retval != 0) { -+ S3C2410X_CLEAR_EINTPEND(); -+ } -+ return IRQ_RETVAL(retval); -+} -+ -+/** Creates Status Change bitmap for the root hub and root port. The bitmap is -+ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 -+ * is the status change indicator for the single root port. Returns 1 if either -+ * change indicator is 1, otherwise returns 0. */ -+int hub_status_data(struct usb_hcd *hcd, char *buf) -+{ -+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ -+ buf[0] = 0; -+ buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1; -+ -+ return (buf[0] != 0); -+} -+ -+/** Handles hub class-specific requests. */ -+int hub_control(struct usb_hcd *hcd, -+ u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) -+{ -+ int retval; -+ -+ retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd), -+ typeReq, wValue, wIndex, buf, wLength); -+ -+ switch (retval) { -+ case -DWC_E_INVALID: -+ retval = -EINVAL; -+ break; -+ } -+ -+ return retval; -+} -+ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -new file mode 100644 -index 0000000..cfed807 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -@@ -0,0 +1,732 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ -+ * $Revision: #39 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237477 $ -+ * -+ * 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_DEVICE_ONLY -+ -+/** -+ * @file -+ * -+ * This file contains the functions to manage Queue Heads and Queue -+ * Transfer Descriptors. -+ */ -+ -+#include "dwc_otg_hcd.h" -+#include "dwc_otg_regs.h" -+ -+/** -+ * Free each QTD in the QH's QTD-list then free the QH. QH should already be -+ * removed from a list. QTD list should already be empty if called from URB -+ * Dequeue. -+ * -+ * @param hcd HCD instance. -+ * @param qh The QH to free. -+ */ -+void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ dwc_otg_qtd_t *qtd, *qtd_tmp; -+ uint64_t flags; -+ -+ /* Free each QTD in the QTD list */ -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { -+ DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); -+ dwc_otg_hcd_qtd_free(qtd); -+ } -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ -+ if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_qh_free_ddma(hcd, qh); -+ } -+ else if (qh->dw_align_buf) { -+ uint32_t buf_size; -+ if(qh->ep_type == UE_ISOCHRONOUS) { -+ buf_size = 4096; -+ } else { -+ buf_size = hcd->core_if->core_params->max_transfer_size; -+ } -+ dwc_dma_free(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); -+ } -+ -+ -+ -+ dwc_free(qh); -+ return; -+} -+ -+#define BitStuffTime(bytecount) ((8 * 7* bytecount) / 6) -+#define HS_HOST_DELAY 5 /* nanoseconds */ -+#define FS_LS_HOST_DELAY 1000 /* nanoseconds */ -+#define HUB_LS_SETUP 333 /* nanoseconds */ -+#define NS_TO_US(ns) ((ns + 500) / 1000) -+ /* convert & round nanoseconds to microseconds */ -+ -+static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, -+ int bytecount) -+{ -+ unsigned long retval; -+ -+ switch (speed) { -+ case USB_SPEED_HIGH: -+ if (is_isoc) { -+ retval = -+ ((38 * 8 * 2083) + -+ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + -+ HS_HOST_DELAY; -+ } else { -+ retval = -+ ((55 * 8 * 2083) + -+ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + -+ HS_HOST_DELAY; -+ } -+ break; -+ case USB_SPEED_FULL: -+ if (is_isoc) { -+ retval = -+ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; -+ if (is_in) { -+ retval = 7268 + FS_LS_HOST_DELAY + retval; -+ } else { -+ retval = 6265 + FS_LS_HOST_DELAY + retval; -+ } -+ } else { -+ retval = -+ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; -+ retval = 9107 + FS_LS_HOST_DELAY + retval; -+ } -+ break; -+ case USB_SPEED_LOW: -+ if (is_in) { -+ retval = -+ (67667 * (31 + 10 * BitStuffTime(bytecount))) / -+ 1000; -+ retval = -+ 64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + -+ retval; -+ } else { -+ retval = -+ (66700 * (31 + 10 * BitStuffTime(bytecount))) / -+ 1000; -+ retval = -+ 64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + -+ retval; -+ } -+ break; -+ default: -+ DWC_WARN("Unknown device speed\n"); -+ retval = -1; -+ } -+ -+ return NS_TO_US(retval); -+} -+ -+/** -+ * Initializes a QH structure. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh The QH to init. -+ * @param urb Holds the information about the device/endpoint that we need -+ * to initialize the QH. -+ */ -+#define SCHEDULE_SLOP 10 -+void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, -+ dwc_otg_hcd_urb_t * urb) -+{ -+ char *speed, *type; -+ int dev_speed; -+ uint32_t hub_addr, hub_port; -+ -+ dwc_memset(qh, 0, sizeof(dwc_otg_qh_t)); -+ -+ /* Initialize QH */ -+ qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); -+ -+ qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; -+ -+ qh->data_toggle = DWC_OTG_HC_PID_DATA0; -+ qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info); -+ DWC_CIRCLEQ_INIT(&qh->qtd_list); -+ DWC_LIST_INIT(&qh->qh_list_entry); -+ qh->channel = NULL; -+ -+ /* FS/LS Enpoint on HS Hub -+ * NOT virtual root hub */ -+ dev_speed = hcd->fops->speed(hcd, urb->priv); -+ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port); -+ qh->do_split = 0; -+ if (((dev_speed == USB_SPEED_LOW) || -+ (dev_speed == USB_SPEED_FULL)) && -+ (hub_addr != 0 && hub_addr != 1)) { -+ -+ DWC_DEBUGPL(DBG_HCD, -+ "QH init: EP %d: TT found at hub addr %d, for port %d\n", -+ dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, -+ hub_port); -+ -+ qh->do_split = 1; -+ } -+ -+ if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) { -+ /* Compute scheduling parameters once and save them. */ -+ hprt0_data_t hprt; -+ -+ /** @todo Account for split transfers in the bus time. */ -+ int bytecount = -+ dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); -+ -+ qh->usecs = calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), -+ qh->ep_is_in, -+ (qh->ep_type == UE_ISOCHRONOUS), -+ bytecount); -+ /* Start in a slightly future (micro)frame. */ -+ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, -+ SCHEDULE_SLOP); -+ qh->interval = urb->interval; -+ -+#if 0 -+ /* Increase interrupt polling rate for debugging. */ -+ if (qh->ep_type == UE_INTERRUPT) { -+ qh->interval = 8; -+ } -+#endif -+ hprt.d32 = dwc_read_reg32(hcd->core_if->host_if->hprt0); -+ if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && -+ ((dev_speed == USB_SPEED_LOW) || -+ (dev_speed == USB_SPEED_FULL))) { -+ qh->interval *= 8; -+ qh->sched_frame |= 0x7; -+ qh->start_split_frame = qh->sched_frame; -+ } -+ -+ } -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n"); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n", -+ dwc_otg_hcd_get_dev_addr(&urb->pipe_info)); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n", -+ dwc_otg_hcd_get_ep_num(&urb->pipe_info), -+ dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"); -+ switch (dev_speed) { -+ case USB_SPEED_LOW: -+ qh->dev_speed = DWC_OTG_EP_SPEED_LOW; -+ speed = "low"; -+ break; -+ case USB_SPEED_FULL: -+ qh->dev_speed = DWC_OTG_EP_SPEED_FULL; -+ speed = "full"; -+ break; -+ case USB_SPEED_HIGH: -+ qh->dev_speed = DWC_OTG_EP_SPEED_HIGH; -+ speed = "high"; -+ break; -+ default: -+ speed = "?"; -+ break; -+ } -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", speed); -+ -+ switch (qh->ep_type) { -+ case UE_ISOCHRONOUS: -+ type = "isochronous"; -+ break; -+ case UE_INTERRUPT: -+ type = "interrupt"; -+ break; -+ case UE_CONTROL: -+ type = "control"; -+ break; -+ case UE_BULK: -+ type = "bulk"; -+ break; -+ default: -+ type = "?"; -+ break; -+ } -+ -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", type); -+ -+#ifdef DEBUG -+ if (qh->ep_type == UE_INTERRUPT) { -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n", -+ qh->usecs); -+ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n", -+ qh->interval); -+ } -+#endif -+ -+} -+ -+/** -+ * This function allocates and initializes a QH. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param urb Holds the information about the device/endpoint that we need -+ * to initialize the QH. -+ * -+ * @return Returns pointer to the newly allocated QH, or NULL on error. */ -+dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, -+ dwc_otg_hcd_urb_t * urb) -+{ -+ dwc_otg_qh_t *qh; -+ -+ /* Allocate memory */ -+ /** @todo add memflags argument */ -+ qh = dwc_otg_hcd_qh_alloc(); -+ if (qh == NULL) { -+ return NULL; -+ } -+ -+ qh_init(hcd, qh, urb); -+ -+ if (hcd->core_if->dma_desc_enable && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { -+ dwc_otg_hcd_qh_free(hcd, qh); -+ return NULL; -+ } -+ -+ return qh; -+} -+ -+/** -+ * Checks that a channel is available for a periodic transfer. -+ * -+ * @return 0 if successful, negative error code otherise. -+ */ -+static int periodic_channel_available(dwc_otg_hcd_t * hcd) -+{ -+ /* -+ * Currently assuming that there is a dedicated host channnel for each -+ * periodic transaction plus at least one host channel for -+ * non-periodic transactions. -+ */ -+ int status; -+ int num_channels; -+ -+ num_channels = hcd->core_if->core_params->host_channels; -+ if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) && -+ (hcd->periodic_channels < num_channels - 1)) { -+ status = 0; -+ } else { -+ DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", -+ __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels); //NOTICE -+ status = -DWC_E_NO_SPACE; -+ } -+ -+ return status; -+} -+ -+/** -+ * Checks that there is sufficient bandwidth for the specified QH in the -+ * periodic schedule. For simplicity, this calculation assumes that all the -+ * transfers in the periodic schedule may occur in the same (micro)frame. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh QH containing periodic bandwidth required. -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ int status; -+ int16_t max_claimed_usecs; -+ -+ status = 0; -+ -+ if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) { -+ /* -+ * High speed mode. -+ * Max periodic usecs is 80% x 125 usec = 100 usec. -+ */ -+ -+ max_claimed_usecs = 100 - qh->usecs; -+ } else { -+ /* -+ * Full speed mode. -+ * Max periodic usecs is 90% x 1000 usec = 900 usec. -+ */ -+ max_claimed_usecs = 900 - qh->usecs; -+ } -+ -+ if (hcd->periodic_usecs > max_claimed_usecs) { -+ DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs); //NOTICE -+ status = -DWC_E_NO_SPACE; -+ } -+ -+ return status; -+} -+ -+/** -+ * Checks that the max transfer size allowed in a host channel is large enough -+ * to handle the maximum data transfer in a single (micro)frame for a periodic -+ * transfer. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh QH for a periodic endpoint. -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ int status; -+ uint32_t max_xfer_size; -+ uint32_t max_channel_xfer_size; -+ -+ status = 0; -+ -+ max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp); -+ max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size; -+ -+ if (max_xfer_size > max_channel_xfer_size) { -+ DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n", -+ __func__, max_xfer_size, max_channel_xfer_size); //NOTICE -+ status = -DWC_E_NO_SPACE; -+ } -+ -+ return status; -+} -+ -+/** -+ * Schedules an interrupt or isochronous transfer in the periodic schedule. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh QH for the periodic transfer. The QH should already contain the -+ * scheduling information. -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ int status = 0; -+ -+ status = periodic_channel_available(hcd); -+ if (status) { -+ DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE -+ return status; -+ } -+ -+ status = check_periodic_bandwidth(hcd, qh); -+ if (status) { -+ DWC_INFO("%s: Insufficient periodic bandwidth for " "periodic transfer.\n", __func__); //NOTICE -+ return status; -+ } -+ -+ status = check_max_xfer_size(hcd, qh); -+ if (status) { -+ DWC_INFO("%s: Channel max transfer size too small " "for periodic transfer.\n", __func__); //NOTICE -+ return status; -+ } -+ -+ if (hcd->core_if->dma_desc_enable) { -+ /* Don't rely on SOF and start in ready schedule */ -+ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry); -+ } -+ else { -+ /* Always start in the inactive schedule. */ -+ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry); -+ } -+ -+ /* Reserve the periodic channel. */ -+ hcd->periodic_channels++; -+ -+ /* Update claimed usecs per (micro)frame. */ -+ hcd->periodic_usecs += qh->usecs; -+ -+ return status; -+} -+ -+/** -+ * This function adds a QH to either the non periodic or periodic schedule if -+ * it is not already in the schedule. If the QH is already in the schedule, no -+ * action is taken. -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ int status = 0; -+ uint64_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ -+ if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { -+ /* QH already in a schedule. */ -+ goto done; -+ } -+ -+ /* Add the new QH to the appropriate schedule */ -+ if (dwc_qh_is_non_per(qh)) { -+ /* Always start in the inactive schedule. */ -+ DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive, -+ &qh->qh_list_entry); -+ } else { -+ status = schedule_periodic(hcd, qh); -+ } -+ -+ done: -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ -+ return status; -+} -+ -+/** -+ * Removes an interrupt or isochronous transfer from the periodic schedule. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh QH for the periodic transfer. -+ */ -+static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); -+ -+ /* Release the periodic channel reservation. */ -+ hcd->periodic_channels--; -+ -+ /* Update claimed usecs per (micro)frame. */ -+ hcd->periodic_usecs -= qh->usecs; -+} -+ -+/** -+ * Removes a QH from either the non-periodic or periodic schedule. Memory is -+ * not freed. -+ * -+ * @param hcd The HCD state structure. -+ * @param qh QH to remove from schedule. */ -+void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ -+ if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { -+ /* QH is not in a schedule. */ -+ goto done; -+ } -+ -+ if (dwc_qh_is_non_per(qh)) { -+ if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) { -+ hcd->non_periodic_qh_ptr = -+ hcd->non_periodic_qh_ptr->next; -+ } -+ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); -+ } else { -+ deschedule_periodic(hcd, qh); -+ } -+ -+ done: -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+} -+ -+/** -+ * Deactivates a QH. For non-periodic QHs, removes the QH from the active -+ * non-periodic schedule. The QH is added to the inactive non-periodic -+ * schedule if any QTDs are still attached to the QH. -+ * -+ * For periodic QHs, the QH is removed from the periodic queued schedule. If -+ * there are any QTDs still attached to the QH, the QH is added to either the -+ * periodic inactive schedule or the periodic ready schedule and its next -+ * scheduled frame is calculated. The QH is placed in the ready schedule if -+ * the scheduled frame has been reached already. Otherwise it's placed in the -+ * inactive schedule. If there are no QTDs attached to the QH, the QH is -+ * completely removed from the periodic schedule. -+ */ -+void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, -+ int sched_next_periodic_split) -+{ -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ -+ if (dwc_qh_is_non_per(qh)) { -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -+ /* Add back to inactive non-periodic schedule. */ -+ dwc_otg_hcd_qh_add(hcd, qh); -+ } -+ } else { -+ uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd); -+ -+ if (qh->do_split) { -+ /* Schedule the next continuing periodic split transfer */ -+ if (sched_next_periodic_split) { -+ -+ qh->sched_frame = frame_number; -+ if (dwc_frame_num_le(frame_number, -+ dwc_frame_num_inc(qh-> -+ start_split_frame, -+ 1))) { -+ /* -+ * Allow one frame to elapse after start -+ * split microframe before scheduling -+ * complete split, but DONT if we are -+ * doing the next start split in the -+ * same frame for an ISOC out. -+ */ -+ if ((qh->ep_type != UE_ISOCHRONOUS) || -+ (qh->ep_is_in != 0)) { -+ qh->sched_frame = -+ dwc_frame_num_inc(qh->sched_frame, 1); -+ } -+ } -+ } else { -+ qh->sched_frame = -+ dwc_frame_num_inc(qh->start_split_frame, -+ qh->interval); -+ if (dwc_frame_num_le -+ (qh->sched_frame, frame_number)) { -+ qh->sched_frame = frame_number; -+ } -+ qh->sched_frame |= 0x7; -+ qh->start_split_frame = qh->sched_frame; -+ } -+ } else { -+ qh->sched_frame = -+ dwc_frame_num_inc(qh->sched_frame, qh->interval); -+ if (dwc_frame_num_le(qh->sched_frame, frame_number)) { -+ qh->sched_frame = frame_number; -+ } -+ } -+ -+ if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ } else { -+ /* -+ * Remove from periodic_sched_queued and move to -+ * appropriate queue. -+ */ -+ if (qh->sched_frame == frame_number) { -+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, -+ &qh->qh_list_entry); -+ } else { -+ DWC_LIST_MOVE_HEAD(&hcd-> -+ periodic_sched_inactive, -+ &qh->qh_list_entry); -+ } -+ } -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+} -+ -+/** -+ * This function allocates and initializes a QTD. -+ * -+ * @param urb The URB to create a QTD from. Each URB-QTD pair will end up -+ * pointing to each other so each pair should have a unique correlation. -+ * -+ * @return Returns pointer to the newly allocated QTD, or NULL on error. */ -+dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb) -+{ -+ dwc_otg_qtd_t *qtd; -+ -+ qtd = dwc_otg_hcd_qtd_alloc(); -+ if (qtd == NULL) { -+ return NULL; -+ } -+ -+ dwc_otg_hcd_qtd_init(qtd, urb); -+ return qtd; -+} -+ -+/** -+ * Initializes a QTD structure. -+ * -+ * @param qtd The QTD to initialize. -+ * @param urb The URB to use for initialization. */ -+void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb) -+{ -+ dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t)); -+ qtd->urb = urb; -+ if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) { -+ /* -+ * The only time the QTD data toggle is used is on the data -+ * phase of control transfers. This phase always starts with -+ * DATA1. -+ */ -+ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; -+ qtd->control_phase = DWC_OTG_CONTROL_SETUP; -+ } -+ -+ /* start split */ -+ qtd->complete_split = 0; -+ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; -+ qtd->isoc_split_offset = 0; -+ qtd->in_process = 0; -+ -+ /* Store the qtd ptr in the urb to reference what QTD. */ -+ urb->qtd = qtd; -+ return; -+} -+ -+/** -+ * This function adds a QTD to the QTD-list of a QH. It will find the correct -+ * QH to place the QTD into. If it does not find a QH, then it will create a -+ * new QH. If the QH to which the QTD is added is not currently scheduled, it -+ * is placed into the proper schedule based on its EP type. -+ * -+ * @param[in] qtd The QTD to add -+ * @param[in] hcd The DWC HCD structure -+ * @param[out] qh out parameter to return queue head -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, -+ dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh) -+{ -+ int retval = 0; -+ uint64_t flags; -+ -+ dwc_otg_hcd_urb_t *urb = qtd->urb; -+ -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ -+ /* -+ * Get the QH which holds the QTD-list to insert to. Create QH if it -+ * doesn't exist. -+ */ -+ if (*qh == NULL) { -+ *qh = dwc_otg_hcd_qh_create(hcd, urb); -+ if (*qh == NULL) { -+ retval = -1; -+ goto done; -+ } -+ } -+ -+ retval = dwc_otg_hcd_qh_add(hcd, *qh); -+ if (retval == 0) { -+ DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd, -+ qtd_list_entry); -+ } -+ -+ done: -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ -+ return retval; -+} -+ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -new file mode 100644 -index 0000000..6043b99 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -@@ -0,0 +1,2067 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ -+ * $Revision: #79 $ -+ * $Date: 2009/04/10 $ -+ * $Change: 1230501 $ -+ * -+ * 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_HOST_ONLY -+ -+/** @file -+ * This file implements PCD Core. All code in this file is portable and don't -+ * use any OS specific functions. -+ * PCD Core provides Interface, defined in -+ * header file, which can be used to implement OS specific PCD interface. -+ * -+ * An important function of the PCD is managing interrupts generated -+ * by the DWC_otg controller. The implementation of the DWC_otg device -+ * mode interrupt service routines is in dwc_otg_pcd_intr.c. -+ * -+ * @todo Add Device Mode test modes (Test J mode, Test K mode, etc). -+ * @todo Does it work when the request size is greater than DEPTSIZ -+ * transfer size -+ * -+ */ -+ -+#include "dwc_otg_pcd.h" -+ -+#ifdef DWC_UTE_CFI -+#include "dwc_otg_cfi.h" -+ -+extern int init_cfi(cfiobject_t * cfiobj); -+#endif -+ -+static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) -+{ -+ int i; -+ if (pcd->ep0.priv == handle) { -+ return &pcd->ep0; -+ } -+ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { -+ if (pcd->in_ep[i].priv == handle) -+ return &pcd->in_ep[i]; -+ if (pcd->out_ep[i].priv == handle) -+ return &pcd->out_ep[i]; -+ } -+ -+ return NULL; -+} -+ -+/** -+ * This function completes a request. It call's the request call back. -+ */ -+void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req, -+ int32_t status) -+{ -+ unsigned stopped = ep->stopped; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, ep); -+ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); -+ -+ /* don't modify queue heads during completion callback */ -+ ep->stopped = 1; -+ DWC_SPINUNLOCK(ep->pcd->lock); -+ ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status, -+ req->actual); -+ DWC_SPINLOCK(ep->pcd->lock); -+ -+ if (ep->pcd->request_pending > 0) { -+ --ep->pcd->request_pending; -+ } -+ -+ ep->stopped = stopped; -+ dwc_free(req); -+} -+ -+/** -+ * This function terminates all the requsts in the EP request queue. -+ */ -+void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep) -+{ -+ dwc_otg_pcd_request_t *req; -+ -+ ep->stopped = 1; -+ -+ /* called with irqs blocked?? */ -+ while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN); -+ } -+} -+ -+void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, -+ const struct dwc_otg_pcd_function_ops *fops) -+{ -+ pcd->fops = fops; -+} -+ -+/** -+ * PCD Callback function for initializing the PCD when switching to -+ * device mode. -+ * -+ * @param p void pointer to the dwc_otg_pcd_t -+ */ -+static int32_t dwc_otg_pcd_start_cb(void *p) -+{ -+ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; -+ -+ /* -+ * Initialized the Core for Device mode. -+ */ -+ if (dwc_otg_is_device_mode(GET_CORE_IF(pcd))) { -+ dwc_otg_core_dev_init(GET_CORE_IF(pcd)); -+ } -+ return 1; -+} -+ -+/** CFI-specific buffer allocation function for EP */ -+#ifdef DWC_UTE_CFI -+uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, -+ size_t buflen, int flags) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ ep = get_ep_from_handle(pcd, pep); -+ return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen, -+ flags); -+} -+#else -+uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, -+ size_t buflen, int flags); -+#endif -+ -+/** -+ * PCD Callback function for notifying the PCD when resuming from -+ * suspend. -+ * -+ * @param p void pointer to the dwc_otg_pcd_t -+ */ -+static int32_t dwc_otg_pcd_resume_cb(void *p) -+{ -+ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; -+ -+ if (pcd->fops->resume) { -+ pcd->fops->resume(pcd); -+ } -+ -+ /* Stop the SRP timeout timer. */ -+ if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS) -+ || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) { -+ if (GET_CORE_IF(pcd)->srp_timer_started) { -+ GET_CORE_IF(pcd)->srp_timer_started = 0; -+ DWC_TIMER_CANCEL(pcd->srp_timer); -+ } -+ } -+ return 1; -+} -+ -+/** -+ * PCD Callback function for notifying the PCD device is suspended. -+ * -+ * @param p void pointer to the dwc_otg_pcd_t -+ */ -+static int32_t dwc_otg_pcd_suspend_cb(void *p) -+{ -+ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; -+ -+ if (pcd->fops->suspend) { -+ pcd->fops->suspend(pcd); -+ } -+ -+ return 1; -+} -+ -+/** -+ * PCD Callback function for stopping the PCD when switching to Host -+ * mode. -+ * -+ * @param p void pointer to the dwc_otg_pcd_t -+ */ -+static int32_t dwc_otg_pcd_stop_cb(void *p) -+{ -+ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; -+ extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd); -+ -+ dwc_otg_pcd_stop(pcd); -+ return 1; -+} -+ -+/** -+ * PCD Callback structure for handling mode switching. -+ */ -+static dwc_otg_cil_callbacks_t pcd_callbacks = { -+ .start = dwc_otg_pcd_start_cb, -+ .stop = dwc_otg_pcd_stop_cb, -+ .suspend = dwc_otg_pcd_suspend_cb, -+ .resume_wakeup = dwc_otg_pcd_resume_cb, -+ .p = 0, /* Set at registration */ -+}; -+ -+/** -+ * This function allocates a DMA Descriptor chain for the Endpoint -+ * buffer to be used for a transfer to/from the specified endpoint. -+ */ -+dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(uint32_t * dma_desc_addr, -+ uint32_t count) -+{ -+ -+ return dwc_dma_alloc(count * sizeof(dwc_otg_dev_dma_desc_t), dma_desc_addr); -+} -+ -+/** -+ * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. -+ */ -+void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, -+ uint32_t dma_desc_addr, uint32_t count) -+{ -+ dwc_dma_free(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, -+ dma_desc_addr); -+} -+ -+#ifdef DWC_EN_ISOC -+ -+/** -+ * This function initializes a descriptor chain for Isochronous transfer -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param dwc_ep The EP to start the transfer on. -+ * -+ */ -+void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * dwc_ep) -+{ -+ -+ dsts_data_t dsts = {.d32 = 0 }; -+ depctl_data_t depctl = {.d32 = 0 }; -+ volatile uint32_t *addr; -+ int i, j; -+ -+ if (dwc_ep->is_in) -+ dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval; -+ else -+ dwc_ep->desc_cnt = -+ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / -+ dwc_ep->bInterval; -+ -+ /** Allocate descriptors for double buffering */ -+ dwc_ep->iso_desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr, -+ dwc_ep->desc_cnt * 2); -+ if (dwc_ep->desc_addr) { -+ DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__); -+ return; -+ } -+ -+ dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ -+ /** ISO OUT EP */ -+ if (dwc_ep->is_in == 0) { -+ dev_dma_desc_sts_t sts = {.d32 = 0 }; -+ dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr; -+ dma_addr_t dma_ad; -+ uint32_t data_per_desc; -+ dwc_otg_dev_out_ep_regs_t *out_regs = -+ core_if->dev_if->out_ep_regs[dwc_ep->num]; -+ int offset; -+ -+ addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; -+ dma_ad = (dma_addr_t) dwc_read_reg32(&(out_regs->doepdma)); -+ -+ /** Buffer 0 descriptors setup */ -+ dma_ad = dwc_ep->dma_addr0; -+ -+ sts.b_iso_out.bs = BS_HOST_READY; -+ sts.b_iso_out.rxsts = 0; -+ sts.b_iso_out.l = 0; -+ sts.b_iso_out.sp = 0; -+ sts.b_iso_out.ioc = 0; -+ sts.b_iso_out.pid = 0; -+ sts.b_iso_out.framenum = 0; -+ -+ offset = 0; -+ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; -+ i += dwc_ep->pkt_per_frm) { -+ -+ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep-> -+ data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - -+ data_per_desc % -+ 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ offset += data_per_desc; -+ dma_desc++; -+ dma_ad += data_per_desc; -+ } -+ } -+ -+ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ offset += data_per_desc; -+ dma_desc++; -+ dma_ad += data_per_desc; -+ } -+ -+ sts.b_iso_out.ioc = 1; -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ dma_desc++; -+ -+ /** Buffer 1 descriptors setup */ -+ sts.b_iso_out.ioc = 0; -+ dma_ad = dwc_ep->dma_addr1; -+ -+ offset = 0; -+ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; -+ i += dwc_ep->pkt_per_frm) { -+ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep-> -+ data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - -+ data_per_desc % -+ 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ offset += data_per_desc; -+ dma_desc++; -+ dma_ad += data_per_desc; -+ } -+ } -+ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ offset += data_per_desc; -+ dma_desc++; -+ dma_ad += data_per_desc; -+ } -+ -+ sts.b_iso_out.ioc = 1; -+ sts.b_iso_out.l = 1; -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ dwc_ep->next_frame = 0; -+ -+ /** Write dma_ad into DOEPDMA register */ -+ dwc_write_reg32(&(out_regs->doepdma), -+ (uint32_t) dwc_ep->iso_dma_desc_addr); -+ -+ } -+ /** ISO IN EP */ -+ else { -+ dev_dma_desc_sts_t sts = {.d32 = 0 }; -+ dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr; -+ dma_addr_t dma_ad; -+ dwc_otg_dev_in_ep_regs_t *in_regs = -+ core_if->dev_if->in_ep_regs[dwc_ep->num]; -+ unsigned int frmnumber; -+ fifosize_data_t txfifosize, rxfifosize; -+ -+ txfifosize.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[dwc_ep->num]-> -+ dtxfsts); -+ rxfifosize.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->grxfsiz); -+ -+ addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; -+ -+ dma_ad = dwc_ep->dma_addr0; -+ -+ dsts.d32 = -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ -+ sts.b_iso_in.bs = BS_HOST_READY; -+ sts.b_iso_in.txsts = 0; -+ sts.b_iso_in.sp = -+ (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0; -+ sts.b_iso_in.ioc = 0; -+ sts.b_iso_in.pid = dwc_ep->pkt_per_frm; -+ -+ frmnumber = dwc_ep->next_frame; -+ -+ sts.b_iso_in.framenum = frmnumber; -+ sts.b_iso_in.txbytes = dwc_ep->data_per_frame; -+ sts.b_iso_in.l = 0; -+ -+ /** Buffer 0 descriptors setup */ -+ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ dma_desc++; -+ -+ dma_ad += dwc_ep->data_per_frame; -+ sts.b_iso_in.framenum += dwc_ep->bInterval; -+ } -+ -+ sts.b_iso_in.ioc = 1; -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ ++dma_desc; -+ -+ /** Buffer 1 descriptors setup */ -+ sts.b_iso_in.ioc = 0; -+ dma_ad = dwc_ep->dma_addr1; -+ -+ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; -+ i += dwc_ep->pkt_per_frm) { -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ dma_desc++; -+ -+ dma_ad += dwc_ep->data_per_frame; -+ sts.b_iso_in.framenum += dwc_ep->bInterval; -+ -+ sts.b_iso_in.ioc = 0; -+ } -+ sts.b_iso_in.ioc = 1; -+ sts.b_iso_in.l = 1; -+ -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval; -+ -+ /** Write dma_ad into diepdma register */ -+ dwc_write_reg32(&(in_regs->diepdma), -+ (uint32_t) dwc_ep->iso_dma_desc_addr); -+ } -+ /** Enable endpoint, clear nak */ -+ depctl.d32 = 0; -+ depctl.b.epena = 1; -+ depctl.b.usbactep = 1; -+ depctl.b.cnak = 1; -+ -+ dwc_modify_reg32(addr, depctl.d32, depctl.d32); -+ depctl.d32 = dwc_read_reg32(addr); -+} -+ -+/** -+ * This function initializes a descriptor chain for Isochronous transfer -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ * -+ */ -+ -+void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * ep) -+{ -+ depctl_data_t depctl = {.d32 = 0 }; -+ volatile uint32_t *addr; -+ -+ if (ep->is_in) { -+ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; -+ } else { -+ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; -+ } -+ -+ if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) { -+ return; -+ } else { -+ deptsiz_data_t deptsiz = {.d32 = 0 }; -+ -+ ep->xfer_len = -+ ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval; -+ ep->pkt_cnt = -+ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; -+ ep->xfer_count = 0; -+ ep->xfer_buff = -+ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; -+ ep->dma_addr = -+ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; -+ -+ if (ep->is_in) { -+ /* Program the transfer size and packet count -+ * as follows: xfersize = N * maxpacket + -+ * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) -+ */ -+ deptsiz.b.mc = ep->pkt_per_frm; -+ deptsiz.b.xfersize = ep->xfer_len; -+ deptsiz.b.pktcnt = -+ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; -+ dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ dieptsiz, deptsiz.d32); -+ -+ /* Write the DMA register */ -+ dwc_write_reg32(& -+ (core_if->dev_if->in_ep_regs[ep->num]-> -+ diepdma), (uint32_t) ep->dma_addr); -+ -+ } else { -+ deptsiz.b.pktcnt = -+ (ep->xfer_len + (ep->maxpacket - 1)) / -+ ep->maxpacket; -+ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; -+ -+ dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> -+ doeptsiz, deptsiz.d32); -+ -+ /* Write the DMA register */ -+ dwc_write_reg32(& -+ (core_if->dev_if->out_ep_regs[ep->num]-> -+ doepdma), (uint32_t) ep->dma_addr); -+ -+ } -+ /** Enable endpoint, clear nak */ -+ depctl.d32 = 0; -+ dwc_modify_reg32(addr, depctl.d32, depctl.d32); -+ -+ depctl.b.epena = 1; -+ depctl.b.cnak = 1; -+ -+ dwc_modify_reg32(addr, depctl.d32, depctl.d32); -+ } -+} -+ -+/** -+ * This function does the setup for a data transfer for an EP and -+ * starts the transfer. For an IN transfer, the packets will be -+ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, -+ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ */ -+ -+static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * ep) -+{ -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable) { -+ if (ep->is_in) { -+ ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm; -+ } else { -+ ep->desc_cnt = ep->pkt_cnt; -+ } -+ dwc_otg_iso_ep_start_ddma_transfer(core_if, ep); -+ } else { -+ if (core_if->pti_enh_enable) { -+ dwc_otg_iso_ep_start_buf_transfer(core_if, ep); -+ } else { -+ ep->cur_pkt_addr = -+ (ep->proc_buf_num) ? ep->xfer_buff1 : ep-> -+ xfer_buff0; -+ ep->cur_pkt_dma_addr = -+ (ep->proc_buf_num) ? ep->dma_addr1 : ep-> -+ dma_addr0; -+ dwc_otg_iso_ep_start_frm_transfer(core_if, ep); -+ } -+ } -+ } else { -+ ep->cur_pkt_addr = -+ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; -+ ep->cur_pkt_dma_addr = -+ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; -+ dwc_otg_iso_ep_start_frm_transfer(core_if, ep); -+ } -+} -+ -+/** -+ * This function does the setup for a data transfer for an EP and -+ * starts the transfer. For an IN transfer, the packets will be -+ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, -+ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ */ -+ -+void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ depctl_data_t depctl = {.d32 = 0 }; -+ volatile uint32_t *addr; -+ -+ if (ep->is_in == 1) { -+ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; -+ } else { -+ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; -+ } -+ -+ /* disable the ep */ -+ depctl.d32 = dwc_read_reg32(addr); -+ -+ depctl.b.epdis = 1; -+ depctl.b.snak = 1; -+ -+ dwc_write_reg32(addr, depctl.d32); -+ -+ if (core_if->dma_desc_enable && -+ ep->iso_desc_addr && ep->iso_dma_desc_addr) { -+ dwc_otg_ep_free_desc_chain(ep->iso_desc_addr, -+ ep->iso_dma_desc_addr, -+ ep->desc_cnt * 2); -+ } -+ -+ /* reset varibales */ -+ ep->dma_addr0 = 0; -+ ep->dma_addr1 = 0; -+ ep->xfer_buff0 = 0; -+ ep->xfer_buff1 = 0; -+ ep->data_per_frame = 0; -+ ep->data_pattern_frame = 0; -+ ep->sync_frame = 0; -+ ep->buf_proc_intrvl = 0; -+ ep->bInterval = 0; -+ ep->proc_buf_num = 0; -+ ep->pkt_per_frm = 0; -+ ep->pkt_per_frm = 0; -+ ep->desc_cnt = 0; -+ ep->iso_desc_addr = 0; -+ ep->iso_dma_desc_addr = 0; -+} -+ -+int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, -+ uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0, -+ dwc_dma_t dma1, int sync_frame, int dp_frame, -+ int data_per_frame, int start_frame, -+ int buf_proc_intrvl, void *req_handle, -+ int atomic_alloc) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ uint64_t flags = 0; -+ dwc_ep_t *dwc_ep; -+ int32_t frm_data; -+ dsts_data_t dsts; -+ dwc_otg_core_if_t *core_if; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ -+ if (!ep->desc || ep->dwc_ep.num == 0) { -+ DWC_WARN("bad ep\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ core_if = GET_CORE_IF(pcd); -+ dwc_ep = &ep->dwc_ep; -+ -+ if (ep->iso_req_handle) { -+ DWC_WARN("ISO request in progress\n"); -+ } -+ -+ dwc_ep->dma_addr0 = dma0; -+ dwc_ep->dma_addr1 = dma1; -+ -+ dwc_ep->xfer_buff0 = buf0; -+ dwc_ep->xfer_buff1 = buf1; -+ -+ dwc_ep->data_per_frame = data_per_frame; -+ -+ /** @todo - pattern data support is to be implemented in the future */ -+ dwc_ep->data_pattern_frame = dp_frame; -+ dwc_ep->sync_frame = sync_frame; -+ -+ dwc_ep->buf_proc_intrvl = buf_proc_intrvl; -+ -+ dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1); -+ -+ dwc_ep->proc_buf_num = 0; -+ -+ dwc_ep->pkt_per_frm = 0; -+ frm_data = ep->dwc_ep.data_per_frame; -+ while (frm_data > 0) { -+ dwc_ep->pkt_per_frm++; -+ frm_data -= ep->dwc_ep.maxpacket; -+ } -+ -+ dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ -+ if (start_frame == -1) { -+ dwc_ep->next_frame = dsts.b.soffn + 1; -+ if (dwc_ep->bInterval != 1) { -+ dwc_ep->next_frame = -+ dwc_ep->next_frame + (dwc_ep->bInterval - 1 - -+ dwc_ep->next_frame % -+ dwc_ep->bInterval); -+ } -+ } else { -+ dwc_ep->next_frame = start_frame; -+ } -+ -+ if (!core_if->pti_enh_enable) { -+ dwc_ep->pkt_cnt = -+ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / -+ dwc_ep->bInterval; -+ } else { -+ dwc_ep->pkt_cnt = -+ (dwc_ep->data_per_frame * -+ (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval) -+ - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket; -+ } -+ -+ if (core_if->dma_desc_enable) { -+ dwc_ep->desc_cnt = -+ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / -+ dwc_ep->bInterval; -+ } -+ -+ if (atomic_alloc) { -+ dwc_ep->pkt_info = -+ dwc_alloc_atomic(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); -+ } else { -+ dwc_ep->pkt_info = -+ dwc_alloc(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); -+ } -+ if (!dwc_ep->pkt_info) { -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ return -DWC_E_NO_MEMORY; -+ } -+ if (core_if->pti_enh_enable) { -+ dwc_memset(dwc_ep->pkt_info, 0, -+ sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); -+ } -+ -+ dwc_ep->cur_pkt = 0; -+ ep->iso_req_handle = req_handle; -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ dwc_otg_iso_ep_start_transfer(core_if, dwc_ep); -+ return 0; -+} -+ -+int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle) -+{ -+ uint64_t flags = 0; -+ dwc_otg_pcd_ep_t *ep; -+ dwc_ep_t *dwc_ep; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { -+ DWC_WARN("bad ep\n"); -+ return -DWC_E_INVALID; -+ } -+ dwc_ep = &ep->dwc_ep; -+ -+ dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep); -+ -+ dwc_free(dwc_ep->pkt_info); -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ if (ep->iso_req_handle != req_handle) { -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ return -DWC_E_INVALID; -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ -+ ep->iso_req_handle = 0; -+ return 0; -+} -+ -+/** -+ * This function is used for perodical data exchnage between PCD and gadget drivers. -+ * for Isochronous EPs -+ * -+ * - Every time a sync period completes this function is called to -+ * perform data exchange between PCD and gadget -+ */ -+void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, -+ void *req_handle) -+{ -+ int i; -+ dwc_ep_t *dwc_ep; -+ -+ dwc_ep = &ep->dwc_ep; -+ -+ DWC_SPINUNLOCK(ep->pcd->lock); -+ pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle, -+ dwc_ep->proc_buf_num ^ 0x1); -+ DWC_SPINLOCK(ep->pcd->lock); -+ -+ for (i = 0; i < dwc_ep->pkt_cnt; ++i) { -+ dwc_ep->pkt_info[i].status = 0; -+ dwc_ep->pkt_info[i].offset = 0; -+ dwc_ep->pkt_info[i].length = 0; -+ } -+} -+ -+int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *iso_req_handle) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ dwc_ep_t *dwc_ep; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ dwc_ep = &ep->dwc_ep; -+ -+ return dwc_ep->pkt_cnt; -+} -+ -+void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *iso_req_handle, int packet, -+ int *status, int *actual, int *offset) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ dwc_ep_t *dwc_ep; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ dwc_ep = &ep->dwc_ep; -+ -+ *status = dwc_ep->pkt_info[packet].status; -+ *actual = dwc_ep->pkt_info[packet].length; -+ *offset = dwc_ep->pkt_info[packet].offset; -+} -+ -+#endif /* DWC_EN_ISOC */ -+ -+static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep, -+ uint32_t is_in, uint32_t ep_num) -+{ -+ /* Init EP structure */ -+ pcd_ep->desc = 0; -+ pcd_ep->pcd = pcd; -+ pcd_ep->stopped = 1; -+ pcd_ep->queue_sof = 0; -+ -+ /* Init DWC ep structure */ -+ pcd_ep->dwc_ep.is_in = is_in; -+ pcd_ep->dwc_ep.num = ep_num; -+ pcd_ep->dwc_ep.active = 0; -+ pcd_ep->dwc_ep.tx_fifo_num = 0; -+ /* Control until ep is actvated */ -+ pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; -+ pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE; -+ pcd_ep->dwc_ep.dma_addr = 0; -+ pcd_ep->dwc_ep.start_xfer_buff = 0; -+ pcd_ep->dwc_ep.xfer_buff = 0; -+ pcd_ep->dwc_ep.xfer_len = 0; -+ pcd_ep->dwc_ep.xfer_count = 0; -+ pcd_ep->dwc_ep.sent_zlp = 0; -+ pcd_ep->dwc_ep.total_len = 0; -+ pcd_ep->dwc_ep.desc_addr = 0; -+ pcd_ep->dwc_ep.dma_desc_addr = 0; -+ DWC_CIRCLEQ_INIT(&pcd_ep->queue); -+} -+ -+/** -+ * Initialise ep's -+ */ -+static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd) -+{ -+ int i; -+ uint32_t hwcfg1; -+ dwc_otg_pcd_ep_t *ep; -+ int in_ep_cntr, out_ep_cntr; -+ uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps; -+ uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps; -+ -+ /** -+ * Initialize the EP0 structure. -+ */ -+ ep = &pcd->ep0; -+ dwc_otg_pcd_init_ep(pcd, ep, 0, 0); -+ -+ in_ep_cntr = 0; -+ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3; -+ for (i = 1; in_ep_cntr < num_in_eps; i++) { -+ if ((hwcfg1 & 0x1) == 0) { -+ dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr]; -+ in_ep_cntr++; -+ /** -+ * @todo NGS: Add direction to EP, based on contents -+ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? -+ * sprintf(";r -+ */ -+ dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i); -+ -+ DWC_CIRCLEQ_INIT(&ep->queue); -+ } -+ hwcfg1 >>= 2; -+ } -+ -+ out_ep_cntr = 0; -+ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2; -+ for (i = 1; out_ep_cntr < num_out_eps; i++) { -+ if ((hwcfg1 & 0x1) == 0) { -+ dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr]; -+ out_ep_cntr++; -+ /** -+ * @todo NGS: Add direction to EP, based on contents -+ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? -+ * sprintf(";r -+ */ -+ dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i); -+ DWC_CIRCLEQ_INIT(&ep->queue); -+ } -+ hwcfg1 >>= 2; -+ } -+ -+ pcd->ep0state = EP0_DISCONNECT; -+ pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE; -+ pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; -+} -+ -+/** -+ * This function is called when the SRP timer expires. The SRP should -+ * complete within 6 seconds. -+ */ -+static void srp_timeout(void *ptr) -+{ -+ gotgctl_data_t gotgctl; -+ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; -+ volatile uint32_t *addr = &core_if->core_global_regs->gotgctl; -+ -+ gotgctl.d32 = dwc_read_reg32(addr); -+ -+ core_if->srp_timer_started = 0; -+ -+ if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) && -+ (core_if->core_params->i2c_enable)) { -+ DWC_PRINTF("SRP Timeout\n"); -+ -+ if ((core_if->srp_success) && (gotgctl.b.bsesvld)) { -+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb-> -+ p); -+ } -+ -+ /* Clear Session Request */ -+ gotgctl.d32 = 0; -+ gotgctl.b.sesreq = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gotgctl, -+ gotgctl.d32, 0); -+ -+ core_if->srp_success = 0; -+ } else { -+ __DWC_ERROR("Device not connected/responding\n"); -+ gotgctl.b.sesreq = 0; -+ dwc_write_reg32(addr, gotgctl.d32); -+ } -+ } else if (gotgctl.b.sesreq) { -+ DWC_PRINTF("SRP Timeout\n"); -+ -+ __DWC_ERROR("Device not connected/responding\n"); -+ gotgctl.b.sesreq = 0; -+ dwc_write_reg32(addr, gotgctl.d32); -+ } else { -+ DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32); -+ } -+} -+ -+/** -+ * Tasklet -+ * -+ */ -+extern void start_next_request(dwc_otg_pcd_ep_t * ep); -+ -+static void start_xfer_tasklet_func(void *data) -+{ -+ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ -+ int i; -+ depctl_data_t diepctl; -+ -+ DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n"); -+ -+ diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -+ -+ if (pcd->ep0.queue_sof) { -+ pcd->ep0.queue_sof = 0; -+ start_next_request(&pcd->ep0); -+ // break; -+ } -+ -+ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { -+ depctl_data_t diepctl; -+ diepctl.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[i]->diepctl); -+ -+ if (pcd->in_ep[i].queue_sof) { -+ pcd->in_ep[i].queue_sof = 0; -+ start_next_request(&pcd->in_ep[i]); -+ // break; -+ } -+ } -+ -+ return; -+} -+ -+/** -+ * This function initialized the PCD portion of the driver. -+ * -+ */ -+dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) -+{ -+ dwc_otg_pcd_t *pcd = 0; -+ dwc_otg_dev_if_t *dev_if; -+ -+ /* -+ * Allocate PCD structure -+ */ -+ pcd = dwc_alloc(sizeof(dwc_otg_pcd_t)); -+ -+ if (pcd == 0) { -+ return NULL; -+ } -+ -+ pcd->lock = DWC_SPINLOCK_ALLOC(); -+ DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n", -+ pcd, core_if);//GRAYG -+ pcd->core_if = core_if; -+ if (!pcd->lock) { -+ DWC_ERROR("Could not allocate lock for pcd"); -+ dwc_free(pcd); -+ return NULL; -+ } -+ dev_if = core_if->dev_if; -+ -+ if (core_if->hwcfg4.b.ded_fifo_en) { -+ DWC_PRINTF("Dedicated Tx FIFOs mode\n"); -+ } else { -+ DWC_PRINTF("Shared Tx FIFO mode\n"); -+ } -+ -+ /* -+ * Initialized the Core for Device mode. -+ */ -+ if (dwc_otg_is_device_mode(core_if)) { -+ dwc_otg_core_dev_init(core_if); -+ } -+ -+ /* -+ * Register the PCD Callbacks. -+ */ -+ dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd); -+ -+ /* -+ * Initialize the DMA buffer for SETUP packets -+ */ -+ if (GET_CORE_IF(pcd)->dma_enable) { -+ pcd->setup_pkt = -+ dwc_dma_alloc(sizeof(*pcd->setup_pkt) * 5, -+ &pcd->setup_pkt_dma_handle); -+ if (pcd->setup_pkt == 0) { -+ dwc_free(pcd); -+ return NULL; -+ } -+ -+ pcd->status_buf = -+ dwc_dma_alloc(sizeof(uint16_t), -+ &pcd->status_buf_dma_handle); -+ if (pcd->status_buf == 0) { -+ dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, -+ pcd->setup_pkt, pcd->setup_pkt_dma_handle); -+ dwc_free(pcd); -+ return NULL; -+ } -+ -+ if (GET_CORE_IF(pcd)->dma_desc_enable) { -+ dev_if->setup_desc_addr[0] = -+ dwc_otg_ep_alloc_desc_chain(&dev_if-> -+ dma_setup_desc_addr[0], -+ 1); -+ dev_if->setup_desc_addr[1] = -+ dwc_otg_ep_alloc_desc_chain(&dev_if-> -+ dma_setup_desc_addr[1], -+ 1); -+ dev_if->in_desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&dev_if-> -+ dma_in_desc_addr, 1); -+ dev_if->out_desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&dev_if-> -+ dma_out_desc_addr, 1); -+ -+ if (dev_if->setup_desc_addr[0] == 0 -+ || dev_if->setup_desc_addr[1] == 0 -+ || dev_if->in_desc_addr == 0 -+ || dev_if->out_desc_addr == 0) { -+ -+ if (dev_if->out_desc_addr) -+ dwc_otg_ep_free_desc_chain(dev_if-> -+ out_desc_addr, -+ dev_if-> -+ dma_out_desc_addr, -+ 1); -+ if (dev_if->in_desc_addr) -+ dwc_otg_ep_free_desc_chain(dev_if-> -+ in_desc_addr, -+ dev_if-> -+ dma_in_desc_addr, -+ 1); -+ if (dev_if->setup_desc_addr[1]) -+ dwc_otg_ep_free_desc_chain(dev_if-> -+ setup_desc_addr -+ [1], -+ dev_if-> -+ dma_setup_desc_addr -+ [1], 1); -+ if (dev_if->setup_desc_addr[0]) -+ dwc_otg_ep_free_desc_chain(dev_if-> -+ setup_desc_addr -+ [0], -+ dev_if-> -+ dma_setup_desc_addr -+ [0], 1); -+ -+ dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, -+ pcd->setup_pkt, -+ pcd->setup_pkt_dma_handle); -+ dwc_dma_free(sizeof(*pcd->status_buf), -+ pcd->status_buf, -+ pcd->status_buf_dma_handle); -+ -+ dwc_free(pcd); -+ -+ return NULL; -+ } -+ } -+ } else { -+ pcd->setup_pkt = dwc_alloc(sizeof(*pcd->setup_pkt) * 5); -+ if (pcd->setup_pkt == 0) { -+ dwc_free(pcd); -+ return NULL; -+ } -+ -+ pcd->status_buf = dwc_alloc(sizeof(uint16_t)); -+ if (pcd->status_buf == 0) { -+ dwc_free(pcd->setup_pkt); -+ dwc_free(pcd); -+ return NULL; -+ } -+ } -+ -+ dwc_otg_pcd_reinit(pcd); -+ -+ /* Allocate the cfi object for the PCD */ -+#ifdef DWC_UTE_CFI -+ pcd->cfi = dwc_alloc(sizeof(cfiobject_t)); -+ if (NULL == pcd->cfi) -+ return NULL; -+ if (init_cfi(pcd->cfi)) { -+ CFI_INFO("%s: Failed to init the CFI object\n", __func__); -+ return NULL; -+ } -+#endif -+ -+ /* Initialize tasklets */ -+ pcd->start_xfer_tasklet = DWC_TASK_ALLOC(start_xfer_tasklet_func, pcd); -+ pcd->test_mode_tasklet = DWC_TASK_ALLOC(do_test_mode, pcd); -+ /* Initialize timer */ -+ pcd->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if); -+ return pcd; -+} -+ -+void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; -+ -+ if (GET_CORE_IF(pcd)->dma_enable) { -+ dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, -+ pcd->setup_pkt_dma_handle); -+ dwc_dma_free(sizeof(uint16_t), pcd->status_buf, -+ pcd->status_buf_dma_handle); -+ if (GET_CORE_IF(pcd)->dma_desc_enable) { -+ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], -+ dev_if-> -+ dma_setup_desc_addr[0], 1); -+ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], -+ dev_if-> -+ dma_setup_desc_addr[1], 1); -+ dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, -+ dev_if->dma_in_desc_addr, 1); -+ dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, -+ dev_if->dma_out_desc_addr, -+ 1); -+ } -+ } else { -+ dwc_free(pcd->setup_pkt); -+ dwc_free(pcd->status_buf); -+ } -+ DWC_SPINLOCK_FREE(pcd->lock); -+ DWC_TASK_FREE(pcd->start_xfer_tasklet); -+ DWC_TASK_FREE(pcd->test_mode_tasklet); -+ DWC_TIMER_FREE(pcd->srp_timer); -+ -+/* Release the CFI object's dynamic memory */ -+#ifdef DWC_UTE_CFI -+ if (pcd->cfi->ops.release) { -+ pcd->cfi->ops.release(pcd->cfi); -+ } -+#endif -+ -+ dwc_free(pcd); -+} -+ -+uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ -+ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) || -+ ((core_if->hwcfg2.b.hs_phy_type == 2) && -+ (core_if->hwcfg2.b.fs_phy_type == 1) && -+ (core_if->core_params->ulpi_fs_ls))) { -+ return 0; -+ } -+ -+ return 1; -+} -+ -+uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ gusbcfg_data_t usbcfg = {.d32 = 0 }; -+ -+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg); -+ if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) { -+ return 0; -+ } -+ -+ return 1; -+} -+ -+/** -+ * This function assigns periodic Tx FIFO to an periodic EP -+ * in shared Tx FIFO mode -+ */ -+static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if) -+{ -+ uint32_t TxMsk = 1; -+ int i; -+ -+ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) { -+ if ((TxMsk & core_if->tx_msk) == 0) { -+ core_if->tx_msk |= TxMsk; -+ return i + 1; -+ } -+ TxMsk <<= 1; -+ } -+ return 0; -+} -+ -+/** -+ * This function assigns periodic Tx FIFO to an periodic EP -+ * in shared Tx FIFO mode -+ */ -+static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if) -+{ -+ uint32_t PerTxMsk = 1; -+ int i; -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) { -+ if ((PerTxMsk & core_if->p_tx_msk) == 0) { -+ core_if->p_tx_msk |= PerTxMsk; -+ return i + 1; -+ } -+ PerTxMsk <<= 1; -+ } -+ return 0; -+} -+ -+/** -+ * This function releases periodic Tx FIFO -+ * in shared Tx FIFO mode -+ */ -+static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if, -+ uint32_t fifo_num) -+{ -+ core_if->p_tx_msk = -+ (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk; -+} -+ -+/** -+ * This function releases periodic Tx FIFO -+ * in shared Tx FIFO mode -+ */ -+static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num) -+{ -+ core_if->tx_msk = -+ (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk; -+} -+ -+int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, -+ const uint8_t * ep_desc, void *usb_ep) -+{ -+ int num, dir; -+ dwc_otg_pcd_ep_t *ep = 0; -+ const usb_endpoint_descriptor_t *desc; -+ uint64_t flags; -+ int retval = 0; -+ -+ desc = (const usb_endpoint_descriptor_t *)ep_desc; -+ -+ if (!desc) { -+ pcd->ep0.priv = usb_ep; -+ ep = &pcd->ep0; -+ retval = -DWC_E_INVALID; -+ goto out; -+ } -+ -+ num = UE_GET_ADDR(desc->bEndpointAddress); -+ dir = UE_GET_DIR(desc->bEndpointAddress); -+ -+ if (!desc->wMaxPacketSize) { -+ DWC_WARN("bad maxpacketsize\n"); -+ retval = -DWC_E_INVALID; -+ goto out; -+ } -+ -+ if (dir == UE_DIR_IN) { -+ ep = &pcd->in_ep[num - 1]; -+ } else { -+ ep = &pcd->out_ep[num - 1]; -+ } -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ -+ ep->desc = desc; -+ ep->priv = usb_ep; -+ -+ /* -+ * Activate the EP -+ */ -+ ep->stopped = 0; -+ -+ ep->dwc_ep.is_in = (dir == UE_DIR_IN); -+ ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize); -+ -+ ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE; -+ -+ if (ep->dwc_ep.is_in) { -+ if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) { -+ ep->dwc_ep.tx_fifo_num = 0; -+ -+ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { -+ /* -+ * if ISOC EP then assign a Periodic Tx FIFO. -+ */ -+ ep->dwc_ep.tx_fifo_num = -+ assign_perio_tx_fifo(GET_CORE_IF(pcd)); -+ } -+ } else { -+ /* -+ * if Dedicated FIFOs mode is on then assign a Tx FIFO. -+ */ -+ ep->dwc_ep.tx_fifo_num = -+ assign_tx_fifo(GET_CORE_IF(pcd)); -+ -+ } -+ } -+ /* Set initial data PID. */ -+ if (ep->dwc_ep.type == UE_BULK) { -+ ep->dwc_ep.data_pid_start = 0; -+ } -+ -+ /* Alloc DMA Descriptors */ -+ if (GET_CORE_IF(pcd)->dma_desc_enable) { -+ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { -+ ep->dwc_ep.desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&ep->dwc_ep. -+ dma_desc_addr, -+ MAX_DMA_DESC_CNT); -+ if (!ep->dwc_ep.desc_addr) { -+ DWC_WARN("%s, can't allocate DMA descriptor\n", -+ __func__); -+ retval = -DWC_E_SHUTDOWN; -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ goto out; -+ } -+ } -+ } -+ -+ DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n", -+ (ep->dwc_ep.is_in ? "IN" : "OUT"), -+ ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc); -+ -+ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); -+ -+#ifdef DWC_UTE_CFI -+ if (pcd->cfi->ops.ep_enable) { -+ pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep); -+ } -+#endif -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ -+ out: -+ return retval; -+} -+ -+int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ uint64_t flags; -+ dwc_otg_dev_dma_desc_t *desc_addr; -+ dwc_dma_t dma_desc_addr; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ -+ if (!ep || !ep->desc) { -+ DWC_DEBUGPL(DBG_PCD, "%s, %d %s not enabled\n", __func__, -+ ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); -+ return -DWC_E_INVALID; -+ } -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ -+ dwc_otg_request_nuke(ep); -+ -+ dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep); -+ ep->desc = 0; -+ ep->stopped = 1; -+ -+ if (ep->dwc_ep.is_in) { -+ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); -+ release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); -+ release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); -+ } -+ -+ /* Free DMA Descriptors */ -+ if (GET_CORE_IF(pcd)->dma_desc_enable) { -+ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { -+ desc_addr = ep->dwc_ep.desc_addr; -+ dma_desc_addr = ep->dwc_ep.dma_desc_addr; -+ -+ /* Cannot call dma_free_coherent() with IRQs disabled */ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, -+ MAX_DMA_DESC_CNT); -+ -+ goto out_unlocked; -+ } -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ -+ out_unlocked: -+ DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num, -+ ep->dwc_ep.is_in ? "IN" : "OUT"); -+ return 0; -+ -+} -+ -+int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, -+ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, -+ int zero, void *req_handle, int atomic_alloc) -+{ -+ int prevented = 0; -+ uint64_t flags; -+ dwc_otg_pcd_request_t *req; -+ dwc_otg_pcd_ep_t *ep; -+ uint32_t max_transfer; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ if ((!ep->desc && ep->dwc_ep.num != 0)) { -+ DWC_WARN("bad ep\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if (atomic_alloc) { -+ req = dwc_alloc_atomic(sizeof(*req)); -+ } else { -+ req = dwc_alloc(sizeof(*req)); -+ } -+ -+ if (!req) { -+ return -DWC_E_NO_MEMORY; -+ } -+ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); -+ if (!GET_CORE_IF(pcd)->core_params->opt) { -+ if (ep->dwc_ep.num != 0) { -+ DWC_ERROR("queue req %p, len %d buf %p\n", -+ req_handle, buflen, buf); -+ } -+ } -+ -+ req->buf = buf; -+ req->dma = dma_buf; -+ req->length = buflen; -+ req->sent_zlp = zero; -+ req->priv = req_handle; -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ -+ /* -+ * For EP0 IN without premature status, zlp is required? -+ */ -+ if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) { -+ DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num); -+ //_req->zero = 1; -+ } -+ -+ /* Start the transfer */ -+ if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) { -+ /* EP0 Transfer? */ -+ if (ep->dwc_ep.num == 0) { -+ switch (pcd->ep0state) { -+ case EP0_IN_DATA_PHASE: -+ DWC_DEBUGPL(DBG_PCD, -+ "%s ep0: EP0_IN_DATA_PHASE\n", -+ __func__); -+ break; -+ -+ case EP0_OUT_DATA_PHASE: -+ DWC_DEBUGPL(DBG_PCD, -+ "%s ep0: EP0_OUT_DATA_PHASE\n", -+ __func__); -+ if (pcd->request_config) { -+ /* Complete STATUS PHASE */ -+ ep->dwc_ep.is_in = 1; -+ pcd->ep0state = EP0_IN_STATUS_PHASE; -+ } -+ break; -+ -+ case EP0_IN_STATUS_PHASE: -+ DWC_DEBUGPL(DBG_PCD, -+ "%s ep0: EP0_IN_STATUS_PHASE\n", -+ __func__); -+ break; -+ -+ default: -+ DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", -+ pcd->ep0state); -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ return -DWC_E_SHUTDOWN; -+ } -+ -+ ep->dwc_ep.dma_addr = dma_buf; -+ ep->dwc_ep.start_xfer_buff = buf; -+ ep->dwc_ep.xfer_buff = buf; -+ ep->dwc_ep.xfer_len = buflen; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; -+ -+ if (zero) { -+ if ((ep->dwc_ep.xfer_len % -+ ep->dwc_ep.maxpacket == 0) -+ && (ep->dwc_ep.xfer_len != 0)) { -+ ep->dwc_ep.sent_zlp = 1; -+ } -+ -+ } -+ -+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), -+ &ep->dwc_ep); -+ } // non-ep0 endpoints -+ else { -+#ifdef DWC_UTE_CFI -+ if (ep->dwc_ep.buff_mode != BM_STANDARD) { -+ /* store the request length */ -+ ep->dwc_ep.cfi_req_len = buflen; -+ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, -+ ep, req); -+ } else { -+#endif -+ max_transfer = -+ GET_CORE_IF(ep->pcd)->core_params-> -+ max_transfer_size; -+ -+ /* Setup and start the Transfer */ -+ ep->dwc_ep.dma_addr = dma_buf; -+ ep->dwc_ep.start_xfer_buff = buf; -+ ep->dwc_ep.xfer_buff = buf; -+ ep->dwc_ep.xfer_len = 0; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = buflen; -+ -+ ep->dwc_ep.maxxfer = max_transfer; -+ if (GET_CORE_IF(pcd)->dma_desc_enable) { -+ uint32_t out_max_xfer = -+ DDMA_MAX_TRANSFER_SIZE - -+ (DDMA_MAX_TRANSFER_SIZE % 4); -+ if (ep->dwc_ep.is_in) { -+ if (ep->dwc_ep.maxxfer > -+ DDMA_MAX_TRANSFER_SIZE) { -+ ep->dwc_ep.maxxfer = -+ DDMA_MAX_TRANSFER_SIZE; -+ } -+ } else { -+ if (ep->dwc_ep.maxxfer > -+ out_max_xfer) { -+ ep->dwc_ep.maxxfer = -+ out_max_xfer; -+ } -+ } -+ } -+ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { -+ ep->dwc_ep.maxxfer -= -+ (ep->dwc_ep.maxxfer % -+ ep->dwc_ep.maxpacket); -+ } -+ -+ if (zero) { -+ if ((ep->dwc_ep.total_len % -+ ep->dwc_ep.maxpacket == 0) -+ && (ep->dwc_ep.total_len != 0)) { -+ ep->dwc_ep.sent_zlp = 1; -+ } -+ } -+#ifdef DWC_UTE_CFI -+ } -+#endif -+ dwc_otg_ep_start_transfer(GET_CORE_IF(pcd), -+ &ep->dwc_ep); -+ } -+ } -+ -+ if ((req != 0) || prevented) { -+ ++pcd->request_pending; -+ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); -+ if (ep->dwc_ep.is_in && ep->stopped -+ && !(GET_CORE_IF(pcd)->dma_enable)) { -+ /** @todo NGS Create a function for this. */ -+ diepmsk_data_t diepmsk = {.d32 = 0 }; -+ diepmsk.b.intktxfemp = 1; -+ if (GET_CORE_IF(pcd)->multiproc_int_enable) { -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ dev_global_regs-> -+ diepeachintmsk[ep->dwc_ep.num], -+ 0, diepmsk.d32); -+ } else { -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ dev_global_regs->diepmsk, 0, -+ diepmsk.d32); -+ } -+ -+ } -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ -+ return 0; -+} -+int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle) -+{ -+ uint64_t flags; -+ dwc_otg_pcd_request_t *req; -+ dwc_otg_pcd_ep_t *ep; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ if (!ep->desc && ep->dwc_ep.num != 0) { -+ DWC_WARN("bad argument\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ -+ /* make sure it's actually queued on this endpoint */ -+ DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { -+ if (req->priv == (void *)req_handle) { -+ break; -+ } -+ } -+ -+ if (req->priv != (void *)req_handle) { -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ return -DWC_E_INVALID; -+ } -+ -+ if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) { -+ dwc_otg_request_done(ep, req, -DWC_E_RESTART); -+ } else { -+ req = 0; -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ -+ return req ? 0 : -DWC_E_SHUTDOWN; -+ -+} -+ -+/** -+ * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests -+ * -+ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT) -+ * requests. If the gadget driver clears the halt status, it will -+ * automatically unwedge the endpoint. -+ * -+ * Returns zero on success, else negative DWC error code. -+ */ -+int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ uint64_t flags; -+ int retval = 0; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ -+ if ((!ep->desc && ep != &pcd->ep0) || -+ (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { -+ DWC_WARN("%s, bad ep\n", __func__); -+ return -DWC_E_INVALID; -+ } -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num, -+ ep->dwc_ep.is_in ? "IN" : "OUT"); -+ retval = -DWC_E_AGAIN; -+ } else { -+ /* This code needs to be reviewed */ -+ if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) { -+ dtxfsts_data_t txstatus; -+ fifosize_data_t txfifosize; -+ -+ txfifosize.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs-> -+ dptxfsiz_dieptxf[ep->dwc_ep. -+ tx_fifo_num]); -+ txstatus.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ in_ep_regs[ep->dwc_ep.num]->dtxfsts); -+ -+ if (txstatus.b.txfspcavail < txfifosize.b.depth) { -+ DWC_WARN("%s() Data In Tx Fifo\n", __func__); -+ retval = -DWC_E_AGAIN; -+ } else { -+ if (ep->dwc_ep.num == 0) { -+ pcd->ep0state = EP0_STALL; -+ } -+ -+ ep->stopped = 1; -+ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), -+ &ep->dwc_ep); -+ } -+ } else { -+ if (ep->dwc_ep.num == 0) { -+ pcd->ep0state = EP0_STALL; -+ } -+ -+ ep->stopped = 1; -+ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep); -+ } -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ -+ return retval; -+} -+ -+int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ uint64_t flags; -+ int retval = 0; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ -+ if ((!ep->desc && ep != &pcd->ep0) || -+ (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { -+ DWC_WARN("%s, bad ep\n", __func__); -+ return -DWC_E_INVALID; -+ } -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num, -+ ep->dwc_ep.is_in ? "IN" : "OUT"); -+ retval = -DWC_E_AGAIN; -+ } else if (value == 0) { -+ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); -+ } else if (value == 1) { -+ if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) { -+ dtxfsts_data_t txstatus; -+ fifosize_data_t txfifosize; -+ -+ txfifosize.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs-> -+ dptxfsiz_dieptxf[ep->dwc_ep. -+ tx_fifo_num]); -+ txstatus.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ in_ep_regs[ep->dwc_ep.num]->dtxfsts); -+ -+ if (txstatus.b.txfspcavail < txfifosize.b.depth) { -+ DWC_WARN("%s() Data In Tx Fifo\n", __func__); -+ retval = -DWC_E_AGAIN; -+ } else { -+ if (ep->dwc_ep.num == 0) { -+ pcd->ep0state = EP0_STALL; -+ } -+ -+ ep->stopped = 1; -+ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), -+ &ep->dwc_ep); -+ } -+ } else { -+ if (ep->dwc_ep.num == 0) { -+ pcd->ep0state = EP0_STALL; -+ } -+ -+ ep->stopped = 1; -+ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep); -+ } -+ } else if (value == 2) { -+ ep->dwc_ep.stall_clear_flag = 0; -+ } else if (value == 3) { -+ ep->dwc_ep.stall_clear_flag = 1; -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ -+ return retval; -+} -+ -+/** -+ * This function initiates remote wakeup of the host from suspend state. -+ */ -+void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set) -+{ -+ dctl_data_t dctl = { 0 }; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dsts_data_t dsts; -+ -+ dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ if (!dsts.b.suspsts) { -+ DWC_WARN("Remote wakeup while is not in suspend state\n"); -+ } -+ /* Check if DEVICE_REMOTE_WAKEUP feature enabled */ -+ if (pcd->remote_wakeup_enable) { -+ if (set) { -+ dctl.b.rmtwkupsig = 1; -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ dctl, 0, dctl.d32); -+ DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); -+ dwc_mdelay(2); -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ dctl, dctl.d32, 0); -+ DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); -+ } -+ } else { -+ DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n"); -+ } -+} -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+/** -+ * This function initiates remote wakeup of the host from L1 sleep state. -+ */ -+void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set) -+{ -+ glpmcfg_data_t lpmcfg; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ -+ /* Check if we are in L1 state */ -+ if (!lpmcfg.b.prt_sleep_sts) { -+ DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n"); -+ return; -+ } -+ -+ /* Check if host allows remote wakeup */ -+ if (!lpmcfg.b.rem_wkup_en) { -+ DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n"); -+ return; -+ } -+ -+ /* Check if Resume OK */ -+ if (!lpmcfg.b.sleep_state_resumeok) { -+ DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n"); -+ return; -+ } -+ -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ lpmcfg.b.en_utmi_sleep = 0; -+ lpmcfg.b.hird_thres &= (~(1 << 4)); -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); -+ -+ if (set) { -+ dctl_data_t dctl = {.d32 = 0 }; -+ dctl.b.rmtwkupsig = 1; -+ /* Set RmtWkUpSig bit to start remote wakup signaling. -+ * Hardware will automatically clear this bit. -+ */ -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, -+ 0, dctl.d32); -+ DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); -+ } -+ -+} -+#endif -+ -+/** -+ * Performs remote wakeup. -+ */ -+void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ if (dwc_otg_is_device_mode(core_if)) { -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ if (core_if->lx_state == DWC_OTG_L1) { -+ dwc_otg_pcd_rem_wkup_from_sleep(pcd, set); -+ } else { -+#endif -+ dwc_otg_pcd_rem_wkup_from_suspend(pcd, set); -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ } -+#endif -+ } -+ return; -+} -+ -+int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) -+{ -+ dsts_data_t dsts; -+ gotgctl_data_t gotgctl; -+ uint64_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ -+ /* -+ * This function starts the Protocol if no session is in progress. If -+ * a session is already in progress, but the device is suspended, -+ * remote wakeup signaling is started. -+ */ -+ -+ /* Check if valid session */ -+ gotgctl.d32 = -+ dwc_read_reg32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); -+ if (gotgctl.b.bsesvld) { -+ /* Check if suspend state */ -+ dsts.d32 = -+ dwc_read_reg32(& -+ (GET_CORE_IF(pcd)->dev_if->dev_global_regs-> -+ dsts)); -+ if (dsts.b.suspsts) { -+ dwc_otg_pcd_remote_wakeup(pcd, 1); -+ } -+ } else { -+ dwc_otg_pcd_initiate_srp(pcd); -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ return 0; -+ -+} -+ -+/** -+ * Start the SRP timer to detect when the SRP does not complete within -+ * 6 seconds. -+ * -+ * @param pcd the pcd structure. -+ */ -+void dwc_otg_pcd_start_srp_timer(dwc_otg_pcd_t * pcd) -+{ -+ GET_CORE_IF(pcd)->srp_timer_started = 1; -+ DWC_TIMER_SCHEDULE(pcd->srp_timer, 6000 /* 6 secs */ ); -+} -+ -+void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd) -+{ -+ uint32_t *addr = -+ (uint32_t *) & (GET_CORE_IF(pcd)->core_global_regs->gotgctl); -+ gotgctl_data_t mem; -+ gotgctl_data_t val; -+ -+ val.d32 = dwc_read_reg32(addr); -+ if (val.b.sesreq) { -+ DWC_ERROR("Session Request Already active!\n"); -+ return; -+ } -+ -+ DWC_INFO("Session Request Initated\n"); //NOTICE -+ mem.d32 = dwc_read_reg32(addr); -+ mem.b.sesreq = 1; -+ dwc_write_reg32(addr, mem.d32); -+ -+ /* Start the SRP timer */ -+ dwc_otg_pcd_start_srp_timer(pcd); -+ return; -+} -+ -+int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd) -+{ -+ return dwc_otg_get_frame_number(GET_CORE_IF(pcd)); -+} -+ -+int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd) -+{ -+ return GET_CORE_IF(pcd)->core_params->lpm_enable; -+} -+ -+uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd) -+{ -+ return pcd->b_hnp_enable; -+} -+ -+uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd) -+{ -+ return pcd->a_hnp_support; -+} -+ -+uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd) -+{ -+ return pcd->a_alt_hnp_support; -+} -+ -+int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd) -+{ -+ return pcd->remote_wakeup_enable; -+} -+ -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -new file mode 100644 -index 0000000..d38e169 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -@@ -0,0 +1,216 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ -+ * $Revision: #39 $ -+ * $Date: 2008/12/16 $ -+ * $Change: 1153731 $ -+ * -+ * 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_HOST_ONLY -+#if !defined(__DWC_PCD_H__) -+#define __DWC_PCD_H__ -+ -+#include "usb.h" -+#include "dwc_otg_cil.h" -+#include "dwc_otg_pcd_if.h" -+struct cfiobject; -+ -+/** -+ * @file -+ * -+ * This file contains the structures, constants, and interfaces for -+ * the Perpherial Contoller Driver (PCD). -+ * -+ * The Peripheral Controller Driver (PCD) for Linux will implement the -+ * Gadget API, so that the existing Gadget drivers can be used. For -+ * the Mass Storage Function driver the File-backed USB Storage Gadget -+ * (FBS) driver will be used. The FBS driver supports the -+ * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only -+ * transports. -+ * -+ */ -+ -+/** Max Transfer size for any EP */ -+#define DDMA_MAX_TRANSFER_SIZE 65535 -+ -+/** Max DMA Descriptor count for any EP */ -+#define MAX_DMA_DESC_CNT 64 -+ -+/** -+ * Get the pointer to the core_if from the pcd pointer. -+ */ -+#define GET_CORE_IF( _pcd ) (_pcd->core_if) -+ -+/** -+ * States of EP0. -+ */ -+typedef enum ep0_state { -+ EP0_DISCONNECT, /* no host */ -+ EP0_IDLE, -+ EP0_IN_DATA_PHASE, -+ EP0_OUT_DATA_PHASE, -+ EP0_IN_STATUS_PHASE, -+ EP0_OUT_STATUS_PHASE, -+ EP0_STALL, -+} ep0state_e; -+ -+/** Fordward declaration.*/ -+struct dwc_otg_pcd; -+ -+/** DWC_otg iso request structure. -+ * -+ */ -+typedef struct usb_iso_request dwc_otg_pcd_iso_request_t; -+ -+/** DWC_otg request structure. -+ * This structure is a list of requests. -+ */ -+typedef struct dwc_otg_pcd_request { -+ void *priv; -+ void *buf; -+ dwc_dma_t dma; -+ uint32_t length; -+ uint32_t actual; -+ unsigned sent_zlp:1; -+ -+ DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry; -+} dwc_otg_pcd_request_t; -+ -+DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request); -+ -+/** PCD EP structure. -+ * This structure describes an EP, there is an array of EPs in the PCD -+ * structure. -+ */ -+typedef struct dwc_otg_pcd_ep { -+ /** USB EP Descriptor */ -+ const usb_endpoint_descriptor_t *desc; -+ -+ /** queue of dwc_otg_pcd_requests. */ -+ struct req_list queue; -+ unsigned stopped:1; -+ unsigned disabling:1; -+ unsigned dma:1; -+ unsigned queue_sof:1; -+ -+#ifdef DWC_EN_ISOC -+ /** ISOC req handle passed */ -+ void *iso_req_handle; -+#endif //_EN_ISOC_ -+ -+ /** DWC_otg ep data. */ -+ dwc_ep_t dwc_ep; -+ -+ /** Pointer to PCD */ -+ struct dwc_otg_pcd *pcd; -+ -+ void *priv; -+} dwc_otg_pcd_ep_t; -+ -+/** DWC_otg PCD Structure. -+ * This structure encapsulates the data for the dwc_otg PCD. -+ */ -+struct dwc_otg_pcd { -+ const struct dwc_otg_pcd_function_ops *fops; -+ /** Core Interface */ -+ dwc_otg_core_if_t *core_if; -+ /** State of EP0 */ -+ ep0state_e ep0state; -+ /** EP0 Request is pending */ -+ unsigned ep0_pending:1; -+ /** Indicates when SET CONFIGURATION Request is in process */ -+ unsigned request_config:1; -+ /** The state of the Remote Wakeup Enable. */ -+ unsigned remote_wakeup_enable:1; -+ /** The state of the B-Device HNP Enable. */ -+ unsigned b_hnp_enable:1; -+ /** The state of A-Device HNP Support. */ -+ unsigned a_hnp_support:1; -+ /** The state of the A-Device Alt HNP support. */ -+ unsigned a_alt_hnp_support:1; -+ /** Count of pending Requests */ -+ unsigned request_pending; -+ -+ /** SETUP packet for EP0 -+ * This structure is allocated as a DMA buffer on PCD initialization -+ * with enough space for up to 3 setup packets. -+ */ -+ union { -+ usb_device_request_t req; -+ uint32_t d32[2]; -+ } *setup_pkt; -+ -+ dwc_dma_t setup_pkt_dma_handle; -+ -+ /** 2-byte dma buffer used to return status from GET_STATUS */ -+ uint16_t *status_buf; -+ dwc_dma_t status_buf_dma_handle; -+ -+ /** EP0 */ -+ dwc_otg_pcd_ep_t ep0; -+ -+ /** Array of IN EPs. */ -+ dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1]; -+ /** Array of OUT EPs. */ -+ dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1]; -+ /** number of valid EPs in the above array. */ -+// unsigned num_eps : 4; -+ dwc_spinlock_t *lock; -+ /** Timer for SRP. If it expires before SRP is successful -+ * clear the SRP. */ -+ dwc_timer_t *srp_timer; -+ -+ /** Tasklet to defer starting of TEST mode transmissions until -+ * Status Phase has been completed. -+ */ -+ dwc_tasklet_t *test_mode_tasklet; -+ -+ /** Tasklet to delay starting of xfer in DMA mode */ -+ dwc_tasklet_t *start_xfer_tasklet; -+ -+ /** The test mode to enter when the tasklet is executed. */ -+ unsigned test_mode; -+ /** The cfi_api structure that implements most of the CFI API -+ * and OTG specific core configuration functionality -+ */ -+#ifdef DWC_UTE_CFI -+ struct cfiobject *cfi; -+#endif -+ -+}; -+ -+//FIXME this functions should be static, and this prototypes should be removed -+extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep); -+extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, -+ dwc_otg_pcd_request_t * req, int32_t status); -+ -+void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, -+ void *req_handle); -+ -+extern void do_test_mode(void *data); -+#endif -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -new file mode 100644 -index 0000000..66e9db7 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -@@ -0,0 +1,333 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ -+ * $Revision: #6 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225059 $ -+ * -+ * 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_HOST_ONLY -+ -+#if !defined(__DWC_PCD_IF_H__) -+#define __DWC_PCD_IF_H__ -+ -+#include "dwc_os.h" -+#include "dwc_otg_core_if.h" -+ -+/** @file -+ * This file defines DWC_OTG PCD Core API. -+ */ -+ -+struct dwc_otg_pcd; -+typedef struct dwc_otg_pcd dwc_otg_pcd_t; -+ -+/** Maxpacket size for EP0 */ -+#define MAX_EP0_SIZE 64 -+/** Maxpacket size for any EP */ -+#define MAX_PACKET_SIZE 1024 -+ -+/** @name Function Driver Callbacks */ -+/** @{ */ -+ -+/** This function will be called whenever a previously queued request has -+ * completed. The status value will be set to -DWC_E_SHUTDOWN to indicated a -+ * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset, -+ * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid -+ * parameters. */ -+typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle, int32_t status, -+ uint32_t actual); -+/** -+ * This function will be called whenever a previousle queued ISOC request has -+ * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count -+ * function. -+ * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_* -+ * functions. -+ */ -+typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle, int proc_buf_num); -+/** This function should handle any SETUP request that cannot be handled by the -+ * PCD Core. This includes most GET_DESCRIPTORs, SET_CONFIGS, Any -+ * class-specific requests, etc. The function must non-blocking. -+ * -+ * Returns 0 on success. -+ * Returns -DWC_E_NOT_SUPPORTED if the request is not supported. -+ * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes. -+ * Returns -DWC_E_SHUTDOWN on any other error. */ -+typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes); -+/** This is called whenever the device has been disconnected. The function -+ * driver should take appropriate action to clean up all pending requests in the -+ * PCD Core, remove all endpoints (except ep0), and initialize back to reset -+ * state. */ -+typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd); -+/** This function is called when device has been connected. */ -+typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed); -+/** This function is called when device has been suspended */ -+typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd); -+/** This function is called when device has received LPM tokens, i.e. -+ * device has been sent to sleep state. */ -+typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd); -+/** This function is called when device has been resumed -+ * from suspend(L2) or L1 sleep state. */ -+typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd); -+/** This function is called whenever hnp params has been changed. -+ * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions -+ * to get hnp parameters. */ -+typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd); -+/** This function is called whenever USB RESET is detected. */ -+typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd); -+ -+typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes); -+ -+/** Function Driver Ops Data Structure */ -+struct dwc_otg_pcd_function_ops { -+ dwc_connect_cb_t connect; -+ dwc_disconnect_cb_t disconnect; -+ dwc_setup_cb_t setup; -+ dwc_completion_cb_t complete; -+ dwc_isoc_completion_cb_t isoc_complete; -+ dwc_suspend_cb_t suspend; -+ dwc_sleep_cb_t sleep; -+ dwc_resume_cb_t resume; -+ dwc_reset_cb_t reset; -+ dwc_hnp_params_changed_cb_t hnp_changed; -+ cfi_setup_cb_t cfi_setup; -+}; -+/** @} */ -+ -+/** @name Function Driver Functions */ -+/** @{ */ -+ -+/** Call this function to get pointer on dwc_otg_pcd_t, -+ * this pointer will be used for all PCD API functions. -+ * -+ * @param core_if The DWC_OTG Core -+ */ -+extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if); -+ -+/** Frees PCD allocated by dwc_otg_pcd_init -+ * -+ * @param pcd The PCD -+ */ -+extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd); -+ -+/** Call this to bind the function driver to the PCD Core. -+ * -+ * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function. -+ * @param fops The Function Driver Ops data structure containing pointers to all callbacks. -+ */ -+extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, -+ const struct dwc_otg_pcd_function_ops *fops); -+ -+/** Enables an endpoint for use. This function enables an endpoint in -+ * the PCD. The endpoint is described by the ep_desc which has the -+ * same format as a USB ep descriptor. The ep_handle parameter is used to refer -+ * to the endpoint from other API functions and in callbacks. Normally this -+ * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the -+ * core for that interface. -+ * -+ * Returns -DWC_E_INVALID if invalid parameters were passed. -+ * Returns -DWC_E_SHUTDOWN if any other error ocurred. -+ * Returns 0 on success. -+ * -+ * @param pcd The PCD -+ * @param ep_desc Endpoint descriptor -+ * @param ep_handle Handle on endpoint, that will be used to identify endpoint. -+ */ -+extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, -+ const uint8_t * ep_desc, void *ep_handle); -+ -+/** Disable the endpoint referenced by ep_handle. -+ * -+ * Returns -DWC_E_INVALID if invalid parameters were passed. -+ * Returns -DWC_E_SHUTDOWN if any other error ocurred. -+ * Returns 0 on success. */ -+extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle); -+ -+/** Queue a data transfer request on the endpoint referenced by ep_handle. -+ * After the transfer is completes, the complete callback will be called with -+ * the request status. -+ * -+ * @param pcd The PCD -+ * @param ep_handle The handle of the endpoint -+ * @param buf The buffer for the data -+ * @param dma_buf The DMA buffer for the data -+ * @param buflen The length of the data transfer -+ * @param zero Specifies whether to send zero length last packet. -+ * @param req_handle Set this handle to any value to use to reference this -+ * request in the ep_dequeue function or from the complete callback -+ * @param atomic_alloc If driver need to perform atomic allocations -+ * for internal data structures. -+ * -+ * Returns -DWC_E_INVALID if invalid parameters were passed. -+ * Returns -DWC_E_SHUTDOWN if any other error ocurred. -+ * Returns 0 on success. */ -+extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, -+ uint8_t * buf, dwc_dma_t dma_buf, -+ uint32_t buflen, int zero, void *req_handle, -+ int atomic_alloc); -+ -+/** De-queue the specified data transfer that has not yet completed. -+ * -+ * Returns -DWC_E_INVALID if invalid parameters were passed. -+ * Returns -DWC_E_SHUTDOWN if any other error ocurred. -+ * Returns 0 on success. */ -+extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle); -+ -+/** Halt (STALL) an endpoint or clear it. -+ * -+ * Returns -DWC_E_INVALID if invalid parameters were passed. -+ * Returns -DWC_E_SHUTDOWN if any other error ocurred. -+ * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later -+ * Returns 0 on success. */ -+extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value); -+ -+/** This function */ -+extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle); -+ -+/** This function should be called on every hardware interrupt */ -+extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd); -+ -+/** This function returns current frame number */ -+extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd); -+ -+/** -+ * Start isochronous transfers on the endpoint referenced by ep_handle. -+ * For isochronous transfers duble buffering is used. -+ * After processing each of buffers comlete callback will be called with -+ * status for each transaction. -+ * -+ * @param pcd The PCD -+ * @param ep_handle The handle of the endpoint -+ * @param buf0 The virtual address of first data buffer -+ * @param buf1 The virtual address of second data buffer -+ * @param dma0 The DMA address of first data buffer -+ * @param dma1 The DMA address of second data buffer -+ * @param sync_frame Data pattern frame number -+ * @param dp_frame Data size for pattern frame -+ * @param data_per_frame Data size for regular frame -+ * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP. -+ * @param buf_proc_intrvl Interval of ISOC Buffer processing -+ * @param req_handle Handle of ISOC request -+ * @param atomic_alloc Specefies whether to perform atomic allocation for -+ * internal data structures. -+ * -+ * Returns -DWC_E_NO_MEMORY if there is no enough memory. -+ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function. -+ * Returns -DW_E_SHUTDOWN for any other error. -+ * Returns 0 on success -+ */ -+extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, -+ uint8_t * buf0, uint8_t * buf1, -+ dwc_dma_t dma0, dwc_dma_t dma1, -+ int sync_frame, int dp_frame, -+ int data_per_frame, int start_frame, -+ int buf_proc_intrvl, void *req_handle, -+ int atomic_alloc); -+ -+/** Stop ISOC transfers on endpoint referenced by ep_handle. -+ * -+ * @param pcd The PCD -+ * @param ep_handle The handle of the endpoint -+ * @param req_handle Handle of ISOC request -+ * -+ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function -+ * Returns 0 on success -+ */ -+int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle); -+ -+/** Get ISOC packet status. -+ * -+ * @param pcd The PCD -+ * @param ep_handle The handle of the endpoint -+ * @param iso_req_handle Isochronoush request handle -+ * @param packet Number of packet -+ * @param status Out parameter for returning status -+ * @param actual Out parameter for returning actual length -+ * @param offset Out parameter for returning offset -+ * -+ */ -+extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, -+ void *ep_handle, -+ void *iso_req_handle, int packet, -+ int *status, int *actual, -+ int *offset); -+ -+/** Get ISOC packet count. -+ * -+ * @param pcd The PCD -+ * @param ep_handle The handle of the endpoint -+ * @param iso_req_handle -+ */ -+extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, -+ void *ep_handle, -+ void *iso_req_handle); -+ -+/** This function starts the SRP Protocol if no session is in progress. If -+ * a session is already in progress, but the device is suspended, -+ * remote wakeup signaling is started. -+ */ -+extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd); -+ -+/** This function returns 1 if LPM support is enabled, and 0 otherwise. */ -+extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd); -+ -+/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */ -+extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd); -+ -+/** Initiate SRP */ -+extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd); -+ -+/** Starts remote wakeup signaling. */ -+extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set); -+ -+/** This function returns whether device is dualspeed.*/ -+extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd); -+ -+/** This function returns whether device is otg. */ -+extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd); -+ -+/** These functions allow to get hnp parameters */ -+extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd); -+extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd); -+extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd); -+ -+/** CFI specific Interface functions */ -+/** Allocate a cfi buffer */ -+extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, -+ dwc_dma_t * addr, size_t buflen, -+ int flags); -+ -+/******************************************************************************/ -+ -+/** @} */ -+ -+#endif /* __DWC_PCD_IF_H__ */ -+ -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -new file mode 100644 -index 0000000..f89e878 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -@@ -0,0 +1,4077 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ -+ * $Revision: #93 $ -+ * $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_HOST_ONLY -+ -+#include "dwc_otg_pcd.h" -+ -+#ifdef DWC_UTE_CFI -+#include "dwc_otg_cfi.h" -+#endif -+ -+//#define PRINT_CFI_DMA_DESCS -+ -+#define DEBUG_EP0 -+ -+/** -+ * This function updates OTG. -+ */ -+static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset) -+{ -+ -+ if (reset) { -+ pcd->b_hnp_enable = 0; -+ pcd->a_hnp_support = 0; -+ pcd->a_alt_hnp_support = 0; -+ } -+ -+ if (pcd->fops->hnp_changed) { -+ pcd->fops->hnp_changed(pcd); -+ } -+} -+ -+/** @file -+ * This file contains the implementation of the PCD Interrupt handlers. -+ * -+ * The PCD handles the device interrupts. Many conditions can cause a -+ * device interrupt. When an interrupt occurs, the device interrupt -+ * service routine determines the cause of the interrupt and -+ * dispatches handling to the appropriate function. These interrupt -+ * handling functions are described below. -+ * All interrupt registers are processed from LSB to MSB. -+ */ -+ -+/** -+ * This function prints the ep0 state for debug purposes. -+ */ -+static inline void print_ep0_state(dwc_otg_pcd_t * pcd) -+{ -+#ifdef DEBUG -+ char str[40]; -+ -+ switch (pcd->ep0state) { -+ case EP0_DISCONNECT: -+ dwc_strcpy(str, "EP0_DISCONNECT"); -+ break; -+ case EP0_IDLE: -+ dwc_strcpy(str, "EP0_IDLE"); -+ break; -+ case EP0_IN_DATA_PHASE: -+ dwc_strcpy(str, "EP0_IN_DATA_PHASE"); -+ break; -+ case EP0_OUT_DATA_PHASE: -+ dwc_strcpy(str, "EP0_OUT_DATA_PHASE"); -+ break; -+ case EP0_IN_STATUS_PHASE: -+ dwc_strcpy(str, "EP0_IN_STATUS_PHASE"); -+ break; -+ case EP0_OUT_STATUS_PHASE: -+ dwc_strcpy(str, "EP0_OUT_STATUS_PHASE"); -+ break; -+ case EP0_STALL: -+ dwc_strcpy(str, "EP0_STALL"); -+ break; -+ default: -+ dwc_strcpy(str, "EP0_INVALID"); -+ } -+ -+ DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state); -+#endif -+} -+ -+#ifdef DWC_UTE_CFI -+static inline void print_desc(struct dwc_otg_dma_desc *ddesc, -+ const uint8_t * epname, int descnum) -+{ -+ CFI_INFO -+ ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n", -+ epname, descnum, ddesc->buf, ddesc->status.b.bytes, -+ ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts, -+ ddesc->status.b.bs); -+} -+#endif -+ -+/** -+ * This function returns pointer to in ep struct with number ep_num -+ */ -+static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num) -+{ -+ int i; -+ int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; -+ if (ep_num == 0) { -+ return &pcd->ep0; -+ } else { -+ for (i = 0; i < num_in_eps; ++i) { -+ if (pcd->in_ep[i].dwc_ep.num == ep_num) -+ return &pcd->in_ep[i]; -+ } -+ return 0; -+ } -+} -+ -+/** -+ * This function returns pointer to out ep struct with number ep_num -+ */ -+static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num) -+{ -+ int i; -+ int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; -+ if (ep_num == 0) { -+ return &pcd->ep0; -+ } else { -+ for (i = 0; i < num_out_eps; ++i) { -+ if (pcd->out_ep[i].dwc_ep.num == ep_num) -+ return &pcd->out_ep[i]; -+ } -+ return 0; -+ } -+} -+ -+/** -+ * This functions gets a pointer to an EP from the wIndex address -+ * value of the control request. -+ */ -+dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex) -+{ -+ dwc_otg_pcd_ep_t *ep; -+ uint32_t ep_num = UE_GET_ADDR(wIndex); -+ -+ if (ep_num == 0) { -+ ep = &pcd->ep0; -+ } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) { /* in ep */ -+ ep = &pcd->in_ep[ep_num - 1]; -+ } else { -+ ep = &pcd->out_ep[ep_num - 1]; -+ } -+ -+ return ep; -+} -+ -+/** -+ * This function checks the EP request queue, if the queue is not -+ * empty the next request is started. -+ */ -+void start_next_request(dwc_otg_pcd_ep_t * ep) -+{ -+ dwc_otg_pcd_request_t *req = 0; -+ uint32_t max_transfer = -+ GET_CORE_IF(ep->pcd)->core_params->max_transfer_size; -+ -+#ifdef DWC_UTE_CFI -+ struct dwc_otg_pcd *pcd; -+ pcd = ep->pcd; -+#endif -+ -+ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ -+#ifdef DWC_UTE_CFI -+ if (ep->dwc_ep.buff_mode != BM_STANDARD) { -+ ep->dwc_ep.cfi_req_len = req->length; -+ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req); -+ } else { -+#endif -+ /* Setup and start the Transfer */ -+ ep->dwc_ep.dma_addr = req->dma; -+ ep->dwc_ep.start_xfer_buff = req->buf; -+ ep->dwc_ep.xfer_buff = req->buf; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = req->length; -+ ep->dwc_ep.xfer_len = 0; -+ ep->dwc_ep.xfer_count = 0; -+ -+ ep->dwc_ep.maxxfer = max_transfer; -+ if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { -+ uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE -+ - (DDMA_MAX_TRANSFER_SIZE % 4); -+ if (ep->dwc_ep.is_in) { -+ if (ep->dwc_ep.maxxfer > -+ DDMA_MAX_TRANSFER_SIZE) { -+ ep->dwc_ep.maxxfer = -+ DDMA_MAX_TRANSFER_SIZE; -+ } -+ } else { -+ if (ep->dwc_ep.maxxfer > out_max_xfer) { -+ ep->dwc_ep.maxxfer = -+ out_max_xfer; -+ } -+ } -+ } -+ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { -+ ep->dwc_ep.maxxfer -= -+ (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket); -+ } -+ if (req->sent_zlp) { -+ if ((ep->dwc_ep.total_len % -+ ep->dwc_ep.maxpacket == 0) -+ && (ep->dwc_ep.total_len != 0)) { -+ ep->dwc_ep.sent_zlp = 1; -+ } -+ -+ } -+#ifdef DWC_UTE_CFI -+ } -+#endif -+ dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep); -+ } -+} -+ -+/** -+ * This function handles the SOF Interrupts. At this time the SOF -+ * Interrupt is disabled. -+ */ -+int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ -+ gintsts_data_t gintsts; -+ -+ DWC_DEBUGPL(DBG_PCD, "SOF\n"); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.sofintr = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This function handles the Rx Status Queue Level Interrupt, which -+ * indicates that there is a least one packet in the Rx FIFO. The -+ * packets are moved from the FIFO to memory, where they will be -+ * processed when the Endpoint Interrupt Register indicates Transfer -+ * Complete or SETUP Phase Done. -+ * -+ * Repeat the following until the Rx Status Queue is empty: -+ * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet -+ * info -+ * -# If Receive FIFO is empty then skip to step Clear the interrupt -+ * and exit -+ * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the -+ * SETUP data to the buffer -+ * -# If OUT Data Packet call dwc_otg_read_packet to copy the data -+ * to the destination buffer -+ */ -+int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ gintmsk_data_t gintmask = {.d32 = 0 }; -+ device_grxsts_data_t status; -+ dwc_otg_pcd_ep_t *ep; -+ gintsts_data_t gintsts; -+#ifdef DEBUG -+ static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" }; -+#endif -+ -+ //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); -+ /* Disable the Rx Status Queue Level interrupt */ -+ gintmask.b.rxstsqlvl = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, gintmask.d32, 0); -+ -+ /* Get the Status from the top of the FIFO */ -+ status.d32 = dwc_read_reg32(&global_regs->grxstsp); -+ -+ DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s " -+ "pktsts:%x Frame:%d(0x%0x)\n", -+ status.b.epnum, status.b.bcnt, -+ dpid_str[status.b.dpid], -+ status.b.pktsts, status.b.fn, status.b.fn); -+ /* Get pointer to EP structure */ -+ ep = get_out_ep(pcd, status.b.epnum); -+ -+ switch (status.b.pktsts) { -+ case DWC_DSTS_GOUT_NAK: -+ DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); -+ break; -+ case DWC_STS_DATA_UPDT: -+ DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n"); -+ if (status.b.bcnt && ep->dwc_ep.xfer_buff) { -+ /** @todo NGS Check for buffer overflow? */ -+ dwc_otg_read_packet(core_if, -+ ep->dwc_ep.xfer_buff, -+ status.b.bcnt); -+ ep->dwc_ep.xfer_count += status.b.bcnt; -+ ep->dwc_ep.xfer_buff += status.b.bcnt; -+ } -+ break; -+ case DWC_STS_XFER_COMP: -+ DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n"); -+ break; -+ case DWC_DSTS_SETUP_COMP: -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n"); -+#endif -+ break; -+ case DWC_DSTS_SETUP_UPDT: -+ dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32); -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, -+ "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n", -+ pcd->setup_pkt->req.bmRequestType, -+ pcd->setup_pkt->req.bRequest, -+ UGETW(pcd->setup_pkt->req.wValue), -+ UGETW(pcd->setup_pkt->req.wIndex), -+ UGETW(pcd->setup_pkt->req.wLength)); -+#endif -+ ep->dwc_ep.xfer_count += status.b.bcnt; -+ break; -+ default: -+ DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n", -+ status.b.pktsts); -+ break; -+ } -+ -+ /* Enable the Rx Status Queue Level interrupt */ -+ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmask.d32); -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.rxstsqlvl = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__); -+ return 1; -+} -+ -+/** -+ * This function examines the Device IN Token Learning Queue to -+ * determine the EP number of the last IN token received. This -+ * implementation is for the Mass Storage device where there are only -+ * 2 IN EPs (Control-IN and BULK-IN). -+ * -+ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there -+ * are 8 EP Numbers in each of the other possible DTKNQ Registers. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * -+ */ -+static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if) -+{ -+ dwc_otg_device_global_regs_t *dev_global_regs = -+ core_if->dev_if->dev_global_regs; -+ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; -+ /* Number of Token Queue Registers */ -+ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; -+ dtknq1_data_t dtknqr1; -+ uint32_t in_tkn_epnums[4]; -+ int ndx = 0; -+ int i = 0; -+ volatile uint32_t *addr = &dev_global_regs->dtknqr1; -+ int epnum = 0; -+ -+ //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH); -+ -+ /* Read the DTKNQ Registers */ -+ for (i = 0; i < DTKNQ_REG_CNT; i++) { -+ in_tkn_epnums[i] = dwc_read_reg32(addr); -+ DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, -+ in_tkn_epnums[i]); -+ if (addr == &dev_global_regs->dvbusdis) { -+ addr = &dev_global_regs->dtknqr3_dthrctl; -+ } else { -+ ++addr; -+ } -+ -+ } -+ -+ /* Copy the DTKNQR1 data to the bit field. */ -+ dtknqr1.d32 = in_tkn_epnums[0]; -+ /* Get the EP numbers */ -+ in_tkn_epnums[0] = dtknqr1.b.epnums0_5; -+ ndx = dtknqr1.b.intknwptr - 1; -+ -+ //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx); -+ if (ndx == -1) { -+ /** @todo Find a simpler way to calculate the max -+ * queue position.*/ -+ int cnt = TOKEN_Q_DEPTH; -+ if (TOKEN_Q_DEPTH <= 6) { -+ cnt = TOKEN_Q_DEPTH - 1; -+ } else if (TOKEN_Q_DEPTH <= 14) { -+ cnt = TOKEN_Q_DEPTH - 7; -+ } else if (TOKEN_Q_DEPTH <= 22) { -+ cnt = TOKEN_Q_DEPTH - 15; -+ } else { -+ cnt = TOKEN_Q_DEPTH - 23; -+ } -+ epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF; -+ } else { -+ if (ndx <= 5) { -+ epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF; -+ } else if (ndx <= 13) { -+ ndx -= 6; -+ epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF; -+ } else if (ndx <= 21) { -+ ndx -= 14; -+ epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF; -+ } else if (ndx <= 29) { -+ ndx -= 22; -+ epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF; -+ } -+ } -+ //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum); -+ return epnum; -+} -+ -+/** -+ * This interrupt occurs when the non-periodic Tx FIFO is half-empty. -+ * The active request is checked for the next packet to be loaded into -+ * the non-periodic Tx FIFO. -+ */ -+int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ dwc_otg_dev_in_ep_regs_t *ep_regs; -+ gnptxsts_data_t txstatus = {.d32 = 0 }; -+ gintsts_data_t gintsts; -+ -+ int epnum = 0; -+ dwc_otg_pcd_ep_t *ep = 0; -+ uint32_t len = 0; -+ int dwords; -+ -+ /* Get the epnum from the IN Token Learning Queue. */ -+ epnum = get_ep_of_last_in_token(core_if); -+ ep = get_in_ep(pcd, epnum); -+ -+ DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum); -+ -+ ep_regs = core_if->dev_if->in_ep_regs[epnum]; -+ -+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; -+ if (len > ep->dwc_ep.maxpacket) { -+ len = ep->dwc_ep.maxpacket; -+ } -+ dwords = (len + 3) / 4; -+ -+ /* While there is space in the queue and space in the FIFO and -+ * More data to tranfer, Write packets to the Tx FIFO */ -+ txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32); -+ -+ while (txstatus.b.nptxqspcavail > 0 && -+ txstatus.b.nptxfspcavail > dwords && -+ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) { -+ /* Write the FIFO */ -+ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); -+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; -+ -+ if (len > ep->dwc_ep.maxpacket) { -+ len = ep->dwc_ep.maxpacket; -+ } -+ -+ dwords = (len + 3) / 4; -+ txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32); -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", -+ dwc_read_reg32(&global_regs->gnptxsts)); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.nptxfempty = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This function is called when dedicated Tx FIFO Empty interrupt occurs. -+ * The active request is checked for the next packet to be loaded into -+ * apropriate Tx FIFO. -+ */ -+static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ dwc_otg_dev_in_ep_regs_t *ep_regs; -+ dtxfsts_data_t txstatus = {.d32 = 0 }; -+ dwc_otg_pcd_ep_t *ep = 0; -+ uint32_t len = 0; -+ int dwords; -+ -+ ep = get_in_ep(pcd, epnum); -+ -+ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); -+ -+ ep_regs = core_if->dev_if->in_ep_regs[epnum]; -+ -+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; -+ -+ if (len > ep->dwc_ep.maxpacket) { -+ len = ep->dwc_ep.maxpacket; -+ } -+ -+ dwords = (len + 3) / 4; -+ -+ /* While there is space in the queue and space in the FIFO and -+ * More data to tranfer, Write packets to the Tx FIFO */ -+ txstatus.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts); -+ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); -+ -+ while (txstatus.b.txfspcavail > dwords && -+ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len && -+ ep->dwc_ep.xfer_len != 0) { -+ /* Write the FIFO */ -+ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); -+ -+ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; -+ if (len > ep->dwc_ep.maxpacket) { -+ len = ep->dwc_ep.maxpacket; -+ } -+ -+ dwords = (len + 3) / 4; -+ txstatus.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts); -+ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, -+ txstatus.d32); -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, -+ dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts)); -+ -+ return 1; -+} -+ -+/** -+ * This function is called when the Device is disconnected. It stops -+ * any active requests and informs the Gadget driver of the -+ * disconnect. -+ */ -+void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd) -+{ -+ int i, num_in_eps, num_out_eps; -+ dwc_otg_pcd_ep_t *ep; -+ -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_SPINLOCK(pcd->lock); -+ -+ num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; -+ num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__); -+ /* don't disconnect drivers more than once */ -+ if (pcd->ep0state == EP0_DISCONNECT) { -+ DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__); -+ return; -+ } -+ pcd->ep0state = EP0_DISCONNECT; -+ -+ /* Reset the OTG state. */ -+ dwc_otg_pcd_update_otg(pcd, 1); -+ -+ /* Disable the NP Tx Fifo Empty Interrupt. */ -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+ /* Flush the FIFOs */ -+ /**@todo NGS Flush Periodic FIFOs */ -+ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10); -+ dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd)); -+ -+ /* prevent new request submissions, kill any outstanding requests */ -+ ep = &pcd->ep0; -+ dwc_otg_request_nuke(ep); -+ /* prevent new request submissions, kill any outstanding requests */ -+ for (i = 0; i < num_in_eps; i++) { -+ dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i]; -+ dwc_otg_request_nuke(ep); -+ } -+ /* prevent new request submissions, kill any outstanding requests */ -+ for (i = 0; i < num_out_eps; i++) { -+ dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i]; -+ dwc_otg_request_nuke(ep); -+ } -+ -+ /* report disconnect; the driver is already quiesced */ -+ if (pcd->fops->disconnect) { -+ DWC_SPINUNLOCK(pcd->lock); -+ pcd->fops->disconnect(pcd); -+ DWC_SPINLOCK(pcd->lock); -+ } -+ DWC_SPINUNLOCK(pcd->lock); -+} -+ -+/** -+ * This interrupt indicates that ... -+ */ -+int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd) -+{ -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ gintsts_data_t gintsts; -+ -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr"); -+ intr_mask.b.i2cintr = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.i2cintr = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that ... -+ */ -+int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd) -+{ -+ gintsts_data_t gintsts; -+#if defined(VERBOSE) -+ DWC_PRINTF("Early Suspend Detected\n"); -+#endif -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.erlysuspend = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ return 1; -+} -+ -+/** -+ * This function configures EPO to receive SETUP packets. -+ * -+ * @todo NGS: Update the comments from the HW FS. -+ * -+ * -# Program the following fields in the endpoint specific registers -+ * for Control OUT EP 0, in order to receive a setup packet -+ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back -+ * setup packets) -+ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back -+ * to back setup packets) -+ * - In DMA mode, DOEPDMA0 Register with a memory address to -+ * store any setup packets received -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param pcd Programming view of the PCD. -+ */ -+static inline void ep0_out_start(dwc_otg_core_if_t * core_if, -+ dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ depctl_data_t doepctl = {.d32 = 0 }; -+ -+#ifdef VERBOSE -+ DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__, -+ dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); -+#endif -+ -+ doeptsize0.b.supcnt = 3; -+ doeptsize0.b.pktcnt = 1; -+ doeptsize0.b.xfersize = 8 * 3; -+ -+ if (core_if->dma_enable) { -+ if (!core_if->dma_desc_enable) { -+ /** put here as for Hermes mode deptisz register should not be written */ -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz, -+ doeptsize0.d32); -+ -+ /** @todo dma needs to handle multiple setup packets (up to 3) */ -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, -+ pcd->setup_pkt_dma_handle); -+ } else { -+ dev_if->setup_desc_index = -+ (dev_if->setup_desc_index + 1) & 1; -+ dma_desc = -+ dev_if->setup_desc_addr[dev_if->setup_desc_index]; -+ -+ /** DMA Descriptor Setup */ -+ dma_desc->status.b.bs = BS_HOST_BUSY; -+ dma_desc->status.b.l = 1; -+ dma_desc->status.b.ioc = 1; -+ dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket; -+ dma_desc->buf = pcd->setup_pkt_dma_handle; -+ dma_desc->status.b.bs = BS_HOST_READY; -+ -+ /** DOEPDMA0 Register write */ -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, -+ dev_if->dma_setup_desc_addr[dev_if-> -+ setup_desc_index]); -+ } -+ -+ } else { -+ /** put here as for Hermes mode deptisz register should not be written */ -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz, -+ doeptsize0.d32); -+ } -+ -+ /** DOEPCTL0 Register write */ -+ doepctl.b.epena = 1; -+ doepctl.b.cnak = 1; -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); -+ -+#ifdef VERBOSE -+ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", -+ dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); -+ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", -+ dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl)); -+#endif -+} -+ -+/** -+ * This interrupt occurs when a USB Reset is detected. When the USB -+ * Reset Interrupt occurs the device state is set to DEFAULT and the -+ * EP0 state is set to IDLE. -+ * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) -+ * -# Unmask the following interrupt bits -+ * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint) -+ * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint) -+ * - DOEPMSK.SETUP = 1 -+ * - DOEPMSK.XferCompl = 1 -+ * - DIEPMSK.XferCompl = 1 -+ * - DIEPMSK.TimeOut = 1 -+ * -# Program the following fields in the endpoint specific registers -+ * for Control OUT EP 0, in order to receive a setup packet -+ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back -+ * setup packets) -+ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back -+ * to back setup packets) -+ * - In DMA mode, DOEPDMA0 Register with a memory address to -+ * store any setup packets received -+ * At this point, all the required initialization, except for enabling -+ * the control 0 OUT endpoint is done, for receiving SETUP packets. -+ */ -+int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ depctl_data_t doepctl = {.d32 = 0 }; -+ daint_data_t daintmsk = {.d32 = 0 }; -+ doepmsk_data_t doepmsk = {.d32 = 0 }; -+ diepmsk_data_t diepmsk = {.d32 = 0 }; -+ dcfg_data_t dcfg = {.d32 = 0 }; -+ grstctl_t resetctl = {.d32 = 0 }; -+ dctl_data_t dctl = {.d32 = 0 }; -+ int i = 0; -+ gintsts_data_t gintsts; -+ pcgcctl_data_t power = {.d32 = 0 }; -+ -+ power.d32 = dwc_read_reg32(core_if->pcgcctl); -+ if (power.b.stoppclk) { -+ power.d32 = 0; -+ power.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); -+ -+ power.b.pwrclmp = 1; -+ dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); -+ -+ power.b.rstpdwnmodule = 1; -+ dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); -+ } -+ -+ core_if->lx_state = DWC_OTG_L0; -+ -+ DWC_PRINTF("USB RESET\n"); -+#ifdef DWC_EN_ISOC -+ for (i = 1; i < 16; ++i) { -+ dwc_otg_pcd_ep_t *ep; -+ dwc_ep_t *dwc_ep; -+ ep = get_in_ep(pcd, i); -+ if (ep != 0) { -+ dwc_ep = &ep->dwc_ep; -+ dwc_ep->next_frame = 0xffffffff; -+ } -+ } -+#endif /* DWC_EN_ISOC */ -+ -+ /* reset the HNP settings */ -+ dwc_otg_pcd_update_otg(pcd, 1); -+ -+ /* Clear the Remote Wakeup Signalling */ -+ dctl.b.rmtwkupsig = 1; -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); -+ -+ /* Set NAK for all OUT EPs */ -+ doepctl.b.snak = 1; -+ for (i = 0; i <= dev_if->num_out_eps; i++) { -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); -+ } -+ -+ /* Flush the NP Tx FIFO */ -+ dwc_otg_flush_tx_fifo(core_if, 0x10); -+ /* Flush the Learning Queue */ -+ resetctl.b.intknqflsh = 1; -+ dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); -+ -+ if (core_if->multiproc_int_enable) { -+ daintmsk.b.inep0 = 1; -+ daintmsk.b.outep0 = 1; -+ dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk, -+ daintmsk.d32); -+ -+ doepmsk.b.setup = 1; -+ doepmsk.b.xfercompl = 1; -+ doepmsk.b.ahberr = 1; -+ doepmsk.b.epdisabled = 1; -+ -+ if (core_if->dma_desc_enable) { -+ doepmsk.b.stsphsercvd = 1; -+ doepmsk.b.bna = 1; -+ } -+/* -+ doepmsk.b.babble = 1; -+ doepmsk.b.nyet = 1; -+ -+ if(core_if->dma_enable) { -+ doepmsk.b.nak = 1; -+ } -+*/ -+ dwc_write_reg32(&dev_if->dev_global_regs->doepeachintmsk[0], -+ doepmsk.d32); -+ -+ diepmsk.b.xfercompl = 1; -+ diepmsk.b.timeout = 1; -+ diepmsk.b.epdisabled = 1; -+ diepmsk.b.ahberr = 1; -+ diepmsk.b.intknepmis = 1; -+ -+ if (core_if->dma_desc_enable) { -+ diepmsk.b.bna = 1; -+ } -+/* -+ if(core_if->dma_enable) { -+ diepmsk.b.nak = 1; -+ } -+*/ -+ dwc_write_reg32(&dev_if->dev_global_regs->diepeachintmsk[0], -+ diepmsk.d32); -+ } else { -+ daintmsk.b.inep0 = 1; -+ daintmsk.b.outep0 = 1; -+ dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, -+ daintmsk.d32); -+ -+ doepmsk.b.setup = 1; -+ doepmsk.b.xfercompl = 1; -+ doepmsk.b.ahberr = 1; -+ doepmsk.b.epdisabled = 1; -+ -+ if (core_if->dma_desc_enable) { -+ doepmsk.b.stsphsercvd = 1; -+ doepmsk.b.bna = 1; -+ } -+ dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); -+ -+ diepmsk.b.xfercompl = 1; -+ diepmsk.b.timeout = 1; -+ diepmsk.b.epdisabled = 1; -+ diepmsk.b.ahberr = 1; -+ diepmsk.b.intknepmis = 1; -+ -+ if (core_if->dma_desc_enable) { -+ diepmsk.b.bna = 1; -+ } -+ -+ dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); -+ } -+ -+ /* Reset Device Address */ -+ dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg); -+ dcfg.b.devaddr = 0; -+ dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ -+ /* setup EP0 to receive SETUP packets */ -+ ep0_out_start(core_if, pcd); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.usbreset = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * Get the device speed from the device status register and convert it -+ * to USB speed constant. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static int get_device_speed(dwc_otg_core_if_t * core_if) -+{ -+ dsts_data_t dsts; -+ int speed = 0; -+ dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ -+ switch (dsts.b.enumspd) { -+ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: -+ speed = USB_SPEED_HIGH; -+ break; -+ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: -+ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: -+ speed = USB_SPEED_FULL; -+ break; -+ -+ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: -+ speed = USB_SPEED_LOW; -+ break; -+ } -+ -+ return speed; -+} -+ -+/** -+ * Read the device status register and set the device speed in the -+ * data structure. -+ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate. -+ */ -+int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; -+ gintsts_data_t gintsts; -+ gusbcfg_data_t gusbcfg; -+ dwc_otg_core_global_regs_t *global_regs = -+ GET_CORE_IF(pcd)->core_global_regs; -+ uint8_t utmi16b, utmi8b; -+ int speed; -+ DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); -+ -+ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { -+ utmi16b = 6; -+ utmi8b = 9; -+ } else { -+ utmi16b = 4; -+ utmi8b = 8; -+ } -+ dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep); -+ -+#ifdef DEBUG_EP0 -+ print_ep0_state(pcd); -+#endif -+ -+ if (pcd->ep0state == EP0_DISCONNECT) { -+ pcd->ep0state = EP0_IDLE; -+ } else if (pcd->ep0state == EP0_STALL) { -+ pcd->ep0state = EP0_IDLE; -+ } -+ -+ pcd->ep0state = EP0_IDLE; -+ -+ ep0->stopped = 0; -+ -+ speed = get_device_speed(GET_CORE_IF(pcd)); -+ pcd->fops->connect(pcd, speed); -+ -+ /* Set USB turnaround time based on device speed and PHY interface. */ -+ gusbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ if (speed == USB_SPEED_HIGH) { -+ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == -+ DWC_HWCFG2_HS_PHY_TYPE_ULPI) { -+ /* ULPI interface */ -+ gusbcfg.b.usbtrdtim = 9; -+ } -+ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == -+ DWC_HWCFG2_HS_PHY_TYPE_UTMI) { -+ /* UTMI+ interface */ -+ if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) { -+ gusbcfg.b.usbtrdtim = utmi8b; -+ } else if (GET_CORE_IF(pcd)->hwcfg4.b. -+ utmi_phy_data_width == 1) { -+ gusbcfg.b.usbtrdtim = utmi16b; -+ } else if (GET_CORE_IF(pcd)->core_params-> -+ phy_utmi_width == 8) { -+ gusbcfg.b.usbtrdtim = utmi8b; -+ } else { -+ gusbcfg.b.usbtrdtim = utmi16b; -+ } -+ } -+ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == -+ DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) { -+ /* UTMI+ OR ULPI interface */ -+ if (gusbcfg.b.ulpi_utmi_sel == 1) { -+ /* ULPI interface */ -+ gusbcfg.b.usbtrdtim = 9; -+ } else { -+ /* UTMI+ interface */ -+ if (GET_CORE_IF(pcd)->core_params-> -+ phy_utmi_width == 16) { -+ gusbcfg.b.usbtrdtim = utmi16b; -+ } else { -+ gusbcfg.b.usbtrdtim = utmi8b; -+ } -+ } -+ } -+ } else { -+ /* Full or low speed */ -+ gusbcfg.b.usbtrdtim = 9; -+ } -+ dwc_write_reg32(&global_regs->gusbcfg, gusbcfg.d32); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.enumdone = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that the ISO OUT Packet was dropped due to -+ * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs -+ * read all the data from the Rx FIFO. -+ */ -+int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd) -+{ -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ gintsts_data_t gintsts; -+ -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "ISOC Out Dropped"); -+ -+ intr_mask.b.isooutdrop = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.isooutdrop = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates the end of the portion of the micro-frame -+ * for periodic transactions. If there is a periodic transaction for -+ * the next frame, load the packets into the EP periodic Tx FIFO. -+ */ -+int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd) -+{ -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ gintsts_data_t gintsts; -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP"); -+ -+ intr_mask.b.eopframe = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.eopframe = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that EP of the packet on the top of the -+ * non-periodic Tx FIFO does not match EP of the IN Token received. -+ * -+ * The "Device IN Token Queue" Registers are read to determine the -+ * order the IN Tokens have been received. The non-periodic Tx FIFO -+ * is flushed, so it can be reloaded in the order seen in the IN Token -+ * Queue. -+ */ -+int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_core_if_t * core_if) -+{ -+ gintsts_data_t gintsts; -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.epmismatch = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This funcion stalls EP0. -+ */ -+static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val) -+{ -+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; -+ usb_device_request_t *ctrl = &pcd->setup_pkt->req; -+ DWC_WARN("req %02x.%02x protocol STALL; err %d\n", -+ ctrl->bmRequestType, ctrl->bRequest, err_val); -+ -+ ep0->dwc_ep.is_in = 1; -+ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep); -+ pcd->ep0.stopped = 1; -+ pcd->ep0state = EP0_IDLE; -+ ep0_out_start(GET_CORE_IF(pcd), pcd); -+} -+ -+/** -+ * This functions delegates the setup command to the gadget driver. -+ */ -+static inline void do_gadget_setup(dwc_otg_pcd_t * pcd, -+ usb_device_request_t * ctrl) -+{ -+ int ret = 0; -+ DWC_SPINUNLOCK(pcd->lock); -+ ret = pcd->fops->setup(pcd, (uint8_t *) ctrl); -+ DWC_SPINLOCK(pcd->lock); -+ if (ret < 0) { -+ ep0_do_stall(pcd, ret); -+ } -+ -+ /** @todo This is a g_file_storage gadget driver specific -+ * workaround: a DELAYED_STATUS result from the fsg_setup -+ * routine will result in the gadget queueing a EP0 IN status -+ * phase for a two-stage control transfer. Exactly the same as -+ * a SET_CONFIGURATION/SET_INTERFACE except that this is a class -+ * specific request. Need a generic way to know when the gadget -+ * driver will queue the status phase. Can we assume when we -+ * call the gadget driver setup() function that it will always -+ * queue and require the following flag? Need to look into -+ * this. -+ */ -+ -+ if (ret == 256 + 999) { -+ pcd->request_config = 1; -+ } -+} -+ -+#ifdef DWC_UTE_CFI -+/** -+ * This functions delegates the CFI setup commands to the gadget driver. -+ * This function will return a negative value to indicate a failure. -+ */ -+static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd, -+ struct cfi_usb_ctrlrequest *ctrl_req) -+{ -+ int ret = 0; -+ -+ if (pcd->fops && pcd->fops->cfi_setup) { -+ DWC_SPINUNLOCK(pcd->lock); -+ ret = pcd->fops->cfi_setup(pcd, ctrl_req); -+ DWC_SPINLOCK(pcd->lock); -+ if (ret < 0) { -+ ep0_do_stall(pcd, ret); -+ return ret; -+ } -+ } -+ -+ return ret; -+} -+#endif -+ -+/** -+ * This function starts the Zero-Length Packet for the IN status phase -+ * of a 2 stage control transfer. -+ */ -+static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; -+ if (pcd->ep0state == EP0_STALL) { -+ return; -+ } -+ -+ pcd->ep0state = EP0_IN_STATUS_PHASE; -+ -+ /* Prepare for more SETUP Packets */ -+ DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n"); -+ ep0->dwc_ep.xfer_len = 0; -+ ep0->dwc_ep.xfer_count = 0; -+ ep0->dwc_ep.is_in = 1; -+ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; -+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); -+ -+ /* Prepare for more SETUP Packets */ -+ //ep0_out_start(GET_CORE_IF(pcd), pcd); -+} -+ -+/** -+ * This function starts the Zero-Length Packet for the OUT status phase -+ * of a 2 stage control transfer. -+ */ -+static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; -+ if (pcd->ep0state == EP0_STALL) { -+ DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n"); -+ return; -+ } -+ pcd->ep0state = EP0_OUT_STATUS_PHASE; -+ -+ DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n"); -+ ep0->dwc_ep.xfer_len = 0; -+ ep0->dwc_ep.xfer_count = 0; -+ ep0->dwc_ep.is_in = 0; -+ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; -+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); -+ -+ /* Prepare for more SETUP Packets */ -+ if (GET_CORE_IF(pcd)->dma_enable == 0) { -+ ep0_out_start(GET_CORE_IF(pcd), pcd); -+ } -+} -+ -+/** -+ * Clear the EP halt (STALL) and if pending requests start the -+ * transfer. -+ */ -+static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) -+{ -+ if (ep->dwc_ep.stall_clear_flag == 0) -+ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); -+ -+ /* Reactive the EP */ -+ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); -+ if (ep->stopped) { -+ ep->stopped = 0; -+ /* If there is a request in the EP queue start it */ -+ -+ /** @todo FIXME: this causes an EP mismatch in DMA mode. -+ * epmismatch not yet implemented. */ -+ -+ /* -+ * Above fixme is solved by implmenting a tasklet to call the -+ * start_next_request(), outside of interrupt context at some -+ * time after the current time, after a clear-halt setup packet. -+ * Still need to implement ep mismatch in the future if a gadget -+ * ever uses more than one endpoint at once -+ */ -+ ep->queue_sof = 1; -+ DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet); -+ } -+ /* Start Control Status Phase */ -+ do_setup_in_status_phase(pcd); -+} -+ -+/** -+ * This function is called when the SET_FEATURE TEST_MODE Setup packet -+ * is sent from the host. The Device Control register is written with -+ * the Test Mode bits set to the specified Test Mode. This is done as -+ * a tasklet so that the "Status" phase of the control transfer -+ * completes before transmitting the TEST packets. -+ * -+ * @todo This has not been tested since the tasklet struct was put -+ * into the PCD struct! -+ * -+ */ -+void do_test_mode(void *data) -+{ -+ dctl_data_t dctl; -+ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ int test_mode = pcd->test_mode; -+ -+// DWC_WARN("%s() has not been tested since being rewritten!\n", __func__); -+ -+ dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl); -+ switch (test_mode) { -+ case 1: // TEST_J -+ dctl.b.tstctl = 1; -+ break; -+ -+ case 2: // TEST_K -+ dctl.b.tstctl = 2; -+ break; -+ -+ case 3: // TEST_SE0_NAK -+ dctl.b.tstctl = 3; -+ break; -+ -+ case 4: // TEST_PACKET -+ dctl.b.tstctl = 4; -+ break; -+ -+ case 5: // TEST_FORCE_ENABLE -+ dctl.b.tstctl = 5; -+ break; -+ } -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); -+} -+ -+/** -+ * This function process the GET_STATUS Setup Commands. -+ */ -+static inline void do_get_status(dwc_otg_pcd_t * pcd) -+{ -+ usb_device_request_t ctrl = pcd->setup_pkt->req; -+ dwc_otg_pcd_ep_t *ep; -+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; -+ uint16_t *status = pcd->status_buf; -+ -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, -+ "GET_STATUS %02x.%02x v%04x i%04x l%04x\n", -+ ctrl.bmRequestType, ctrl.bRequest, -+ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), -+ UGETW(ctrl.wLength)); -+#endif -+ -+ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { -+ case UT_DEVICE: -+ *status = 0x1; /* Self powered */ -+ *status |= pcd->remote_wakeup_enable << 1; -+ break; -+ -+ case UT_INTERFACE: -+ *status = 0; -+ break; -+ -+ case UT_ENDPOINT: -+ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); -+ if (ep == 0 || UGETW(ctrl.wLength) > 2) { -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; -+ } -+ /** @todo check for EP stall */ -+ *status = ep->stopped; -+ break; -+ } -+ pcd->ep0_pending = 1; -+ ep0->dwc_ep.start_xfer_buff = (uint8_t *) status; -+ ep0->dwc_ep.xfer_buff = (uint8_t *) status; -+ ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle; -+ ep0->dwc_ep.xfer_len = 2; -+ ep0->dwc_ep.xfer_count = 0; -+ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; -+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); -+} -+ -+/** -+ * This function process the SET_FEATURE Setup Commands. -+ */ -+static inline void do_set_feature(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ usb_device_request_t ctrl = pcd->setup_pkt->req; -+ dwc_otg_pcd_ep_t *ep = 0; -+ int32_t otg_cap_param = core_if->core_params->otg_cap; -+ gotgctl_data_t gotgctl = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n", -+ ctrl.bmRequestType, ctrl.bRequest, -+ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), -+ UGETW(ctrl.wLength)); -+ DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param); -+ -+ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { -+ case UT_DEVICE: -+ switch (UGETW(ctrl.wValue)) { -+ case UF_DEVICE_REMOTE_WAKEUP: -+ pcd->remote_wakeup_enable = 1; -+ break; -+ -+ case UF_TEST_MODE: -+ /* Setup the Test Mode tasklet to do the Test -+ * Packet generation after the SETUP Status -+ * phase has completed. */ -+ -+ /** @todo This has not been tested since the -+ * tasklet struct was put into the PCD -+ * struct! */ -+ pcd->test_mode = UGETW(ctrl.wIndex) >> 8; -+ DWC_TASK_SCHEDULE(pcd->test_mode_tasklet); -+ break; -+ -+ case UF_DEVICE_B_HNP_ENABLE: -+ DWC_DEBUGPL(DBG_PCDV, -+ "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n"); -+ -+ /* dev may initiate HNP */ -+ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { -+ pcd->b_hnp_enable = 1; -+ dwc_otg_pcd_update_otg(pcd, 0); -+ DWC_DEBUGPL(DBG_PCD, "Request B HNP\n"); -+ /**@todo Is the gotgctl.devhnpen cleared -+ * by a USB Reset? */ -+ gotgctl.b.devhnpen = 1; -+ gotgctl.b.hnpreq = 1; -+ dwc_write_reg32(&global_regs->gotgctl, -+ gotgctl.d32); -+ } else { -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ } -+ break; -+ -+ case UF_DEVICE_A_HNP_SUPPORT: -+ /* RH port supports HNP */ -+ DWC_DEBUGPL(DBG_PCDV, -+ "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n"); -+ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { -+ pcd->a_hnp_support = 1; -+ dwc_otg_pcd_update_otg(pcd, 0); -+ } else { -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ } -+ break; -+ -+ case UF_DEVICE_A_ALT_HNP_SUPPORT: -+ /* other RH port does */ -+ DWC_DEBUGPL(DBG_PCDV, -+ "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n"); -+ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { -+ pcd->a_alt_hnp_support = 1; -+ dwc_otg_pcd_update_otg(pcd, 0); -+ } else { -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ } -+ break; -+ } -+ do_setup_in_status_phase(pcd); -+ break; -+ -+ case UT_INTERFACE: -+ do_gadget_setup(pcd, &ctrl); -+ break; -+ -+ case UT_ENDPOINT: -+ if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) { -+ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); -+ if (ep == 0) { -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; -+ } -+ ep->stopped = 1; -+ dwc_otg_ep_set_stall(core_if, &ep->dwc_ep); -+ } -+ do_setup_in_status_phase(pcd); -+ break; -+ } -+} -+ -+/** -+ * This function process the CLEAR_FEATURE Setup Commands. -+ */ -+static inline void do_clear_feature(dwc_otg_pcd_t * pcd) -+{ -+ usb_device_request_t ctrl = pcd->setup_pkt->req; -+ dwc_otg_pcd_ep_t *ep = 0; -+ -+ DWC_DEBUGPL(DBG_PCD, -+ "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n", -+ ctrl.bmRequestType, ctrl.bRequest, -+ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), -+ UGETW(ctrl.wLength)); -+ -+ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { -+ case UT_DEVICE: -+ switch (UGETW(ctrl.wValue)) { -+ case UF_DEVICE_REMOTE_WAKEUP: -+ pcd->remote_wakeup_enable = 0; -+ break; -+ -+ case UF_TEST_MODE: -+ /** @todo Add CLEAR_FEATURE for TEST modes. */ -+ break; -+ } -+ do_setup_in_status_phase(pcd); -+ break; -+ -+ case UT_ENDPOINT: -+ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); -+ if (ep == 0) { -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; -+ } -+ -+ pcd_clear_halt(pcd, ep); -+ -+ break; -+ } -+} -+ -+/** -+ * This function process the SET_ADDRESS Setup Commands. -+ */ -+static inline void do_set_address(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; -+ usb_device_request_t ctrl = pcd->setup_pkt->req; -+ -+ if (ctrl.bmRequestType == UT_DEVICE) { -+ dcfg_data_t dcfg = {.d32 = 0 }; -+ -+#ifdef DEBUG_EP0 -+// DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); -+#endif -+ dcfg.b.devaddr = UGETW(ctrl.wValue); -+ dwc_modify_reg32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); -+ do_setup_in_status_phase(pcd); -+ } -+} -+ -+/** -+ * This function processes SETUP commands. In Linux, the USB Command -+ * processing is done in two places - the first being the PCD and the -+ * second in the Gadget Driver (for example, the File-Backed Storage -+ * Gadget Driver). -+ * -+ *
Parameter NameMeaning
otg_capSpecifies the OTG capabilities. The driver will automatically detect the -+ value for this parameter if none is specified. -+ - 0: HNP and SRP capable (default, if available) -+ - 1: SRP Only capable -+ - 2: No HNP/SRP capable -+
dma_enableSpecifies 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) -+
dma_burst_sizeThe DMA Burst size (applicable only for External DMA Mode). -+ - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32) -+
speedSpecifies 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. -+ - 0: High Speed (default) -+ - 1: Full Speed -+
host_support_fs_ls_low_powerSpecifies 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 -+
host_ls_low_power_phy_clkSpecifies 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. -+ - 0: 48 MHz (default) -+ - 1: 6 MHz -+
enable_dynamic_fifo Specifies whether FIFOs may be resized by the driver software. -+ - 0: Use cC FIFO size parameters -+ - 1: Allow dynamic FIFO sizing (default) -+
data_fifo_sizeTotal number of 4-byte words in the data FIFO memory. This memory -+ includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs. -+ - Values: 32 to 32768 (default 8192) -+ -+ Note: The total FIFO memory depth in the FPGA configuration is 8192. -+
dev_rx_fifo_sizeNumber of 4-byte words in the Rx FIFO in device mode when dynamic -+ FIFO sizing is enabled. -+ - Values: 16 to 32768 (default 1064) -+
dev_nperio_tx_fifo_sizeNumber of 4-byte words in the non-periodic Tx FIFO in device mode when -+ dynamic FIFO sizing is enabled. -+ - Values: 16 to 32768 (default 1024) -+
dev_perio_tx_fifo_size_n (n = 1 to 15)Number of 4-byte words in each of the periodic Tx FIFOs in device mode -+ when dynamic FIFO sizing is enabled. -+ - Values: 4 to 768 (default 256) -+
host_rx_fifo_sizeNumber of 4-byte words in the Rx FIFO in host mode when dynamic FIFO -+ sizing is enabled. -+ - Values: 16 to 32768 (default 1024) -+
host_nperio_tx_fifo_sizeNumber of 4-byte words in the non-periodic Tx FIFO in host mode when -+ dynamic FIFO sizing is enabled in the core. -+ - Values: 16 to 32768 (default 1024) -+
host_perio_tx_fifo_sizeNumber of 4-byte words in the host periodic Tx FIFO when dynamic FIFO -+ sizing is enabled. -+ - Values: 16 to 32768 (default 1024) -+
max_transfer_sizeThe maximum transfer size supported in bytes. -+ - Values: 2047 to 65,535 (default 65,535) -+
max_packet_countThe maximum number of packets in a transfer. -+ - Values: 15 to 511 (default 511) -+
host_channelsThe number of host channel registers to use. -+ - Values: 1 to 16 (default 12) -+ -+ Note: The FPGA configuration supports a maximum of 12 host channels. -+
dev_endpointsThe number of endpoints in addition to EP0 available for device mode -+ operations. -+ - Values: 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. -+
phy_typeSpecifies the type of PHY interface to use. By default, the driver will -+ automatically detect the phy_type. -+ - 0: Full Speed -+ - 1: UTMI+ (default, if available) -+ - 2: ULPI -+
phy_utmi_widthSpecifies the UTMI+ Data Width. This parameter is applicable for a -+ phy_type of UTMI+. 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. -+ - Values: 8 or 16 bits (default 16) -+
phy_ulpi_ddrSpecifies 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 -+
i2c_enableSpecifies whether to use the I2C interface for full speed PHY. This -+ parameter is only applicable if PHY_TYPE is FS. -+ - 0: Disabled (default) -+ - 1: Enabled -+
otg_en_multiple_tx_fifoSpecifies whether dedicatedto tx fifos are enabled for non periodic IN EPs. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: Disabled -+ - 1: Enabled (default, if available) -+
dev_tx_fifo_size_n (n = 1 to 15)Number of 4-byte words in each of the Tx FIFOs in device mode -+ when dynamic FIFO sizing is enabled. -+ - Values: 4 to 768 (default 256) -+
tx_thr_lengthTransmit Threshold length in 32 bit double words -+ - Values: 8 to 128 (default 64) -+
rx_thr_lengthReceive Threshold length in 32 bit double words -+ - Values: 8 to 128 (default 64) -+
thr_ctlSpecifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of this -+ parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and Rx -+ transfers accordingly. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - Values: 0 to 7 (default 0) -+ Bit values indicate: -+ - 0: Thresholding disabled -+ - 1: Thresholding enabled -+
dma_desc_enableSpecifies whether to enable Descriptor DMA mode. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: Descriptor DMA disabled -+ - 1: Descriptor DMA (default, if available) -+
mpi_enableSpecifies whether to enable MPI enhancement mode. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: MPI disabled (default) -+ - 1: MPI enable -+
pti_enableSpecifies whether to enable PTI enhancement support. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: PTI disabled (default) -+ - 1: PTI enable -+
lpm_enableSpecifies whether to enable LPM support. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: LPM disabled -+ - 1: LPM enable (default, if available) -+
ahb_thr_ratioSpecifies AHB Threshold ratio. -+ - Values: 0 to 3 (default 0) -+
-+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ * -+ *
Command Driver Description
GET_STATUS PCD Command is processed as -+ * defined in chapter 9 of the USB 2.0 Specification chapter 9 -+ *
CLEAR_FEATURE PCD The Device and Endpoint -+ * requests are the ENDPOINT_HALT feature is procesed, all others the -+ * interface requests are ignored.
SET_FEATURE PCD The Device and Endpoint -+ * requests are processed by the PCD. Interface requests are passed -+ * to the Gadget Driver.
SET_ADDRESS PCD Program the DCFG reg, -+ * with device address received
GET_DESCRIPTOR Gadget Driver Return the -+ * requested descriptor
SET_DESCRIPTOR Gadget Driver Optional - -+ * not implemented by any of the existing Gadget Drivers.
SET_CONFIGURATION Gadget Driver Disable -+ * all EPs and enable EPs for new configuration.
GET_CONFIGURATION Gadget Driver Return -+ * the current configuration
SET_INTERFACE Gadget Driver Disable all -+ * EPs and enable EPs for new configuration.
GET_INTERFACE Gadget Driver Return the -+ * current interface.
SYNC_FRAME PCD Display debug -+ * message.
-+ * -+ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are -+ * processed by pcd_setup. Calling the Function Driver's setup function from -+ * pcd_setup processes the gadget SETUP commands. -+ */ -+static inline void pcd_setup(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ usb_device_request_t ctrl = pcd->setup_pkt->req; -+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; -+ -+ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; -+ -+#ifdef DWC_UTE_CFI -+ int retval = 0; -+ struct cfi_usb_ctrlrequest cfi_req; -+#endif -+ -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", -+ ctrl.bmRequestType, ctrl.bRequest, -+ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), -+ UGETW(ctrl.wLength)); -+#endif -+ -+ doeptsize0.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doeptsiz); -+ -+ /** @todo handle > 1 setup packet , assert error for now */ -+ -+ if (core_if->dma_enable && core_if->dma_desc_enable == 0 -+ && (doeptsize0.b.supcnt < 2)) { -+ DWC_ERROR -+ ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n"); -+ } -+ -+ /* Clean up the request queue */ -+ dwc_otg_request_nuke(ep0); -+ ep0->stopped = 0; -+ -+ if (ctrl.bmRequestType & UE_DIR_IN) { -+ ep0->dwc_ep.is_in = 1; -+ pcd->ep0state = EP0_IN_DATA_PHASE; -+ } else { -+ ep0->dwc_ep.is_in = 0; -+ pcd->ep0state = EP0_OUT_DATA_PHASE; -+ } -+ -+ if (UGETW(ctrl.wLength) == 0) { -+ ep0->dwc_ep.is_in = 1; -+ pcd->ep0state = EP0_IN_STATUS_PHASE; -+ } -+ -+ if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) { -+ -+#ifdef DWC_UTE_CFI -+ DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t)); -+ -+ //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ctrl.bRequestType, ctrl.bRequest); -+ if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) { -+ if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) { -+ retval = cfi_setup(pcd, &cfi_req); -+ if (retval < 0) { -+ ep0_do_stall(pcd, retval); -+ pcd->ep0_pending = 0; -+ return; -+ } -+ -+ /* if need gadget setup then call it and check the retval */ -+ if (pcd->cfi->need_gadget_att) { -+ retval = -+ cfi_gadget_setup(pcd, -+ &pcd->cfi-> -+ ctrl_req); -+ if (retval < 0) { -+ pcd->ep0_pending = 0; -+ return; -+ } -+ } -+ -+ if (pcd->cfi->need_status_in_complete) { -+ do_setup_in_status_phase(pcd); -+ } -+ return; -+ } -+ } -+#endif -+ -+ /* handle non-standard (class/vendor) requests in the gadget driver */ -+ do_gadget_setup(pcd, &ctrl); -+ return; -+ } -+ -+ /** @todo NGS: Handle bad setup packet? */ -+ -+/////////////////////////////////////////// -+//// --- Standard Request handling --- //// -+ -+ switch (ctrl.bRequest) { -+ case UR_GET_STATUS: -+ do_get_status(pcd); -+ break; -+ -+ case UR_CLEAR_FEATURE: -+ do_clear_feature(pcd); -+ break; -+ -+ case UR_SET_FEATURE: -+ do_set_feature(pcd); -+ break; -+ -+ case UR_SET_ADDRESS: -+ do_set_address(pcd); -+ break; -+ -+ case UR_SET_INTERFACE: -+ case UR_SET_CONFIG: -+// _pcd->request_config = 1; /* Configuration changed */ -+ do_gadget_setup(pcd, &ctrl); -+ break; -+ -+ case UR_SYNCH_FRAME: -+ do_gadget_setup(pcd, &ctrl); -+ break; -+ -+ default: -+ /* Call the Gadget Driver's setup functions */ -+ do_gadget_setup(pcd, &ctrl); -+ break; -+ } -+} -+ -+/** -+ * This function completes the ep0 control transfer. -+ */ -+static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ dwc_otg_dev_in_ep_regs_t *in_ep_regs = -+ dev_if->in_ep_regs[ep->dwc_ep.num]; -+#ifdef DEBUG_EP0 -+ dwc_otg_dev_out_ep_regs_t *out_ep_regs = -+ dev_if->out_ep_regs[ep->dwc_ep.num]; -+#endif -+ deptsiz0_data_t deptsiz; -+ dev_dma_desc_sts_t desc_sts; -+ dwc_otg_pcd_request_t *req; -+ int is_last = 0; -+ dwc_otg_pcd_t *pcd = ep->pcd; -+ -+#ifdef DWC_UTE_CFI -+ struct cfi_usb_ctrlrequest *ctrlreq; -+ int retval = -DWC_E_NOT_SUPPORTED; -+#endif -+ -+ if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ if (ep->dwc_ep.is_in) { -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n"); -+#endif -+ do_setup_out_status_phase(pcd); -+ } else { -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n"); -+#endif -+ -+#ifdef DWC_UTE_CFI -+ ctrlreq = &pcd->cfi->ctrl_req; -+ -+ if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) { -+ if (ctrlreq->bRequest > 0xB0 -+ && ctrlreq->bRequest < 0xBF) { -+ -+ /* Return if the PCD failed to handle the request */ -+ if ((retval = -+ pcd->cfi->ops. -+ ctrl_write_complete(pcd->cfi, -+ pcd)) < 0) { -+ CFI_INFO -+ ("ERROR setting a new value in the PCD(%d)\n", -+ retval); -+ ep0_do_stall(pcd, retval); -+ pcd->ep0_pending = 0; -+ return 0; -+ } -+ -+ /* If the gadget needs to be notified on the request */ -+ if (pcd->cfi->need_gadget_att == 1) { -+ //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req); -+ retval = -+ cfi_gadget_setup(pcd, -+ &pcd->cfi-> -+ ctrl_req); -+ -+ /* Return from the function if the gadget failed to process -+ * the request properly - this should never happen !!! -+ */ -+ if (retval < 0) { -+ CFI_INFO -+ ("ERROR setting a new value in the gadget(%d)\n", -+ retval); -+ pcd->ep0_pending = 0; -+ return 0; -+ } -+ } -+ -+ CFI_INFO("%s: RETVAL=%d\n", __func__, -+ retval); -+ /* If we hit here then the PCD and the gadget has properly -+ * handled the request - so send the ZLP IN to the host. -+ */ -+ /* @todo: MAS - decide whether we need to start the setup -+ * stage based on the need_setup value of the cfi object -+ */ -+ do_setup_in_status_phase(pcd); -+ pcd->ep0_pending = 0; -+ return 1; -+ } -+ } -+#endif -+ -+ do_setup_in_status_phase(pcd); -+ } -+ pcd->ep0_pending = 0; -+ return 1; -+ } -+ -+ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ return 0; -+ } -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ -+ if (pcd->ep0state == EP0_OUT_STATUS_PHASE -+ || pcd->ep0state == EP0_IN_STATUS_PHASE) { -+ is_last = 1; -+ } else if (ep->dwc_ep.is_in) { -+ deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz); -+ if (core_if->dma_desc_enable != 0) -+ desc_sts = dev_if->in_desc_addr->status; -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCDV, "%d len=%d xfersize=%d pktcnt=%d\n", -+ ep->dwc_ep.num, ep->dwc_ep.xfer_len, -+ deptsiz.b.xfersize, deptsiz.b.pktcnt); -+#endif -+ -+ if (((core_if->dma_desc_enable == 0) -+ && (deptsiz.b.xfersize == 0)) -+ || ((core_if->dma_desc_enable != 0) -+ && (desc_sts.b.bytes == 0))) { -+ req->actual = ep->dwc_ep.xfer_count; -+ /* Is a Zero Len Packet needed? */ -+ if (req->sent_zlp) { -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n"); -+#endif -+ req->sent_zlp = 0; -+ } -+ do_setup_out_status_phase(pcd); -+ } -+ } else { -+ /* ep0-OUT */ -+#ifdef DEBUG_EP0 -+ deptsiz.d32 = dwc_read_reg32(&out_ep_regs->doeptsiz); -+ DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n", -+ ep->dwc_ep.num, ep->dwc_ep.xfer_len, -+ deptsiz.b.xfersize, deptsiz.b.pktcnt); -+#endif -+ req->actual = ep->dwc_ep.xfer_count; -+ -+ /* Is a Zero Len Packet needed? */ -+ if (req->sent_zlp) { -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n"); -+#endif -+ req->sent_zlp = 0; -+ } -+ if (core_if->dma_desc_enable == 0) -+ do_setup_in_status_phase(pcd); -+ } -+ -+ /* Complete the request */ -+ if (is_last) { -+ dwc_otg_request_done(ep, req, 0); -+ ep->dwc_ep.start_xfer_buff = 0; -+ ep->dwc_ep.xfer_buff = 0; -+ ep->dwc_ep.xfer_len = 0; -+ return 1; -+ } -+ return 0; -+} -+ -+#ifdef DWC_UTE_CFI -+/** -+ * This function calculates traverses all the CFI DMA descriptors and -+ * and accumulates the bytes that are left to be transfered. -+ * -+ * @return The total bytes left to transfered, or a negative value as failure -+ */ -+static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep) -+{ -+ int32_t ret = 0; -+ int i; -+ struct dwc_otg_dma_desc *ddesc = NULL; -+ struct cfi_ep *cfiep; -+ -+ /* See if the pcd_ep has its respective cfi_ep mapped */ -+ cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep); -+ if (!cfiep) { -+ CFI_INFO("%s: Failed to find ep\n", __func__); -+ return -1; -+ } -+ -+ ddesc = ep->dwc_ep.descs; -+ -+ for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) { -+ -+#if defined(PRINT_CFI_DMA_DESCS) -+ print_desc(ddesc, ep->ep.name, i); -+#endif -+ ret += ddesc->status.b.bytes; -+ ddesc++; -+ } -+ -+ if (ret) -+ CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__, -+ ret); -+ -+ return ret; -+} -+#endif -+ -+/** -+ * This function completes the request for the EP. If there are -+ * additional requests for the EP in the queue they will be started. -+ */ -+static void complete_ep(dwc_otg_pcd_ep_t * ep) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ dwc_otg_dev_in_ep_regs_t *in_ep_regs = -+ dev_if->in_ep_regs[ep->dwc_ep.num]; -+ deptsiz_data_t deptsiz; -+ dev_dma_desc_sts_t desc_sts; -+ dwc_otg_pcd_request_t *req = 0; -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ uint32_t byte_count = 0; -+ int is_last = 0; -+ int i; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num, -+ (ep->dwc_ep.is_in ? "IN" : "OUT")); -+ -+ /* Get any pending requests */ -+ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ if (!req) { -+ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); -+ return; -+ } -+ } else { -+ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); -+ return; -+ } -+ -+ DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending); -+ -+ if (ep->dwc_ep.is_in) { -+ deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz); -+ -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable == 0) { -+ if (deptsiz.b.xfersize == 0 -+ && deptsiz.b.pktcnt == 0) { -+ byte_count = -+ ep->dwc_ep.xfer_len - -+ ep->dwc_ep.xfer_count; -+ -+ ep->dwc_ep.xfer_buff += byte_count; -+ ep->dwc_ep.dma_addr += byte_count; -+ ep->dwc_ep.xfer_count += byte_count; -+ -+ DWC_DEBUGPL(DBG_PCDV, -+ "%d-%s len=%d xfersize=%d pktcnt=%d\n", -+ ep->dwc_ep.num, -+ (ep->dwc_ep. -+ is_in ? "IN" : "OUT"), -+ ep->dwc_ep.xfer_len, -+ deptsiz.b.xfersize, -+ deptsiz.b.pktcnt); -+ -+ if (ep->dwc_ep.xfer_len < -+ ep->dwc_ep.total_len) { -+ dwc_otg_ep_start_transfer -+ (core_if, &ep->dwc_ep); -+ } else if (ep->dwc_ep.sent_zlp) { -+ /* -+ * This fragment of code should initiate 0 -+ * length trasfer in case if it is queued -+ * a trasfer with size divisible to EPs max -+ * packet size and with usb_request zero field -+ * is set, which means that after data is transfered, -+ * it is also should be transfered -+ * a 0 length packet at the end. For Slave and -+ * Buffer DMA modes in this case SW has -+ * to initiate 2 transfers one with transfer size, -+ * and the second with 0 size. For Desriptor -+ * DMA mode SW is able to initiate a transfer, -+ * which will handle all the packets including -+ * the last 0 legth. -+ */ -+ ep->dwc_ep.sent_zlp = 0; -+ dwc_otg_ep_start_zl_transfer -+ (core_if, &ep->dwc_ep); -+ } else { -+ is_last = 1; -+ } -+ } else { -+ DWC_WARN -+ ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", -+ ep->dwc_ep.num, -+ (ep->dwc_ep.is_in ? "IN" : "OUT"), -+ deptsiz.b.xfersize, -+ deptsiz.b.pktcnt); -+ } -+ } else { -+ dma_desc = ep->dwc_ep.desc_addr; -+ byte_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ -+#ifdef DWC_UTE_CFI -+ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, -+ ep->dwc_ep.buff_mode); -+ if (ep->dwc_ep.buff_mode != BM_STANDARD) { -+ int residue; -+ -+ residue = cfi_calc_desc_residue(ep); -+ if (residue < 0) -+ return; -+ -+ byte_count = residue; -+ } else { -+#endif -+ for (i = 0; i < ep->dwc_ep.desc_cnt; -+ ++i) { -+ desc_sts = dma_desc->status; -+ byte_count += desc_sts.b.bytes; -+ dma_desc++; -+ } -+#ifdef DWC_UTE_CFI -+ } -+#endif -+ if (byte_count == 0) { -+ ep->dwc_ep.xfer_count = -+ ep->dwc_ep.total_len; -+ is_last = 1; -+ } else { -+ DWC_WARN("Incomplete transfer\n"); -+ } -+ } -+ } else { -+ if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) { -+ DWC_DEBUGPL(DBG_PCDV, -+ "%d-%s len=%d xfersize=%d pktcnt=%d\n", -+ ep->dwc_ep.num, -+ ep->dwc_ep.is_in ? "IN" : "OUT", -+ ep->dwc_ep.xfer_len, -+ deptsiz.b.xfersize, -+ deptsiz.b.pktcnt); -+ -+ /* Check if the whole transfer was completed, -+ * if no, setup transfer for next portion of data -+ */ -+ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { -+ dwc_otg_ep_start_transfer(core_if, -+ &ep->dwc_ep); -+ } else if (ep->dwc_ep.sent_zlp) { -+ /* -+ * This fragment of code should initiate 0 -+ * length trasfer in case if it is queued -+ * a trasfer with size divisible to EPs max -+ * packet size and with usb_request zero field -+ * is set, which means that after data is transfered, -+ * it is also should be transfered -+ * a 0 length packet at the end. For Slave and -+ * Buffer DMA modes in this case SW has -+ * to initiate 2 transfers one with transfer size, -+ * and the second with 0 size. For Desriptor -+ * DMA mode SW is able to initiate a transfer, -+ * which will handle all the packets including -+ * the last 0 legth. -+ */ -+ ep->dwc_ep.sent_zlp = 0; -+ dwc_otg_ep_start_zl_transfer(core_if, -+ &ep-> -+ dwc_ep); -+ } else { -+ is_last = 1; -+ } -+ } else { -+ DWC_WARN -+ ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n", -+ ep->dwc_ep.num, -+ (ep->dwc_ep.is_in ? "IN" : "OUT"), -+ deptsiz.b.xfersize, deptsiz.b.pktcnt); -+ } -+ } -+ } else { -+ dwc_otg_dev_out_ep_regs_t *out_ep_regs = -+ dev_if->out_ep_regs[ep->dwc_ep.num]; -+ desc_sts.d32 = 0; -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable) { -+ dma_desc = ep->dwc_ep.desc_addr; -+ byte_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ -+#ifdef DWC_UTE_CFI -+ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, -+ ep->dwc_ep.buff_mode); -+ if (ep->dwc_ep.buff_mode != BM_STANDARD) { -+ int residue; -+ residue = cfi_calc_desc_residue(ep); -+ if (residue < 0) -+ return; -+ byte_count = residue; -+ } else { -+#endif -+ -+ for (i = 0; i < ep->dwc_ep.desc_cnt; -+ ++i) { -+ desc_sts = dma_desc->status; -+ byte_count += desc_sts.b.bytes; -+ dma_desc++; -+ } -+ -+#ifdef DWC_UTE_CFI -+ } -+#endif -+ ep->dwc_ep.xfer_count = ep->dwc_ep.total_len -+ - byte_count + -+ ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3); -+ is_last = 1; -+ } else { -+ deptsiz.d32 = 0; -+ deptsiz.d32 = -+ dwc_read_reg32(&out_ep_regs->doeptsiz); -+ -+ byte_count = (ep->dwc_ep.xfer_len - -+ ep->dwc_ep.xfer_count - -+ deptsiz.b.xfersize); -+ ep->dwc_ep.xfer_buff += byte_count; -+ ep->dwc_ep.dma_addr += byte_count; -+ ep->dwc_ep.xfer_count += byte_count; -+ -+ /* Check if the whole transfer was completed, -+ * if no, setup transfer for next portion of data -+ */ -+ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { -+ dwc_otg_ep_start_transfer(core_if, -+ &ep->dwc_ep); -+ } else if (ep->dwc_ep.sent_zlp) { -+ /* -+ * This fragment of code should initiate 0 -+ * length trasfer in case if it is queued -+ * a trasfer with size divisible to EPs max -+ * packet size and with usb_request zero field -+ * is set, which means that after data is transfered, -+ * it is also should be transfered -+ * a 0 length packet at the end. For Slave and -+ * Buffer DMA modes in this case SW has -+ * to initiate 2 transfers one with transfer size, -+ * and the second with 0 size. For Desriptor -+ * DMA mode SW is able to initiate a transfer, -+ * which will handle all the packets including -+ * the last 0 legth. -+ */ -+ ep->dwc_ep.sent_zlp = 0; -+ dwc_otg_ep_start_zl_transfer(core_if, -+ &ep-> -+ dwc_ep); -+ } else { -+ is_last = 1; -+ } -+ } -+ } else { -+ /* Check if the whole transfer was completed, -+ * if no, setup transfer for next portion of data -+ */ -+ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { -+ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); -+ } else if (ep->dwc_ep.sent_zlp) { -+ /* -+ * This fragment of code should initiate 0 -+ * length trasfer in case if it is queued -+ * a trasfer with size divisible to EPs max -+ * packet size and with usb_request zero field -+ * is set, which means that after data is transfered, -+ * it is also should be transfered -+ * a 0 length packet at the end. For Slave and -+ * Buffer DMA modes in this case SW has -+ * to initiate 2 transfers one with transfer size, -+ * and the second with 0 size. For Desriptor -+ * DMA mode SW is able to initiate a transfer, -+ * which will handle all the packets including -+ * the last 0 legth. -+ */ -+ ep->dwc_ep.sent_zlp = 0; -+ dwc_otg_ep_start_zl_transfer(core_if, -+ &ep->dwc_ep); -+ } else { -+ is_last = 1; -+ } -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, -+ "addr %p, %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n", -+ &out_ep_regs->doeptsiz, ep->dwc_ep.num, -+ ep->dwc_ep.is_in ? "IN" : "OUT", -+ ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count, -+ deptsiz.b.xfersize, deptsiz.b.pktcnt); -+ } -+ -+ /* Complete the request */ -+ if (is_last) { -+#ifdef DWC_UTE_CFI -+ if (ep->dwc_ep.buff_mode != BM_STANDARD) { -+ req->actual = ep->dwc_ep.cfi_req_len - byte_count; -+ } else { -+#endif -+ req->actual = ep->dwc_ep.xfer_count; -+#ifdef DWC_UTE_CFI -+ } -+#endif -+ -+ dwc_otg_request_done(ep, req, 0); -+ -+ ep->dwc_ep.start_xfer_buff = 0; -+ ep->dwc_ep.xfer_buff = 0; -+ ep->dwc_ep.xfer_len = 0; -+ -+ /* If there is a request in the queue start it. */ -+ start_next_request(ep); -+ } -+} -+ -+#ifdef DWC_EN_ISOC -+ -+/** -+ * This function BNA interrupt for Isochronous EPs -+ * -+ */ -+static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep) -+{ -+ dwc_ep_t *dwc_ep = &ep->dwc_ep; -+ volatile uint32_t *addr; -+ depctl_data_t depctl = {.d32 = 0 }; -+ dwc_otg_pcd_t *pcd = ep->pcd; -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ int i; -+ -+ dma_desc = -+ dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num); -+ -+ if (dwc_ep->is_in) { -+ dev_dma_desc_sts_t sts = {.d32 = 0 }; -+ for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { -+ sts.d32 = dma_desc->status.d32; -+ sts.b_iso_in.bs = BS_HOST_READY; -+ dma_desc->status.d32 = sts.d32; -+ } -+ } else { -+ dev_dma_desc_sts_t sts = {.d32 = 0 }; -+ for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { -+ sts.d32 = dma_desc->status.d32; -+ sts.b_iso_out.bs = BS_HOST_READY; -+ dma_desc->status.d32 = sts.d32; -+ } -+ } -+ -+ if (dwc_ep->is_in == 0) { -+ addr = -+ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]-> -+ doepctl; -+ } else { -+ addr = -+ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; -+ } -+ depctl.b.epena = 1; -+ dwc_modify_reg32(addr, depctl.d32, depctl.d32); -+} -+ -+/** -+ * This function sets latest iso packet information(non-PTI mode) -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ * -+ */ -+void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ deptsiz_data_t deptsiz = {.d32 = 0 }; -+ dma_addr_t dma_addr; -+ uint32_t offset; -+ -+ if (ep->proc_buf_num) -+ dma_addr = ep->dma_addr1; -+ else -+ dma_addr = ep->dma_addr0; -+ -+ if (ep->is_in) { -+ deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ dieptsiz); -+ offset = ep->data_per_frame; -+ } else { -+ deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> -+ doeptsiz); -+ offset = -+ ep->data_per_frame + -+ (0x4 & (0x4 - (ep->data_per_frame & 0x3))); -+ } -+ -+ if (!deptsiz.b.xfersize) { -+ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; -+ ep->pkt_info[ep->cur_pkt].offset = -+ ep->cur_pkt_dma_addr - dma_addr; -+ ep->pkt_info[ep->cur_pkt].status = 0; -+ } else { -+ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; -+ ep->pkt_info[ep->cur_pkt].offset = -+ ep->cur_pkt_dma_addr - dma_addr; -+ ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA; -+ } -+ ep->cur_pkt_addr += offset; -+ ep->cur_pkt_dma_addr += offset; -+ ep->cur_pkt++; -+} -+ -+/** -+ * This function sets latest iso packet information(DDMA mode) -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param dwc_ep The EP to start the transfer on. -+ * -+ */ -+static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * dwc_ep) -+{ -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ dev_dma_desc_sts_t sts = {.d32 = 0 }; -+ iso_pkt_info_t *iso_packet; -+ uint32_t data_per_desc; -+ uint32_t offset; -+ int i, j; -+ -+ iso_packet = dwc_ep->pkt_info; -+ -+ /** Reinit closed DMA Descriptors*/ -+ /** ISO OUT EP */ -+ if (dwc_ep->is_in == 0) { -+ dma_desc = -+ dwc_ep->iso_desc_addr + -+ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; -+ offset = 0; -+ -+ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; -+ i += dwc_ep->pkt_per_frm) { -+ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep-> -+ data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - -+ data_per_desc % -+ 4) : 0; -+ -+ sts.d32 = dma_desc->status.d32; -+ -+ /* Write status in iso_packet_decsriptor */ -+ iso_packet->status = -+ sts.b_iso_out.rxsts + -+ (sts.b_iso_out.bs ^ BS_DMA_DONE); -+ if (iso_packet->status) { -+ iso_packet->status = -DWC_E_NO_DATA; -+ } -+ -+ /* Received data length */ -+ if (!sts.b_iso_out.rxbytes) { -+ iso_packet->length = -+ data_per_desc - -+ sts.b_iso_out.rxbytes; -+ } else { -+ iso_packet->length = -+ data_per_desc - -+ sts.b_iso_out.rxbytes + (4 - -+ dwc_ep-> -+ data_per_frame -+ % 4); -+ } -+ -+ iso_packet->offset = offset; -+ -+ offset += data_per_desc; -+ dma_desc++; -+ iso_packet++; -+ } -+ } -+ -+ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ -+ sts.d32 = dma_desc->status.d32; -+ -+ /* Write status in iso_packet_decsriptor */ -+ iso_packet->status = -+ sts.b_iso_out.rxsts + -+ (sts.b_iso_out.bs ^ BS_DMA_DONE); -+ if (iso_packet->status) { -+ iso_packet->status = -DWC_E_NO_DATA; -+ } -+ -+ /* Received data length */ -+ iso_packet->length = -+ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; -+ -+ iso_packet->offset = offset; -+ -+ offset += data_per_desc; -+ iso_packet++; -+ dma_desc++; -+ } -+ -+ sts.d32 = dma_desc->status.d32; -+ -+ /* Write status in iso_packet_decsriptor */ -+ iso_packet->status = -+ sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE); -+ if (iso_packet->status) { -+ iso_packet->status = -DWC_E_NO_DATA; -+ } -+ /* Received data length */ -+ if (!sts.b_iso_out.rxbytes) { -+ iso_packet->length = -+ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; -+ } else { -+ iso_packet->length = -+ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes + -+ (4 - dwc_ep->data_per_frame % 4); -+ } -+ -+ iso_packet->offset = offset; -+ } else { -+/** ISO IN EP */ -+ -+ dma_desc = -+ dwc_ep->iso_desc_addr + -+ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; -+ -+ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { -+ sts.d32 = dma_desc->status.d32; -+ -+ /* Write status in iso packet descriptor */ -+ iso_packet->status = -+ sts.b_iso_in.txsts + -+ (sts.b_iso_in.bs ^ BS_DMA_DONE); -+ if (iso_packet->status != 0) { -+ iso_packet->status = -DWC_E_NO_DATA; -+ -+ } -+ /* Bytes has been transfered */ -+ iso_packet->length = -+ dwc_ep->data_per_frame - sts.b_iso_in.txbytes; -+ -+ dma_desc++; -+ iso_packet++; -+ } -+ -+ sts.d32 = dma_desc->status.d32; -+ while (sts.b_iso_in.bs == BS_DMA_BUSY) { -+ sts.d32 = dma_desc->status.d32; -+ } -+ -+ /* Write status in iso packet descriptor ??? do be done with ERROR codes */ -+ iso_packet->status = -+ sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE); -+ if (iso_packet->status != 0) { -+ iso_packet->status = -DWC_E_NO_DATA; -+ } -+ -+ /* Bytes has been transfered */ -+ iso_packet->length = -+ dwc_ep->data_per_frame - sts.b_iso_in.txbytes; -+ } -+} -+ -+/** -+ * This function reinitialize DMA Descriptors for Isochronous transfer -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param dwc_ep The EP to start the transfer on. -+ * -+ */ -+static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) -+{ -+ int i, j; -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ dma_addr_t dma_ad; -+ volatile uint32_t *addr; -+ dev_dma_desc_sts_t sts = {.d32 = 0 }; -+ uint32_t data_per_desc; -+ -+ if (dwc_ep->is_in == 0) { -+ addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; -+ } else { -+ addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; -+ } -+ -+ if (dwc_ep->proc_buf_num == 0) { -+ /** Buffer 0 descriptors setup */ -+ dma_ad = dwc_ep->dma_addr0; -+ } else { -+ /** Buffer 1 descriptors setup */ -+ dma_ad = dwc_ep->dma_addr1; -+ } -+ -+ /** Reinit closed DMA Descriptors*/ -+ /** ISO OUT EP */ -+ if (dwc_ep->is_in == 0) { -+ dma_desc = -+ dwc_ep->iso_desc_addr + -+ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; -+ -+ sts.b_iso_out.bs = BS_HOST_READY; -+ sts.b_iso_out.rxsts = 0; -+ sts.b_iso_out.l = 0; -+ sts.b_iso_out.sp = 0; -+ sts.b_iso_out.ioc = 0; -+ sts.b_iso_out.pid = 0; -+ sts.b_iso_out.framenum = 0; -+ -+ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; -+ i += dwc_ep->pkt_per_frm) { -+ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep-> -+ data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - -+ data_per_desc % -+ 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ dma_ad += data_per_desc; -+ dma_desc++; -+ } -+ } -+ -+ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { -+ -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ dma_desc++; -+ dma_ad += data_per_desc; -+ } -+ -+ sts.b_iso_out.ioc = 1; -+ sts.b_iso_out.l = dwc_ep->proc_buf_num; -+ -+ data_per_desc = -+ ((j + 1) * dwc_ep->maxpacket > -+ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket : dwc_ep->maxpacket; -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ sts.b_iso_out.rxbytes = data_per_desc; -+ -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ } else { -+/** ISO IN EP */ -+ -+ dma_desc = -+ dwc_ep->iso_desc_addr + -+ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; -+ -+ sts.b_iso_in.bs = BS_HOST_READY; -+ sts.b_iso_in.txsts = 0; -+ sts.b_iso_in.sp = 0; -+ sts.b_iso_in.ioc = 0; -+ sts.b_iso_in.pid = dwc_ep->pkt_per_frm; -+ sts.b_iso_in.framenum = dwc_ep->next_frame; -+ sts.b_iso_in.txbytes = dwc_ep->data_per_frame; -+ sts.b_iso_in.l = 0; -+ -+ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ sts.b_iso_in.framenum += dwc_ep->bInterval; -+ dma_ad += dwc_ep->data_per_frame; -+ dma_desc++; -+ } -+ -+ sts.b_iso_in.ioc = 1; -+ sts.b_iso_in.l = dwc_ep->proc_buf_num; -+ -+ dma_desc->buf = dma_ad; -+ dma_desc->status.d32 = sts.d32; -+ -+ dwc_ep->next_frame = -+ sts.b_iso_in.framenum + dwc_ep->bInterval * 1; -+ } -+ dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; -+} -+ -+/** -+ * This function is to handle Iso EP transfer complete interrupt -+ * in case Iso out packet was dropped -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param dwc_ep The EP for wihich transfer complete was asserted -+ * -+ */ -+static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if, -+ dwc_ep_t * dwc_ep) -+{ -+ uint32_t dma_addr; -+ uint32_t drp_pkt; -+ uint32_t drp_pkt_cnt; -+ deptsiz_data_t deptsiz = {.d32 = 0 }; -+ depctl_data_t depctl = {.d32 = 0 }; -+ int i; -+ -+ deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]-> -+ doeptsiz); -+ -+ drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt; -+ drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm); -+ -+ /* Setting dropped packets status */ -+ for (i = 0; i < drp_pkt_cnt; ++i) { -+ dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA; -+ drp_pkt++; -+ deptsiz.b.pktcnt--; -+ } -+ -+ if (deptsiz.b.pktcnt > 0) { -+ deptsiz.b.xfersize = -+ dwc_ep->xfer_len - (dwc_ep->pkt_cnt - -+ deptsiz.b.pktcnt) * dwc_ep->maxpacket; -+ } else { -+ deptsiz.b.xfersize = 0; -+ deptsiz.b.pktcnt = 0; -+ } -+ -+ dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, -+ deptsiz.d32); -+ -+ if (deptsiz.b.pktcnt > 0) { -+ if (dwc_ep->proc_buf_num) { -+ dma_addr = -+ dwc_ep->dma_addr1 + dwc_ep->xfer_len - -+ deptsiz.b.xfersize; -+ } else { -+ dma_addr = -+ dwc_ep->dma_addr0 + dwc_ep->xfer_len - -+ deptsiz.b.xfersize;; -+ } -+ -+ dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]-> -+ doepdma, dma_addr); -+ -+ /** Re-enable endpoint, clear nak */ -+ depctl.d32 = 0; -+ depctl.b.epena = 1; -+ depctl.b.cnak = 1; -+ -+ dwc_modify_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]-> -+ doepctl, depctl.d32, depctl.d32); -+ return 0; -+ } else { -+ return 1; -+ } -+} -+ -+/** -+ * This function sets iso packets information(PTI mode) -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ * @param ep The EP to start the transfer on. -+ * -+ */ -+static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) -+{ -+ int i, j; -+ dma_addr_t dma_ad; -+ iso_pkt_info_t *packet_info = ep->pkt_info; -+ uint32_t offset; -+ uint32_t frame_data; -+ deptsiz_data_t deptsiz; -+ -+ if (ep->proc_buf_num == 0) { -+ /** Buffer 0 descriptors setup */ -+ dma_ad = ep->dma_addr0; -+ } else { -+ /** Buffer 1 descriptors setup */ -+ dma_ad = ep->dma_addr1; -+ } -+ -+ if (ep->is_in) { -+ deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ dieptsiz); -+ } else { -+ deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> -+ doeptsiz); -+ } -+ -+ if (!deptsiz.b.xfersize) { -+ offset = 0; -+ for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) { -+ frame_data = ep->data_per_frame; -+ for (j = 0; j < ep->pkt_per_frm; ++j) { -+ -+ /* Packet status - is not set as initially -+ * it is set to 0 and if packet was sent -+ successfully, status field will remain 0*/ -+ -+ /* Bytes has been transfered */ -+ packet_info->length = -+ (ep->maxpacket < -+ frame_data) ? ep->maxpacket : frame_data; -+ -+ /* Received packet offset */ -+ packet_info->offset = offset; -+ offset += packet_info->length; -+ frame_data -= packet_info->length; -+ -+ packet_info++; -+ } -+ } -+ return 1; -+ } else { -+ /* This is a workaround for in case of Transfer Complete with -+ * PktDrpSts interrupts merging - in this case Transfer complete -+ * interrupt for Isoc Out Endpoint is asserted without PktDrpSts -+ * set and with DOEPTSIZ register non zero. Investigations showed, -+ * that this happens when Out packet is dropped, but because of -+ * interrupts merging during first interrupt handling PktDrpSts -+ * bit is cleared and for next merged interrupts it is not reset. -+ * In this case SW hadles the interrupt as if PktDrpSts bit is set. -+ */ -+ if (ep->is_in) { -+ return 1; -+ } else { -+ return handle_iso_out_pkt_dropped(core_if, ep); -+ } -+ } -+} -+ -+/** -+ * This function is to handle Iso EP transfer complete interrupt -+ * -+ * @param pcd The PCD -+ * @param ep The EP for which transfer complete was asserted -+ * -+ */ -+static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); -+ dwc_ep_t *dwc_ep = &ep->dwc_ep; -+ uint8_t is_last = 0; -+ -+ if(ep->dwc_ep.next_frame == 0xffffffff) { -+ DWC_WARN("Next frame is not set!\n"); -+ return; -+ } -+ -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable) { -+ set_ddma_iso_pkts_info(core_if, dwc_ep); -+ reinit_ddma_iso_xfer(core_if, dwc_ep); -+ is_last = 1; -+ } else { -+ if (core_if->pti_enh_enable) { -+ if (set_iso_pkts_info(core_if, dwc_ep)) { -+ dwc_ep->proc_buf_num = -+ (dwc_ep->proc_buf_num ^ 1) & 0x1; -+ dwc_otg_iso_ep_start_buf_transfer -+ (core_if, dwc_ep); -+ is_last = 1; -+ } -+ } else { -+ set_current_pkt_info(core_if, dwc_ep); -+ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { -+ is_last = 1; -+ dwc_ep->cur_pkt = 0; -+ dwc_ep->proc_buf_num = -+ (dwc_ep->proc_buf_num ^ 1) & 0x1; -+ if (dwc_ep->proc_buf_num) { -+ dwc_ep->cur_pkt_addr = -+ dwc_ep->xfer_buff1; -+ dwc_ep->cur_pkt_dma_addr = -+ dwc_ep->dma_addr1; -+ } else { -+ dwc_ep->cur_pkt_addr = -+ dwc_ep->xfer_buff0; -+ dwc_ep->cur_pkt_dma_addr = -+ dwc_ep->dma_addr0; -+ } -+ -+ } -+ dwc_otg_iso_ep_start_frm_transfer(core_if, -+ dwc_ep); -+ } -+ } -+ } else { -+ set_current_pkt_info(core_if, dwc_ep); -+ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { -+ is_last = 1; -+ dwc_ep->cur_pkt = 0; -+ dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; -+ if (dwc_ep->proc_buf_num) { -+ dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1; -+ dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1; -+ } else { -+ dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0; -+ dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0; -+ } -+ -+ } -+ dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep); -+ } -+ if (is_last) -+ dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle); -+} -+#endif /* DWC_EN_ISOC */ -+ -+/** -+ * This function handles EP0 Control transfers. -+ * -+ * The state of the control tranfers are tracked in -+ * ep0state. -+ */ -+static void handle_ep0(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; -+ dev_dma_desc_sts_t desc_sts; -+ deptsiz0_data_t deptsiz; -+ uint32_t byte_count; -+ -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); -+ print_ep0_state(pcd); -+#endif -+ -+// DWC_PRINTF("HANDLE EP0\n"); -+ -+ switch (pcd->ep0state) { -+ case EP0_DISCONNECT: -+ break; -+ -+ case EP0_IDLE: -+ pcd->request_config = 0; -+ -+ pcd_setup(pcd); -+ break; -+ -+ case EP0_IN_DATA_PHASE: -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n", -+ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), -+ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); -+#endif -+ -+ if (core_if->dma_enable != 0) { -+ /* -+ * For EP0 we can only program 1 packet at a time so we -+ * need to do the make calculations after each complete. -+ * Call write_packet to make the calculations, as in -+ * slave mode, and use those values to determine if we -+ * can complete. -+ */ -+ if (core_if->dma_desc_enable == 0) { -+ deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if-> -+ in_ep_regs[0]->dieptsiz); -+ byte_count = -+ ep0->dwc_ep.xfer_len - deptsiz.b.xfersize; -+ } else { -+ desc_sts = -+ core_if->dev_if->in_desc_addr->status; -+ byte_count = -+ ep0->dwc_ep.xfer_len - desc_sts.b.bytes; -+ } -+ ep0->dwc_ep.xfer_count += byte_count; -+ ep0->dwc_ep.xfer_buff += byte_count; -+ ep0->dwc_ep.dma_addr += byte_count; -+ } -+ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { -+ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), -+ &ep0->dwc_ep); -+ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); -+ } else if (ep0->dwc_ep.sent_zlp) { -+ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), -+ &ep0->dwc_ep); -+ ep0->dwc_ep.sent_zlp = 0; -+ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); -+ } else { -+ ep0_complete_request(ep0); -+ DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); -+ } -+ break; -+ case EP0_OUT_DATA_PHASE: -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n", -+ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), -+ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); -+#endif -+ if (core_if->dma_enable != 0) { -+ if (core_if->dma_desc_enable == 0) { -+ deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if-> -+ out_ep_regs[0]->doeptsiz); -+ byte_count = -+ ep0->dwc_ep.maxpacket - deptsiz.b.xfersize; -+ } else { -+ desc_sts = -+ core_if->dev_if->out_desc_addr->status; -+ byte_count = -+ ep0->dwc_ep.maxpacket - desc_sts.b.bytes; -+ } -+ ep0->dwc_ep.xfer_count += byte_count; -+ ep0->dwc_ep.xfer_buff += byte_count; -+ ep0->dwc_ep.dma_addr += byte_count; -+ } -+ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { -+ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), -+ &ep0->dwc_ep); -+ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); -+ } else if (ep0->dwc_ep.sent_zlp) { -+ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), -+ &ep0->dwc_ep); -+ ep0->dwc_ep.sent_zlp = 0; -+ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); -+ } else { -+ ep0_complete_request(ep0); -+ DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); -+ } -+ break; -+ -+ case EP0_IN_STATUS_PHASE: -+ case EP0_OUT_STATUS_PHASE: -+ DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n"); -+ ep0_complete_request(ep0); -+ pcd->ep0state = EP0_IDLE; -+ ep0->stopped = 1; -+ ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */ -+ -+ /* Prepare for more SETUP Packets */ -+ if (core_if->dma_enable) { -+ ep0_out_start(core_if, pcd); -+ } -+ break; -+ -+ case EP0_STALL: -+ DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n"); -+ break; -+ } -+#ifdef DEBUG_EP0 -+ print_ep0_state(pcd); -+#endif -+} -+ -+/** -+ * Restart transfer -+ */ -+static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum) -+{ -+ dwc_otg_core_if_t *core_if; -+ dwc_otg_dev_if_t *dev_if; -+ deptsiz_data_t dieptsiz = {.d32 = 0 }; -+ dwc_otg_pcd_ep_t *ep; -+ -+ ep = get_in_ep(pcd, epnum); -+ -+#ifdef DWC_EN_ISOC -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { -+ return; -+ } -+#endif /* DWC_EN_ISOC */ -+ -+ core_if = GET_CORE_IF(pcd); -+ dev_if = core_if->dev_if; -+ -+ dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz); -+ -+ DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x" -+ " stopped=%d\n", ep->dwc_ep.xfer_buff, -+ ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped); -+ /* -+ * If xfersize is 0 and pktcnt in not 0, resend the last packet. -+ */ -+ if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 && -+ ep->dwc_ep.start_xfer_buff != 0) { -+ if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) { -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff; -+ ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; -+ } else { -+ ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket; -+ /* convert packet size to dwords. */ -+ ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket; -+ ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; -+ } -+ ep->stopped = 0; -+ DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x " -+ "xfer_len=%0x stopped=%d\n", -+ ep->dwc_ep.xfer_buff, -+ ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, -+ ep->stopped); -+ if (epnum == 0) { -+ dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep); -+ } else { -+ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); -+ } -+ } -+} -+ -+/** -+ * handle the IN EP disable interrupt. -+ */ -+static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd, -+ const uint32_t epnum) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ deptsiz_data_t dieptsiz = {.d32 = 0 }; -+ dctl_data_t dctl = {.d32 = 0 }; -+ dwc_otg_pcd_ep_t *ep; -+ dwc_ep_t *dwc_ep; -+ -+ ep = get_in_ep(pcd, epnum); -+ dwc_ep = &ep->dwc_ep; -+ -+ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); -+ return; -+ } -+ -+ DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum, -+ dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl)); -+ dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz); -+ -+ DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", -+ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); -+ -+ if (ep->stopped) { -+ /* Flush the Tx FIFO */ -+ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); -+ /* Clear the Global IN NP NAK */ -+ dctl.d32 = 0; -+ dctl.b.cgnpinnak = 1; -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, 0); -+ /* Restart the transaction */ -+ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { -+ restart_transfer(pcd, epnum); -+ } -+ } else { -+ /* Restart the transaction */ -+ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { -+ restart_transfer(pcd, epnum); -+ } -+ DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); -+ } -+} -+ -+/** -+ * Handler for the IN EP timeout handshake interrupt. -+ */ -+static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd, -+ const uint32_t epnum) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ -+#ifdef DEBUG -+ deptsiz_data_t dieptsiz = {.d32 = 0 }; -+ uint32_t num = 0; -+#endif -+ dctl_data_t dctl = {.d32 = 0 }; -+ dwc_otg_pcd_ep_t *ep; -+ -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ ep = get_in_ep(pcd, epnum); -+ -+ /* Disable the NP Tx Fifo Empty Interrrupt */ -+ if (!core_if->dma_enable) { -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ } -+ /** @todo NGS Check EP type. -+ * Implement for Periodic EPs */ -+ /* -+ * Non-periodic EP -+ */ -+ /* Enable the Global IN NAK Effective Interrupt */ -+ intr_mask.b.ginnakeff = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); -+ -+ /* Set Global IN NAK */ -+ dctl.b.sgnpinnak = 1; -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); -+ -+ ep->stopped = 1; -+ -+#ifdef DEBUG -+ dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[num]->dieptsiz); -+ DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", -+ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); -+#endif -+ -+#ifdef DISABLE_PERIODIC_EP -+ /* -+ * Set the NAK bit for this EP to -+ * start the disable process. -+ */ -+ diepctl.d32 = 0; -+ diepctl.b.snak = 1; -+ dwc_modify_reg32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, -+ diepctl.d32); -+ ep->disabling = 1; -+ ep->stopped = 1; -+#endif -+} -+ -+/** -+ * Handler for the IN EP NAK interrupt. -+ */ -+static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd, -+ const uint32_t epnum) -+{ -+ /** @todo implement ISR */ -+ dwc_otg_core_if_t *core_if; -+ diepmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK"); -+ core_if = GET_CORE_IF(pcd); -+ intr_mask.b.nak = 1; -+ -+ if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ diepeachintmsk[epnum], intr_mask.d32, 0); -+ } else { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->diepmsk, -+ intr_mask.d32, 0); -+ } -+ -+ return 1; -+} -+ -+/** -+ * Handler for the OUT EP Babble interrupt. -+ */ -+static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd, -+ const uint32_t epnum) -+{ -+ /** @todo implement ISR */ -+ dwc_otg_core_if_t *core_if; -+ doepmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "OUT EP Babble"); -+ core_if = GET_CORE_IF(pcd); -+ intr_mask.b.babble = 1; -+ -+ if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ doepeachintmsk[epnum], intr_mask.d32, 0); -+ } else { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, -+ intr_mask.d32, 0); -+ } -+ -+ return 1; -+} -+ -+/** -+ * Handler for the OUT EP NAK interrupt. -+ */ -+static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd, -+ const uint32_t epnum) -+{ -+ /** @todo implement ISR */ -+ dwc_otg_core_if_t *core_if; -+ doepmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); -+ core_if = GET_CORE_IF(pcd); -+ intr_mask.b.nak = 1; -+ -+ if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ doepeachintmsk[epnum], intr_mask.d32, 0); -+ } else { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, -+ intr_mask.d32, 0); -+ } -+ -+ return 1; -+} -+ -+/** -+ * Handler for the OUT EP NYET interrupt. -+ */ -+static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd, -+ const uint32_t epnum) -+{ -+ /** @todo implement ISR */ -+ dwc_otg_core_if_t *core_if; -+ doepmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET"); -+ core_if = GET_CORE_IF(pcd); -+ intr_mask.b.nyet = 1; -+ -+ if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ doepeachintmsk[epnum], intr_mask.d32, 0); -+ } else { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, -+ intr_mask.d32, 0); -+ } -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that an IN EP has a pending Interrupt. -+ * The sequence for handling the IN EP interrupt is shown below: -+ * -# Read the Device All Endpoint Interrupt register -+ * -# Repeat the following for each IN EP interrupt bit set (from -+ * LSB to MSB). -+ * -# Read the Device Endpoint Interrupt (DIEPINTn) register -+ * -# If "Transfer Complete" call the request complete function -+ * -# If "Endpoint Disabled" complete the EP disable procedure. -+ * -# If "AHB Error Interrupt" log error -+ * -# If "Time-out Handshake" log error -+ * -# If "IN Token Received when TxFIFO Empty" write packet to Tx -+ * FIFO. -+ * -# If "IN Token EP Mismatch" (disable, this is handled by EP -+ * Mismatch Interrupt) -+ */ -+static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) -+{ -+#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \ -+do { \ -+ diepint_data_t diepint = {.d32=0}; \ -+ diepint.b.__intr = 1; \ -+ dwc_write_reg32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ -+ diepint.d32); \ -+} while (0) -+ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ diepint_data_t diepint = {.d32 = 0 }; -+ dctl_data_t dctl = {.d32 = 0 }; -+ depctl_data_t depctl = {.d32 = 0 }; -+ uint32_t ep_intr; -+ uint32_t epnum = 0; -+ dwc_otg_pcd_ep_t *ep; -+ dwc_ep_t *dwc_ep; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd); -+ -+ /* Read in the device interrupt bits */ -+ ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if); -+ -+ /* Service the Device IN interrupts for each endpoint */ -+ while (ep_intr) { -+ if (ep_intr & 0x1) { -+ uint32_t empty_msk; -+ /* Get EP pointer */ -+ ep = get_in_ep(pcd, epnum); -+ dwc_ep = &ep->dwc_ep; -+ -+ depctl.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl); -+ empty_msk = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ dtknqr4_fifoemptymsk); -+ -+ DWC_DEBUGPL(DBG_PCDV, -+ "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n", -+ epnum, empty_msk, depctl.d32); -+ -+ DWC_DEBUGPL(DBG_PCD, -+ "EP%d-%s: type=%d, mps=%d\n", -+ dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"), -+ dwc_ep->type, dwc_ep->maxpacket); -+ -+ diepint.d32 = -+ dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep); -+ -+ DWC_DEBUGPL(DBG_PCDV, -+ "EP %d Interrupt Register - 0x%x\n", epnum, -+ diepint.d32); -+ /* Transfer complete */ -+ if (diepint.b.xfercompl) { -+ /* Disable the NP Tx FIFO Empty -+ * Interrrupt */ -+ if (core_if->en_multiple_tx_fifo == 0) { -+ intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if-> -+ core_global_regs-> -+ gintmsk, intr_mask.d32, -+ 0); -+ } else { -+ /* Disable the Tx FIFO Empty Interrupt for this EP */ -+ uint32_t fifoemptymsk = -+ 0x1 << dwc_ep->num; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, -+ fifoemptymsk, 0); -+ } -+ /* Clear the bit in DIEPINTn for this interrupt */ -+ CLEAR_IN_EP_INTR(core_if, epnum, xfercompl); -+ -+ /* Complete the transfer */ -+ if (epnum == 0) { -+ handle_ep0(pcd); -+ } -+#ifdef DWC_EN_ISOC -+ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ if (!ep->stopped) -+ complete_iso_ep(pcd, ep); -+ } -+#endif /* DWC_EN_ISOC */ -+ else { -+ -+ complete_ep(ep); -+ } -+ } -+ /* Endpoint disable */ -+ if (diepint.b.epdisabled) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n", -+ epnum); -+ handle_in_ep_disable_intr(pcd, epnum); -+ -+ /* Clear the bit in DIEPINTn for this interrupt */ -+ CLEAR_IN_EP_INTR(core_if, epnum, epdisabled); -+ } -+ /* AHB Error */ -+ if (diepint.b.ahberr) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d IN AHB Error\n", -+ epnum); -+ /* Clear the bit in DIEPINTn for this interrupt */ -+ CLEAR_IN_EP_INTR(core_if, epnum, ahberr); -+ } -+ /* TimeOUT Handshake (non-ISOC IN EPs) */ -+ if (diepint.b.timeout) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d IN Time-out\n", -+ epnum); -+ handle_in_ep_timeout_intr(pcd, epnum); -+ -+ CLEAR_IN_EP_INTR(core_if, epnum, timeout); -+ } -+ /** IN Token received with TxF Empty */ -+ if (diepint.b.intktxfemp) { -+ DWC_DEBUGPL(DBG_ANY, -+ "EP%d IN TKN TxFifo Empty\n", -+ epnum); -+ if (!ep->stopped && epnum != 0) { -+ -+ diepmsk_data_t diepmsk = {.d32 = 0 }; -+ diepmsk.b.intktxfemp = 1; -+ -+ if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&dev_if-> -+ dev_global_regs-> -+ diepeachintmsk -+ [epnum], -+ diepmsk.d32, -+ 0); -+ } else { -+ dwc_modify_reg32(&dev_if-> -+ dev_global_regs-> -+ diepmsk, -+ diepmsk.d32, -+ 0); -+ } -+ } else if (core_if->dma_desc_enable -+ && epnum == 0 -+ && pcd->ep0state == -+ EP0_OUT_STATUS_PHASE) { -+ // EP0 IN set STALL -+ depctl.d32 = -+ dwc_read_reg32(&dev_if-> -+ in_ep_regs[epnum]-> -+ diepctl); -+ -+ /* set the disable and stall bits */ -+ if (depctl.b.epena) { -+ depctl.b.epdis = 1; -+ } -+ depctl.b.stall = 1; -+ dwc_write_reg32(&dev_if-> -+ in_ep_regs[epnum]-> -+ diepctl, depctl.d32); -+ } -+ CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp); -+ } -+ /** IN Token Received with EP mismatch */ -+ if (diepint.b.intknepmis) { -+ DWC_DEBUGPL(DBG_ANY, -+ "EP%d IN TKN EP Mismatch\n", epnum); -+ CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); -+ } -+ /** IN Endpoint NAK Effective */ -+ if (diepint.b.inepnakeff) { -+ DWC_DEBUGPL(DBG_ANY, -+ "EP%d IN EP NAK Effective\n", -+ epnum); -+ /* Periodic EP */ -+ if (ep->disabling) { -+ depctl.d32 = 0; -+ depctl.b.snak = 1; -+ depctl.b.epdis = 1; -+ dwc_modify_reg32(&dev_if-> -+ in_ep_regs[epnum]-> -+ diepctl, depctl.d32, -+ depctl.d32); -+ } -+ CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff); -+ -+ } -+ -+ /** IN EP Tx FIFO Empty Intr */ -+ if (diepint.b.emptyintr) { -+ DWC_DEBUGPL(DBG_ANY, -+ "EP%d Tx FIFO Empty Intr \n", -+ epnum); -+ write_empty_tx_fifo(pcd, epnum); -+ -+ CLEAR_IN_EP_INTR(core_if, epnum, emptyintr); -+ -+ } -+ -+ /** IN EP BNA Intr */ -+ if (diepint.b.bna) { -+ CLEAR_IN_EP_INTR(core_if, epnum, bna); -+ if (core_if->dma_desc_enable) { -+#ifdef DWC_EN_ISOC -+ if (dwc_ep->type == -+ DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * This checking is performed to prevent first "false" BNA -+ * handling occuring right after reconnect -+ */ -+ if (dwc_ep->next_frame != -+ 0xffffffff) -+ dwc_otg_pcd_handle_iso_bna -+ (ep); -+ } else -+#endif /* DWC_EN_ISOC */ -+ { -+ dctl.d32 = -+ dwc_read_reg32(&dev_if-> -+ dev_global_regs-> -+ dctl); -+ -+ /* If Global Continue on BNA is disabled - disable EP */ -+ if (!dctl.b.gcontbna) { -+ depctl.d32 = 0; -+ depctl.b.snak = 1; -+ depctl.b.epdis = 1; -+ dwc_modify_reg32 -+ (&dev_if-> -+ in_ep_regs[epnum]-> -+ diepctl, -+ depctl.d32, -+ depctl.d32); -+ } else { -+ start_next_request(ep); -+ } -+ } -+ } -+ } -+ /* NAK Interrutp */ -+ if (diepint.b.nak) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n", -+ epnum); -+ handle_in_ep_nak_intr(pcd, epnum); -+ -+ CLEAR_IN_EP_INTR(core_if, epnum, nak); -+ } -+ } -+ epnum++; -+ ep_intr >>= 1; -+ } -+ -+ return 1; -+#undef CLEAR_IN_EP_INTR -+} -+ -+/** -+ * This interrupt indicates that an OUT EP has a pending Interrupt. -+ * The sequence for handling the OUT EP interrupt is shown below: -+ * -# Read the Device All Endpoint Interrupt register -+ * -# Repeat the following for each OUT EP interrupt bit set (from -+ * LSB to MSB). -+ * -# Read the Device Endpoint Interrupt (DOEPINTn) register -+ * -# If "Transfer Complete" call the request complete function -+ * -# If "Endpoint Disabled" complete the EP disable procedure. -+ * -# If "AHB Error Interrupt" log error -+ * -# If "Setup Phase Done" process Setup Packet (See Standard USB -+ * Command Processing) -+ */ -+static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) -+{ -+#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \ -+do { \ -+ doepint_data_t doepint = {.d32=0}; \ -+ doepint.b.__intr = 1; \ -+ dwc_write_reg32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ -+ doepint.d32); \ -+} while (0) -+ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ uint32_t ep_intr; -+ doepint_data_t doepint = {.d32 = 0 }; -+ dctl_data_t dctl = {.d32 = 0 }; -+ depctl_data_t doepctl = {.d32 = 0 }; -+ uint32_t epnum = 0; -+ dwc_otg_pcd_ep_t *ep; -+ dwc_ep_t *dwc_ep; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); -+ -+ /* Read in the device interrupt bits */ -+ ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if); -+ -+ while (ep_intr) { -+ if (ep_intr & 0x1) { -+ /* Get EP pointer */ -+ ep = get_out_ep(pcd, epnum); -+ dwc_ep = &ep->dwc_ep; -+ -+#ifdef VERBOSE -+ DWC_DEBUGPL(DBG_PCDV, -+ "EP%d-%s: type=%d, mps=%d\n", -+ dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"), -+ dwc_ep->type, dwc_ep->maxpacket); -+#endif -+ doepint.d32 = -+ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep); -+ -+ /* Transfer complete */ -+ if (doepint.b.xfercompl) { -+ -+ if (epnum == 0) { -+ /* Clear the bit in DOEPINTn for this interrupt */ -+ CLEAR_OUT_EP_INTR(core_if, epnum, -+ xfercompl); -+ if (core_if->dma_desc_enable == 0 -+ || pcd->ep0state != EP0_IDLE) -+ handle_ep0(pcd); -+#ifdef DWC_EN_ISOC -+ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ if (doepint.b.pktdrpsts == 0) { -+ /* Clear the bit in DOEPINTn for this interrupt */ -+ CLEAR_OUT_EP_INTR(core_if, -+ epnum, -+ xfercompl); -+ complete_iso_ep(pcd, ep); -+ } else { -+ -+ doepint_data_t doepint = {.d32 = -+ 0 }; -+ doepint.b.xfercompl = 1; -+ doepint.b.pktdrpsts = 1; -+ dwc_write_reg32(&core_if-> -+ dev_if-> -+ out_ep_regs -+ [epnum]-> -+ doepint, -+ doepint.d32); -+ if (handle_iso_out_pkt_dropped -+ (core_if, dwc_ep)) { -+ complete_iso_ep(pcd, -+ ep); -+ } -+ } -+#endif /* DWC_EN_ISOC */ -+ } else { -+ /* Clear the bit in DOEPINTn for this interrupt */ -+ CLEAR_OUT_EP_INTR(core_if, epnum, -+ xfercompl); -+ complete_ep(ep); -+ } -+ -+ } -+ -+ /* Endpoint disable */ -+ if (doepint.b.epdisabled) { -+ -+ /* Clear the bit in DOEPINTn for this interrupt */ -+ CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled); -+ } -+ /* AHB Error */ -+ if (doepint.b.ahberr) { -+ DWC_DEBUGPL(DBG_PCD, "EP%d OUT AHB Error\n", -+ epnum); -+ DWC_DEBUGPL(DBG_PCD, "EP DMA REG %d \n", -+ core_if->dev_if-> -+ out_ep_regs[epnum]->doepdma); -+ CLEAR_OUT_EP_INTR(core_if, epnum, ahberr); -+ } -+ /* Setup Phase Done (contorl EPs) */ -+ if (doepint.b.setup) { -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", -+ epnum); -+#endif -+ CLEAR_OUT_EP_INTR(core_if, epnum, setup); -+ -+ handle_ep0(pcd); -+ } -+ -+ /** OUT EP BNA Intr */ -+ if (doepint.b.bna) { -+ CLEAR_OUT_EP_INTR(core_if, epnum, bna); -+ if (core_if->dma_desc_enable) { -+#ifdef DWC_EN_ISOC -+ if (dwc_ep->type == -+ DWC_OTG_EP_TYPE_ISOC) { -+ /* -+ * This checking is performed to prevent first "false" BNA -+ * handling occuring right after reconnect -+ */ -+ if (dwc_ep->next_frame != -+ 0xffffffff) -+ dwc_otg_pcd_handle_iso_bna -+ (ep); -+ } else -+#endif /* DWC_EN_ISOC */ -+ { -+ dctl.d32 = -+ dwc_read_reg32(&dev_if-> -+ dev_global_regs-> -+ dctl); -+ -+ /* If Global Continue on BNA is disabled - disable EP */ -+ if (!dctl.b.gcontbna) { -+ doepctl.d32 = 0; -+ doepctl.b.snak = 1; -+ doepctl.b.epdis = 1; -+ dwc_modify_reg32 -+ (&dev_if-> -+ out_ep_regs -+ [epnum]->doepctl, -+ doepctl.d32, -+ doepctl.d32); -+ } else { -+ start_next_request(ep); -+ } -+ } -+ } -+ } -+ if (doepint.b.stsphsercvd) { -+ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); -+ if (core_if->dma_desc_enable) { -+ do_setup_in_status_phase(pcd); -+ } -+ } -+ /* Babble Interrutp */ -+ if (doepint.b.babble) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n", -+ epnum); -+ handle_out_ep_babble_intr(pcd, epnum); -+ -+ CLEAR_OUT_EP_INTR(core_if, epnum, babble); -+ } -+ /* NAK Interrutp */ -+ if (doepint.b.nak) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum); -+ handle_out_ep_nak_intr(pcd, epnum); -+ -+ CLEAR_OUT_EP_INTR(core_if, epnum, nak); -+ } -+ /* NYET Interrutp */ -+ if (doepint.b.nyet) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum); -+ handle_out_ep_nyet_intr(pcd, epnum); -+ -+ CLEAR_OUT_EP_INTR(core_if, epnum, nyet); -+ } -+ } -+ -+ epnum++; -+ ep_intr >>= 1; -+ } -+ -+ return 1; -+ -+#undef CLEAR_OUT_EP_INTR -+} -+ -+/** -+ * Incomplete ISO IN Transfer Interrupt. -+ * This interrupt indicates one of the following conditions occurred -+ * while transmitting an ISOC transaction. -+ * - Corrupted IN Token for ISOC EP. -+ * - Packet not complete in FIFO. -+ * The follow actions will be taken: -+ * -# Determine the EP -+ * -# Set incomplete flag in dwc_ep structure -+ * -# Disable EP; when "Endpoint Disabled" interrupt is received -+ * Flush FIFO -+ */ -+int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) -+{ -+ gintsts_data_t gintsts; -+ -+#ifdef DWC_EN_ISOC -+ dwc_otg_dev_if_t *dev_if; -+ deptsiz_data_t deptsiz = {.d32 = 0 }; -+ depctl_data_t depctl = {.d32 = 0 }; -+ dsts_data_t dsts = {.d32 = 0 }; -+ dwc_ep_t *dwc_ep; -+ int i; -+ -+ dev_if = GET_CORE_IF(pcd)->dev_if; -+ -+ for (i = 1; i <= dev_if->num_in_eps; ++i) { -+ dwc_ep = &pcd->in_ep[i].dwc_ep; -+ if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ deptsiz.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[i]->dieptsiz); -+ depctl.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); -+ -+ if (depctl.b.epdis && deptsiz.d32) { -+ set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep); -+ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { -+ dwc_ep->cur_pkt = 0; -+ dwc_ep->proc_buf_num = -+ (dwc_ep->proc_buf_num ^ 1) & 0x1; -+ -+ if (dwc_ep->proc_buf_num) { -+ dwc_ep->cur_pkt_addr = -+ dwc_ep->xfer_buff1; -+ dwc_ep->cur_pkt_dma_addr = -+ dwc_ep->dma_addr1; -+ } else { -+ dwc_ep->cur_pkt_addr = -+ dwc_ep->xfer_buff0; -+ dwc_ep->cur_pkt_dma_addr = -+ dwc_ep->dma_addr0; -+ } -+ -+ } -+ -+ dsts.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ dev_global_regs->dsts); -+ dwc_ep->next_frame = dsts.b.soffn; -+ -+ dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF -+ (pcd), -+ dwc_ep); -+ } -+ } -+ } -+ -+#else -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "IN ISOC Incomplete"); -+ -+ intr_mask.b.incomplisoin = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+#endif //DWC_EN_ISOC -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.incomplisoin = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * Incomplete ISO OUT Transfer Interrupt. -+ * -+ * This interrupt indicates that the core has dropped an ISO OUT -+ * packet. The following conditions can be the cause: -+ * - FIFO Full, the entire packet would not fit in the FIFO. -+ * - CRC Error -+ * - Corrupted Token -+ * The follow actions will be taken: -+ * -# Determine the EP -+ * -# Set incomplete flag in dwc_ep structure -+ * -# Read any data from the FIFO -+ * -# Disable EP. when "Endpoint Disabled" interrupt is received -+ * re-enable EP. -+ */ -+int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) -+{ -+ -+ gintsts_data_t gintsts; -+ -+#ifdef DWC_EN_ISOC -+ dwc_otg_dev_if_t *dev_if; -+ deptsiz_data_t deptsiz = {.d32 = 0 }; -+ depctl_data_t depctl = {.d32 = 0 }; -+ dsts_data_t dsts = {.d32 = 0 }; -+ dwc_ep_t *dwc_ep; -+ int i; -+ -+ dev_if = GET_CORE_IF(pcd)->dev_if; -+ -+ for (i = 1; i <= dev_if->num_out_eps; ++i) { -+ dwc_ep = &pcd->in_ep[i].dwc_ep; -+ if (pcd->out_ep[i].dwc_ep.active && -+ pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { -+ deptsiz.d32 = -+ dwc_read_reg32(&dev_if->out_ep_regs[i]->doeptsiz); -+ depctl.d32 = -+ dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); -+ -+ if (depctl.b.epdis && deptsiz.d32) { -+ set_current_pkt_info(GET_CORE_IF(pcd), -+ &pcd->out_ep[i].dwc_ep); -+ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { -+ dwc_ep->cur_pkt = 0; -+ dwc_ep->proc_buf_num = -+ (dwc_ep->proc_buf_num ^ 1) & 0x1; -+ -+ if (dwc_ep->proc_buf_num) { -+ dwc_ep->cur_pkt_addr = -+ dwc_ep->xfer_buff1; -+ dwc_ep->cur_pkt_dma_addr = -+ dwc_ep->dma_addr1; -+ } else { -+ dwc_ep->cur_pkt_addr = -+ dwc_ep->xfer_buff0; -+ dwc_ep->cur_pkt_dma_addr = -+ dwc_ep->dma_addr0; -+ } -+ -+ } -+ -+ dsts.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ dev_global_regs->dsts); -+ dwc_ep->next_frame = dsts.b.soffn; -+ -+ dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF -+ (pcd), -+ dwc_ep); -+ } -+ } -+ } -+#else -+ /** @todo implement ISR */ -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "OUT ISOC Incomplete"); -+ -+ intr_mask.b.incomplisoout = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+#endif /* DWC_EN_ISOC */ -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.incomplisoout = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This function handles the Global IN NAK Effective interrupt. -+ * -+ */ -+int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; -+ depctl_data_t diepctl = {.d32 = 0 }; -+ depctl_data_t diepctl_rd = {.d32 = 0 }; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ gintsts_data_t gintsts; -+ int i; -+ -+ DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n"); -+ -+ /* Disable all active IN EPs */ -+ diepctl.b.epdis = 1; -+ diepctl.b.snak = 1; -+ -+ for (i = 0; i <= dev_if->num_in_eps; i++) { -+ diepctl_rd.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); -+ if (diepctl_rd.b.epena) { -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, -+ diepctl.d32); -+ } -+ } -+ /* Disable the Global IN NAK Effective Interrupt */ -+ intr_mask.b.ginnakeff = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.ginnakeff = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * OUT NAK Effective. -+ * -+ */ -+int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) -+{ -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ gintsts_data_t gintsts; -+ -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "Global IN NAK Effective\n"); -+ /* Disable the Global IN NAK Effective Interrupt */ -+ intr_mask.b.goutnakeff = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.goutnakeff = 1; -+ dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * PCD interrupt handler. -+ * -+ * The PCD handles the device interrupts. Many conditions can cause a -+ * device interrupt. When an interrupt occurs, the device interrupt -+ * service routine determines the cause of the interrupt and -+ * dispatches handling to the appropriate function. These interrupt -+ * handling functions are described below. -+ * -+ * All interrupt registers are processed from LSB to MSB. -+ * -+ */ -+int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+#ifdef VERBOSE -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+#endif -+ gintsts_data_t gintr_status; -+ int32_t retval = 0; -+ -+#ifdef VERBOSE -+ DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n", -+ __func__, -+ dwc_read_reg32(&global_regs->gintsts), -+ dwc_read_reg32(&global_regs->gintmsk)); -+#endif -+ -+ if (dwc_otg_is_device_mode(core_if)) { -+ DWC_SPINLOCK(pcd->lock); -+#ifdef VERBOSE -+ DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n", -+ __func__, -+ dwc_read_reg32(&global_regs->gintsts), -+ dwc_read_reg32(&global_regs->gintmsk)); -+#endif -+ -+ gintr_status.d32 = dwc_otg_read_core_intr(core_if); -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n", -+ __func__, gintr_status.d32); -+ -+ if (gintr_status.b.sofintr) { -+ retval |= dwc_otg_pcd_handle_sof_intr(pcd); -+ } -+ if (gintr_status.b.rxstsqlvl) { -+ retval |= -+ dwc_otg_pcd_handle_rx_status_q_level_intr(pcd); -+ } -+ if (gintr_status.b.nptxfempty) { -+ retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd); -+ } -+ if (gintr_status.b.ginnakeff) { -+ retval |= dwc_otg_pcd_handle_in_nak_effective(pcd); -+ } -+ if (gintr_status.b.goutnakeff) { -+ retval |= dwc_otg_pcd_handle_out_nak_effective(pcd); -+ } -+ if (gintr_status.b.i2cintr) { -+ retval |= dwc_otg_pcd_handle_i2c_intr(pcd); -+ } -+ if (gintr_status.b.erlysuspend) { -+ retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd); -+ } -+ if (gintr_status.b.usbreset) { -+ retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd); -+ } -+ if (gintr_status.b.enumdone) { -+ retval |= dwc_otg_pcd_handle_enum_done_intr(pcd); -+ } -+ if (gintr_status.b.isooutdrop) { -+ retval |= -+ dwc_otg_pcd_handle_isoc_out_packet_dropped_intr -+ (pcd); -+ } -+ if (gintr_status.b.eopframe) { -+ retval |= -+ dwc_otg_pcd_handle_end_periodic_frame_intr(pcd); -+ } -+ if (gintr_status.b.epmismatch) { -+ retval |= dwc_otg_pcd_handle_ep_mismatch_intr(core_if); -+ } -+ if (gintr_status.b.inepint) { -+ if (!core_if->multiproc_int_enable) { -+ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); -+ } -+ } -+ if (gintr_status.b.outepintr) { -+ if (!core_if->multiproc_int_enable) { -+ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); -+ } -+ } -+ if (gintr_status.b.incomplisoin) { -+ retval |= -+ dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd); -+ } -+ if (gintr_status.b.incomplisoout) { -+ retval |= -+ dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd); -+ } -+ -+ /* In MPI mode De vice Endpoints intterrupts are asserted -+ * without setting outepintr and inepint bits set, so these -+ * Interrupt handlers are called without checking these bit-fields -+ */ -+ if (core_if->multiproc_int_enable) { -+ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); -+ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); -+ } -+#ifdef VERBOSE -+ DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__, -+ dwc_read_reg32(&global_regs->gintsts)); -+#endif -+ DWC_SPINUNLOCK(pcd->lock); -+ } -+ return retval; -+} -+ -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -new file mode 100644 -index 0000000..6ce0d97 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -0,0 +1,1288 @@ -+ /* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ -+ * $Revision: #7 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225160 $ -+ * -+ * 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_HOST_ONLY -+ -+/** @file -+ * This file implements the Peripheral Controller Driver. -+ * -+ * The Peripheral Controller Driver (PCD) is responsible for -+ * translating requests from the Function Driver into the appropriate -+ * actions on the DWC_otg controller. It isolates the Function Driver -+ * from the specifics of the controller by providing an API to the -+ * Function Driver. -+ * -+ * The Peripheral Controller Driver for Linux will implement the -+ * Gadget API, so that the existing Gadget drivers can be used. -+ * (Gadget Driver is the Linux terminology for a Function Driver.) -+ * -+ * The Linux Gadget API is defined in the header file -+ * . The USB EP operations API is -+ * defined in the structure usb_ep_ops and the USB -+ * Controller API is defined in the structure -+ * usb_gadget_ops. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#if defined(LM_INTERFACE) -+//# include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#else -+/* by 2.6.31, at least, the location of some headers has changed -+*/ -+#include -+#endif -+ -+#elif defined(PLATFORM_INTERFACE) -+#include -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#include -+#include -+#else -+/* by 2.6.31, at least, the location of some headers has changed -+*/ -+#include -+#include -+#include -+#endif -+ -+#include -+ -+#include "dwc_otg_pcd_if.h" -+#include "dwc_otg_driver.h" -+#include "dwc_otg_dbg.h" -+ -+static struct gadget_wrapper { -+ dwc_otg_pcd_t *pcd; -+ -+ struct usb_gadget gadget; -+ struct usb_gadget_driver *driver; -+ -+ struct usb_ep ep0; -+ struct usb_ep in_ep[16]; -+ struct usb_ep out_ep[16]; -+ -+} *gadget_wrapper; -+ -+/* Display the contents of the buffer */ -+extern void dump_msg(const u8 * buf, unsigned int length); -+ -+/* USB Endpoint Operations */ -+/* -+ * The following sections briefly describe the behavior of the Gadget -+ * API endpoint operations implemented in the DWC_otg driver -+ * software. Detailed descriptions of the generic behavior of each of -+ * these functions can be found in the Linux header file -+ * include/linux/usb_gadget.h. -+ * -+ * The Gadget API provides wrapper functions for each of the function -+ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper -+ * function, which then calls the underlying PCD function. The -+ * following sections are named according to the wrapper -+ * functions. Within each section, the corresponding DWC_otg PCD -+ * function name is specified. -+ * -+ */ -+ -+/** -+ * This function is called by the Gadget Driver for each EP to be -+ * configured for the current configuration (SET_CONFIGURATION). -+ * -+ * This function initializes the dwc_otg_ep_t data structure, and then -+ * calls dwc_otg_ep_activate. -+ */ -+static int ep_enable(struct usb_ep *usb_ep, -+ const struct usb_endpoint_descriptor *ep_desc) -+{ -+ int retval; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc); -+ -+ if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) { -+ DWC_WARN("%s, bad ep or descriptor\n", __func__); -+ return -EINVAL; -+ } -+ if (usb_ep == &gadget_wrapper->ep0) { -+ DWC_WARN("%s, bad ep(0)\n", __func__); -+ return -EINVAL; -+ } -+ -+ /* Check FIFO size? */ -+ if (!ep_desc->wMaxPacketSize) { -+ DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name); -+ return -ERANGE; -+ } -+ -+ if (!gadget_wrapper->driver || -+ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { -+ DWC_WARN("%s, bogus device state\n", __func__); -+ return -ESHUTDOWN; -+ } -+ -+ retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd, -+ (const uint8_t *)ep_desc, -+ (void *)usb_ep); -+ if (retval) { -+ DWC_WARN("dwc_otg_pcd_ep_enable failed\n"); -+ return -EINVAL; -+ } -+ -+ usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize); -+ -+ return 0; -+} -+ -+/** -+ * This function is called when an EP is disabled due to disconnect or -+ * change in configuration. Any pending requests will terminate with a -+ * status of -ESHUTDOWN. -+ * -+ * This function modifies the dwc_otg_ep_t data structure for this EP, -+ * and then calls dwc_otg_ep_deactivate. -+ */ -+static int ep_disable(struct usb_ep *usb_ep) -+{ -+ int retval; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep); -+ if (!usb_ep) { -+ DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__, -+ usb_ep ? usb_ep->name : NULL); -+ return -EINVAL; -+ } -+ -+ retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep); -+ if (retval) { -+ retval = -EINVAL; -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function allocates a request object to use with the specified -+ * endpoint. -+ * -+ * @param ep The endpoint to be used with with the request -+ * @param gfp_flags the GFP_* flags to use. -+ */ -+static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep, -+ gfp_t gfp_flags) -+{ -+ struct usb_request *usb_req; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags); -+ if (0 == ep) { -+ DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n"); -+ return 0; -+ } -+ usb_req = kmalloc(sizeof(*usb_req), gfp_flags); -+ if (0 == usb_req) { -+ DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n"); -+ return 0; -+ } -+ memset(usb_req, 0, sizeof(*usb_req)); -+ usb_req->dma = DWC_INVALID_DMA_ADDR; -+ -+ return usb_req; -+} -+ -+/** -+ * This function frees a request object. -+ * -+ * @param ep The endpoint associated with the request -+ * @param req The request being freed -+ */ -+static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req) -+{ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req); -+ -+ if (0 == ep || 0 == req) { -+ DWC_WARN("%s() %s\n", __func__, -+ "Invalid ep or req argument!\n"); -+ return; -+ } -+ -+ kfree(req); -+} -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+/** -+ * This function allocates an I/O buffer to be used for a transfer -+ * to/from the specified endpoint. -+ * -+ * @param usb_ep The endpoint to be used with with the request -+ * @param bytes The desired number of bytes for the buffer -+ * @param dma Pointer to the buffer's DMA address; must be valid -+ * @param gfp_flags the GFP_* flags to use. -+ * @return address of a new buffer or null is buffer could not be allocated. -+ */ -+static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, -+ dma_addr_t * dma, gfp_t gfp_flags) -+{ -+ void *buf; -+ dwc_otg_pcd_t *pcd = 0; -+ -+ pcd = gadget_wrapper->pcd; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes, -+ dma, gfp_flags); -+ -+ /* Check dword alignment */ -+ if ((bytes & 0x3UL) != 0) { -+ DWC_WARN("%s() Buffer size is not a multiple of" -+ "DWORD size (%d)", __func__, bytes); -+ } -+ -+ buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); -+ -+ /* Check dword alignment */ -+ if (((int)buf & 0x3UL) != 0) { -+ DWC_WARN("%s() Buffer is not DWORD aligned (%p)", -+ __func__, buf); -+ } -+ -+ return buf; -+} -+ -+/** -+ * This function frees an I/O buffer that was allocated by alloc_buffer. -+ * -+ * @param usb_ep the endpoint associated with the buffer -+ * @param buf address of the buffer -+ * @param dma The buffer's DMA address -+ * @param bytes The number of bytes of the buffer -+ */ -+static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf, -+ dma_addr_t dma, unsigned bytes) -+{ -+ dwc_otg_pcd_t *pcd = 0; -+ -+ pcd = gadget_wrapper->pcd; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes); -+ -+ dma_free_coherent(NULL, bytes, buf, dma); -+} -+#endif -+ -+/** -+ * This function is used to submit an I/O Request to an EP. -+ * -+ * - When the request completes the request's completion callback -+ * is called to return the request to the driver. -+ * - An EP, except control EPs, may have multiple requests -+ * pending. -+ * - Once submitted the request cannot be examined or modified. -+ * - Each request is turned into one or more packets. -+ * - A BULK EP can queue any amount of data; the transfer is -+ * packetized. -+ * - Zero length Packets are specified with the request 'zero' -+ * flag. -+ */ -+static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, -+ gfp_t gfp_flags) -+{ -+ dwc_otg_pcd_t *pcd; -+ int retval; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n", -+ __func__, usb_ep, usb_req, gfp_flags); -+ -+ if (!usb_req || !usb_req->complete || !usb_req->buf) { -+ DWC_WARN("bad params\n"); -+ return -EINVAL; -+ } -+ -+ if (!usb_ep) { -+ DWC_WARN("bad ep\n"); -+ return -EINVAL; -+ } -+ -+ pcd = gadget_wrapper->pcd; -+ if (!gadget_wrapper->driver || -+ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { -+ DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", -+ gadget_wrapper->gadget.speed); -+ DWC_WARN("bogus device state\n"); -+ return -ESHUTDOWN; -+ } -+ -+ DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n", -+ usb_ep->name, usb_req, usb_req->length, usb_req->buf); -+ -+ usb_req->status = -EINPROGRESS; -+ usb_req->actual = 0; -+ -+ retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, usb_req->dma, -+ usb_req->length, usb_req->zero, usb_req, -+ gfp_flags == GFP_ATOMIC ? 1 : 0); -+ if (retval) { -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * This function cancels an I/O request from an EP. -+ */ -+static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) -+{ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req); -+ -+ if (!usb_ep || !usb_req) { -+ DWC_WARN("bad argument\n"); -+ return -EINVAL; -+ } -+ if (!gadget_wrapper->driver || -+ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { -+ DWC_WARN("bogus device state\n"); -+ return -ESHUTDOWN; -+ } -+ if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) { -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * usb_ep_set_halt stalls an endpoint. -+ * -+ * usb_ep_clear_halt clears an endpoint halt and resets its data -+ * toggle. -+ * -+ * Both of these functions are implemented with the same underlying -+ * function. The behavior depends on the value argument. -+ * -+ * @param[in] usb_ep the Endpoint to halt or clear halt. -+ * @param[in] value -+ * - 0 means clear_halt. -+ * - 1 means set_halt, -+ * - 2 means clear stall lock flag. -+ * - 3 means set stall lock flag. -+ */ -+static int ep_halt(struct usb_ep *usb_ep, int value) -+{ -+ int retval = 0; -+ -+ DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value); -+ -+ if (!usb_ep) { -+ DWC_WARN("bad ep\n"); -+ return -EINVAL; -+ } -+ -+ retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value); -+ if (retval == -DWC_E_AGAIN) { -+ return -EAGAIN; -+ } else if (retval) { -+ retval = -EINVAL; -+ } -+ -+ return retval; -+} -+ -+//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) -+#if 0 -+/** -+ * ep_wedge: sets the halt feature and ignores clear requests -+ * -+ * @usb_ep: the endpoint being wedged -+ * -+ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT) -+ * requests. If the gadget driver clears the halt status, it will -+ * automatically unwedge the endpoint. -+ * -+ * Returns zero on success, else negative errno. * -+ * Check usb_ep_set_wedge() at "usb_gadget.h" for details -+ */ -+static int ep_wedge(struct usb_ep *usb_ep) -+{ -+ int retval = 0; -+ -+ DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name); -+ -+ if (!usb_ep) { -+ DWC_WARN("bad ep\n"); -+ return -EINVAL; -+ } -+ -+ retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep); -+ if (retval == -DWC_E_AGAIN) { -+ retval = -EAGAIN; -+ } else if (retval) { -+ retval = -EINVAL; -+ } -+ -+ return retval; -+} -+#endif -+ -+#ifdef DWC_EN_ISOC -+/** -+ * This function is used to submit an ISOC Transfer Request to an EP. -+ * -+ * - Every time a sync period completes the request's completion callback -+ * is called to provide data to the gadget driver. -+ * - Once submitted the request cannot be modified. -+ * - Each request is turned into periodic data packets untill ISO -+ * Transfer is stopped.. -+ */ -+static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req, -+ gfp_t gfp_flags) -+{ -+ int retval = 0; -+ -+ if (!req || !req->process_buffer || !req->buf0 || !req->buf1) { -+ DWC_WARN("bad params\n"); -+ return -EINVAL; -+ } -+ -+ if (!usb_ep) { -+ DWC_PRINTF("bad params\n"); -+ return -EINVAL; -+ } -+ -+ req->status = -EINPROGRESS; -+ -+ retval = -+ dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0, -+ req->buf1, req->dma0, req->dma1, -+ req->sync_frame, req->data_pattern_frame, -+ req->data_per_frame, -+ req->flags & USB_REQ_ISO_ASAP ? -1 : req-> -+ start_frame, req->buf_proc_intrvl, req, -+ gfp_flags == GFP_ATOMIC ? 1 : 0); -+ -+ if (retval) { -+ return -EINVAL; -+ } -+ -+ return retval; -+} -+ -+/** -+ * This function stops ISO EP Periodic Data Transfer. -+ */ -+static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req) -+{ -+ int retval = 0; -+ if (!usb_ep) { -+ DWC_WARN("bad ep\n"); -+ } -+ -+ if (!gadget_wrapper->driver || -+ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { -+ DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", -+ gadget_wrapper->gadget.speed); -+ DWC_WARN("bogus device state\n"); -+ } -+ -+ dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req); -+ if (retval) { -+ retval = -EINVAL; -+ } -+ -+ return retval; -+} -+ -+static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep, -+ int packets, gfp_t gfp_flags) -+{ -+ struct usb_iso_request *pReq = NULL; -+ uint32_t req_size; -+ -+ req_size = sizeof(struct usb_iso_request); -+ req_size += -+ (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor))); -+ -+ pReq = kmalloc(req_size, gfp_flags); -+ if (!pReq) { -+ DWC_WARN("Can't allocate Iso Request\n"); -+ return 0; -+ } -+ pReq->iso_packet_desc0 = (void *)(pReq + 1); -+ -+ pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets; -+ -+ return pReq; -+} -+ -+static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) -+{ -+ kfree(req); -+} -+ -+static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = { -+ .ep_ops = { -+ .enable = ep_enable, -+ .disable = ep_disable, -+ -+ .alloc_request = dwc_otg_pcd_alloc_request, -+ .free_request = dwc_otg_pcd_free_request, -+ -+ .alloc_buffer = dwc_otg_pcd_alloc_buffer, -+ .free_buffer = dwc_otg_pcd_free_buffer, -+ -+ .queue = ep_queue, -+ .dequeue = ep_dequeue, -+ -+ .set_halt = ep_halt, -+ .fifo_status = 0, -+ .fifo_flush = 0, -+ }, -+ .iso_ep_start = iso_ep_start, -+ .iso_ep_stop = iso_ep_stop, -+ .alloc_iso_request = alloc_iso_request, -+ .free_iso_request = free_iso_request, -+}; -+ -+#else -+ -+ int (*enable) (struct usb_ep *ep, -+ const struct usb_endpoint_descriptor *desc); -+ int (*disable) (struct usb_ep *ep); -+ -+ struct usb_request *(*alloc_request) (struct usb_ep *ep, -+ gfp_t gfp_flags); -+ void (*free_request) (struct usb_ep *ep, struct usb_request *req); -+ -+ int (*queue) (struct usb_ep *ep, struct usb_request *req, -+ gfp_t gfp_flags); -+ int (*dequeue) (struct usb_ep *ep, struct usb_request *req); -+ -+ int (*set_halt) (struct usb_ep *ep, int value); -+ int (*set_wedge) (struct usb_ep *ep); -+ -+ int (*fifo_status) (struct usb_ep *ep); -+ void (*fifo_flush) (struct usb_ep *ep); -+static struct usb_ep_ops dwc_otg_pcd_ep_ops = { -+ .enable = ep_enable, -+ .disable = ep_disable, -+ -+ .alloc_request = dwc_otg_pcd_alloc_request, -+ .free_request = dwc_otg_pcd_free_request, -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ .alloc_buffer = dwc_otg_pcd_alloc_buffer, -+ .free_buffer = dwc_otg_pcd_free_buffer, -+#else -+ /* .set_wedge = ep_wedge, */ -+ .set_wedge = NULL, /* uses set_halt instead */ -+#endif -+ -+ .queue = ep_queue, -+ .dequeue = ep_dequeue, -+ -+ .set_halt = ep_halt, -+ .fifo_status = 0, -+ .fifo_flush = 0, -+ -+}; -+ -+#endif /* _EN_ISOC_ */ -+/* Gadget Operations */ -+/** -+ * The following gadget operations will be implemented in the DWC_otg -+ * PCD. Functions in the API that are not described below are not -+ * implemented. -+ * -+ * The Gadget API provides wrapper functions for each of the function -+ * pointers defined in usb_gadget_ops. The Gadget Driver calls the -+ * wrapper function, which then calls the underlying PCD function. The -+ * following sections are named according to the wrapper functions -+ * (except for ioctl, which doesn't have a wrapper function). Within -+ * each section, the corresponding DWC_otg PCD function name is -+ * specified. -+ * -+ */ -+ -+/** -+ *Gets the USB Frame number of the last SOF. -+ */ -+static int get_frame_number(struct usb_gadget *gadget) -+{ -+ struct gadget_wrapper *d; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); -+ -+ if (gadget == 0) { -+ return -ENODEV; -+ } -+ -+ d = container_of(gadget, struct gadget_wrapper, gadget); -+ return dwc_otg_pcd_get_frame_number(d->pcd); -+} -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+static int test_lpm_enabled(struct usb_gadget *gadget) -+{ -+ struct gadget_wrapper *d; -+ -+ d = container_of(gadget, struct gadget_wrapper, gadget); -+ -+ return dwc_otg_pcd_is_lpm_enabled(d->pcd); -+} -+#endif -+ -+/** -+ * Initiates Session Request Protocol (SRP) to wakeup the host if no -+ * session is in progress. If a session is already in progress, but -+ * the device is suspended, remote wakeup signaling is started. -+ * -+ */ -+static int wakeup(struct usb_gadget *gadget) -+{ -+ struct gadget_wrapper *d; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); -+ -+ if (gadget == 0) { -+ return -ENODEV; -+ } else { -+ d = container_of(gadget, struct gadget_wrapper, gadget); -+ } -+ dwc_otg_pcd_wakeup(d->pcd); -+ return 0; -+} -+ -+static const struct usb_gadget_ops dwc_otg_pcd_ops = { -+ .get_frame = get_frame_number, -+ .wakeup = wakeup, -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ .lpm_support = test_lpm_enabled, -+#endif -+ // current versions must always be self-powered -+}; -+ -+static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes) -+{ -+ int retval = -DWC_E_NOT_SUPPORTED; -+ if (gadget_wrapper->driver && gadget_wrapper->driver->setup) { -+ retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget, -+ (struct usb_ctrlrequest -+ *)bytes); -+ } -+ -+ if (retval == -ENOTSUPP) { -+ retval = -DWC_E_NOT_SUPPORTED; -+ } else if (retval < 0) { -+ retval = -DWC_E_INVALID; -+ } -+ -+ return retval; -+} -+ -+#ifdef DWC_EN_ISOC -+static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle, int proc_buf_num) -+{ -+ int i, packet_count; -+ struct usb_gadget_iso_packet_descriptor *iso_packet = 0; -+ struct usb_iso_request *iso_req = req_handle; -+ -+ if (proc_buf_num) { -+ iso_packet = iso_req->iso_packet_desc1; -+ } else { -+ iso_packet = iso_req->iso_packet_desc0; -+ } -+ packet_count = -+ dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle); -+ for (i = 0; i < packet_count; ++i) { -+ int status; -+ int actual; -+ int offset; -+ dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle, -+ i, &status, &actual, &offset); -+ switch (status) { -+ case -DWC_E_NO_DATA: -+ status = -ENODATA; -+ break; -+ default: -+ if (status) { -+ DWC_PRINTF("unknown status in isoc packet\n"); -+ } -+ -+ } -+ iso_packet[i].status = status; -+ iso_packet[i].offset = offset; -+ iso_packet[i].actual_length = actual; -+ } -+ -+ iso_req->status = 0; -+ iso_req->process_buffer(ep_handle, iso_req); -+ -+ return 0; -+} -+#endif /* DWC_EN_ISOC */ -+ -+static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle, int32_t status, uint32_t actual) -+{ -+ struct usb_request *req = (struct usb_request *)req_handle; -+ -+ if (req && req->complete) { -+ switch (status) { -+ case -DWC_E_SHUTDOWN: -+ req->status = -ESHUTDOWN; -+ break; -+ case -DWC_E_RESTART: -+ req->status = -ECONNRESET; -+ break; -+ case -DWC_E_INVALID: -+ req->status = -EINVAL; -+ break; -+ case -DWC_E_TIMEOUT: -+ req->status = -ETIMEDOUT; -+ break; -+ default: -+ req->status = status; -+ -+ } -+ req->actual = actual; -+ req->complete(ep_handle, req); -+ } -+ -+ return 0; -+} -+ -+static int _connect(dwc_otg_pcd_t * pcd, int speed) -+{ -+ gadget_wrapper->gadget.speed = speed; -+ return 0; -+} -+ -+static int _disconnect(dwc_otg_pcd_t * pcd) -+{ -+ if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) { -+ gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget); -+ } -+ return 0; -+} -+ -+static int _resume(dwc_otg_pcd_t * pcd) -+{ -+ if (gadget_wrapper->driver && gadget_wrapper->driver->resume) { -+ gadget_wrapper->driver->resume(&gadget_wrapper->gadget); -+ } -+ -+ return 0; -+} -+ -+static int _suspend(dwc_otg_pcd_t * pcd) -+{ -+ if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) { -+ gadget_wrapper->driver->suspend(&gadget_wrapper->gadget); -+ } -+ return 0; -+} -+ -+/** -+ * This function updates the otg values in the gadget structure. -+ */ -+static int _hnp_changed(dwc_otg_pcd_t * pcd) -+{ -+ -+ if (!gadget_wrapper->gadget.is_otg) -+ return 0; -+ -+ gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd); -+ gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd); -+ gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd); -+ return 0; -+} -+ -+static int _reset(dwc_otg_pcd_t * pcd) -+{ -+ return 0; -+} -+ -+#ifdef DWC_UTE_CFI -+static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req) -+{ -+ int retval = -DWC_E_INVALID; -+ if (gadget_wrapper->driver->cfi_feature_setup) { -+ retval = -+ gadget_wrapper->driver->cfi_feature_setup(&gadget_wrapper-> -+ gadget, -+ (struct -+ cfi_usb_ctrlrequest -+ *)cfi_req); -+ } -+ -+ return retval; -+} -+#endif -+ -+static const struct dwc_otg_pcd_function_ops fops = { -+ .complete = _complete, -+#ifdef DWC_EN_ISOC -+ .isoc_complete = _isoc_complete, -+#endif -+ .setup = _setup, -+ .disconnect = _disconnect, -+ .connect = _connect, -+ .resume = _resume, -+ .suspend = _suspend, -+ .hnp_changed = _hnp_changed, -+ .reset = _reset, -+#ifdef DWC_UTE_CFI -+ .cfi_setup = _cfi_setup, -+#endif -+}; -+ -+/** -+ * This function is the top level PCD interrupt handler. -+ */ -+static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev) -+{ -+ dwc_otg_pcd_t *pcd = dev; -+ int32_t retval = IRQ_NONE; -+ -+ retval = dwc_otg_pcd_handle_intr(pcd); -+ if (retval != 0) { -+ S3C2410X_CLEAR_EINTPEND(); -+ } -+ return IRQ_RETVAL(retval); -+} -+ -+/** -+ * This function initialized the usb_ep structures to there default -+ * state. -+ * -+ * @param d Pointer on gadget_wrapper. -+ */ -+void gadget_add_eps(struct gadget_wrapper *d) -+{ -+ static const char *names[] = { -+ -+ "ep0", -+ "ep1in", -+ "ep2in", -+ "ep3in", -+ "ep4in", -+ "ep5in", -+ "ep6in", -+ "ep7in", -+ "ep8in", -+ "ep9in", -+ "ep10in", -+ "ep11in", -+ "ep12in", -+ "ep13in", -+ "ep14in", -+ "ep15in", -+ "ep1out", -+ "ep2out", -+ "ep3out", -+ "ep4out", -+ "ep5out", -+ "ep6out", -+ "ep7out", -+ "ep8out", -+ "ep9out", -+ "ep10out", -+ "ep11out", -+ "ep12out", -+ "ep13out", -+ "ep14out", -+ "ep15out" -+ }; -+ -+ int i; -+ struct usb_ep *ep; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__); -+ -+ INIT_LIST_HEAD(&d->gadget.ep_list); -+ d->gadget.ep0 = &d->ep0; -+ d->gadget.speed = USB_SPEED_UNKNOWN; -+ -+ INIT_LIST_HEAD(&d->gadget.ep0->ep_list); -+ -+ /** -+ * Initialize the EP0 structure. -+ */ -+ ep = &d->ep0; -+ -+ /* Init the usb_ep structure. */ -+ ep->name = names[0]; -+ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; -+ -+ /** -+ * @todo NGS: What should the max packet size be set to -+ * here? Before EP type is set? -+ */ -+ ep->maxpacket = MAX_PACKET_SIZE; -+ dwc_otg_pcd_ep_enable(d->pcd, NULL, ep); -+ -+ list_add_tail(&ep->ep_list, &d->gadget.ep_list); -+ -+ /** -+ * Initialize the EP structures. -+ */ -+ -+ for (i = 0; i < 15; i++) { -+ ep = &d->in_ep[i]; -+ -+ /* Init the usb_ep structure. */ -+ ep->name = names[i + 1]; -+ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; -+ -+ /** -+ * @todo NGS: What should the max packet size be set to -+ * here? Before EP type is set? -+ */ -+ ep->maxpacket = MAX_PACKET_SIZE; -+ list_add_tail(&ep->ep_list, &d->gadget.ep_list); -+ } -+ -+ for (i = 0; i < 15; i++) { -+ ep = &d->out_ep[i]; -+ -+ /* Init the usb_ep structure. */ -+ ep->name = names[15 + i + 1]; -+ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; -+ -+ /** -+ * @todo NGS: What should the max packet size be set to -+ * here? Before EP type is set? -+ */ -+ ep->maxpacket = MAX_PACKET_SIZE; -+ -+ list_add_tail(&ep->ep_list, &d->gadget.ep_list); -+ } -+ -+ /* remove ep0 from the list. There is a ep0 pointer. */ -+ list_del_init(&d->ep0.ep_list); -+ -+ d->ep0.maxpacket = MAX_EP0_SIZE; -+} -+ -+/** -+ * This function releases the Gadget device. -+ * required by device_unregister(). -+ * -+ * @todo Should this do something? Should it free the PCD? -+ */ -+static void dwc_otg_pcd_gadget_release(struct device *dev) -+{ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev); -+} -+ -+static struct gadget_wrapper *alloc_wrapper( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) -+{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ static char pcd_name[] = "dwc_otg_pcd"; -+ -+ struct gadget_wrapper *d; -+ int retval; -+ -+ d = dwc_alloc(sizeof(*d)); -+ if (d == NULL) { -+ return NULL; -+ } -+ -+ memset(d, 0, sizeof(*d)); -+ -+ d->gadget.name = pcd_name; -+ d->pcd = otg_dev->pcd; -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ strcpy(d->gadget.dev.bus_id, "gadget"); -+#else -+ /*d->gadget.dev.bus = NULL;*/ -+ d->gadget.dev.init_name = "gadget"; -+#endif -+ d->gadget.dev.parent = &_dev->dev; -+ d->gadget.dev.release = dwc_otg_pcd_gadget_release; -+ d->gadget.ops = &dwc_otg_pcd_ops; -+ d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL; -+ d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd); -+ -+ d->driver = 0; -+ /* Register the gadget device */ -+ retval = device_register(&d->gadget.dev); -+ if (retval != 0) { -+ DWC_ERROR("device_register failed\n"); -+ dwc_free(d); -+ return NULL; -+ } -+ -+ return d; -+} -+ -+static void free_wrapper(struct gadget_wrapper *d) -+{ -+ if (d->driver) { -+ /* should have been done already by driver model core */ -+ DWC_WARN("driver '%s' is still registered\n", -+ d->driver->driver.name); -+ usb_gadget_unregister_driver(d->driver); -+ } -+ -+ device_unregister(&d->gadget.dev); -+ dwc_free(d); -+} -+ -+/** -+ * This function initialized the PCD portion of the driver. -+ * -+ */ -+int pcd_init( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) -+ -+{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ int devirq; -+ -+ int retval = 0; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev); -+ -+ otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if); -+ -+ if (!otg_dev->pcd) { -+ DWC_ERROR("dwc_otg_pcd_init failed\n"); -+ return -ENOMEM; -+ } -+ -+ gadget_wrapper = alloc_wrapper(_dev); -+ -+ /* -+ * Initialize EP structures -+ */ -+ gadget_add_eps(gadget_wrapper); -+ -+ /* -+ * Setup interupt handler -+ */ -+#ifdef PLATFORM_INTERFACE -+ devirq = platform_get_irq(_dev, 0); -+#else -+ devirq = _dev->irq; -+#endif -+ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", devirq); -+ retval = request_irq(devirq, dwc_otg_pcd_irq, -+ IRQF_SHARED, gadget_wrapper->gadget.name, -+ otg_dev->pcd); -+ if (retval != 0) { -+ DWC_ERROR("request of irq%d failed\n", devirq); -+ free_wrapper(gadget_wrapper); -+ return -EBUSY; -+ } -+ -+ dwc_otg_pcd_start(gadget_wrapper->pcd, &fops); -+ -+ return retval; -+} -+ -+/** -+ * Cleanup the PCD. -+ */ -+void pcd_remove( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) -+{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ dwc_otg_pcd_t *pcd = otg_dev->pcd; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev); -+ -+ /* -+ * Free the IRQ -+ */ -+#ifdef PLATFORM_INTERFACE -+ free_irq(platform_get_irq(_dev, 0), pcd); -+#else -+ free_irq(_dev->irq, pcd); -+#endif -+ dwc_otg_pcd_remove(otg_dev->pcd); -+ free_wrapper(gadget_wrapper); -+ otg_dev->pcd = 0; -+} -+ -+/** -+ * This function registers a gadget driver with the PCD. -+ * -+ * When a driver is successfully registered, it will receive control -+ * requests including set_configuration(), which enables non-control -+ * requests. then usb traffic follows until a disconnect is reported. -+ * then a host may connect again, or the driver might get unbound. -+ * -+ * @param driver The driver being registered -+ */ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -+int usb_gadget_register_driver(struct usb_gadget_driver *driver) -+#else -+int usb_gadget_probe_driver(struct usb_gadget_driver *driver, -+ int (*bind)(struct usb_gadget *)) -+#endif -+{ -+ int retval; -+ -+ DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", -+ driver->driver.name); -+ -+ if (!driver || driver->max_speed == USB_SPEED_UNKNOWN || -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -+ !driver->bind || -+#else -+ !bind || -+#endif -+ !driver->unbind || !driver->disconnect || !driver->setup) { -+ DWC_DEBUGPL(DBG_PCDV, "EINVAL\n"); -+ return -EINVAL; -+ } -+ if (gadget_wrapper == 0) { -+ DWC_DEBUGPL(DBG_PCDV, "ENODEV\n"); -+ return -ENODEV; -+ } -+ if (gadget_wrapper->driver != 0) { -+ DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver); -+ return -EBUSY; -+ } -+ -+ /* hook up the driver */ -+ gadget_wrapper->driver = driver; -+ gadget_wrapper->gadget.dev.driver = &driver->driver; -+ -+ DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -+ retval = driver->bind(&gadget_wrapper->gadget); -+#else -+ retval = bind(&gadget_wrapper->gadget); -+#endif -+ if (retval) { -+ DWC_ERROR("bind to driver %s --> error %d\n", -+ driver->driver.name, retval); -+ gadget_wrapper->driver = 0; -+ gadget_wrapper->gadget.dev.driver = 0; -+ return retval; -+ } -+ DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n", -+ driver->driver.name); -+ return 0; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -+EXPORT_SYMBOL(usb_gadget_register_driver); -+#else -+EXPORT_SYMBOL(usb_gadget_probe_driver); -+#endif -+ -+/** -+ * This function unregisters a gadget driver -+ * -+ * @param driver The driver being unregistered -+ */ -+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) -+{ -+ //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver); -+ -+ if (gadget_wrapper == 0) { -+ DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__, -+ -ENODEV); -+ return -ENODEV; -+ } -+ if (driver == 0 || driver != gadget_wrapper->driver) { -+ DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__, -+ -EINVAL); -+ return -EINVAL; -+ } -+ -+ driver->unbind(&gadget_wrapper->gadget); -+ gadget_wrapper->driver = 0; -+ -+ DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name); -+ return 0; -+} -+ -+EXPORT_SYMBOL(usb_gadget_unregister_driver); -+ -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h -new file mode 100644 -index 0000000..e8220ad ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h -@@ -0,0 +1,2237 @@ -+/* ========================================================================== -+ * $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 "dwc_otg_core_if.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. Offset: 000h */ -+ volatile uint32_t gotgctl; -+ /** OTG Interrupt Register. Offset: 004h */ -+ volatile uint32_t gotgint; -+ /**Core AHB Configuration Register. Offset: 008h */ -+ 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. Offset: 00Ch */ -+ volatile uint32_t gusbcfg; -+ /**Core Reset Register. Offset: 010h */ -+ volatile uint32_t grstctl; -+ /**Core Interrupt Register. Offset: 014h */ -+ volatile uint32_t gintsts; -+ /**Core Interrupt Mask Register. Offset: 018h */ -+ volatile uint32_t gintmsk; -+ /**Receive Status Queue Read Register (Read Only). Offset: 01Ch */ -+ volatile uint32_t grxstsr; -+ /**Receive Status Queue Read & POP Register (Read Only). Offset: 020h*/ -+ volatile uint32_t grxstsp; -+ /**Receive FIFO Size Register. Offset: 024h */ -+ volatile uint32_t grxfsiz; -+ /**Non Periodic Transmit FIFO Size Register. Offset: 028h */ -+ volatile uint32_t gnptxfsiz; -+ /**Non Periodic Transmit FIFO/Queue Status Register (Read -+ * Only). Offset: 02Ch */ -+ volatile uint32_t gnptxsts; -+ /**I2C Access Register. Offset: 030h */ -+ volatile uint32_t gi2cctl; -+ /**PHY Vendor Control Register. Offset: 034h */ -+ volatile uint32_t gpvndctl; -+ /**General Purpose Input/Output Register. Offset: 038h */ -+ volatile uint32_t ggpio; -+ /**User ID Register. Offset: 03Ch */ -+ volatile uint32_t guid; -+ /**Synopsys ID Register (Read Only). Offset: 040h */ -+ volatile uint32_t gsnpsid; -+ /**User HW Config1 Register (Read Only). Offset: 044h */ -+ volatile uint32_t ghwcfg1; -+ /**User HW Config2 Register (Read Only). Offset: 048h */ -+ 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). Offset: 04Ch */ -+ volatile uint32_t ghwcfg3; -+ /**User HW Config4 Register (Read Only). Offset: 050h*/ -+ volatile uint32_t ghwcfg4; -+ /** Core LPM Configuration register */ -+ volatile uint32_t glpmcfg; -+ /** Reserved Offset: 058h-0FFh */ -+ volatile uint32_t reserved[42]; -+ /** Host Periodic Transmit FIFO Size Register. Offset: 100h */ -+ volatile uint32_t hptxfsiz; -+ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, -+ otherwise Device Transmit FIFO#n Register. -+ * Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15). */ -+ 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 d32 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 d32 -+ * 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 d32 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 d32 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 d32 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 -+ * d32 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)
-+ * -+ * 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.

The application must first -+ * ensure that the core is not in the middle of a -+ * transaction.

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.

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.

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.

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 d32 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 -+ * d32 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 d32 -+ * element then read out the bits using the bit 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 d32 -+ * element then read out the bits using the bit 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 d32 element then -+ * read out the bits using the bit 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 -+ * d32 element then read out the bits using the bit -+ * 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 -+ * d32 element then read out the bits using the bit -+ * 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 d32 element then read out the -+ * bits using the bit 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 d32 element then read -+ * out the bits using the bit 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 d32 element then read -+ * out the bits using the bit 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 d32 element then read -+ * out the bits using the bit 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 d32 element then read -+ * out the bits using the bit 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. Offsets 800h-BFFh -+ * -+ * The following structures define the size and relative field offsets -+ * for the Device Mode Registers. -+ * -+ * These registers are visible only in Device mode and must not be -+ * accessed in Host mode, as the results are unknown. -+ */ -+typedef struct dwc_otg_dev_global_regs { -+ /** Device Configuration Register. Offset 800h */ -+ volatile uint32_t dcfg; -+ /** Device Control Register. Offset: 804h */ -+ volatile uint32_t dctl; -+ /** Device Status Register (Read Only). Offset: 808h */ -+ volatile uint32_t dsts; -+ /** Reserved. Offset: 80Ch */ -+ uint32_t unused; -+ /** Device IN Endpoint Common Interrupt Mask -+ * Register. Offset: 810h */ -+ volatile uint32_t diepmsk; -+ /** Device OUT Endpoint Common Interrupt Mask -+ * Register. Offset: 814h */ -+ volatile uint32_t doepmsk; -+ /** Device All Endpoints Interrupt Register. Offset: 818h */ -+ volatile uint32_t daint; -+ /** Device All Endpoints Interrupt Mask Register. Offset: -+ * 81Ch */ -+ volatile uint32_t daintmsk; -+ /** Device IN Token Queue Read Register-1 (Read Only). -+ * Offset: 820h */ -+ volatile uint32_t dtknqr1; -+ /** Device IN Token Queue Read Register-2 (Read Only). -+ * Offset: 824h */ -+ volatile uint32_t dtknqr2; -+ /** Device VBUS discharge Register. Offset: 828h */ -+ volatile uint32_t dvbusdis; -+ /** Device VBUS Pulse Register. Offset: 82Ch */ -+ volatile uint32_t dvbuspulse; -+ /** Device IN Token Queue Read Register-3 (Read Only). / -+ * Device Thresholding control register (Read/Write) -+ * Offset: 830h */ -+ volatile uint32_t dtknqr3_dthrctl; -+ /** Device IN Token Queue Read Register-4 (Read Only). / -+ * Device IN EPs empty Inr. Mask Register (Read/Write) -+ * Offset: 834h */ -+ volatile uint32_t dtknqr4_fifoemptymsk; -+ /** Device Each Endpoint Interrupt Register (Read Only). / -+ * Offset: 838h */ -+ volatile uint32_t deachint; -+ /** Device Each Endpoint Interrupt mask Register (Read/Write). / -+ * Offset: 83Ch */ -+ volatile uint32_t deachintmsk; -+ /** Device Each In Endpoint Interrupt mask Register (Read/Write). / -+ * Offset: 840h */ -+ volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS]; -+ /** Device Each Out Endpoint Interrupt mask Register (Read/Write). / -+ * Offset: 880h */ -+ volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS]; -+} dwc_otg_device_global_regs_t; -+ -+/** -+ * This union represents the bit fields in the Device Configuration -+ * Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. Write the -+ * d32 member to the dcfg register. -+ */ -+typedef union dcfg_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Device Speed */ -+ unsigned devspd:2; -+ /** Non Zero Length Status OUT Handshake */ -+ unsigned nzstsouthshk:1; -+#define DWC_DCFG_SEND_STALL 1 -+ -+ unsigned reserved3:1; -+ /** Device Addresses */ -+ unsigned devaddr:7; -+ /** Periodic Frame Interval */ -+ unsigned perfrint:2; -+#define DWC_DCFG_FRAME_INTERVAL_80 0 -+#define DWC_DCFG_FRAME_INTERVAL_85 1 -+#define DWC_DCFG_FRAME_INTERVAL_90 2 -+#define DWC_DCFG_FRAME_INTERVAL_95 3 -+ -+ unsigned reserved13_17:5; -+ /** In Endpoint Mis-match count */ -+ unsigned epmscnt:5; -+ /** Enable Descriptor DMA in Device mode */ -+ unsigned descdma:1; -+ } b; -+} dcfg_data_t; -+ -+/** -+ * This union represents the bit fields in the Device Control -+ * Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+typedef union dctl_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Remote Wakeup */ -+ unsigned rmtwkupsig:1; -+ /** Soft Disconnect */ -+ unsigned sftdiscon:1; -+ /** Global Non-Periodic IN NAK Status */ -+ unsigned gnpinnaksts:1; -+ /** Global OUT NAK Status */ -+ unsigned goutnaksts:1; -+ /** Test Control */ -+ unsigned tstctl:3; -+ /** Set Global Non-Periodic IN NAK */ -+ unsigned sgnpinnak:1; -+ /** Clear Global Non-Periodic IN NAK */ -+ unsigned cgnpinnak:1; -+ /** Set Global OUT NAK */ -+ unsigned sgoutnak:1; -+ /** Clear Global OUT NAK */ -+ unsigned cgoutnak:1; -+ -+ /** Power-On Programming Done */ -+ unsigned pwronprgdone:1; -+ /** Global Continue on BNA */ -+ unsigned gcontbna:1; -+ /** Global Multi Count */ -+ unsigned gmc:2; -+ /** Ignore Frame Number for ISOC EPs */ -+ unsigned ifrmnum:1; -+ /** NAK on Babble */ -+ unsigned nakonbble:1; -+ -+ unsigned reserved17_31:15; -+ } b; -+} dctl_data_t; -+ -+/** -+ * This union represents the bit fields in the Device Status -+ * Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+typedef union dsts_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Suspend Status */ -+ unsigned suspsts:1; -+ /** Enumerated Speed */ -+ unsigned enumspd:2; -+#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 -+#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 -+#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2 -+#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3 -+ /** Erratic Error */ -+ unsigned errticerr:1; -+ unsigned reserved4_7:4; -+ /** Frame or Microframe Number of the received SOF */ -+ unsigned soffn:14; -+ unsigned reserved22_31:10; -+ } b; -+} dsts_data_t; -+ -+/** -+ * This union represents the bit fields in the Device IN EP Interrupt -+ * Register and the Device IN EP Common Mask Register. -+ * -+ * - Read the register into the d32 member then set/clear the -+ * bits using the bit elements. -+ */ -+typedef union diepint_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Transfer complete mask */ -+ unsigned xfercompl:1; -+ /** Endpoint disable mask */ -+ unsigned epdisabled:1; -+ /** AHB Error mask */ -+ unsigned ahberr:1; -+ /** TimeOUT Handshake mask (non-ISOC EPs) */ -+ unsigned timeout:1; -+ /** IN Token received with TxF Empty mask */ -+ unsigned intktxfemp:1; -+ /** IN Token Received with EP mismatch mask */ -+ unsigned intknepmis:1; -+ /** IN Endpoint HAK Effective mask */ -+ unsigned inepnakeff:1; -+ /** IN Endpoint HAK Effective mask */ -+ unsigned emptyintr:1; -+ -+ unsigned txfifoundrn:1; -+ -+ /** BNA Interrupt mask */ -+ unsigned bna:1; -+ -+ unsigned reserved10_12:3; -+ /** BNA Interrupt mask */ -+ unsigned nak:1; -+ -+ unsigned reserved14_31:18; -+ } b; -+} diepint_data_t; -+ -+/** -+ * This union represents the bit fields in the Device IN EP -+ * Common/Dedicated Interrupt Mask Register. -+ */ -+typedef union diepint_data diepmsk_data_t; -+ -+/** -+ * This union represents the bit fields in the Device OUT EP Interrupt -+ * Registerand Device OUT EP Common Interrupt Mask Register. -+ * -+ * - Read the register into the d32 member then set/clear the -+ * bits using the bit elements. -+ */ -+typedef union doepint_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Transfer complete */ -+ unsigned xfercompl:1; -+ /** Endpoint disable */ -+ unsigned epdisabled:1; -+ /** AHB Error */ -+ unsigned ahberr:1; -+ /** Setup Phase Done (contorl EPs) */ -+ unsigned setup:1; -+ /** OUT Token Received when Endpoint Disabled */ -+ unsigned outtknepdis:1; -+ -+ unsigned stsphsercvd:1; -+ /** Back-to-Back SETUP Packets Received */ -+ unsigned back2backsetup:1; -+ -+ unsigned reserved7:1; -+ /** OUT packet Error */ -+ unsigned outpkterr:1; -+ /** BNA Interrupt */ -+ unsigned bna:1; -+ -+ unsigned reserved10:1; -+ /** Packet Drop Status */ -+ unsigned pktdrpsts:1; -+ /** Babble Interrupt */ -+ unsigned babble:1; -+ /** NAK Interrupt */ -+ unsigned nak:1; -+ /** NYET Interrupt */ -+ unsigned nyet:1; -+ -+ unsigned reserved15_31:17; -+ } b; -+} doepint_data_t; -+ -+/** -+ * This union represents the bit fields in the Device OUT EP -+ * Common/Dedicated Interrupt Mask Register. -+ */ -+typedef union doepint_data doepmsk_data_t; -+ -+/** -+ * This union represents the bit fields in the Device All EP Interrupt -+ * and Mask Registers. -+ * - Read the register into the d32 member then set/clear the -+ * bits using the bit elements. -+ */ -+typedef union daint_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** IN Endpoint bits */ -+ unsigned in:16; -+ /** OUT Endpoint bits */ -+ unsigned out:16; -+ } ep; -+ struct { -+ /** IN Endpoint bits */ -+ unsigned inep0:1; -+ unsigned inep1:1; -+ unsigned inep2:1; -+ unsigned inep3:1; -+ unsigned inep4:1; -+ unsigned inep5:1; -+ unsigned inep6:1; -+ unsigned inep7:1; -+ unsigned inep8:1; -+ unsigned inep9:1; -+ unsigned inep10:1; -+ unsigned inep11:1; -+ unsigned inep12:1; -+ unsigned inep13:1; -+ unsigned inep14:1; -+ unsigned inep15:1; -+ /** OUT Endpoint bits */ -+ unsigned outep0:1; -+ unsigned outep1:1; -+ unsigned outep2:1; -+ unsigned outep3:1; -+ unsigned outep4:1; -+ unsigned outep5:1; -+ unsigned outep6:1; -+ unsigned outep7:1; -+ unsigned outep8:1; -+ unsigned outep9:1; -+ unsigned outep10:1; -+ unsigned outep11:1; -+ unsigned outep12:1; -+ unsigned outep13:1; -+ unsigned outep14:1; -+ unsigned outep15:1; -+ } b; -+} daint_data_t; -+ -+/** -+ * This union represents the bit fields in the Device IN Token Queue -+ * Read Registers. -+ * - Read the register into the d32 member. -+ * - READ-ONLY Register -+ */ -+typedef union dtknq1_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** In Token Queue Write Pointer */ -+ unsigned intknwptr:5; -+ /** Reserved */ -+ unsigned reserved05_06:2; -+ /** write pointer has wrapped. */ -+ unsigned wrap_bit:1; -+ /** EP Numbers of IN Tokens 0 ... 4 */ -+ unsigned epnums0_5:24; -+ } b; -+} dtknq1_data_t; -+ -+/** -+ * This union represents Threshold control Register -+ * - Read and write the register into the d32 member. -+ * - READ-WRITABLE Register -+ */ -+typedef union dthrctl_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** non ISO Tx Thr. Enable */ -+ unsigned non_iso_thr_en:1; -+ /** ISO Tx Thr. Enable */ -+ unsigned iso_thr_en:1; -+ /** Tx Thr. Length */ -+ unsigned tx_thr_len:9; -+ /** AHB Threshold ratio */ -+ unsigned ahb_thr_ratio:2; -+ /** Reserved */ -+ unsigned reserved13_15:3; -+ /** Rx Thr. Enable */ -+ unsigned rx_thr_en:1; -+ /** Rx Thr. Length */ -+ unsigned rx_thr_len:9; -+ /** Reserved */ -+ unsigned reserved26_31:6; -+ } b; -+} dthrctl_data_t; -+ -+/** -+ * Device Logical IN Endpoint-Specific Registers. Offsets -+ * 900h-AFCh -+ * -+ * There will be one set of endpoint registers per logical endpoint -+ * implemented. -+ * -+ * These registers are visible only in Device mode and must not be -+ * accessed in Host mode, as the results are unknown. -+ */ -+typedef struct dwc_otg_dev_in_ep_regs { -+ /** Device IN Endpoint Control Register. Offset:900h + -+ * (ep_num * 20h) + 00h */ -+ volatile uint32_t diepctl; -+ /** Reserved. Offset:900h + (ep_num * 20h) + 04h */ -+ uint32_t reserved04; -+ /** Device IN Endpoint Interrupt Register. Offset:900h + -+ * (ep_num * 20h) + 08h */ -+ volatile uint32_t diepint; -+ /** Reserved. Offset:900h + (ep_num * 20h) + 0Ch */ -+ uint32_t reserved0C; -+ /** Device IN Endpoint Transfer Size -+ * Register. Offset:900h + (ep_num * 20h) + 10h */ -+ volatile uint32_t dieptsiz; -+ /** Device IN Endpoint DMA Address Register. Offset:900h + -+ * (ep_num * 20h) + 14h */ -+ volatile uint32_t diepdma; -+ /** Device IN Endpoint Transmit FIFO Status Register. Offset:900h + -+ * (ep_num * 20h) + 18h */ -+ volatile uint32_t dtxfsts; -+ /** Device IN Endpoint DMA Buffer Register. Offset:900h + -+ * (ep_num * 20h) + 1Ch */ -+ volatile uint32_t diepdmab; -+} dwc_otg_dev_in_ep_regs_t; -+ -+/** -+ * Device Logical OUT Endpoint-Specific Registers. Offsets: -+ * B00h-CFCh -+ * -+ * There will be one set of endpoint registers per logical endpoint -+ * implemented. -+ * -+ * These registers are visible only in Device mode and must not be -+ * accessed in Host mode, as the results are unknown. -+ */ -+typedef struct dwc_otg_dev_out_ep_regs { -+ /** Device OUT Endpoint Control Register. Offset:B00h + -+ * (ep_num * 20h) + 00h */ -+ volatile uint32_t doepctl; -+ /** Device OUT Endpoint Frame number Register. Offset: -+ * B00h + (ep_num * 20h) + 04h */ -+ volatile uint32_t doepfn; -+ /** Device OUT Endpoint Interrupt Register. Offset:B00h + -+ * (ep_num * 20h) + 08h */ -+ volatile uint32_t doepint; -+ /** Reserved. Offset:B00h + (ep_num * 20h) + 0Ch */ -+ uint32_t reserved0C; -+ /** Device OUT Endpoint Transfer Size Register. Offset: -+ * B00h + (ep_num * 20h) + 10h */ -+ volatile uint32_t doeptsiz; -+ /** Device OUT Endpoint DMA Address Register. Offset:B00h -+ * + (ep_num * 20h) + 14h */ -+ volatile uint32_t doepdma; -+ /** Reserved. Offset:B00h + * (ep_num * 20h) + 18h */ -+ uint32_t unused; -+ /** Device OUT Endpoint DMA Buffer Register. Offset:B00h -+ * + (ep_num * 20h) + 1Ch */ -+ uint32_t doepdmab; -+} dwc_otg_dev_out_ep_regs_t; -+ -+/** -+ * This union represents the bit fields in the Device EP Control -+ * Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+typedef union depctl_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Maximum Packet Size -+ * IN/OUT EPn -+ * IN/OUT EP0 - 2 bits -+ * 2'b00: 64 Bytes -+ * 2'b01: 32 -+ * 2'b10: 16 -+ * 2'b11: 8 */ -+ unsigned mps:11; -+#define DWC_DEP0CTL_MPS_64 0 -+#define DWC_DEP0CTL_MPS_32 1 -+#define DWC_DEP0CTL_MPS_16 2 -+#define DWC_DEP0CTL_MPS_8 3 -+ -+ /** Next Endpoint -+ * IN EPn/IN EP0 -+ * OUT EPn/OUT EP0 - reserved */ -+ unsigned nextep:4; -+ -+ /** USB Active Endpoint */ -+ unsigned usbactep:1; -+ -+ /** Endpoint DPID (INTR/Bulk IN and OUT endpoints) -+ * This field contains the PID of the packet going to -+ * be received or transmitted on this endpoint. The -+ * application should program the PID of the first -+ * packet going to be received or transmitted on this -+ * endpoint , after the endpoint is -+ * activated. Application use the SetD1PID and -+ * SetD0PID fields of this register to program either -+ * D0 or D1 PID. -+ * -+ * The encoding for this field is -+ * - 0: D0 -+ * - 1: D1 -+ */ -+ unsigned dpid:1; -+ -+ /** NAK Status */ -+ unsigned naksts:1; -+ -+ /** Endpoint Type -+ * 2'b00: Control -+ * 2'b01: Isochronous -+ * 2'b10: Bulk -+ * 2'b11: Interrupt */ -+ unsigned eptype:2; -+ -+ /** Snoop Mode -+ * OUT EPn/OUT EP0 -+ * IN EPn/IN EP0 - reserved */ -+ unsigned snp:1; -+ -+ /** Stall Handshake */ -+ unsigned stall:1; -+ -+ /** Tx Fifo Number -+ * IN EPn/IN EP0 -+ * OUT EPn/OUT EP0 - reserved */ -+ unsigned txfnum:4; -+ -+ /** Clear NAK */ -+ unsigned cnak:1; -+ /** Set NAK */ -+ unsigned snak:1; -+ /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints) -+ * Writing to this field sets the Endpoint DPID (DPID) -+ * field in this register to DATA0. Set Even -+ * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints) -+ * Writing to this field sets the Even/Odd -+ * (micro)frame (EO_FrNum) field to even (micro) -+ * frame. -+ */ -+ unsigned setd0pid:1; -+ /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints) -+ * Writing to this field sets the Endpoint DPID (DPID) -+ * field in this register to DATA1 Set Odd -+ * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints) -+ * Writing to this field sets the Even/Odd -+ * (micro)frame (EO_FrNum) field to odd (micro) frame. -+ */ -+ unsigned setd1pid:1; -+ -+ /** Endpoint Disable */ -+ unsigned epdis:1; -+ /** Endpoint Enable */ -+ unsigned epena:1; -+ } b; -+} depctl_data_t; -+ -+/** -+ * This union represents the bit fields in the Device EP Transfer -+ * Size Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+typedef union deptsiz_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Transfer size */ -+ unsigned xfersize:19; -+ /** Packet Count */ -+ unsigned pktcnt:10; -+ /** Multi Count - Periodic IN endpoints */ -+ unsigned mc:2; -+ unsigned reserved:1; -+ } b; -+} deptsiz_data_t; -+ -+/** -+ * This union represents the bit fields in the Device EP 0 Transfer -+ * Size Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+typedef union deptsiz0_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Transfer size */ -+ unsigned xfersize:7; -+ /** Reserved */ -+ unsigned reserved7_18:12; -+ /** Packet Count */ -+ unsigned pktcnt:1; -+ /** Reserved */ -+ unsigned reserved20_28:9; -+ /**Setup Packet Count (DOEPTSIZ0 Only) */ -+ unsigned supcnt:2; -+ unsigned reserved31; -+ } b; -+} deptsiz0_data_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 d32 member then -+ * set/clear the bits using the bit, b_iso_out and -+ * b_iso_in 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; -+ -+/** -+ * The dwc_otg_dev_if structure contains information needed to manage -+ * the DWC_otg controller acting in device mode. It represents the -+ * programming view of the device-specific aspects of the controller. -+ */ -+typedef struct dwc_otg_dev_if { -+ /** Pointer to device Global registers. -+ * Device Global Registers starting at offset 800h -+ */ -+ dwc_otg_device_global_regs_t *dev_global_regs; -+#define DWC_DEV_GLOBAL_REG_OFFSET 0x800 -+ -+ /** -+ * Device Logical IN Endpoint-Specific Registers 900h-AFCh -+ */ -+ dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS]; -+#define DWC_DEV_IN_EP_REG_OFFSET 0x900 -+#define DWC_EP_REG_OFFSET 0x20 -+ -+ /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */ -+ dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS]; -+#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00 -+ -+ /* Device configuration information */ -+ uint8_t speed; /**< Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */ -+ uint8_t num_in_eps; /**< Number # of Tx EP range: 0-15 exept ep0 */ -+ uint8_t num_out_eps; /**< Number # of Rx EP range: 0-15 exept ep 0*/ -+ -+ /** Size of periodic FIFOs (Bytes) */ -+ uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS]; -+ -+ /** Size of Tx FIFOs (Bytes) */ -+ uint16_t tx_fifo_size[MAX_TX_FIFOS]; -+ -+ /** Thresholding enable flags and length varaiables **/ -+ uint16_t rx_thr_en; -+ uint16_t iso_tx_thr_en; -+ uint16_t non_iso_tx_thr_en; -+ -+ uint16_t rx_thr_length; -+ uint16_t tx_thr_length; -+ -+ /** -+ * Pointers to the DMA Descriptors for EP0 Control -+ * transfers (virtual and physical) -+ */ -+ -+ /** 2 descriptors for SETUP packets */ -+ dwc_dma_t dma_setup_desc_addr[2]; -+ dwc_otg_dev_dma_desc_t *setup_desc_addr[2]; -+ -+ /** Pointer to Descriptor with latest SETUP packet */ -+ dwc_otg_dev_dma_desc_t *psetup; -+ -+ /** Index of current SETUP handler descriptor */ -+ uint32_t setup_desc_index; -+ -+ /** Descriptor for Data In or Status In phases */ -+ dwc_dma_t dma_in_desc_addr; -+ dwc_otg_dev_dma_desc_t *in_desc_addr; -+ -+ /** Descriptor for Data Out or Status Out phases */ -+ dwc_dma_t dma_out_desc_addr; -+ dwc_otg_dev_dma_desc_t *out_desc_addr; -+ -+ /** Setup Packet Detected - if set clear NAK when queueing */ -+ uint32_t spd; -+ -+} dwc_otg_dev_if_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. Offset: 400h */ -+ volatile uint32_t hcfg; -+ /** Host Frame Interval Register. Offset: 404h */ -+ volatile uint32_t hfir; -+ /** Host Frame Number / Frame Remaining Register. Offset: 408h */ -+ volatile uint32_t hfnum; -+ /** Reserved. Offset: 40Ch */ -+ uint32_t reserved40C; -+ /** Host Periodic Transmit FIFO/ Queue Status Register. Offset: 410h */ -+ volatile uint32_t hptxsts; -+ /** Host All Channels Interrupt Register. Offset: 414h */ -+ volatile uint32_t haint; -+ /** Host All Channels Interrupt Mask Register. Offset: 418h */ -+ volatile uint32_t haintmsk; -+ /** Host Frame List Base Address Register . Offset: 41Ch */ -+ 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 d32 member then set/clear the bits using -+ * the bit elements. Write the d32 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 d32 member then set/clear the -+ * bits using the bit elements. Write the d32 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. 500h-5FCh -+ */ -+typedef struct dwc_otg_hc_regs -+{ -+ /** Host Channel 0 Characteristic Register. Offset: 500h + (chan_num * 20h) + 00h */ -+ volatile uint32_t hcchar; -+ /** Host Channel 0 Split Control Register. Offset: 500h + (chan_num * 20h) + 04h */ -+ volatile uint32_t hcsplt; -+ /** Host Channel 0 Interrupt Register. Offset: 500h + (chan_num * 20h) + 08h */ -+ volatile uint32_t hcint; -+ /** Host Channel 0 Interrupt Mask Register. Offset: 500h + (chan_num * 20h) + 0Ch */ -+ volatile uint32_t hcintmsk; -+ /** Host Channel 0 Transfer Size Register. Offset: 500h + (chan_num * 20h) + 10h */ -+ volatile uint32_t hctsiz; -+ /** Host Channel 0 DMA Address Register. Offset: 500h + (chan_num * 20h) + 14h */ -+ volatile uint32_t hcdma; -+ volatile uint32_t reserved; -+ /** Host Channel 0 DMA Buffer Address Register. Offset: 500h + (chan_num * 20h) + 1Ch */ -+ 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 d32 member then set/clear the -+ * bits using the bit elements. Write the d32 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 d32 member then set/clear the -+ * bits using the bit elements. Write the d32 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 d32 member then set/clear the -+ * bits using the bit elements. Write the d32 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 d32 member then -+ * set/clear the bits using the bit 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 d32 member then set/clear the -+ * bits using the bit 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/drivers/usb/host/dwc_otg/test/Makefile b/drivers/usb/host/dwc_otg/test/Makefile -new file mode 100644 -index 0000000..fc45375 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/test/Makefile -@@ -0,0 +1,16 @@ -+ -+PERL=/usr/bin/perl -+PL_TESTS=test_sysfs.pl test_mod_param.pl -+ -+.PHONY : test -+test : perl_tests -+ -+perl_tests : -+ @echo -+ @echo Running perl tests -+ @for test in $(PL_TESTS); do \ -+ if $(PERL) ./$$test ; then \ -+ echo "=======> $$test, PASSED" ; \ -+ else echo "=======> $$test, FAILED" ; \ -+ fi \ -+ done -diff --git a/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm -new file mode 100644 -index 0000000..233b04a ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm -@@ -0,0 +1,337 @@ -+package dwc_otg_test; -+ -+use strict; -+use Exporter (); -+ -+use vars qw(@ISA @EXPORT -+$sysfsdir $paramdir $errors $params -+); -+ -+@ISA = qw(Exporter); -+ -+# -+# Globals -+# -+$sysfsdir = "/sys/devices/lm0"; -+$paramdir = "/sys/module/dwc_otg"; -+$errors = 0; -+ -+$params = [ -+ { -+ NAME => "otg_cap", -+ DEFAULT => 0, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 2 -+ }, -+ { -+ NAME => "dma_enable", -+ DEFAULT => 0, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 1 -+ }, -+ { -+ NAME => "dma_burst_size", -+ DEFAULT => 32, -+ ENUM => [1, 4, 8, 16, 32, 64, 128, 256], -+ LOW => 1, -+ HIGH => 256 -+ }, -+ { -+ NAME => "host_speed", -+ DEFAULT => 0, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 1 -+ }, -+ { -+ NAME => "host_support_fs_ls_low_power", -+ DEFAULT => 0, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 1 -+ }, -+ { -+ NAME => "host_ls_low_power_phy_clk", -+ DEFAULT => 0, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 1 -+ }, -+ { -+ NAME => "dev_speed", -+ DEFAULT => 0, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 1 -+ }, -+ { -+ NAME => "enable_dynamic_fifo", -+ DEFAULT => 1, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 1 -+ }, -+ { -+ NAME => "data_fifo_size", -+ DEFAULT => 8192, -+ ENUM => [], -+ LOW => 32, -+ HIGH => 32768 -+ }, -+ { -+ NAME => "dev_rx_fifo_size", -+ DEFAULT => 1064, -+ ENUM => [], -+ LOW => 16, -+ HIGH => 32768 -+ }, -+ { -+ NAME => "dev_nperio_tx_fifo_size", -+ DEFAULT => 1024, -+ ENUM => [], -+ LOW => 16, -+ HIGH => 32768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_1", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_2", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_3", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_4", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_5", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_6", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_7", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_8", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_9", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_10", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_11", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_12", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_13", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_14", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "dev_perio_tx_fifo_size_15", -+ DEFAULT => 256, -+ ENUM => [], -+ LOW => 4, -+ HIGH => 768 -+ }, -+ { -+ NAME => "host_rx_fifo_size", -+ DEFAULT => 1024, -+ ENUM => [], -+ LOW => 16, -+ HIGH => 32768 -+ }, -+ { -+ NAME => "host_nperio_tx_fifo_size", -+ DEFAULT => 1024, -+ ENUM => [], -+ LOW => 16, -+ HIGH => 32768 -+ }, -+ { -+ NAME => "host_perio_tx_fifo_size", -+ DEFAULT => 1024, -+ ENUM => [], -+ LOW => 16, -+ HIGH => 32768 -+ }, -+ { -+ NAME => "max_transfer_size", -+ DEFAULT => 65535, -+ ENUM => [], -+ LOW => 2047, -+ HIGH => 65535 -+ }, -+ { -+ NAME => "max_packet_count", -+ DEFAULT => 511, -+ ENUM => [], -+ LOW => 15, -+ HIGH => 511 -+ }, -+ { -+ NAME => "host_channels", -+ DEFAULT => 12, -+ ENUM => [], -+ LOW => 1, -+ HIGH => 16 -+ }, -+ { -+ NAME => "dev_endpoints", -+ DEFAULT => 6, -+ ENUM => [], -+ LOW => 1, -+ HIGH => 15 -+ }, -+ { -+ NAME => "phy_type", -+ DEFAULT => 1, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 2 -+ }, -+ { -+ NAME => "phy_utmi_width", -+ DEFAULT => 16, -+ ENUM => [8, 16], -+ LOW => 8, -+ HIGH => 16 -+ }, -+ { -+ NAME => "phy_ulpi_ddr", -+ DEFAULT => 0, -+ ENUM => [], -+ LOW => 0, -+ HIGH => 1 -+ }, -+ ]; -+ -+ -+# -+# -+sub check_arch { -+ $_ = `uname -m`; -+ chomp; -+ unless (m/armv4tl/) { -+ warn "# \n# Can't execute on $_. Run on integrator platform.\n# \n"; -+ return 0; -+ } -+ return 1; -+} -+ -+# -+# -+sub load_module { -+ my $params = shift; -+ print "\nRemoving Module\n"; -+ system "rmmod dwc_otg"; -+ print "Loading Module\n"; -+ if ($params ne "") { -+ print "Module Parameters: $params\n"; -+ } -+ if (system("modprobe dwc_otg $params")) { -+ warn "Unable to load module\n"; -+ return 0; -+ } -+ return 1; -+} -+ -+# -+# -+sub test_status { -+ my $arg = shift; -+ -+ print "\n"; -+ -+ if (defined $arg) { -+ warn "WARNING: $arg\n"; -+ } -+ -+ if ($errors > 0) { -+ warn "TEST FAILED with $errors errors\n"; -+ return 0; -+ } else { -+ print "TEST PASSED\n"; -+ return 0 if (defined $arg); -+ } -+ return 1; -+} -+ -+# -+# -+@EXPORT = qw( -+$sysfsdir -+$paramdir -+$params -+$errors -+check_arch -+load_module -+test_status -+); -+ -+1; -diff --git a/drivers/usb/host/dwc_otg/test/test_mod_param.pl b/drivers/usb/host/dwc_otg/test/test_mod_param.pl -new file mode 100644 -index 0000000..e887dce ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl -@@ -0,0 +1,133 @@ -+#!/usr/bin/perl -w -+# -+# Run this program on the integrator. -+# -+# - Tests module parameter default values. -+# - Tests setting of valid module parameter values via modprobe. -+# - Tests invalid module parameter values. -+# ----------------------------------------------------------------------------- -+use strict; -+use dwc_otg_test; -+ -+check_arch() or die; -+ -+# -+# -+sub test { -+ my ($param,$expected) = @_; -+ my $value = get($param); -+ -+ if ($value == $expected) { -+ print "$param = $value, okay\n"; -+ } -+ -+ else { -+ warn "ERROR: value of $param != $expected, $value\n"; -+ $errors ++; -+ } -+} -+ -+# -+# -+sub get { -+ my $param = shift; -+ my $tmp = `cat $paramdir/$param`; -+ chomp $tmp; -+ return $tmp; -+} -+ -+# -+# -+sub test_main { -+ -+ print "\nTesting Module Parameters\n"; -+ -+ load_module("") or die; -+ -+ # Test initial values -+ print "\nTesting Default Values\n"; -+ foreach (@{$params}) { -+ test ($_->{NAME}, $_->{DEFAULT}); -+ } -+ -+ # Test low value -+ print "\nTesting Low Value\n"; -+ my $cmd_params = ""; -+ foreach (@{$params}) { -+ $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} "; -+ } -+ load_module($cmd_params) or die; -+ -+ foreach (@{$params}) { -+ test ($_->{NAME}, $_->{LOW}); -+ } -+ -+ # Test high value -+ print "\nTesting High Value\n"; -+ $cmd_params = ""; -+ foreach (@{$params}) { -+ $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} "; -+ } -+ load_module($cmd_params) or die; -+ -+ foreach (@{$params}) { -+ test ($_->{NAME}, $_->{HIGH}); -+ } -+ -+ # Test Enum -+ print "\nTesting Enumerated\n"; -+ foreach (@{$params}) { -+ if (defined $_->{ENUM}) { -+ my $value; -+ foreach $value (@{$_->{ENUM}}) { -+ $cmd_params = "$_->{NAME}=$value"; -+ load_module($cmd_params) or die; -+ test ($_->{NAME}, $value); -+ } -+ } -+ } -+ -+ # Test Invalid Values -+ print "\nTesting Invalid Values\n"; -+ $cmd_params = ""; -+ foreach (@{$params}) { -+ $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1; -+ } -+ load_module($cmd_params) or die; -+ -+ foreach (@{$params}) { -+ test ($_->{NAME}, $_->{DEFAULT}); -+ } -+ -+ $cmd_params = ""; -+ foreach (@{$params}) { -+ $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1; -+ } -+ load_module($cmd_params) or die; -+ -+ foreach (@{$params}) { -+ test ($_->{NAME}, $_->{DEFAULT}); -+ } -+ -+ print "\nTesting Enumerated\n"; -+ foreach (@{$params}) { -+ if (defined $_->{ENUM}) { -+ my $value; -+ foreach $value (@{$_->{ENUM}}) { -+ $value = $value + 1; -+ $cmd_params = "$_->{NAME}=$value"; -+ load_module($cmd_params) or die; -+ test ($_->{NAME}, $_->{DEFAULT}); -+ $value = $value - 2; -+ $cmd_params = "$_->{NAME}=$value"; -+ load_module($cmd_params) or die; -+ test ($_->{NAME}, $_->{DEFAULT}); -+ } -+ } -+ } -+ -+ test_status() or die; -+} -+ -+test_main(); -+0; -diff --git a/drivers/usb/host/dwc_otg/test/test_sysfs.pl b/drivers/usb/host/dwc_otg/test/test_sysfs.pl -new file mode 100644 -index 0000000..abcf284 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl -@@ -0,0 +1,193 @@ -+#!/usr/bin/perl -w -+# -+# Run this program on the integrator -+# - Tests select sysfs attributes. -+# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc. -+# ----------------------------------------------------------------------------- -+use strict; -+use dwc_otg_test; -+ -+check_arch() or die; -+ -+# -+# -+sub test { -+ my ($attr,$expected) = @_; -+ my $string = get($attr); -+ -+ if ($string eq $expected) { -+ printf("$attr = $string, okay\n"); -+ } -+ else { -+ warn "ERROR: value of $attr != $expected, $string\n"; -+ $errors ++; -+ } -+} -+ -+# -+# -+sub set { -+ my ($reg, $value) = @_; -+ system "echo $value > $sysfsdir/$reg"; -+} -+ -+# -+# -+sub get { -+ my $attr = shift; -+ my $string = `cat $sysfsdir/$attr`; -+ chomp $string; -+ if ($string =~ m/\s\=\s/) { -+ my $tmp; -+ ($tmp, $string) = split /\s=\s/, $string; -+ } -+ return $string; -+} -+ -+# -+# -+sub test_main { -+ print("\nTesting Sysfs Attributes\n"); -+ -+ load_module("") or die; -+ -+ # Test initial values of regoffset/regvalue/guid/gsnpsid -+ print("\nTesting Default Values\n"); -+ -+ test("regoffset", "0xffffffff"); -+ test("regvalue", "invalid offset"); -+ test("guid", "0x12345678"); # this will fail if it has been changed -+ test("gsnpsid", "0x4f54200a"); -+ -+ # Test operation of regoffset/regvalue -+ print("\nTesting regoffset\n"); -+ set('regoffset', '5a5a5a5a'); -+ test("regoffset", "0xffffffff"); -+ -+ set('regoffset', '0'); -+ test("regoffset", "0x00000000"); -+ -+ set('regoffset', '40000'); -+ test("regoffset", "0x00000000"); -+ -+ set('regoffset', '3ffff'); -+ test("regoffset", "0x0003ffff"); -+ -+ set('regoffset', '1'); -+ test("regoffset", "0x00000001"); -+ -+ print("\nTesting regvalue\n"); -+ set('regoffset', '3c'); -+ test("regvalue", "0x12345678"); -+ set('regvalue', '5a5a5a5a'); -+ test("regvalue", "0x5a5a5a5a"); -+ set('regvalue','a5a5a5a5'); -+ test("regvalue", "0xa5a5a5a5"); -+ set('guid','12345678'); -+ -+ # Test HNP Capable -+ print("\nTesting HNP Capable bit\n"); -+ set('hnpcapable', '1'); -+ test("hnpcapable", "0x1"); -+ set('hnpcapable','0'); -+ test("hnpcapable", "0x0"); -+ -+ set('regoffset','0c'); -+ -+ my $old = get('gusbcfg'); -+ print("setting hnpcapable\n"); -+ set('hnpcapable', '1'); -+ test("hnpcapable", "0x1"); -+ test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9))); -+ test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9))); -+ -+ $old = get('gusbcfg'); -+ print("clearing hnpcapable\n"); -+ set('hnpcapable', '0'); -+ test("hnpcapable", "0x0"); -+ test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9))); -+ test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9))); -+ -+ # Test SRP Capable -+ print("\nTesting SRP Capable bit\n"); -+ set('srpcapable', '1'); -+ test("srpcapable", "0x1"); -+ set('srpcapable','0'); -+ test("srpcapable", "0x0"); -+ -+ set('regoffset','0c'); -+ -+ $old = get('gusbcfg'); -+ print("setting srpcapable\n"); -+ set('srpcapable', '1'); -+ test("srpcapable", "0x1"); -+ test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8))); -+ test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8))); -+ -+ $old = get('gusbcfg'); -+ print("clearing srpcapable\n"); -+ set('srpcapable', '0'); -+ test("srpcapable", "0x0"); -+ test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8))); -+ test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8))); -+ -+ # Test GGPIO -+ print("\nTesting GGPIO\n"); -+ set('ggpio','5a5a5a5a'); -+ test('ggpio','0x5a5a0000'); -+ set('ggpio','a5a5a5a5'); -+ test('ggpio','0xa5a50000'); -+ set('ggpio','11110000'); -+ test('ggpio','0x11110000'); -+ set('ggpio','00001111'); -+ test('ggpio','0x00000000'); -+ -+ # Test DEVSPEED -+ print("\nTesting DEVSPEED\n"); -+ set('regoffset','800'); -+ $old = get('regvalue'); -+ set('devspeed','0'); -+ test('devspeed','0x0'); -+ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3))); -+ set('devspeed','1'); -+ test('devspeed','0x1'); -+ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1)); -+ set('devspeed','2'); -+ test('devspeed','0x2'); -+ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2)); -+ set('devspeed','3'); -+ test('devspeed','0x3'); -+ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3)); -+ set('devspeed','4'); -+ test('devspeed','0x0'); -+ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3))); -+ set('devspeed','5'); -+ test('devspeed','0x1'); -+ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1)); -+ -+ -+ # mode Returns the current mode:0 for device mode1 for host mode Read -+ # hnp Initiate the Host Negotiation Protocol. Read returns the status. Read/Write -+ # srp Initiate the Session Request Protocol. Read returns the status. Read/Write -+ # buspower Get or Set the Power State of the bus (0 - Off or 1 - On) Read/Write -+ # bussuspend Suspend the USB bus. Read/Write -+ # busconnected Get the connection status of the bus Read -+ -+ # gotgctl Get or set the Core Control Status Register. Read/Write -+ ## gusbcfg Get or set the Core USB Configuration Register Read/Write -+ # grxfsiz Get or set the Receive FIFO Size Register Read/Write -+ # gnptxfsiz Get or set the non-periodic Transmit Size Register Read/Write -+ # gpvndctl Get or set the PHY Vendor Control Register Read/Write -+ ## ggpio Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write -+ ## guid Get or set the value of the User ID Register Read/Write -+ ## gsnpsid Get the value of the Synopsys ID Regester Read -+ ## devspeed Get or set the device speed setting in the DCFG register Read/Write -+ # enumspeed Gets the device enumeration Speed. Read -+ # hptxfsiz Get the value of the Host Periodic Transmit FIFO Read -+ # hprt0 Get or Set the value in the Host Port Control and Status Register Read/Write -+ -+ test_status("TEST NYI") or die; -+} -+ -+test_main(); -+0; --- -1.8.1.6 - - -From 156c16b81c47700b486056c99cdf8e34cc398578 Mon Sep 17 00:00:00 2001 +From 6080f53cd84a39e1c8245ad0730fb1a3011f0769 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 002/102] Main bcm2708 linux port +Subject: [PATCH 01/88] Main bcm2708 linux port Signed-off-by: popcornmix --- @@ -45223,7 +43,7 @@ Signed-off-by: popcornmix arch/arm/mach-bcm2708/include/mach/vcio.h | 42 + arch/arm/mach-bcm2708/include/mach/vmalloc.h | 20 + arch/arm/mach-bcm2708/power.c | 194 +++ - arch/arm/mach-bcm2708/vc_mem.c | 466 +++++++ + arch/arm/mach-bcm2708/vc_mem.c | 470 +++++++ arch/arm/mach-bcm2708/vcio.c | 308 +++++ arch/arm/mm/Kconfig | 2 +- arch/arm/mm/proc-v6.S | 15 +- @@ -45234,7 +54,7 @@ Signed-off-by: popcornmix drivers/mmc/host/sdhci.c | 209 +++- drivers/mmc/host/sdhci.h | 37 + include/linux/mmc/sdhci.h | 2 + - 49 files changed, 7474 insertions(+), 71 deletions(-) + 49 files changed, 7478 insertions(+), 71 deletions(-) create mode 100644 arch/arm/configs/bcmrpi_cutdown_defconfig create mode 100644 arch/arm/configs/bcmrpi_defconfig create mode 100644 arch/arm/configs/bcmrpi_emergency_defconfig @@ -45275,7 +95,7 @@ Signed-off-by: popcornmix create mode 100644 drivers/mmc/host/sdhci-bcm2708.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 70cd012..448f328 100644 +index 136f263..edae05e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -361,6 +361,21 @@ config ARCH_AT91 @@ -45297,10 +117,10 @@ index 70cd012..448f328 100644 + help + This enables support for Broadcom BCM2708 boards. + - config ARCH_BCM2835 - bool "Broadcom BCM2835 family" + config ARCH_CLPS711X + bool "Cirrus Logic CLPS711x/EP721x/EP731x-based" select ARCH_REQUIRE_GPIOLIB -@@ -1142,6 +1157,7 @@ source "arch/arm/mach-virt/Kconfig" +@@ -1025,6 +1040,7 @@ source "arch/arm/mach-virt/Kconfig" source "arch/arm/mach-vt8500/Kconfig" source "arch/arm/mach-w90x900/Kconfig" @@ -45309,10 +129,10 @@ index 70cd012..448f328 100644 source "arch/arm/mach-zynq/Kconfig" diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 9b31f43..13afe3c 100644 +index 1d41908..52377c9 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug -@@ -483,6 +483,14 @@ choice +@@ -519,6 +519,14 @@ choice For more details about semihosting, please see chapter 8 of DUI0203I_rvct_developer_guide.pdf from ARM Ltd. @@ -45326,9 +146,9 @@ index 9b31f43..13afe3c 100644 + endchoice - config DEBUG_IMX_UART_PORT + config DEBUG_EXYNOS_UART diff --git a/arch/arm/Makefile b/arch/arm/Makefile -index ee4605f..95cc937 100644 +index 1ba358b..fb73cf04 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -139,6 +139,7 @@ textofs-$(CONFIG_ARCH_MSM8960) := 0x00208000 @@ -50584,10 +5404,10 @@ index 0000000..256bf1a +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c new file mode 100644 -index 0000000..67c10ee +index 0000000..fd9d4be --- /dev/null +++ b/arch/arm/mach-bcm2708/vc_mem.c -@@ -0,0 +1,466 @@ +@@ -0,0 +1,470 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +* @@ -50985,6 +5805,7 @@ index 0000000..67c10ee + goto out_class_destroy; + } + ++#if 0 + vc_mem_proc_entry = create_proc_entry(DRIVER_NAME, 0444, NULL); + if (vc_mem_proc_entry == NULL) { + rc = -EFAULT; @@ -50993,6 +5814,7 @@ index 0000000..67c10ee + } + vc_mem_proc_entry->read_proc = vc_mem_proc_read; + vc_mem_proc_entry->write_proc = vc_mem_proc_write; ++#endif + + vc_mem_inited = 1; + return; @@ -51042,7 +5864,9 @@ index 0000000..67c10ee + LOG_DBG("%s: called", __func__); + + if (vc_mem_inited) { ++#if 0 + remove_proc_entry(vc_mem_proc_entry->name, NULL); ++#endif + device_destroy(vc_mem_class, vc_mem_devnum); + class_destroy(vc_mem_class); + cdev_del(&vc_mem_cdev); @@ -51369,7 +6193,7 @@ index 0000000..799a0ac +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bcm-mbox"); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig -index 4045c49..f5cc7bb 100644 +index 35955b5..115f89e 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -358,7 +358,7 @@ config CPU_PJ4B @@ -51382,7 +6206,7 @@ index 4045c49..f5cc7bb 100644 select CPU_ABRT_EV6 select CPU_CACHE_V6 diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S -index 5c07ee4..f7992a5 100644 +index 919405e..ae1cb16 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -73,10 +73,19 @@ ENDPROC(cpu_v6_reset) @@ -51409,22 +6233,22 @@ index 5c07ee4..f7992a5 100644 ENTRY(cpu_v6_dcache_clean_area) diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types -index 831e1fd..bcd2fdb 100644 +index a10297d..c9ddd87 100644 --- a/arch/arm/tools/mach-types +++ b/arch/arm/tools/mach-types -@@ -517,6 +517,7 @@ torbreck MACH_TORBRECK TORBRECK 3090 +@@ -522,6 +522,7 @@ torbreck MACH_TORBRECK TORBRECK 3090 prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103 paz00 MACH_PAZ00 PAZ00 3128 acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129 +bcm2708 MACH_BCM2708 BCM2708 3138 ag5evm MACH_AG5EVM AG5EVM 3189 - tsunagi MACH_TSUNAGI TSUNAGI 3197 ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206 + wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207 diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig -index 9c581c2..92f0790 100644 +index 9ab8f8d..74e7543 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig -@@ -238,6 +238,27 @@ config MMC_SDHCI_S3C_DMA +@@ -249,6 +249,27 @@ config MMC_SDHCI_S3C_DMA YMMV. @@ -51453,12 +6277,12 @@ index 9c581c2..92f0790 100644 tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" depends on ARCH_BCM2835 diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile -index c380e3c..497b3a5 100644 +index cd32280..6a7b985 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile -@@ -14,6 +14,7 @@ obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o - obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o +@@ -15,6 +15,7 @@ obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o + obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o +obj-$(CONFIG_MMC_SDHCI_BCM2708) += sdhci-bcm2708.o obj-$(CONFIG_MMC_WBSD) += wbsd.o @@ -52896,7 +7720,7 @@ index 0000000..e79723d +MODULE_ALIAS("platform:"DRIVER_NAME); + diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index 51bbba4..71e2696 100644 +index 2ea429c..179e83e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -28,6 +28,7 @@ @@ -53137,7 +7961,7 @@ index 51bbba4..71e2696 100644 u16 clk, ctrl_2; /* In case of UHS-I modes, set High Speed Enable */ -@@ -2132,7 +2146,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2164,7 +2178,7 @@ static void sdhci_timeout_timer(unsigned long data) if (host->mrq) { pr_err("%s: Timeout waiting for hardware " @@ -53146,7 +7970,7 @@ index 51bbba4..71e2696 100644 sdhci_dumpregs(host); if (host->data) { -@@ -2177,10 +2191,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) +@@ -2209,10 +2223,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) BUG_ON(intmask == 0); if (!host->cmd) { @@ -53160,7 +7984,7 @@ index 51bbba4..71e2696 100644 return; } -@@ -2250,6 +2267,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) +@@ -2282,6 +2299,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) static void sdhci_show_adma_error(struct sdhci_host *host) { } #endif @@ -53180,7 +8004,7 @@ index 51bbba4..71e2696 100644 static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) { u32 command; -@@ -2279,23 +2309,39 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2311,23 +2341,39 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) } } @@ -53224,7 +8048,7 @@ index 51bbba4..71e2696 100644 pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); sdhci_show_adma_error(host); host->data->error = -EIO; -@@ -2303,11 +2349,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2335,11 +2381,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) host->ops->adma_workaround(host, intmask); } @@ -53247,7 +8071,7 @@ index 51bbba4..71e2696 100644 /* * We currently don't do anything fancy with DMA -@@ -2336,18 +2389,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) +@@ -2368,18 +2421,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); } @@ -53268,7 +8092,7 @@ index 51bbba4..71e2696 100644 } } -@@ -2403,6 +2446,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2435,6 +2478,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) tasklet_schedule(&host->card_tasklet); } @@ -53291,7 +8115,7 @@ index 51bbba4..71e2696 100644 if (intmask & SDHCI_INT_CMD_MASK) { sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS); -@@ -2417,7 +2476,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2449,7 +2508,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); @@ -53306,7 +8130,7 @@ index 51bbba4..71e2696 100644 if (intmask & SDHCI_INT_BUS_POWER) { pr_err("%s: Card is consuming too much power!\n", -@@ -2537,7 +2602,8 @@ int sdhci_resume_host(struct sdhci_host *host) +@@ -2569,7 +2634,8 @@ int sdhci_resume_host(struct sdhci_host *host) { int ret; @@ -53316,7 +8140,7 @@ index 51bbba4..71e2696 100644 if (host->ops->enable_dma) host->ops->enable_dma(host); } -@@ -2753,14 +2819,16 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -2785,14 +2851,16 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; } @@ -53335,7 +8159,7 @@ index 51bbba4..71e2696 100644 } } } -@@ -3043,6 +3111,12 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -3080,6 +3148,12 @@ int sdhci_add_host(struct sdhci_host *host) SDHCI_MAX_CURRENT_MULTIPLIER; } @@ -53348,7 +8172,7 @@ index 51bbba4..71e2696 100644 mmc->ocr_avail = ocr_avail; mmc->ocr_avail_sdio = ocr_avail; if (host->ocr_avail_sdio) -@@ -3173,6 +3247,7 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -3210,6 +3284,7 @@ int sdhci_add_host(struct sdhci_host *host) pr_info("%s: SDHCI controller on %s [%s] using %s\n", mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), @@ -53435,10 +8259,57092 @@ index b838ffc..f3a39c1 100644 1.8.1.6 -From 5d42fc9149ad65168f95eb522c7913a0170d2118 Mon Sep 17 00:00:00 2001 +From 17f5dfb674bf0a817f8f3075d4d16ea0da3e2451 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 1 May 2013 19:46:17 +0100 +Subject: [PATCH 02/88] Add dwc_otg driver + +Signed-off-by: popcornmix +--- + drivers/usb/Makefile | 1 + + drivers/usb/core/generic.c | 1 + + drivers/usb/core/message.c | 79 + + drivers/usb/core/otg_whitelist.h | 172 +- + drivers/usb/gadget/file_storage.c | 3676 ++++++++++ + drivers/usb/host/Kconfig | 13 + + drivers/usb/host/Makefile | 2 + + drivers/usb/host/dwc_common_port/Makefile | 58 + + drivers/usb/host/dwc_common_port/Makefile.fbsd | 17 + + drivers/usb/host/dwc_common_port/Makefile.linux | 49 + + drivers/usb/host/dwc_common_port/changes.txt | 174 + + drivers/usb/host/dwc_common_port/doc/doxygen.cfg | 270 + + drivers/usb/host/dwc_common_port/dwc_cc.c | 532 ++ + drivers/usb/host/dwc_common_port/dwc_cc.h | 225 + + drivers/usb/host/dwc_common_port/dwc_common_fbsd.c | 1308 ++++ + .../usb/host/dwc_common_port/dwc_common_linux.c | 1421 ++++ + drivers/usb/host/dwc_common_port/dwc_common_nbsd.c | 1275 ++++ + drivers/usb/host/dwc_common_port/dwc_crypto.c | 308 + + drivers/usb/host/dwc_common_port/dwc_crypto.h | 111 + + drivers/usb/host/dwc_common_port/dwc_dh.c | 291 + + drivers/usb/host/dwc_common_port/dwc_dh.h | 106 + + drivers/usb/host/dwc_common_port/dwc_list.h | 594 ++ + drivers/usb/host/dwc_common_port/dwc_mem.c | 245 + + drivers/usb/host/dwc_common_port/dwc_modpow.c | 636 ++ + drivers/usb/host/dwc_common_port/dwc_modpow.h | 34 + + drivers/usb/host/dwc_common_port/dwc_notifier.c | 319 + + drivers/usb/host/dwc_common_port/dwc_notifier.h | 122 + + drivers/usb/host/dwc_common_port/dwc_os.h | 1260 ++++ + drivers/usb/host/dwc_common_port/usb.h | 946 +++ + drivers/usb/host/dwc_otg/Makefile | 80 + + drivers/usb/host/dwc_otg/doc/doxygen.cfg | 224 + + drivers/usb/host/dwc_otg/dummy_audio.c | 1575 +++++ + drivers/usb/host/dwc_otg/dwc_cfi_common.h | 142 + + drivers/usb/host/dwc_otg/dwc_otg_adp.c | 854 +++ + drivers/usb/host/dwc_otg/dwc_otg_adp.h | 80 + + drivers/usb/host/dwc_otg/dwc_otg_attr.c | 1210 ++++ + drivers/usb/host/dwc_otg/dwc_otg_attr.h | 89 + + drivers/usb/host/dwc_otg/dwc_otg_cfi.c | 1876 +++++ + drivers/usb/host/dwc_otg/dwc_otg_cfi.h | 320 + + drivers/usb/host/dwc_otg/dwc_otg_cil.c | 7151 ++++++++++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_cil.h | 1464 ++++ + drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 1563 +++++ + drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 705 ++ + drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 116 + + drivers/usb/host/dwc_otg/dwc_otg_driver.c | 1700 +++++ + drivers/usb/host/dwc_otg/dwc_otg_driver.h | 86 + + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 3473 ++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 824 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 1133 ++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 412 ++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2106 ++++++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 893 +++ + drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 922 +++ + drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 185 + + drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 2708 ++++++++ + drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 266 + + drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 360 + + drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 5147 ++++++++++++++ + drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 1358 ++++ + drivers/usb/host/dwc_otg/dwc_otg_regs.h | 2550 +++++++ + drivers/usb/host/dwc_otg/test/Makefile | 16 + + drivers/usb/host/dwc_otg/test/dwc_otg_test.pm | 337 + + drivers/usb/host/dwc_otg/test/test_mod_param.pl | 133 + + drivers/usb/host/dwc_otg/test/test_sysfs.pl | 193 + + 64 files changed, 56447 insertions(+), 49 deletions(-) + create mode 100644 drivers/usb/gadget/file_storage.c + create mode 100644 drivers/usb/host/dwc_common_port/Makefile + create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd + create mode 100644 drivers/usb/host/dwc_common_port/Makefile.linux + create mode 100644 drivers/usb/host/dwc_common_port/changes.txt + create mode 100644 drivers/usb/host/dwc_common_port/doc/doxygen.cfg + create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_cc.h + create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_fbsd.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_linux.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_nbsd.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.h + create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.h + create mode 100644 drivers/usb/host/dwc_common_port/dwc_list.h + create mode 100644 drivers/usb/host/dwc_common_port/dwc_mem.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.h + create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.c + create mode 100644 drivers/usb/host/dwc_common_port/dwc_notifier.h + create mode 100644 drivers/usb/host/dwc_common_port/dwc_os.h + create mode 100644 drivers/usb/host/dwc_common_port/usb.h + create mode 100644 drivers/usb/host/dwc_otg/Makefile + create mode 100644 drivers/usb/host/dwc_otg/doc/doxygen.cfg + create mode 100644 drivers/usb/host/dwc_otg/dummy_audio.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_cfi_common.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_attr.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cfi.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_core_if.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_dbg.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_driver.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c + create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_regs.h + create mode 100644 drivers/usb/host/dwc_otg/test/Makefile + create mode 100644 drivers/usb/host/dwc_otg/test/dwc_otg_test.pm + create mode 100644 drivers/usb/host/dwc_otg/test/test_mod_param.pl + create mode 100644 drivers/usb/host/dwc_otg/test/test_sysfs.pl + +diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile +index c41feba..0b5c606 100644 +--- a/drivers/usb/Makefile ++++ b/drivers/usb/Makefile +@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_U132_HCD) += host/ + obj-$(CONFIG_USB_R8A66597_HCD) += host/ + obj-$(CONFIG_USB_HWA_HCD) += host/ + obj-$(CONFIG_USB_ISP1760_HCD) += host/ ++obj-$(CONFIG_USB_DWCOTG) += host/ + obj-$(CONFIG_USB_IMX21_HCD) += host/ + obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ + +diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c +index acbfeb0..7d675c8 100644 +--- a/drivers/usb/core/generic.c ++++ b/drivers/usb/core/generic.c +@@ -152,6 +152,7 @@ int usb_choose_configuration(struct usb_device *udev) + dev_warn(&udev->dev, + "no configuration chosen from %d choice%s\n", + num_configs, plural(num_configs)); ++ dev_warn(&udev->dev, "No support over %dmA\n", udev->bus_mA); + } + return i; + } +diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c +index 444d30e..3ff77fa 100644 +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -1875,6 +1875,85 @@ int usb_set_configuration(struct usb_device *dev, int configuration) + if (cp->string == NULL && + !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) + cp->string = usb_cache_string(dev, cp->desc.iConfiguration); ++/* Uncomment this define to enable the HS Electrical Test support */ ++#define DWC_HS_ELECT_TST 1 ++#ifdef DWC_HS_ELECT_TST ++ /* Here we implement the HS Electrical Test support. The ++ * tester uses a vendor ID of 0x1A0A to indicate we should ++ * run a special test sequence. The product ID tells us ++ * which sequence to run. We invoke the test sequence by ++ * sending a non-standard SetFeature command to our root ++ * hub port. Our dwc_otg_hcd_hub_control() routine will ++ * recognize the command and perform the desired test ++ * sequence. ++ */ ++ if (dev->descriptor.idVendor == 0x1A0A) { ++ /* HSOTG Electrical Test */ ++ dev_warn(&dev->dev, "VID from HSOTG Electrical Test Fixture\n"); ++ ++ if (dev->bus && dev->bus->root_hub) { ++ struct usb_device *hdev = dev->bus->root_hub; ++ dev_warn(&dev->dev, "Got PID 0x%x\n", dev->descriptor.idProduct); ++ ++ switch (dev->descriptor.idProduct) { ++ case 0x0101: /* TEST_SE0_NAK */ ++ dev_warn(&dev->dev, "TEST_SE0_NAK\n"); ++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ USB_REQ_SET_FEATURE, USB_RT_PORT, ++ USB_PORT_FEAT_TEST, 0x300, NULL, 0, HZ); ++ break; ++ ++ case 0x0102: /* TEST_J */ ++ dev_warn(&dev->dev, "TEST_J\n"); ++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ USB_REQ_SET_FEATURE, USB_RT_PORT, ++ USB_PORT_FEAT_TEST, 0x100, NULL, 0, HZ); ++ break; ++ ++ case 0x0103: /* TEST_K */ ++ dev_warn(&dev->dev, "TEST_K\n"); ++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ USB_REQ_SET_FEATURE, USB_RT_PORT, ++ USB_PORT_FEAT_TEST, 0x200, NULL, 0, HZ); ++ break; ++ ++ case 0x0104: /* TEST_PACKET */ ++ dev_warn(&dev->dev, "TEST_PACKET\n"); ++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ USB_REQ_SET_FEATURE, USB_RT_PORT, ++ USB_PORT_FEAT_TEST, 0x400, NULL, 0, HZ); ++ break; ++ ++ case 0x0105: /* TEST_FORCE_ENABLE */ ++ dev_warn(&dev->dev, "TEST_FORCE_ENABLE\n"); ++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ USB_REQ_SET_FEATURE, USB_RT_PORT, ++ USB_PORT_FEAT_TEST, 0x500, NULL, 0, HZ); ++ break; ++ ++ case 0x0106: /* HS_HOST_PORT_SUSPEND_RESUME */ ++ dev_warn(&dev->dev, "HS_HOST_PORT_SUSPEND_RESUME\n"); ++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ USB_REQ_SET_FEATURE, USB_RT_PORT, ++ USB_PORT_FEAT_TEST, 0x600, NULL, 0, 40 * HZ); ++ break; ++ ++ case 0x0107: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ ++ dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup\n"); ++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ USB_REQ_SET_FEATURE, USB_RT_PORT, ++ USB_PORT_FEAT_TEST, 0x700, NULL, 0, 40 * HZ); ++ break; ++ ++ case 0x0108: /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ ++ dev_warn(&dev->dev, "SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute\n"); ++ usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), ++ USB_REQ_SET_FEATURE, USB_RT_PORT, ++ USB_PORT_FEAT_TEST, 0x800, NULL, 0, 40 * HZ); ++ } ++ } ++ } ++#endif /* DWC_HS_ELECT_TST */ + + /* Now that the interfaces are installed, re-enable LPM. */ + usb_unlocked_enable_lpm(dev); +diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h +index e8cdce5..3a0da17 100644 +--- a/drivers/usb/core/otg_whitelist.h ++++ b/drivers/usb/core/otg_whitelist.h +@@ -19,33 +19,82 @@ + static struct usb_device_id whitelist_table [] = { + + /* hubs are optional in OTG, but very handy ... */ ++#define CERT_WITHOUT_HUBS ++#if defined(CERT_WITHOUT_HUBS) ++{ USB_DEVICE( 0x0000, 0x0000 ), }, /* Root HUB Only*/ ++#else + { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), }, + { USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), }, ++{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 2), }, ++#endif + + #ifdef CONFIG_USB_PRINTER /* ignoring nonstatic linkage! */ + /* FIXME actually, printers are NOT supposed to use device classes; + * they're supposed to use interface classes... + */ +-{ USB_DEVICE_INFO(7, 1, 1) }, +-{ USB_DEVICE_INFO(7, 1, 2) }, +-{ USB_DEVICE_INFO(7, 1, 3) }, ++//{ USB_DEVICE_INFO(7, 1, 1) }, ++//{ USB_DEVICE_INFO(7, 1, 2) }, ++//{ USB_DEVICE_INFO(7, 1, 3) }, + #endif + + #ifdef CONFIG_USB_NET_CDCETHER + /* Linux-USB CDC Ethernet gadget */ +-{ USB_DEVICE(0x0525, 0xa4a1), }, ++//{ USB_DEVICE(0x0525, 0xa4a1), }, + /* Linux-USB CDC Ethernet + RNDIS gadget */ +-{ USB_DEVICE(0x0525, 0xa4a2), }, ++//{ USB_DEVICE(0x0525, 0xa4a2), }, + #endif + + #if defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE) + /* gadget zero, for testing */ +-{ USB_DEVICE(0x0525, 0xa4a0), }, ++//{ USB_DEVICE(0x0525, 0xa4a0), }, + #endif ++ ++/* OPT Tester */ ++{ USB_DEVICE( 0x1a0a, 0x0101 ), }, /* TEST_SE0_NAK */ ++{ USB_DEVICE( 0x1a0a, 0x0102 ), }, /* Test_J */ ++{ USB_DEVICE( 0x1a0a, 0x0103 ), }, /* Test_K */ ++{ USB_DEVICE( 0x1a0a, 0x0104 ), }, /* Test_PACKET */ ++{ USB_DEVICE( 0x1a0a, 0x0105 ), }, /* Test_FORCE_ENABLE */ ++{ USB_DEVICE( 0x1a0a, 0x0106 ), }, /* HS_PORT_SUSPEND_RESUME */ ++{ USB_DEVICE( 0x1a0a, 0x0107 ), }, /* SINGLE_STEP_GET_DESCRIPTOR setup */ ++{ USB_DEVICE( 0x1a0a, 0x0108 ), }, /* SINGLE_STEP_GET_DESCRIPTOR execute */ ++ ++/* Sony cameras */ ++{ USB_DEVICE_VER(0x054c,0x0010,0x0410, 0x0500), }, ++ ++/* Memory Devices */ ++//{ USB_DEVICE( 0x0781, 0x5150 ), }, /* SanDisk */ ++//{ USB_DEVICE( 0x05DC, 0x0080 ), }, /* Lexar */ ++//{ USB_DEVICE( 0x4146, 0x9281 ), }, /* IOMEGA */ ++//{ USB_DEVICE( 0x067b, 0x2507 ), }, /* Hammer 20GB External HD */ ++{ USB_DEVICE( 0x0EA0, 0x2168 ), }, /* Ours Technology Inc. (BUFFALO ClipDrive)*/ ++//{ USB_DEVICE( 0x0457, 0x0150 ), }, /* Silicon Integrated Systems Corp. */ ++ ++/* HP Printers */ ++//{ USB_DEVICE( 0x03F0, 0x1102 ), }, /* HP Photosmart 245 */ ++//{ USB_DEVICE( 0x03F0, 0x1302 ), }, /* HP Photosmart 370 Series */ ++ ++/* Speakers */ ++//{ USB_DEVICE( 0x0499, 0x3002 ), }, /* YAMAHA YST-MS35D USB Speakers */ ++//{ USB_DEVICE( 0x0672, 0x1041 ), }, /* Labtec USB Headset */ + + { } /* Terminating entry */ + }; + ++static inline void report_errors(struct usb_device *dev) ++{ ++ /* OTG MESSAGE: report errors here, customize to match your product */ ++ dev_info(&dev->dev, "device Vendor:%04x Product:%04x is not supported\n", ++ le16_to_cpu(dev->descriptor.idVendor), ++ le16_to_cpu(dev->descriptor.idProduct)); ++ if (USB_CLASS_HUB == dev->descriptor.bDeviceClass){ ++ dev_printk(KERN_CRIT, &dev->dev, "Unsupported Hub Topology\n"); ++ } else { ++ dev_printk(KERN_CRIT, &dev->dev, "Attached Device is not Supported\n"); ++ } ++} ++ ++ + static int is_targeted(struct usb_device *dev) + { + struct usb_device_id *id = whitelist_table; +@@ -55,58 +104,83 @@ static int is_targeted(struct usb_device *dev) + return 1; + + /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */ +- if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a && +- le16_to_cpu(dev->descriptor.idProduct) == 0xbadd)) +- return 0; +- +- /* NOTE: can't use usb_match_id() since interface caches +- * aren't set up yet. this is cut/paste from that code. +- */ +- for (id = whitelist_table; id->match_flags; id++) { +- if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && +- id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && +- id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) +- continue; +- +- /* No need to test id->bcdDevice_lo != 0, since 0 is never +- greater than any unsigned number. */ +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && +- (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && +- (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && +- (id->bDeviceClass != dev->descriptor.bDeviceClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && +- (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass)) +- continue; +- +- if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && +- (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) +- continue; ++ if (dev->descriptor.idVendor == 0x1a0a && ++ dev->descriptor.idProduct == 0xbadd) { ++ return 0; ++ } else if (!enable_whitelist) { ++ return 1; ++ } else { ++ ++#ifdef DEBUG ++ dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n", ++ dev->descriptor.idVendor, ++ dev->descriptor.idProduct, ++ dev->descriptor.bDeviceClass, ++ dev->descriptor.bDeviceSubClass, ++ dev->descriptor.bDeviceProtocol); ++#endif + + return 1; ++ /* NOTE: can't use usb_match_id() since interface caches ++ * aren't set up yet. this is cut/paste from that code. ++ */ ++ for (id = whitelist_table; id->match_flags; id++) { ++#ifdef DEBUG ++ dev_dbg(&dev->dev, ++ "ID: V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n", ++ id->idVendor, ++ id->idProduct, ++ id->bDeviceClass, ++ id->bDeviceSubClass, ++ id->bDeviceProtocol); ++#endif ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && ++ id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && ++ id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) ++ continue; ++ ++ /* No need to test id->bcdDevice_lo != 0, since 0 is never ++ greater than any unsigned number. */ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) && ++ (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice))) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) && ++ (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice))) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) && ++ (id->bDeviceClass != dev->descriptor.bDeviceClass)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) && ++ (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass)) ++ continue; ++ ++ if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && ++ (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) ++ continue; ++ ++ return 1; ++ } + } + + /* add other match criteria here ... */ + +- +- /* OTG MESSAGE: report errors here, customize to match your product */ +- dev_err(&dev->dev, "device v%04x p%04x is not supported\n", +- le16_to_cpu(dev->descriptor.idVendor), +- le16_to_cpu(dev->descriptor.idProduct)); + #ifdef CONFIG_USB_OTG_WHITELIST ++ report_errors(dev); + return 0; + #else +- return 1; ++ if (enable_whitelist) { ++ report_errors(dev); ++ return 0; ++ } else { ++ return 1; ++ } + #endif + } + +diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c +new file mode 100644 +index 0000000..a896d73 +--- /dev/null ++++ b/drivers/usb/gadget/file_storage.c +@@ -0,0 +1,3676 @@ ++/* ++ * file_storage.c -- File-backed USB Storage Gadget, for USB development ++ * ++ * Copyright (C) 2003-2008 Alan Stern ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions, and the following disclaimer, ++ * without modification. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The names of the above-listed copyright holders may not be used ++ * to endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS ++ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR ++ * CONTRIBUTORS 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. ++ */ ++ ++ ++/* ++ * The File-backed Storage Gadget acts as a USB Mass Storage device, ++ * appearing to the host as a disk drive or as a CD-ROM drive. In addition ++ * to providing an example of a genuinely useful gadget driver for a USB ++ * device, it also illustrates a technique of double-buffering for increased ++ * throughput. Last but not least, it gives an easy way to probe the ++ * behavior of the Mass Storage drivers in a USB host. ++ * ++ * Backing storage is provided by a regular file or a block device, specified ++ * by the "file" module parameter. Access can be limited to read-only by ++ * setting the optional "ro" module parameter. (For CD-ROM emulation, ++ * access is always read-only.) The gadget will indicate that it has ++ * removable media if the optional "removable" module parameter is set. ++ * ++ * The gadget supports the Control-Bulk (CB), Control-Bulk-Interrupt (CBI), ++ * and Bulk-Only (also known as Bulk-Bulk-Bulk or BBB) transports, selected ++ * by the optional "transport" module parameter. It also supports the ++ * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), ++ * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by ++ * the optional "protocol" module parameter. In addition, the default ++ * Vendor ID, Product ID, release number and serial number can be overridden. ++ * ++ * There is support for multiple logical units (LUNs), each of which has ++ * its own backing file. The number of LUNs can be set using the optional ++ * "luns" module parameter (anywhere from 1 to 8), and the corresponding ++ * files are specified using comma-separated lists for "file" and "ro". ++ * The default number of LUNs is taken from the number of "file" elements; ++ * it is 1 if "file" is not given. If "removable" is not set then a backing ++ * file must be specified for each LUN. If it is set, then an unspecified ++ * or empty backing filename means the LUN's medium is not loaded. Ideally ++ * each LUN would be settable independently as a disk drive or a CD-ROM ++ * drive, but currently all LUNs have to be the same type. The CD-ROM ++ * emulation includes a single data track and no audio tracks; hence there ++ * need be only one backing file per LUN. ++ * ++ * Requirements are modest; only a bulk-in and a bulk-out endpoint are ++ * needed (an interrupt-out endpoint is also needed for CBI). The memory ++ * requirement amounts to two 16K buffers, size configurable by a parameter. ++ * Support is included for both full-speed and high-speed operation. ++ * ++ * Note that the driver is slightly non-portable in that it assumes a ++ * single memory/DMA buffer will be useable for bulk-in, bulk-out, and ++ * interrupt-in endpoints. With most device controllers this isn't an ++ * issue, but there may be some with hardware restrictions that prevent ++ * a buffer from being used by more than one endpoint. ++ * ++ * Module options: ++ * ++ * file=filename[,filename...] ++ * Required if "removable" is not set, names of ++ * the files or block devices used for ++ * backing storage ++ * serial=HHHH... Required serial number (string of hex chars) ++ * ro=b[,b...] Default false, booleans for read-only access ++ * removable Default false, boolean for removable media ++ * luns=N Default N = number of filenames, number of ++ * LUNs to support ++ * nofua=b[,b...] Default false, booleans for ignore FUA flag ++ * in SCSI WRITE(10,12) commands ++ * stall Default determined according to the type of ++ * USB device controller (usually true), ++ * boolean to permit the driver to halt ++ * bulk endpoints ++ * cdrom Default false, boolean for whether to emulate ++ * a CD-ROM drive ++ * transport=XXX Default BBB, transport name (CB, CBI, or BBB) ++ * protocol=YYY Default SCSI, protocol name (RBC, 8020 or ++ * ATAPI, QIC, UFI, 8070, or SCSI; ++ * also 1 - 6) ++ * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID ++ * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID ++ * release=0xRRRR Override the USB release number (bcdDevice) ++ * buflen=N Default N=16384, buffer size used (will be ++ * rounded down to a multiple of ++ * PAGE_CACHE_SIZE) ++ * ++ * If CONFIG_USB_FILE_STORAGE_TEST is not set, only the "file", "serial", "ro", ++ * "removable", "luns", "nofua", "stall", and "cdrom" options are available; ++ * default values are used for everything else. ++ * ++ * The pathnames of the backing files and the ro settings are available in ++ * the attribute files "file", "nofua", and "ro" in the lun subdirectory of ++ * the gadget's sysfs directory. If the "removable" option is set, writing to ++ * these files will simulate ejecting/loading the medium (writing an empty ++ * line means eject) and adjusting a write-enable tab. Changes to the ro ++ * setting are not allowed when the medium is loaded or if CD-ROM emulation ++ * is being used. ++ * ++ * This gadget driver is heavily based on "Gadget Zero" by David Brownell. ++ * The driver's SCSI command interface was based on the "Information ++ * technology - Small Computer System Interface - 2" document from ++ * X3T9.2 Project 375D, Revision 10L, 7-SEP-93, available at ++ * . The single exception ++ * is opcode 0x23 (READ FORMAT CAPACITIES), which was based on the ++ * "Universal Serial Bus Mass Storage Class UFI Command Specification" ++ * document, Revision 1.0, December 14, 1998, available at ++ * . ++ */ ++ ++ ++/* ++ * Driver Design ++ * ++ * The FSG driver is fairly straightforward. There is a main kernel ++ * thread that handles most of the work. Interrupt routines field ++ * callbacks from the controller driver: bulk- and interrupt-request ++ * completion notifications, endpoint-0 events, and disconnect events. ++ * Completion events are passed to the main thread by wakeup calls. Many ++ * ep0 requests are handled at interrupt time, but SetInterface, ++ * SetConfiguration, and device reset requests are forwarded to the ++ * thread in the form of "exceptions" using SIGUSR1 signals (since they ++ * should interrupt any ongoing file I/O operations). ++ * ++ * The thread's main routine implements the standard command/data/status ++ * parts of a SCSI interaction. It and its subroutines are full of tests ++ * for pending signals/exceptions -- all this polling is necessary since ++ * the kernel has no setjmp/longjmp equivalents. (Maybe this is an ++ * indication that the driver really wants to be running in userspace.) ++ * An important point is that so long as the thread is alive it keeps an ++ * open reference to the backing file. This will prevent unmounting ++ * the backing file's underlying filesystem and could cause problems ++ * during system shutdown, for example. To prevent such problems, the ++ * thread catches INT, TERM, and KILL signals and converts them into ++ * an EXIT exception. ++ * ++ * In normal operation the main thread is started during the gadget's ++ * fsg_bind() callback and stopped during fsg_unbind(). But it can also ++ * exit when it receives a signal, and there's no point leaving the ++ * gadget running when the thread is dead. So just before the thread ++ * exits, it deregisters the gadget driver. This makes things a little ++ * tricky: The driver is deregistered at two places, and the exiting ++ * thread can indirectly call fsg_unbind() which in turn can tell the ++ * thread to exit. The first problem is resolved through the use of the ++ * REGISTERED atomic bitflag; the driver will only be deregistered once. ++ * The second problem is resolved by having fsg_unbind() check ++ * fsg->state; it won't try to stop the thread if the state is already ++ * FSG_STATE_TERMINATED. ++ * ++ * To provide maximum throughput, the driver uses a circular pipeline of ++ * buffer heads (struct fsg_buffhd). In principle the pipeline can be ++ * arbitrarily long; in practice the benefits don't justify having more ++ * than 2 stages (i.e., double buffering). But it helps to think of the ++ * pipeline as being a long one. Each buffer head contains a bulk-in and ++ * a bulk-out request pointer (since the buffer can be used for both ++ * output and input -- directions always are given from the host's ++ * point of view) as well as a pointer to the buffer and various state ++ * variables. ++ * ++ * Use of the pipeline follows a simple protocol. There is a variable ++ * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. ++ * At any time that buffer head may still be in use from an earlier ++ * request, so each buffer head has a state variable indicating whether ++ * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the ++ * buffer head to be EMPTY, filling the buffer either by file I/O or by ++ * USB I/O (during which the buffer head is BUSY), and marking the buffer ++ * head FULL when the I/O is complete. Then the buffer will be emptied ++ * (again possibly by USB I/O, during which it is marked BUSY) and ++ * finally marked EMPTY again (possibly by a completion routine). ++ * ++ * A module parameter tells the driver to avoid stalling the bulk ++ * endpoints wherever the transport specification allows. This is ++ * necessary for some UDCs like the SuperH, which cannot reliably clear a ++ * halt on a bulk endpoint. However, under certain circumstances the ++ * Bulk-only specification requires a stall. In such cases the driver ++ * will halt the endpoint and set a flag indicating that it should clear ++ * the halt in software during the next device reset. Hopefully this ++ * will permit everything to work correctly. Furthermore, although the ++ * specification allows the bulk-out endpoint to halt when the host sends ++ * too much data, implementing this would cause an unavoidable race. ++ * The driver will always use the "no-stall" approach for OUT transfers. ++ * ++ * One subtle point concerns sending status-stage responses for ep0 ++ * requests. Some of these requests, such as device reset, can involve ++ * interrupting an ongoing file I/O operation, which might take an ++ * arbitrarily long time. During that delay the host might give up on ++ * the original ep0 request and issue a new one. When that happens the ++ * driver should not notify the host about completion of the original ++ * request, as the host will no longer be waiting for it. So the driver ++ * assigns to each ep0 request a unique tag, and it keeps track of the ++ * tag value of the request associated with a long-running exception ++ * (device-reset, interface-change, or configuration-change). When the ++ * exception handler is finished, the status-stage response is submitted ++ * only if the current ep0 request tag is equal to the exception request ++ * tag. Thus only the most recently received ep0 request will get a ++ * status-stage response. ++ * ++ * Warning: This driver source file is too long. It ought to be split up ++ * into a header file plus about 3 separate .c files, to handle the details ++ * of the Gadget, USB Mass Storage, and SCSI protocols. ++ */ ++ ++ ++/* #define VERBOSE_DEBUG */ ++/* #define DUMP_MSGS */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "gadget_chips.h" ++ ++ ++ ++/* ++ * Kbuild is not very cooperative with respect to linking separately ++ * compiled library objects into one module. So for now we won't use ++ * separate compilation ... ensuring init/exit sections work to shrink ++ * the runtime footprint, and giving us at least some parts of what ++ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. ++ */ ++#include "usbstring.c" ++#include "config.c" ++#include "epautoconf.c" ++ ++/*-------------------------------------------------------------------------*/ ++ ++#define DRIVER_DESC "File-backed Storage Gadget" ++#define DRIVER_NAME "g_file_storage" ++#define DRIVER_VERSION "1 September 2010" ++ ++static char fsg_string_manufacturer[64]; ++static const char fsg_string_product[] = DRIVER_DESC; ++static const char fsg_string_config[] = "Self-powered"; ++static const char fsg_string_interface[] = "Mass Storage"; ++ ++ ++#include "storage_common.c" ++ ++ ++MODULE_DESCRIPTION(DRIVER_DESC); ++MODULE_AUTHOR("Alan Stern"); ++MODULE_LICENSE("Dual BSD/GPL"); ++ ++/* ++ * This driver assumes self-powered hardware and has no way for users to ++ * trigger remote wakeup. It uses autoconfiguration to select endpoints ++ * and endpoint addresses. ++ */ ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++ ++/* Encapsulate the module parameter settings */ ++ ++static struct { ++ char *file[FSG_MAX_LUNS]; ++ char *serial; ++ bool ro[FSG_MAX_LUNS]; ++ bool nofua[FSG_MAX_LUNS]; ++ unsigned int num_filenames; ++ unsigned int num_ros; ++ unsigned int num_nofuas; ++ unsigned int nluns; ++ ++ bool removable; ++ bool can_stall; ++ bool cdrom; ++ ++ char *transport_parm; ++ char *protocol_parm; ++ unsigned short vendor; ++ unsigned short product; ++ unsigned short release; ++ unsigned int buflen; ++ ++ int transport_type; ++ char *transport_name; ++ int protocol_type; ++ char *protocol_name; ++ ++} mod_data = { // Default values ++ .transport_parm = "BBB", ++ .protocol_parm = "SCSI", ++ .removable = 0, ++ .can_stall = 1, ++ .cdrom = 0, ++ .vendor = FSG_VENDOR_ID, ++ .product = FSG_PRODUCT_ID, ++ .release = 0xffff, // Use controller chip type ++ .buflen = 16384, ++ }; ++ ++ ++module_param_array_named(file, mod_data.file, charp, &mod_data.num_filenames, ++ S_IRUGO); ++MODULE_PARM_DESC(file, "names of backing files or devices"); ++ ++module_param_named(serial, mod_data.serial, charp, S_IRUGO); ++MODULE_PARM_DESC(serial, "USB serial number"); ++ ++module_param_array_named(ro, mod_data.ro, bool, &mod_data.num_ros, S_IRUGO); ++MODULE_PARM_DESC(ro, "true to force read-only"); ++ ++module_param_array_named(nofua, mod_data.nofua, bool, &mod_data.num_nofuas, ++ S_IRUGO); ++MODULE_PARM_DESC(nofua, "true to ignore SCSI WRITE(10,12) FUA bit"); ++ ++module_param_named(luns, mod_data.nluns, uint, S_IRUGO); ++MODULE_PARM_DESC(luns, "number of LUNs"); ++ ++module_param_named(removable, mod_data.removable, bool, S_IRUGO); ++MODULE_PARM_DESC(removable, "true to simulate removable media"); ++ ++module_param_named(stall, mod_data.can_stall, bool, S_IRUGO); ++MODULE_PARM_DESC(stall, "false to prevent bulk stalls"); ++ ++module_param_named(cdrom, mod_data.cdrom, bool, S_IRUGO); ++MODULE_PARM_DESC(cdrom, "true to emulate cdrom instead of disk"); ++ ++/* In the non-TEST version, only the module parameters listed above ++ * are available. */ ++#ifdef CONFIG_USB_FILE_STORAGE_TEST ++ ++module_param_named(transport, mod_data.transport_parm, charp, S_IRUGO); ++MODULE_PARM_DESC(transport, "type of transport (BBB, CBI, or CB)"); ++ ++module_param_named(protocol, mod_data.protocol_parm, charp, S_IRUGO); ++MODULE_PARM_DESC(protocol, "type of protocol (RBC, 8020, QIC, UFI, " ++ "8070, or SCSI)"); ++ ++module_param_named(vendor, mod_data.vendor, ushort, S_IRUGO); ++MODULE_PARM_DESC(vendor, "USB Vendor ID"); ++ ++module_param_named(product, mod_data.product, ushort, S_IRUGO); ++MODULE_PARM_DESC(product, "USB Product ID"); ++ ++module_param_named(release, mod_data.release, ushort, S_IRUGO); ++MODULE_PARM_DESC(release, "USB release number"); ++ ++module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); ++MODULE_PARM_DESC(buflen, "I/O buffer size"); ++ ++#endif /* CONFIG_USB_FILE_STORAGE_TEST */ ++ ++ ++/* ++ * These definitions will permit the compiler to avoid generating code for ++ * parts of the driver that aren't used in the non-TEST version. Even gcc ++ * can recognize when a test of a constant expression yields a dead code ++ * path. ++ */ ++ ++#ifdef CONFIG_USB_FILE_STORAGE_TEST ++ ++#define transport_is_bbb() (mod_data.transport_type == USB_PR_BULK) ++#define transport_is_cbi() (mod_data.transport_type == USB_PR_CBI) ++#define protocol_is_scsi() (mod_data.protocol_type == USB_SC_SCSI) ++ ++#else ++ ++#define transport_is_bbb() 1 ++#define transport_is_cbi() 0 ++#define protocol_is_scsi() 1 ++ ++#endif /* CONFIG_USB_FILE_STORAGE_TEST */ ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++ ++struct fsg_dev { ++ /* lock protects: state, all the req_busy's, and cbbuf_cmnd */ ++ spinlock_t lock; ++ struct usb_gadget *gadget; ++ ++ /* filesem protects: backing files in use */ ++ struct rw_semaphore filesem; ++ ++ /* reference counting: wait until all LUNs are released */ ++ struct kref ref; ++ ++ struct usb_ep *ep0; // Handy copy of gadget->ep0 ++ struct usb_request *ep0req; // For control responses ++ unsigned int ep0_req_tag; ++ const char *ep0req_name; ++ ++ struct usb_request *intreq; // For interrupt responses ++ int intreq_busy; ++ struct fsg_buffhd *intr_buffhd; ++ ++ unsigned int bulk_out_maxpacket; ++ enum fsg_state state; // For exception handling ++ unsigned int exception_req_tag; ++ ++ u8 config, new_config; ++ ++ unsigned int running : 1; ++ unsigned int bulk_in_enabled : 1; ++ unsigned int bulk_out_enabled : 1; ++ unsigned int intr_in_enabled : 1; ++ unsigned int phase_error : 1; ++ unsigned int short_packet_received : 1; ++ unsigned int bad_lun_okay : 1; ++ ++ unsigned long atomic_bitflags; ++#define REGISTERED 0 ++#define IGNORE_BULK_OUT 1 ++#define SUSPENDED 2 ++ ++ struct usb_ep *bulk_in; ++ struct usb_ep *bulk_out; ++ struct usb_ep *intr_in; ++ ++ struct fsg_buffhd *next_buffhd_to_fill; ++ struct fsg_buffhd *next_buffhd_to_drain; ++ ++ int thread_wakeup_needed; ++ struct completion thread_notifier; ++ struct task_struct *thread_task; ++ ++ int cmnd_size; ++ u8 cmnd[MAX_COMMAND_SIZE]; ++ enum data_direction data_dir; ++ u32 data_size; ++ u32 data_size_from_cmnd; ++ u32 tag; ++ unsigned int lun; ++ u32 residue; ++ u32 usb_amount_left; ++ ++ /* The CB protocol offers no way for a host to know when a command ++ * has completed. As a result the next command may arrive early, ++ * and we will still have to handle it. For that reason we need ++ * a buffer to store new commands when using CB (or CBI, which ++ * does not oblige a host to wait for command completion either). */ ++ int cbbuf_cmnd_size; ++ u8 cbbuf_cmnd[MAX_COMMAND_SIZE]; ++ ++ unsigned int nluns; ++ struct fsg_lun *luns; ++ struct fsg_lun *curlun; ++ /* Must be the last entry */ ++ struct fsg_buffhd buffhds[]; ++}; ++ ++typedef void (*fsg_routine_t)(struct fsg_dev *); ++ ++static int exception_in_progress(struct fsg_dev *fsg) ++{ ++ return (fsg->state > FSG_STATE_IDLE); ++} ++ ++/* Make bulk-out requests be divisible by the maxpacket size */ ++static void set_bulk_out_req_length(struct fsg_dev *fsg, ++ struct fsg_buffhd *bh, unsigned int length) ++{ ++ unsigned int rem; ++ ++ bh->bulk_out_intended_length = length; ++ rem = length % fsg->bulk_out_maxpacket; ++ if (rem > 0) ++ length += fsg->bulk_out_maxpacket - rem; ++ bh->outreq->length = length; ++} ++ ++static struct fsg_dev *the_fsg; ++static struct usb_gadget_driver fsg_driver; ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) ++{ ++ const char *name; ++ ++ if (ep == fsg->bulk_in) ++ name = "bulk-in"; ++ else if (ep == fsg->bulk_out) ++ name = "bulk-out"; ++ else ++ name = ep->name; ++ DBG(fsg, "%s set halt\n", name); ++ return usb_ep_set_halt(ep); ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * DESCRIPTORS ... most are static, but strings and (full) configuration ++ * descriptors are built on demand. Also the (static) config and interface ++ * descriptors are adjusted during fsg_bind(). ++ */ ++ ++/* There is only one configuration. */ ++#define CONFIG_VALUE 1 ++ ++static struct usb_device_descriptor ++device_desc = { ++ .bLength = sizeof device_desc, ++ .bDescriptorType = USB_DT_DEVICE, ++ ++ .bcdUSB = cpu_to_le16(0x0200), ++ .bDeviceClass = USB_CLASS_PER_INTERFACE, ++ ++ /* The next three values can be overridden by module parameters */ ++ .idVendor = cpu_to_le16(FSG_VENDOR_ID), ++ .idProduct = cpu_to_le16(FSG_PRODUCT_ID), ++ .bcdDevice = cpu_to_le16(0xffff), ++ ++ .iManufacturer = FSG_STRING_MANUFACTURER, ++ .iProduct = FSG_STRING_PRODUCT, ++ .iSerialNumber = FSG_STRING_SERIAL, ++ .bNumConfigurations = 1, ++}; ++ ++static struct usb_config_descriptor ++config_desc = { ++ .bLength = sizeof config_desc, ++ .bDescriptorType = USB_DT_CONFIG, ++ ++ /* wTotalLength computed by usb_gadget_config_buf() */ ++ .bNumInterfaces = 1, ++ .bConfigurationValue = CONFIG_VALUE, ++ .iConfiguration = FSG_STRING_CONFIG, ++ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, ++ .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, ++}; ++ ++ ++static struct usb_qualifier_descriptor ++dev_qualifier = { ++ .bLength = sizeof dev_qualifier, ++ .bDescriptorType = USB_DT_DEVICE_QUALIFIER, ++ ++ .bcdUSB = cpu_to_le16(0x0200), ++ .bDeviceClass = USB_CLASS_PER_INTERFACE, ++ ++ .bNumConfigurations = 1, ++}; ++ ++static int populate_bos(struct fsg_dev *fsg, u8 *buf) ++{ ++ memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE); ++ buf += USB_DT_BOS_SIZE; ++ ++ memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE); ++ buf += USB_DT_USB_EXT_CAP_SIZE; ++ ++ memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE); ++ ++ return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE ++ + USB_DT_USB_EXT_CAP_SIZE; ++} ++ ++/* ++ * Config descriptors must agree with the code that sets configurations ++ * and with code managing interfaces and their altsettings. They must ++ * also handle different speeds and other-speed requests. ++ */ ++static int populate_config_buf(struct usb_gadget *gadget, ++ u8 *buf, u8 type, unsigned index) ++{ ++ enum usb_device_speed speed = gadget->speed; ++ int len; ++ const struct usb_descriptor_header **function; ++ ++ if (index > 0) ++ return -EINVAL; ++ ++ if (gadget_is_dualspeed(gadget) && type == USB_DT_OTHER_SPEED_CONFIG) ++ speed = (USB_SPEED_FULL + USB_SPEED_HIGH) - speed; ++ function = gadget_is_dualspeed(gadget) && speed == USB_SPEED_HIGH ++ ? (const struct usb_descriptor_header **)fsg_hs_function ++ : (const struct usb_descriptor_header **)fsg_fs_function; ++ ++ /* for now, don't advertise srp-only devices */ ++ if (!gadget_is_otg(gadget)) ++ function++; ++ ++ len = usb_gadget_config_buf(&config_desc, buf, EP0_BUFSIZE, function); ++ ((struct usb_config_descriptor *) buf)->bDescriptorType = type; ++ return len; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* These routines may be called in process context or in_irq */ ++ ++/* Caller must hold fsg->lock */ ++static void wakeup_thread(struct fsg_dev *fsg) ++{ ++ /* Tell the main thread that something has happened */ ++ fsg->thread_wakeup_needed = 1; ++ if (fsg->thread_task) ++ wake_up_process(fsg->thread_task); ++} ++ ++ ++static void raise_exception(struct fsg_dev *fsg, enum fsg_state new_state) ++{ ++ unsigned long flags; ++ ++ /* Do nothing if a higher-priority exception is already in progress. ++ * If a lower-or-equal priority exception is in progress, preempt it ++ * and notify the main thread by sending it a signal. */ ++ spin_lock_irqsave(&fsg->lock, flags); ++ if (fsg->state <= new_state) { ++ fsg->exception_req_tag = fsg->ep0_req_tag; ++ fsg->state = new_state; ++ if (fsg->thread_task) ++ send_sig_info(SIGUSR1, SEND_SIG_FORCED, ++ fsg->thread_task); ++ } ++ spin_unlock_irqrestore(&fsg->lock, flags); ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* The disconnect callback and ep0 routines. These always run in_irq, ++ * except that ep0_queue() is called in the main thread to acknowledge ++ * completion of various requests: set config, set interface, and ++ * Bulk-only device reset. */ ++ ++static void fsg_disconnect(struct usb_gadget *gadget) ++{ ++ struct fsg_dev *fsg = get_gadget_data(gadget); ++ ++ DBG(fsg, "disconnect or port reset\n"); ++ raise_exception(fsg, FSG_STATE_DISCONNECT); ++} ++ ++ ++static int ep0_queue(struct fsg_dev *fsg) ++{ ++ int rc; ++ ++ rc = usb_ep_queue(fsg->ep0, fsg->ep0req, GFP_ATOMIC); ++ if (rc != 0 && rc != -ESHUTDOWN) { ++ ++ /* We can't do much more than wait for a reset */ ++ WARNING(fsg, "error in submission: %s --> %d\n", ++ fsg->ep0->name, rc); ++ } ++ return rc; ++} ++ ++static void ep0_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct fsg_dev *fsg = ep->driver_data; ++ ++ if (req->actual > 0) ++ dump_msg(fsg, fsg->ep0req_name, req->buf, req->actual); ++ if (req->status || req->actual != req->length) ++ DBG(fsg, "%s --> %d, %u/%u\n", __func__, ++ req->status, req->actual, req->length); ++ if (req->status == -ECONNRESET) // Request was cancelled ++ usb_ep_fifo_flush(ep); ++ ++ if (req->status == 0 && req->context) ++ ((fsg_routine_t) (req->context))(fsg); ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* Bulk and interrupt endpoint completion handlers. ++ * These always run in_irq. */ ++ ++static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct fsg_dev *fsg = ep->driver_data; ++ struct fsg_buffhd *bh = req->context; ++ ++ if (req->status || req->actual != req->length) ++ DBG(fsg, "%s --> %d, %u/%u\n", __func__, ++ req->status, req->actual, req->length); ++ if (req->status == -ECONNRESET) // Request was cancelled ++ usb_ep_fifo_flush(ep); ++ ++ /* Hold the lock while we update the request and buffer states */ ++ smp_wmb(); ++ spin_lock(&fsg->lock); ++ bh->inreq_busy = 0; ++ bh->state = BUF_STATE_EMPTY; ++ wakeup_thread(fsg); ++ spin_unlock(&fsg->lock); ++} ++ ++static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct fsg_dev *fsg = ep->driver_data; ++ struct fsg_buffhd *bh = req->context; ++ ++ dump_msg(fsg, "bulk-out", req->buf, req->actual); ++ if (req->status || req->actual != bh->bulk_out_intended_length) ++ DBG(fsg, "%s --> %d, %u/%u\n", __func__, ++ req->status, req->actual, ++ bh->bulk_out_intended_length); ++ if (req->status == -ECONNRESET) // Request was cancelled ++ usb_ep_fifo_flush(ep); ++ ++ /* Hold the lock while we update the request and buffer states */ ++ smp_wmb(); ++ spin_lock(&fsg->lock); ++ bh->outreq_busy = 0; ++ bh->state = BUF_STATE_FULL; ++ wakeup_thread(fsg); ++ spin_unlock(&fsg->lock); ++} ++ ++ ++#ifdef CONFIG_USB_FILE_STORAGE_TEST ++static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) ++{ ++ struct fsg_dev *fsg = ep->driver_data; ++ struct fsg_buffhd *bh = req->context; ++ ++ if (req->status || req->actual != req->length) ++ DBG(fsg, "%s --> %d, %u/%u\n", __func__, ++ req->status, req->actual, req->length); ++ if (req->status == -ECONNRESET) // Request was cancelled ++ usb_ep_fifo_flush(ep); ++ ++ /* Hold the lock while we update the request and buffer states */ ++ smp_wmb(); ++ spin_lock(&fsg->lock); ++ fsg->intreq_busy = 0; ++ bh->state = BUF_STATE_EMPTY; ++ wakeup_thread(fsg); ++ spin_unlock(&fsg->lock); ++} ++ ++#else ++static void intr_in_complete(struct usb_ep *ep, struct usb_request *req) ++{} ++#endif /* CONFIG_USB_FILE_STORAGE_TEST */ ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* Ep0 class-specific handlers. These always run in_irq. */ ++ ++#ifdef CONFIG_USB_FILE_STORAGE_TEST ++static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ struct usb_request *req = fsg->ep0req; ++ static u8 cbi_reset_cmnd[6] = { ++ SEND_DIAGNOSTIC, 4, 0xff, 0xff, 0xff, 0xff}; ++ ++ /* Error in command transfer? */ ++ if (req->status || req->length != req->actual || ++ req->actual < 6 || req->actual > MAX_COMMAND_SIZE) { ++ ++ /* Not all controllers allow a protocol stall after ++ * receiving control-out data, but we'll try anyway. */ ++ fsg_set_halt(fsg, fsg->ep0); ++ return; // Wait for reset ++ } ++ ++ /* Is it the special reset command? */ ++ if (req->actual >= sizeof cbi_reset_cmnd && ++ memcmp(req->buf, cbi_reset_cmnd, ++ sizeof cbi_reset_cmnd) == 0) { ++ ++ /* Raise an exception to stop the current operation ++ * and reinitialize our state. */ ++ DBG(fsg, "cbi reset request\n"); ++ raise_exception(fsg, FSG_STATE_RESET); ++ return; ++ } ++ ++ VDBG(fsg, "CB[I] accept device-specific command\n"); ++ spin_lock(&fsg->lock); ++ ++ /* Save the command for later */ ++ if (fsg->cbbuf_cmnd_size) ++ WARNING(fsg, "CB[I] overwriting previous command\n"); ++ fsg->cbbuf_cmnd_size = req->actual; ++ memcpy(fsg->cbbuf_cmnd, req->buf, fsg->cbbuf_cmnd_size); ++ ++ wakeup_thread(fsg); ++ spin_unlock(&fsg->lock); ++} ++ ++#else ++static void received_cbi_adsc(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{} ++#endif /* CONFIG_USB_FILE_STORAGE_TEST */ ++ ++ ++static int class_setup_req(struct fsg_dev *fsg, ++ const struct usb_ctrlrequest *ctrl) ++{ ++ struct usb_request *req = fsg->ep0req; ++ int value = -EOPNOTSUPP; ++ u16 w_index = le16_to_cpu(ctrl->wIndex); ++ u16 w_value = le16_to_cpu(ctrl->wValue); ++ u16 w_length = le16_to_cpu(ctrl->wLength); ++ ++ if (!fsg->config) ++ return value; ++ ++ /* Handle Bulk-only class-specific requests */ ++ if (transport_is_bbb()) { ++ switch (ctrl->bRequest) { ++ ++ case US_BULK_RESET_REQUEST: ++ if (ctrl->bRequestType != (USB_DIR_OUT | ++ USB_TYPE_CLASS | USB_RECIP_INTERFACE)) ++ break; ++ if (w_index != 0 || w_value != 0 || w_length != 0) { ++ value = -EDOM; ++ break; ++ } ++ ++ /* Raise an exception to stop the current operation ++ * and reinitialize our state. */ ++ DBG(fsg, "bulk reset request\n"); ++ raise_exception(fsg, FSG_STATE_RESET); ++ value = DELAYED_STATUS; ++ break; ++ ++ case US_BULK_GET_MAX_LUN: ++ if (ctrl->bRequestType != (USB_DIR_IN | ++ USB_TYPE_CLASS | USB_RECIP_INTERFACE)) ++ break; ++ if (w_index != 0 || w_value != 0 || w_length != 1) { ++ value = -EDOM; ++ break; ++ } ++ VDBG(fsg, "get max LUN\n"); ++ *(u8 *) req->buf = fsg->nluns - 1; ++ value = 1; ++ break; ++ } ++ } ++ ++ /* Handle CBI class-specific requests */ ++ else { ++ switch (ctrl->bRequest) { ++ ++ case USB_CBI_ADSC_REQUEST: ++ if (ctrl->bRequestType != (USB_DIR_OUT | ++ USB_TYPE_CLASS | USB_RECIP_INTERFACE)) ++ break; ++ if (w_index != 0 || w_value != 0) { ++ value = -EDOM; ++ break; ++ } ++ if (w_length > MAX_COMMAND_SIZE) { ++ value = -EOVERFLOW; ++ break; ++ } ++ value = w_length; ++ fsg->ep0req->context = received_cbi_adsc; ++ break; ++ } ++ } ++ ++ if (value == -EOPNOTSUPP) ++ VDBG(fsg, ++ "unknown class-specific control req " ++ "%02x.%02x v%04x i%04x l%u\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ le16_to_cpu(ctrl->wValue), w_index, w_length); ++ return value; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* Ep0 standard request handlers. These always run in_irq. */ ++ ++static int standard_setup_req(struct fsg_dev *fsg, ++ const struct usb_ctrlrequest *ctrl) ++{ ++ struct usb_request *req = fsg->ep0req; ++ int value = -EOPNOTSUPP; ++ u16 w_index = le16_to_cpu(ctrl->wIndex); ++ u16 w_value = le16_to_cpu(ctrl->wValue); ++ ++ /* Usually this just stores reply data in the pre-allocated ep0 buffer, ++ * but config change events will also reconfigure hardware. */ ++ switch (ctrl->bRequest) { ++ ++ case USB_REQ_GET_DESCRIPTOR: ++ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | ++ USB_RECIP_DEVICE)) ++ break; ++ switch (w_value >> 8) { ++ ++ case USB_DT_DEVICE: ++ VDBG(fsg, "get device descriptor\n"); ++ device_desc.bMaxPacketSize0 = fsg->ep0->maxpacket; ++ value = sizeof device_desc; ++ memcpy(req->buf, &device_desc, value); ++ break; ++ case USB_DT_DEVICE_QUALIFIER: ++ VDBG(fsg, "get device qualifier\n"); ++ if (!gadget_is_dualspeed(fsg->gadget) || ++ fsg->gadget->speed == USB_SPEED_SUPER) ++ break; ++ /* ++ * Assume ep0 uses the same maxpacket value for both ++ * speeds ++ */ ++ dev_qualifier.bMaxPacketSize0 = fsg->ep0->maxpacket; ++ value = sizeof dev_qualifier; ++ memcpy(req->buf, &dev_qualifier, value); ++ break; ++ ++ case USB_DT_OTHER_SPEED_CONFIG: ++ VDBG(fsg, "get other-speed config descriptor\n"); ++ if (!gadget_is_dualspeed(fsg->gadget) || ++ fsg->gadget->speed == USB_SPEED_SUPER) ++ break; ++ goto get_config; ++ case USB_DT_CONFIG: ++ VDBG(fsg, "get configuration descriptor\n"); ++get_config: ++ value = populate_config_buf(fsg->gadget, ++ req->buf, ++ w_value >> 8, ++ w_value & 0xff); ++ break; ++ ++ case USB_DT_STRING: ++ VDBG(fsg, "get string descriptor\n"); ++ ++ /* wIndex == language code */ ++ value = usb_gadget_get_string(&fsg_stringtab, ++ w_value & 0xff, req->buf); ++ break; ++ ++ case USB_DT_BOS: ++ VDBG(fsg, "get bos descriptor\n"); ++ ++ if (gadget_is_superspeed(fsg->gadget)) ++ value = populate_bos(fsg, req->buf); ++ break; ++ } ++ ++ break; ++ ++ /* One config, two speeds */ ++ case USB_REQ_SET_CONFIGURATION: ++ if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | ++ USB_RECIP_DEVICE)) ++ break; ++ VDBG(fsg, "set configuration\n"); ++ if (w_value == CONFIG_VALUE || w_value == 0) { ++ fsg->new_config = w_value; ++ ++ /* Raise an exception to wipe out previous transaction ++ * state (queued bufs, etc) and set the new config. */ ++ raise_exception(fsg, FSG_STATE_CONFIG_CHANGE); ++ value = DELAYED_STATUS; ++ } ++ break; ++ case USB_REQ_GET_CONFIGURATION: ++ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | ++ USB_RECIP_DEVICE)) ++ break; ++ VDBG(fsg, "get configuration\n"); ++ *(u8 *) req->buf = fsg->config; ++ value = 1; ++ break; ++ ++ case USB_REQ_SET_INTERFACE: ++ if (ctrl->bRequestType != (USB_DIR_OUT| USB_TYPE_STANDARD | ++ USB_RECIP_INTERFACE)) ++ break; ++ if (fsg->config && w_index == 0) { ++ ++ /* Raise an exception to wipe out previous transaction ++ * state (queued bufs, etc) and install the new ++ * interface altsetting. */ ++ raise_exception(fsg, FSG_STATE_INTERFACE_CHANGE); ++ value = DELAYED_STATUS; ++ } ++ break; ++ case USB_REQ_GET_INTERFACE: ++ if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | ++ USB_RECIP_INTERFACE)) ++ break; ++ if (!fsg->config) ++ break; ++ if (w_index != 0) { ++ value = -EDOM; ++ break; ++ } ++ VDBG(fsg, "get interface\n"); ++ *(u8 *) req->buf = 0; ++ value = 1; ++ break; ++ ++ default: ++ VDBG(fsg, ++ "unknown control req %02x.%02x v%04x i%04x l%u\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ w_value, w_index, le16_to_cpu(ctrl->wLength)); ++ } ++ ++ return value; ++} ++ ++ ++static int fsg_setup(struct usb_gadget *gadget, ++ const struct usb_ctrlrequest *ctrl) ++{ ++ struct fsg_dev *fsg = get_gadget_data(gadget); ++ int rc; ++ int w_length = le16_to_cpu(ctrl->wLength); ++ ++ ++fsg->ep0_req_tag; // Record arrival of a new request ++ fsg->ep0req->context = NULL; ++ fsg->ep0req->length = 0; ++ dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); ++ ++ if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) ++ rc = class_setup_req(fsg, ctrl); ++ else ++ rc = standard_setup_req(fsg, ctrl); ++ ++ /* Respond with data/status or defer until later? */ ++ if (rc >= 0 && rc != DELAYED_STATUS) { ++ rc = min(rc, w_length); ++ fsg->ep0req->length = rc; ++ fsg->ep0req->zero = rc < w_length; ++ fsg->ep0req_name = (ctrl->bRequestType & USB_DIR_IN ? ++ "ep0-in" : "ep0-out"); ++ rc = ep0_queue(fsg); ++ } ++ ++ /* Device either stalls (rc < 0) or reports success */ ++ return rc; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* All the following routines run in process context */ ++ ++ ++/* Use this for bulk or interrupt transfers, not ep0 */ ++static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, ++ struct usb_request *req, int *pbusy, ++ enum fsg_buffer_state *state) ++{ ++ int rc; ++ ++ if (ep == fsg->bulk_in) ++ dump_msg(fsg, "bulk-in", req->buf, req->length); ++ else if (ep == fsg->intr_in) ++ dump_msg(fsg, "intr-in", req->buf, req->length); ++ ++ spin_lock_irq(&fsg->lock); ++ *pbusy = 1; ++ *state = BUF_STATE_BUSY; ++ spin_unlock_irq(&fsg->lock); ++ rc = usb_ep_queue(ep, req, GFP_KERNEL); ++ if (rc != 0) { ++ *pbusy = 0; ++ *state = BUF_STATE_EMPTY; ++ ++ /* We can't do much more than wait for a reset */ ++ ++ /* Note: currently the net2280 driver fails zero-length ++ * submissions if DMA is enabled. */ ++ if (rc != -ESHUTDOWN && !(rc == -EOPNOTSUPP && ++ req->length == 0)) ++ WARNING(fsg, "error in submission: %s --> %d\n", ++ ep->name, rc); ++ } ++} ++ ++ ++static int sleep_thread(struct fsg_dev *fsg) ++{ ++ int rc = 0; ++ ++ /* Wait until a signal arrives or we are woken up */ ++ for (;;) { ++ try_to_freeze(); ++ set_current_state(TASK_INTERRUPTIBLE); ++ if (signal_pending(current)) { ++ rc = -EINTR; ++ break; ++ } ++ if (fsg->thread_wakeup_needed) ++ break; ++ schedule(); ++ } ++ __set_current_state(TASK_RUNNING); ++ fsg->thread_wakeup_needed = 0; ++ return rc; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int do_read(struct fsg_dev *fsg) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ u32 lba; ++ struct fsg_buffhd *bh; ++ int rc; ++ u32 amount_left; ++ loff_t file_offset, file_offset_tmp; ++ unsigned int amount; ++ ssize_t nread; ++ ++ /* Get the starting Logical Block Address and check that it's ++ * not too big */ ++ if (fsg->cmnd[0] == READ_6) ++ lba = get_unaligned_be24(&fsg->cmnd[1]); ++ else { ++ lba = get_unaligned_be32(&fsg->cmnd[2]); ++ ++ /* We allow DPO (Disable Page Out = don't save data in the ++ * cache) and FUA (Force Unit Access = don't read from the ++ * cache), but we don't implement them. */ ++ if ((fsg->cmnd[1] & ~0x18) != 0) { ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ } ++ if (lba >= curlun->num_sectors) { ++ curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ++ return -EINVAL; ++ } ++ file_offset = ((loff_t) lba) << curlun->blkbits; ++ ++ /* Carry out the file reads */ ++ amount_left = fsg->data_size_from_cmnd; ++ if (unlikely(amount_left == 0)) ++ return -EIO; // No default reply ++ ++ for (;;) { ++ ++ /* Figure out how much we need to read: ++ * Try to read the remaining amount. ++ * But don't read more than the buffer size. ++ * And don't try to read past the end of the file. ++ */ ++ amount = min((unsigned int) amount_left, mod_data.buflen); ++ amount = min((loff_t) amount, ++ curlun->file_length - file_offset); ++ ++ /* Wait for the next buffer to become available */ ++ bh = fsg->next_buffhd_to_fill; ++ while (bh->state != BUF_STATE_EMPTY) { ++ rc = sleep_thread(fsg); ++ if (rc) ++ return rc; ++ } ++ ++ /* If we were asked to read past the end of file, ++ * end with an empty buffer. */ ++ if (amount == 0) { ++ curlun->sense_data = ++ SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ++ curlun->sense_data_info = file_offset >> curlun->blkbits; ++ curlun->info_valid = 1; ++ bh->inreq->length = 0; ++ bh->state = BUF_STATE_FULL; ++ break; ++ } ++ ++ /* Perform the read */ ++ file_offset_tmp = file_offset; ++ nread = vfs_read(curlun->filp, ++ (char __user *) bh->buf, ++ amount, &file_offset_tmp); ++ VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, ++ (unsigned long long) file_offset, ++ (int) nread); ++ if (signal_pending(current)) ++ return -EINTR; ++ ++ if (nread < 0) { ++ LDBG(curlun, "error in file read: %d\n", ++ (int) nread); ++ nread = 0; ++ } else if (nread < amount) { ++ LDBG(curlun, "partial file read: %d/%u\n", ++ (int) nread, amount); ++ nread = round_down(nread, curlun->blksize); ++ } ++ file_offset += nread; ++ amount_left -= nread; ++ fsg->residue -= nread; ++ ++ /* Except at the end of the transfer, nread will be ++ * equal to the buffer size, which is divisible by the ++ * bulk-in maxpacket size. ++ */ ++ bh->inreq->length = nread; ++ bh->state = BUF_STATE_FULL; ++ ++ /* If an error occurred, report it and its position */ ++ if (nread < amount) { ++ curlun->sense_data = SS_UNRECOVERED_READ_ERROR; ++ curlun->sense_data_info = file_offset >> curlun->blkbits; ++ curlun->info_valid = 1; ++ break; ++ } ++ ++ if (amount_left == 0) ++ break; // No more left to read ++ ++ /* Send this buffer and go read some more */ ++ bh->inreq->zero = 0; ++ start_transfer(fsg, fsg->bulk_in, bh->inreq, ++ &bh->inreq_busy, &bh->state); ++ fsg->next_buffhd_to_fill = bh->next; ++ } ++ ++ return -EIO; // No default reply ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int do_write(struct fsg_dev *fsg) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ u32 lba; ++ struct fsg_buffhd *bh; ++ int get_some_more; ++ u32 amount_left_to_req, amount_left_to_write; ++ loff_t usb_offset, file_offset, file_offset_tmp; ++ unsigned int amount; ++ ssize_t nwritten; ++ int rc; ++ ++ if (curlun->ro) { ++ curlun->sense_data = SS_WRITE_PROTECTED; ++ return -EINVAL; ++ } ++ spin_lock(&curlun->filp->f_lock); ++ curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait ++ spin_unlock(&curlun->filp->f_lock); ++ ++ /* Get the starting Logical Block Address and check that it's ++ * not too big */ ++ if (fsg->cmnd[0] == WRITE_6) ++ lba = get_unaligned_be24(&fsg->cmnd[1]); ++ else { ++ lba = get_unaligned_be32(&fsg->cmnd[2]); ++ ++ /* We allow DPO (Disable Page Out = don't save data in the ++ * cache) and FUA (Force Unit Access = write directly to the ++ * medium). We don't implement DPO; we implement FUA by ++ * performing synchronous output. */ ++ if ((fsg->cmnd[1] & ~0x18) != 0) { ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ /* FUA */ ++ if (!curlun->nofua && (fsg->cmnd[1] & 0x08)) { ++ spin_lock(&curlun->filp->f_lock); ++ curlun->filp->f_flags |= O_DSYNC; ++ spin_unlock(&curlun->filp->f_lock); ++ } ++ } ++ if (lba >= curlun->num_sectors) { ++ curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ++ return -EINVAL; ++ } ++ ++ /* Carry out the file writes */ ++ get_some_more = 1; ++ file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits; ++ amount_left_to_req = amount_left_to_write = fsg->data_size_from_cmnd; ++ ++ while (amount_left_to_write > 0) { ++ ++ /* Queue a request for more data from the host */ ++ bh = fsg->next_buffhd_to_fill; ++ if (bh->state == BUF_STATE_EMPTY && get_some_more) { ++ ++ /* Figure out how much we want to get: ++ * Try to get the remaining amount, ++ * but not more than the buffer size. ++ */ ++ amount = min(amount_left_to_req, mod_data.buflen); ++ ++ /* Beyond the end of the backing file? */ ++ if (usb_offset >= curlun->file_length) { ++ get_some_more = 0; ++ curlun->sense_data = ++ SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ++ curlun->sense_data_info = usb_offset >> curlun->blkbits; ++ curlun->info_valid = 1; ++ continue; ++ } ++ ++ /* Get the next buffer */ ++ usb_offset += amount; ++ fsg->usb_amount_left -= amount; ++ amount_left_to_req -= amount; ++ if (amount_left_to_req == 0) ++ get_some_more = 0; ++ ++ /* Except at the end of the transfer, amount will be ++ * equal to the buffer size, which is divisible by ++ * the bulk-out maxpacket size. ++ */ ++ set_bulk_out_req_length(fsg, bh, amount); ++ start_transfer(fsg, fsg->bulk_out, bh->outreq, ++ &bh->outreq_busy, &bh->state); ++ fsg->next_buffhd_to_fill = bh->next; ++ continue; ++ } ++ ++ /* Write the received data to the backing file */ ++ bh = fsg->next_buffhd_to_drain; ++ if (bh->state == BUF_STATE_EMPTY && !get_some_more) ++ break; // We stopped early ++ if (bh->state == BUF_STATE_FULL) { ++ smp_rmb(); ++ fsg->next_buffhd_to_drain = bh->next; ++ bh->state = BUF_STATE_EMPTY; ++ ++ /* Did something go wrong with the transfer? */ ++ if (bh->outreq->status != 0) { ++ curlun->sense_data = SS_COMMUNICATION_FAILURE; ++ curlun->sense_data_info = file_offset >> curlun->blkbits; ++ curlun->info_valid = 1; ++ break; ++ } ++ ++ amount = bh->outreq->actual; ++ if (curlun->file_length - file_offset < amount) { ++ LERROR(curlun, ++ "write %u @ %llu beyond end %llu\n", ++ amount, (unsigned long long) file_offset, ++ (unsigned long long) curlun->file_length); ++ amount = curlun->file_length - file_offset; ++ } ++ ++ /* Don't accept excess data. The spec doesn't say ++ * what to do in this case. We'll ignore the error. ++ */ ++ amount = min(amount, bh->bulk_out_intended_length); ++ ++ /* Don't write a partial block */ ++ amount = round_down(amount, curlun->blksize); ++ if (amount == 0) ++ goto empty_write; ++ ++ /* Perform the write */ ++ file_offset_tmp = file_offset; ++ nwritten = vfs_write(curlun->filp, ++ (char __user *) bh->buf, ++ amount, &file_offset_tmp); ++ VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, ++ (unsigned long long) file_offset, ++ (int) nwritten); ++ if (signal_pending(current)) ++ return -EINTR; // Interrupted! ++ ++ if (nwritten < 0) { ++ LDBG(curlun, "error in file write: %d\n", ++ (int) nwritten); ++ nwritten = 0; ++ } else if (nwritten < amount) { ++ LDBG(curlun, "partial file write: %d/%u\n", ++ (int) nwritten, amount); ++ nwritten = round_down(nwritten, curlun->blksize); ++ } ++ file_offset += nwritten; ++ amount_left_to_write -= nwritten; ++ fsg->residue -= nwritten; ++ ++ /* If an error occurred, report it and its position */ ++ if (nwritten < amount) { ++ curlun->sense_data = SS_WRITE_ERROR; ++ curlun->sense_data_info = file_offset >> curlun->blkbits; ++ curlun->info_valid = 1; ++ break; ++ } ++ ++ empty_write: ++ /* Did the host decide to stop early? */ ++ if (bh->outreq->actual < bh->bulk_out_intended_length) { ++ fsg->short_packet_received = 1; ++ break; ++ } ++ continue; ++ } ++ ++ /* Wait for something to happen */ ++ rc = sleep_thread(fsg); ++ if (rc) ++ return rc; ++ } ++ ++ return -EIO; // No default reply ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int do_synchronize_cache(struct fsg_dev *fsg) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ int rc; ++ ++ /* We ignore the requested LBA and write out all file's ++ * dirty data buffers. */ ++ rc = fsg_lun_fsync_sub(curlun); ++ if (rc) ++ curlun->sense_data = SS_WRITE_ERROR; ++ return 0; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void invalidate_sub(struct fsg_lun *curlun) ++{ ++ struct file *filp = curlun->filp; ++ struct inode *inode = filp->f_path.dentry->d_inode; ++ unsigned long rc; ++ ++ rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); ++ VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc); ++} ++ ++static int do_verify(struct fsg_dev *fsg) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ u32 lba; ++ u32 verification_length; ++ struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; ++ loff_t file_offset, file_offset_tmp; ++ u32 amount_left; ++ unsigned int amount; ++ ssize_t nread; ++ ++ /* Get the starting Logical Block Address and check that it's ++ * not too big */ ++ lba = get_unaligned_be32(&fsg->cmnd[2]); ++ if (lba >= curlun->num_sectors) { ++ curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ++ return -EINVAL; ++ } ++ ++ /* We allow DPO (Disable Page Out = don't save data in the ++ * cache) but we don't implement it. */ ++ if ((fsg->cmnd[1] & ~0x10) != 0) { ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ ++ verification_length = get_unaligned_be16(&fsg->cmnd[7]); ++ if (unlikely(verification_length == 0)) ++ return -EIO; // No default reply ++ ++ /* Prepare to carry out the file verify */ ++ amount_left = verification_length << curlun->blkbits; ++ file_offset = ((loff_t) lba) << curlun->blkbits; ++ ++ /* Write out all the dirty buffers before invalidating them */ ++ fsg_lun_fsync_sub(curlun); ++ if (signal_pending(current)) ++ return -EINTR; ++ ++ invalidate_sub(curlun); ++ if (signal_pending(current)) ++ return -EINTR; ++ ++ /* Just try to read the requested blocks */ ++ while (amount_left > 0) { ++ ++ /* Figure out how much we need to read: ++ * Try to read the remaining amount, but not more than ++ * the buffer size. ++ * And don't try to read past the end of the file. ++ */ ++ amount = min((unsigned int) amount_left, mod_data.buflen); ++ amount = min((loff_t) amount, ++ curlun->file_length - file_offset); ++ if (amount == 0) { ++ curlun->sense_data = ++ SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ++ curlun->sense_data_info = file_offset >> curlun->blkbits; ++ curlun->info_valid = 1; ++ break; ++ } ++ ++ /* Perform the read */ ++ file_offset_tmp = file_offset; ++ nread = vfs_read(curlun->filp, ++ (char __user *) bh->buf, ++ amount, &file_offset_tmp); ++ VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, ++ (unsigned long long) file_offset, ++ (int) nread); ++ if (signal_pending(current)) ++ return -EINTR; ++ ++ if (nread < 0) { ++ LDBG(curlun, "error in file verify: %d\n", ++ (int) nread); ++ nread = 0; ++ } else if (nread < amount) { ++ LDBG(curlun, "partial file verify: %d/%u\n", ++ (int) nread, amount); ++ nread = round_down(nread, curlun->blksize); ++ } ++ if (nread == 0) { ++ curlun->sense_data = SS_UNRECOVERED_READ_ERROR; ++ curlun->sense_data_info = file_offset >> curlun->blkbits; ++ curlun->info_valid = 1; ++ break; ++ } ++ file_offset += nread; ++ amount_left -= nread; ++ } ++ return 0; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int do_inquiry(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ u8 *buf = (u8 *) bh->buf; ++ ++ static char vendor_id[] = "Linux "; ++ static char product_disk_id[] = "File-Stor Gadget"; ++ static char product_cdrom_id[] = "File-CD Gadget "; ++ ++ if (!fsg->curlun) { // Unsupported LUNs are okay ++ fsg->bad_lun_okay = 1; ++ memset(buf, 0, 36); ++ buf[0] = 0x7f; // Unsupported, no device-type ++ buf[4] = 31; // Additional length ++ return 36; ++ } ++ ++ memset(buf, 0, 8); ++ buf[0] = (mod_data.cdrom ? TYPE_ROM : TYPE_DISK); ++ if (mod_data.removable) ++ buf[1] = 0x80; ++ buf[2] = 2; // ANSI SCSI level 2 ++ buf[3] = 2; // SCSI-2 INQUIRY data format ++ buf[4] = 31; // Additional length ++ // No special options ++ sprintf(buf + 8, "%-8s%-16s%04x", vendor_id, ++ (mod_data.cdrom ? product_cdrom_id : ++ product_disk_id), ++ mod_data.release); ++ return 36; ++} ++ ++ ++static int do_request_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ u8 *buf = (u8 *) bh->buf; ++ u32 sd, sdinfo; ++ int valid; ++ ++ /* ++ * From the SCSI-2 spec., section 7.9 (Unit attention condition): ++ * ++ * If a REQUEST SENSE command is received from an initiator ++ * with a pending unit attention condition (before the target ++ * generates the contingent allegiance condition), then the ++ * target shall either: ++ * a) report any pending sense data and preserve the unit ++ * attention condition on the logical unit, or, ++ * b) report the unit attention condition, may discard any ++ * pending sense data, and clear the unit attention ++ * condition on the logical unit for that initiator. ++ * ++ * FSG normally uses option a); enable this code to use option b). ++ */ ++#if 0 ++ if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { ++ curlun->sense_data = curlun->unit_attention_data; ++ curlun->unit_attention_data = SS_NO_SENSE; ++ } ++#endif ++ ++ if (!curlun) { // Unsupported LUNs are okay ++ fsg->bad_lun_okay = 1; ++ sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; ++ sdinfo = 0; ++ valid = 0; ++ } else { ++ sd = curlun->sense_data; ++ sdinfo = curlun->sense_data_info; ++ valid = curlun->info_valid << 7; ++ curlun->sense_data = SS_NO_SENSE; ++ curlun->sense_data_info = 0; ++ curlun->info_valid = 0; ++ } ++ ++ memset(buf, 0, 18); ++ buf[0] = valid | 0x70; // Valid, current error ++ buf[2] = SK(sd); ++ put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ ++ buf[7] = 18 - 8; // Additional sense length ++ buf[12] = ASC(sd); ++ buf[13] = ASCQ(sd); ++ return 18; ++} ++ ++ ++static int do_read_capacity(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ u32 lba = get_unaligned_be32(&fsg->cmnd[2]); ++ int pmi = fsg->cmnd[8]; ++ u8 *buf = (u8 *) bh->buf; ++ ++ /* Check the PMI and LBA fields */ ++ if (pmi > 1 || (pmi == 0 && lba != 0)) { ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ ++ put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); ++ /* Max logical block */ ++ put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */ ++ return 8; ++} ++ ++ ++static int do_read_header(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ int msf = fsg->cmnd[1] & 0x02; ++ u32 lba = get_unaligned_be32(&fsg->cmnd[2]); ++ u8 *buf = (u8 *) bh->buf; ++ ++ if ((fsg->cmnd[1] & ~0x02) != 0) { /* Mask away MSF */ ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ if (lba >= curlun->num_sectors) { ++ curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; ++ return -EINVAL; ++ } ++ ++ memset(buf, 0, 8); ++ buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ ++ store_cdrom_address(&buf[4], msf, lba); ++ return 8; ++} ++ ++ ++static int do_read_toc(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ int msf = fsg->cmnd[1] & 0x02; ++ int start_track = fsg->cmnd[6]; ++ u8 *buf = (u8 *) bh->buf; ++ ++ if ((fsg->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ ++ start_track > 1) { ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ ++ memset(buf, 0, 20); ++ buf[1] = (20-2); /* TOC data length */ ++ buf[2] = 1; /* First track number */ ++ buf[3] = 1; /* Last track number */ ++ buf[5] = 0x16; /* Data track, copying allowed */ ++ buf[6] = 0x01; /* Only track is number 1 */ ++ store_cdrom_address(&buf[8], msf, 0); ++ ++ buf[13] = 0x16; /* Lead-out track is data */ ++ buf[14] = 0xAA; /* Lead-out track number */ ++ store_cdrom_address(&buf[16], msf, curlun->num_sectors); ++ return 20; ++} ++ ++ ++static int do_mode_sense(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ int mscmnd = fsg->cmnd[0]; ++ u8 *buf = (u8 *) bh->buf; ++ u8 *buf0 = buf; ++ int pc, page_code; ++ int changeable_values, all_pages; ++ int valid_page = 0; ++ int len, limit; ++ ++ if ((fsg->cmnd[1] & ~0x08) != 0) { // Mask away DBD ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ pc = fsg->cmnd[2] >> 6; ++ page_code = fsg->cmnd[2] & 0x3f; ++ if (pc == 3) { ++ curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; ++ return -EINVAL; ++ } ++ changeable_values = (pc == 1); ++ all_pages = (page_code == 0x3f); ++ ++ /* Write the mode parameter header. Fixed values are: default ++ * medium type, no cache control (DPOFUA), and no block descriptors. ++ * The only variable value is the WriteProtect bit. We will fill in ++ * the mode data length later. */ ++ memset(buf, 0, 8); ++ if (mscmnd == MODE_SENSE) { ++ buf[2] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA ++ buf += 4; ++ limit = 255; ++ } else { // MODE_SENSE_10 ++ buf[3] = (curlun->ro ? 0x80 : 0x00); // WP, DPOFUA ++ buf += 8; ++ limit = 65535; // Should really be mod_data.buflen ++ } ++ ++ /* No block descriptors */ ++ ++ /* The mode pages, in numerical order. The only page we support ++ * is the Caching page. */ ++ if (page_code == 0x08 || all_pages) { ++ valid_page = 1; ++ buf[0] = 0x08; // Page code ++ buf[1] = 10; // Page length ++ memset(buf+2, 0, 10); // None of the fields are changeable ++ ++ if (!changeable_values) { ++ buf[2] = 0x04; // Write cache enable, ++ // Read cache not disabled ++ // No cache retention priorities ++ put_unaligned_be16(0xffff, &buf[4]); ++ /* Don't disable prefetch */ ++ /* Minimum prefetch = 0 */ ++ put_unaligned_be16(0xffff, &buf[8]); ++ /* Maximum prefetch */ ++ put_unaligned_be16(0xffff, &buf[10]); ++ /* Maximum prefetch ceiling */ ++ } ++ buf += 12; ++ } ++ ++ /* Check that a valid page was requested and the mode data length ++ * isn't too long. */ ++ len = buf - buf0; ++ if (!valid_page || len > limit) { ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ ++ /* Store the mode data length */ ++ if (mscmnd == MODE_SENSE) ++ buf0[0] = len - 1; ++ else ++ put_unaligned_be16(len - 2, buf0); ++ return len; ++} ++ ++ ++static int do_start_stop(struct fsg_dev *fsg) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ int loej, start; ++ ++ if (!mod_data.removable) { ++ curlun->sense_data = SS_INVALID_COMMAND; ++ return -EINVAL; ++ } ++ ++ // int immed = fsg->cmnd[1] & 0x01; ++ loej = fsg->cmnd[4] & 0x02; ++ start = fsg->cmnd[4] & 0x01; ++ ++#ifdef CONFIG_USB_FILE_STORAGE_TEST ++ if ((fsg->cmnd[1] & ~0x01) != 0 || // Mask away Immed ++ (fsg->cmnd[4] & ~0x03) != 0) { // Mask LoEj, Start ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ ++ if (!start) { ++ ++ /* Are we allowed to unload the media? */ ++ if (curlun->prevent_medium_removal) { ++ LDBG(curlun, "unload attempt prevented\n"); ++ curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; ++ return -EINVAL; ++ } ++ if (loej) { // Simulate an unload/eject ++ up_read(&fsg->filesem); ++ down_write(&fsg->filesem); ++ fsg_lun_close(curlun); ++ up_write(&fsg->filesem); ++ down_read(&fsg->filesem); ++ } ++ } else { ++ ++ /* Our emulation doesn't support mounting; the medium is ++ * available for use as soon as it is loaded. */ ++ if (!fsg_lun_is_open(curlun)) { ++ curlun->sense_data = SS_MEDIUM_NOT_PRESENT; ++ return -EINVAL; ++ } ++ } ++#endif ++ return 0; ++} ++ ++ ++static int do_prevent_allow(struct fsg_dev *fsg) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ int prevent; ++ ++ if (!mod_data.removable) { ++ curlun->sense_data = SS_INVALID_COMMAND; ++ return -EINVAL; ++ } ++ ++ prevent = fsg->cmnd[4] & 0x01; ++ if ((fsg->cmnd[4] & ~0x01) != 0) { // Mask away Prevent ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ ++ if (curlun->prevent_medium_removal && !prevent) ++ fsg_lun_fsync_sub(curlun); ++ curlun->prevent_medium_removal = prevent; ++ return 0; ++} ++ ++ ++static int do_read_format_capacities(struct fsg_dev *fsg, ++ struct fsg_buffhd *bh) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ u8 *buf = (u8 *) bh->buf; ++ ++ buf[0] = buf[1] = buf[2] = 0; ++ buf[3] = 8; // Only the Current/Maximum Capacity Descriptor ++ buf += 4; ++ ++ put_unaligned_be32(curlun->num_sectors, &buf[0]); ++ /* Number of blocks */ ++ put_unaligned_be32(curlun->blksize, &buf[4]); /* Block length */ ++ buf[4] = 0x02; /* Current capacity */ ++ return 12; ++} ++ ++ ++static int do_mode_select(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ ++ /* We don't support MODE SELECT */ ++ curlun->sense_data = SS_INVALID_COMMAND; ++ return -EINVAL; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int halt_bulk_in_endpoint(struct fsg_dev *fsg) ++{ ++ int rc; ++ ++ rc = fsg_set_halt(fsg, fsg->bulk_in); ++ if (rc == -EAGAIN) ++ VDBG(fsg, "delayed bulk-in endpoint halt\n"); ++ while (rc != 0) { ++ if (rc != -EAGAIN) { ++ WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); ++ rc = 0; ++ break; ++ } ++ ++ /* Wait for a short time and then try again */ ++ if (msleep_interruptible(100) != 0) ++ return -EINTR; ++ rc = usb_ep_set_halt(fsg->bulk_in); ++ } ++ return rc; ++} ++ ++static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) ++{ ++ int rc; ++ ++ DBG(fsg, "bulk-in set wedge\n"); ++ rc = usb_ep_set_wedge(fsg->bulk_in); ++ if (rc == -EAGAIN) ++ VDBG(fsg, "delayed bulk-in endpoint wedge\n"); ++ while (rc != 0) { ++ if (rc != -EAGAIN) { ++ WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); ++ rc = 0; ++ break; ++ } ++ ++ /* Wait for a short time and then try again */ ++ if (msleep_interruptible(100) != 0) ++ return -EINTR; ++ rc = usb_ep_set_wedge(fsg->bulk_in); ++ } ++ return rc; ++} ++ ++static int throw_away_data(struct fsg_dev *fsg) ++{ ++ struct fsg_buffhd *bh; ++ u32 amount; ++ int rc; ++ ++ while ((bh = fsg->next_buffhd_to_drain)->state != BUF_STATE_EMPTY || ++ fsg->usb_amount_left > 0) { ++ ++ /* Throw away the data in a filled buffer */ ++ if (bh->state == BUF_STATE_FULL) { ++ smp_rmb(); ++ bh->state = BUF_STATE_EMPTY; ++ fsg->next_buffhd_to_drain = bh->next; ++ ++ /* A short packet or an error ends everything */ ++ if (bh->outreq->actual < bh->bulk_out_intended_length || ++ bh->outreq->status != 0) { ++ raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); ++ return -EINTR; ++ } ++ continue; ++ } ++ ++ /* Try to submit another request if we need one */ ++ bh = fsg->next_buffhd_to_fill; ++ if (bh->state == BUF_STATE_EMPTY && fsg->usb_amount_left > 0) { ++ amount = min(fsg->usb_amount_left, ++ (u32) mod_data.buflen); ++ ++ /* Except at the end of the transfer, amount will be ++ * equal to the buffer size, which is divisible by ++ * the bulk-out maxpacket size. ++ */ ++ set_bulk_out_req_length(fsg, bh, amount); ++ start_transfer(fsg, fsg->bulk_out, bh->outreq, ++ &bh->outreq_busy, &bh->state); ++ fsg->next_buffhd_to_fill = bh->next; ++ fsg->usb_amount_left -= amount; ++ continue; ++ } ++ ++ /* Otherwise wait for something to happen */ ++ rc = sleep_thread(fsg); ++ if (rc) ++ return rc; ++ } ++ return 0; ++} ++ ++ ++static int finish_reply(struct fsg_dev *fsg) ++{ ++ struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; ++ int rc = 0; ++ ++ switch (fsg->data_dir) { ++ case DATA_DIR_NONE: ++ break; // Nothing to send ++ ++ /* If we don't know whether the host wants to read or write, ++ * this must be CB or CBI with an unknown command. We mustn't ++ * try to send or receive any data. So stall both bulk pipes ++ * if we can and wait for a reset. */ ++ case DATA_DIR_UNKNOWN: ++ if (mod_data.can_stall) { ++ fsg_set_halt(fsg, fsg->bulk_out); ++ rc = halt_bulk_in_endpoint(fsg); ++ } ++ break; ++ ++ /* All but the last buffer of data must have already been sent */ ++ case DATA_DIR_TO_HOST: ++ if (fsg->data_size == 0) ++ ; // Nothing to send ++ ++ /* If there's no residue, simply send the last buffer */ ++ else if (fsg->residue == 0) { ++ bh->inreq->zero = 0; ++ start_transfer(fsg, fsg->bulk_in, bh->inreq, ++ &bh->inreq_busy, &bh->state); ++ fsg->next_buffhd_to_fill = bh->next; ++ } ++ ++ /* There is a residue. For CB and CBI, simply mark the end ++ * of the data with a short packet. However, if we are ++ * allowed to stall, there was no data at all (residue == ++ * data_size), and the command failed (invalid LUN or ++ * sense data is set), then halt the bulk-in endpoint ++ * instead. */ ++ else if (!transport_is_bbb()) { ++ if (mod_data.can_stall && ++ fsg->residue == fsg->data_size && ++ (!fsg->curlun || fsg->curlun->sense_data != SS_NO_SENSE)) { ++ bh->state = BUF_STATE_EMPTY; ++ rc = halt_bulk_in_endpoint(fsg); ++ } else { ++ bh->inreq->zero = 1; ++ start_transfer(fsg, fsg->bulk_in, bh->inreq, ++ &bh->inreq_busy, &bh->state); ++ fsg->next_buffhd_to_fill = bh->next; ++ } ++ } ++ ++ /* ++ * For Bulk-only, mark the end of the data with a short ++ * packet. If we are allowed to stall, halt the bulk-in ++ * endpoint. (Note: This violates the Bulk-Only Transport ++ * specification, which requires us to pad the data if we ++ * don't halt the endpoint. Presumably nobody will mind.) ++ */ ++ else { ++ bh->inreq->zero = 1; ++ start_transfer(fsg, fsg->bulk_in, bh->inreq, ++ &bh->inreq_busy, &bh->state); ++ fsg->next_buffhd_to_fill = bh->next; ++ if (mod_data.can_stall) ++ rc = halt_bulk_in_endpoint(fsg); ++ } ++ break; ++ ++ /* We have processed all we want from the data the host has sent. ++ * There may still be outstanding bulk-out requests. */ ++ case DATA_DIR_FROM_HOST: ++ if (fsg->residue == 0) ++ ; // Nothing to receive ++ ++ /* Did the host stop sending unexpectedly early? */ ++ else if (fsg->short_packet_received) { ++ raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); ++ rc = -EINTR; ++ } ++ ++ /* We haven't processed all the incoming data. Even though ++ * we may be allowed to stall, doing so would cause a race. ++ * The controller may already have ACK'ed all the remaining ++ * bulk-out packets, in which case the host wouldn't see a ++ * STALL. Not realizing the endpoint was halted, it wouldn't ++ * clear the halt -- leading to problems later on. */ ++#if 0 ++ else if (mod_data.can_stall) { ++ fsg_set_halt(fsg, fsg->bulk_out); ++ raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT); ++ rc = -EINTR; ++ } ++#endif ++ ++ /* We can't stall. Read in the excess data and throw it ++ * all away. */ ++ else ++ rc = throw_away_data(fsg); ++ break; ++ } ++ return rc; ++} ++ ++ ++static int send_status(struct fsg_dev *fsg) ++{ ++ struct fsg_lun *curlun = fsg->curlun; ++ struct fsg_buffhd *bh; ++ int rc; ++ u8 status = US_BULK_STAT_OK; ++ u32 sd, sdinfo = 0; ++ ++ /* Wait for the next buffer to become available */ ++ bh = fsg->next_buffhd_to_fill; ++ while (bh->state != BUF_STATE_EMPTY) { ++ rc = sleep_thread(fsg); ++ if (rc) ++ return rc; ++ } ++ ++ if (curlun) { ++ sd = curlun->sense_data; ++ sdinfo = curlun->sense_data_info; ++ } else if (fsg->bad_lun_okay) ++ sd = SS_NO_SENSE; ++ else ++ sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; ++ ++ if (fsg->phase_error) { ++ DBG(fsg, "sending phase-error status\n"); ++ status = US_BULK_STAT_PHASE; ++ sd = SS_INVALID_COMMAND; ++ } else if (sd != SS_NO_SENSE) { ++ DBG(fsg, "sending command-failure status\n"); ++ status = US_BULK_STAT_FAIL; ++ VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" ++ " info x%x\n", ++ SK(sd), ASC(sd), ASCQ(sd), sdinfo); ++ } ++ ++ if (transport_is_bbb()) { ++ struct bulk_cs_wrap *csw = bh->buf; ++ ++ /* Store and send the Bulk-only CSW */ ++ csw->Signature = cpu_to_le32(US_BULK_CS_SIGN); ++ csw->Tag = fsg->tag; ++ csw->Residue = cpu_to_le32(fsg->residue); ++ csw->Status = status; ++ ++ bh->inreq->length = US_BULK_CS_WRAP_LEN; ++ bh->inreq->zero = 0; ++ start_transfer(fsg, fsg->bulk_in, bh->inreq, ++ &bh->inreq_busy, &bh->state); ++ ++ } else if (mod_data.transport_type == USB_PR_CB) { ++ ++ /* Control-Bulk transport has no status phase! */ ++ return 0; ++ ++ } else { // USB_PR_CBI ++ struct interrupt_data *buf = bh->buf; ++ ++ /* Store and send the Interrupt data. UFI sends the ASC ++ * and ASCQ bytes. Everything else sends a Type (which ++ * is always 0) and the status Value. */ ++ if (mod_data.protocol_type == USB_SC_UFI) { ++ buf->bType = ASC(sd); ++ buf->bValue = ASCQ(sd); ++ } else { ++ buf->bType = 0; ++ buf->bValue = status; ++ } ++ fsg->intreq->length = CBI_INTERRUPT_DATA_LEN; ++ ++ fsg->intr_buffhd = bh; // Point to the right buffhd ++ fsg->intreq->buf = bh->inreq->buf; ++ fsg->intreq->context = bh; ++ start_transfer(fsg, fsg->intr_in, fsg->intreq, ++ &fsg->intreq_busy, &bh->state); ++ } ++ ++ fsg->next_buffhd_to_fill = bh->next; ++ return 0; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* Check whether the command is properly formed and whether its data size ++ * and direction agree with the values we already have. */ ++static int check_command(struct fsg_dev *fsg, int cmnd_size, ++ enum data_direction data_dir, unsigned int mask, ++ int needs_medium, const char *name) ++{ ++ int i; ++ int lun = fsg->cmnd[1] >> 5; ++ static const char dirletter[4] = {'u', 'o', 'i', 'n'}; ++ char hdlen[20]; ++ struct fsg_lun *curlun; ++ ++ /* Adjust the expected cmnd_size for protocol encapsulation padding. ++ * Transparent SCSI doesn't pad. */ ++ if (protocol_is_scsi()) ++ ; ++ ++ /* There's some disagreement as to whether RBC pads commands or not. ++ * We'll play it safe and accept either form. */ ++ else if (mod_data.protocol_type == USB_SC_RBC) { ++ if (fsg->cmnd_size == 12) ++ cmnd_size = 12; ++ ++ /* All the other protocols pad to 12 bytes */ ++ } else ++ cmnd_size = 12; ++ ++ hdlen[0] = 0; ++ if (fsg->data_dir != DATA_DIR_UNKNOWN) ++ sprintf(hdlen, ", H%c=%u", dirletter[(int) fsg->data_dir], ++ fsg->data_size); ++ VDBG(fsg, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", ++ name, cmnd_size, dirletter[(int) data_dir], ++ fsg->data_size_from_cmnd, fsg->cmnd_size, hdlen); ++ ++ /* We can't reply at all until we know the correct data direction ++ * and size. */ ++ if (fsg->data_size_from_cmnd == 0) ++ data_dir = DATA_DIR_NONE; ++ if (fsg->data_dir == DATA_DIR_UNKNOWN) { // CB or CBI ++ fsg->data_dir = data_dir; ++ fsg->data_size = fsg->data_size_from_cmnd; ++ ++ } else { // Bulk-only ++ if (fsg->data_size < fsg->data_size_from_cmnd) { ++ ++ /* Host data size < Device data size is a phase error. ++ * Carry out the command, but only transfer as much ++ * as we are allowed. */ ++ fsg->data_size_from_cmnd = fsg->data_size; ++ fsg->phase_error = 1; ++ } ++ } ++ fsg->residue = fsg->usb_amount_left = fsg->data_size; ++ ++ /* Conflicting data directions is a phase error */ ++ if (fsg->data_dir != data_dir && fsg->data_size_from_cmnd > 0) { ++ fsg->phase_error = 1; ++ return -EINVAL; ++ } ++ ++ /* Verify the length of the command itself */ ++ if (cmnd_size != fsg->cmnd_size) { ++ ++ /* Special case workaround: There are plenty of buggy SCSI ++ * implementations. Many have issues with cbw->Length ++ * field passing a wrong command size. For those cases we ++ * always try to work around the problem by using the length ++ * sent by the host side provided it is at least as large ++ * as the correct command length. ++ * Examples of such cases would be MS-Windows, which issues ++ * REQUEST SENSE with cbw->Length == 12 where it should ++ * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and ++ * REQUEST SENSE with cbw->Length == 10 where it should ++ * be 6 as well. ++ */ ++ if (cmnd_size <= fsg->cmnd_size) { ++ DBG(fsg, "%s is buggy! Expected length %d " ++ "but we got %d\n", name, ++ cmnd_size, fsg->cmnd_size); ++ cmnd_size = fsg->cmnd_size; ++ } else { ++ fsg->phase_error = 1; ++ return -EINVAL; ++ } ++ } ++ ++ /* Check that the LUN values are consistent */ ++ if (transport_is_bbb()) { ++ if (fsg->lun != lun) ++ DBG(fsg, "using LUN %d from CBW, " ++ "not LUN %d from CDB\n", ++ fsg->lun, lun); ++ } ++ ++ /* Check the LUN */ ++ curlun = fsg->curlun; ++ if (curlun) { ++ if (fsg->cmnd[0] != REQUEST_SENSE) { ++ curlun->sense_data = SS_NO_SENSE; ++ curlun->sense_data_info = 0; ++ curlun->info_valid = 0; ++ } ++ } else { ++ fsg->bad_lun_okay = 0; ++ ++ /* INQUIRY and REQUEST SENSE commands are explicitly allowed ++ * to use unsupported LUNs; all others may not. */ ++ if (fsg->cmnd[0] != INQUIRY && ++ fsg->cmnd[0] != REQUEST_SENSE) { ++ DBG(fsg, "unsupported LUN %d\n", fsg->lun); ++ return -EINVAL; ++ } ++ } ++ ++ /* If a unit attention condition exists, only INQUIRY and ++ * REQUEST SENSE commands are allowed; anything else must fail. */ ++ if (curlun && curlun->unit_attention_data != SS_NO_SENSE && ++ fsg->cmnd[0] != INQUIRY && ++ fsg->cmnd[0] != REQUEST_SENSE) { ++ curlun->sense_data = curlun->unit_attention_data; ++ curlun->unit_attention_data = SS_NO_SENSE; ++ return -EINVAL; ++ } ++ ++ /* Check that only command bytes listed in the mask are non-zero */ ++ fsg->cmnd[1] &= 0x1f; // Mask away the LUN ++ for (i = 1; i < cmnd_size; ++i) { ++ if (fsg->cmnd[i] && !(mask & (1 << i))) { ++ if (curlun) ++ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; ++ return -EINVAL; ++ } ++ } ++ ++ /* If the medium isn't mounted and the command needs to access ++ * it, return an error. */ ++ if (curlun && !fsg_lun_is_open(curlun) && needs_medium) { ++ curlun->sense_data = SS_MEDIUM_NOT_PRESENT; ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/* wrapper of check_command for data size in blocks handling */ ++static int check_command_size_in_blocks(struct fsg_dev *fsg, int cmnd_size, ++ enum data_direction data_dir, unsigned int mask, ++ int needs_medium, const char *name) ++{ ++ if (fsg->curlun) ++ fsg->data_size_from_cmnd <<= fsg->curlun->blkbits; ++ return check_command(fsg, cmnd_size, data_dir, ++ mask, needs_medium, name); ++} ++ ++static int do_scsi_command(struct fsg_dev *fsg) ++{ ++ struct fsg_buffhd *bh; ++ int rc; ++ int reply = -EINVAL; ++ int i; ++ static char unknown[16]; ++ ++ dump_cdb(fsg); ++ ++ /* Wait for the next buffer to become available for data or status */ ++ bh = fsg->next_buffhd_to_drain = fsg->next_buffhd_to_fill; ++ while (bh->state != BUF_STATE_EMPTY) { ++ rc = sleep_thread(fsg); ++ if (rc) ++ return rc; ++ } ++ fsg->phase_error = 0; ++ fsg->short_packet_received = 0; ++ ++ down_read(&fsg->filesem); // We're using the backing file ++ switch (fsg->cmnd[0]) { ++ ++ case INQUIRY: ++ fsg->data_size_from_cmnd = fsg->cmnd[4]; ++ if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, ++ (1<<4), 0, ++ "INQUIRY")) == 0) ++ reply = do_inquiry(fsg, bh); ++ break; ++ ++ case MODE_SELECT: ++ fsg->data_size_from_cmnd = fsg->cmnd[4]; ++ if ((reply = check_command(fsg, 6, DATA_DIR_FROM_HOST, ++ (1<<1) | (1<<4), 0, ++ "MODE SELECT(6)")) == 0) ++ reply = do_mode_select(fsg, bh); ++ break; ++ ++ case MODE_SELECT_10: ++ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); ++ if ((reply = check_command(fsg, 10, DATA_DIR_FROM_HOST, ++ (1<<1) | (3<<7), 0, ++ "MODE SELECT(10)")) == 0) ++ reply = do_mode_select(fsg, bh); ++ break; ++ ++ case MODE_SENSE: ++ fsg->data_size_from_cmnd = fsg->cmnd[4]; ++ if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, ++ (1<<1) | (1<<2) | (1<<4), 0, ++ "MODE SENSE(6)")) == 0) ++ reply = do_mode_sense(fsg, bh); ++ break; ++ ++ case MODE_SENSE_10: ++ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); ++ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, ++ (1<<1) | (1<<2) | (3<<7), 0, ++ "MODE SENSE(10)")) == 0) ++ reply = do_mode_sense(fsg, bh); ++ break; ++ ++ case ALLOW_MEDIUM_REMOVAL: ++ fsg->data_size_from_cmnd = 0; ++ if ((reply = check_command(fsg, 6, DATA_DIR_NONE, ++ (1<<4), 0, ++ "PREVENT-ALLOW MEDIUM REMOVAL")) == 0) ++ reply = do_prevent_allow(fsg); ++ break; ++ ++ case READ_6: ++ i = fsg->cmnd[4]; ++ fsg->data_size_from_cmnd = (i == 0) ? 256 : i; ++ if ((reply = check_command_size_in_blocks(fsg, 6, ++ DATA_DIR_TO_HOST, ++ (7<<1) | (1<<4), 1, ++ "READ(6)")) == 0) ++ reply = do_read(fsg); ++ break; ++ ++ case READ_10: ++ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); ++ if ((reply = check_command_size_in_blocks(fsg, 10, ++ DATA_DIR_TO_HOST, ++ (1<<1) | (0xf<<2) | (3<<7), 1, ++ "READ(10)")) == 0) ++ reply = do_read(fsg); ++ break; ++ ++ case READ_12: ++ fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]); ++ if ((reply = check_command_size_in_blocks(fsg, 12, ++ DATA_DIR_TO_HOST, ++ (1<<1) | (0xf<<2) | (0xf<<6), 1, ++ "READ(12)")) == 0) ++ reply = do_read(fsg); ++ break; ++ ++ case READ_CAPACITY: ++ fsg->data_size_from_cmnd = 8; ++ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, ++ (0xf<<2) | (1<<8), 1, ++ "READ CAPACITY")) == 0) ++ reply = do_read_capacity(fsg, bh); ++ break; ++ ++ case READ_HEADER: ++ if (!mod_data.cdrom) ++ goto unknown_cmnd; ++ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); ++ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, ++ (3<<7) | (0x1f<<1), 1, ++ "READ HEADER")) == 0) ++ reply = do_read_header(fsg, bh); ++ break; ++ ++ case READ_TOC: ++ if (!mod_data.cdrom) ++ goto unknown_cmnd; ++ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); ++ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, ++ (7<<6) | (1<<1), 1, ++ "READ TOC")) == 0) ++ reply = do_read_toc(fsg, bh); ++ break; ++ ++ case READ_FORMAT_CAPACITIES: ++ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); ++ if ((reply = check_command(fsg, 10, DATA_DIR_TO_HOST, ++ (3<<7), 1, ++ "READ FORMAT CAPACITIES")) == 0) ++ reply = do_read_format_capacities(fsg, bh); ++ break; ++ ++ case REQUEST_SENSE: ++ fsg->data_size_from_cmnd = fsg->cmnd[4]; ++ if ((reply = check_command(fsg, 6, DATA_DIR_TO_HOST, ++ (1<<4), 0, ++ "REQUEST SENSE")) == 0) ++ reply = do_request_sense(fsg, bh); ++ break; ++ ++ case START_STOP: ++ fsg->data_size_from_cmnd = 0; ++ if ((reply = check_command(fsg, 6, DATA_DIR_NONE, ++ (1<<1) | (1<<4), 0, ++ "START-STOP UNIT")) == 0) ++ reply = do_start_stop(fsg); ++ break; ++ ++ case SYNCHRONIZE_CACHE: ++ fsg->data_size_from_cmnd = 0; ++ if ((reply = check_command(fsg, 10, DATA_DIR_NONE, ++ (0xf<<2) | (3<<7), 1, ++ "SYNCHRONIZE CACHE")) == 0) ++ reply = do_synchronize_cache(fsg); ++ break; ++ ++ case TEST_UNIT_READY: ++ fsg->data_size_from_cmnd = 0; ++ reply = check_command(fsg, 6, DATA_DIR_NONE, ++ 0, 1, ++ "TEST UNIT READY"); ++ break; ++ ++ /* Although optional, this command is used by MS-Windows. We ++ * support a minimal version: BytChk must be 0. */ ++ case VERIFY: ++ fsg->data_size_from_cmnd = 0; ++ if ((reply = check_command(fsg, 10, DATA_DIR_NONE, ++ (1<<1) | (0xf<<2) | (3<<7), 1, ++ "VERIFY")) == 0) ++ reply = do_verify(fsg); ++ break; ++ ++ case WRITE_6: ++ i = fsg->cmnd[4]; ++ fsg->data_size_from_cmnd = (i == 0) ? 256 : i; ++ if ((reply = check_command_size_in_blocks(fsg, 6, ++ DATA_DIR_FROM_HOST, ++ (7<<1) | (1<<4), 1, ++ "WRITE(6)")) == 0) ++ reply = do_write(fsg); ++ break; ++ ++ case WRITE_10: ++ fsg->data_size_from_cmnd = get_unaligned_be16(&fsg->cmnd[7]); ++ if ((reply = check_command_size_in_blocks(fsg, 10, ++ DATA_DIR_FROM_HOST, ++ (1<<1) | (0xf<<2) | (3<<7), 1, ++ "WRITE(10)")) == 0) ++ reply = do_write(fsg); ++ break; ++ ++ case WRITE_12: ++ fsg->data_size_from_cmnd = get_unaligned_be32(&fsg->cmnd[6]); ++ if ((reply = check_command_size_in_blocks(fsg, 12, ++ DATA_DIR_FROM_HOST, ++ (1<<1) | (0xf<<2) | (0xf<<6), 1, ++ "WRITE(12)")) == 0) ++ reply = do_write(fsg); ++ break; ++ ++ /* Some mandatory commands that we recognize but don't implement. ++ * They don't mean much in this setting. It's left as an exercise ++ * for anyone interested to implement RESERVE and RELEASE in terms ++ * of Posix locks. */ ++ case FORMAT_UNIT: ++ case RELEASE: ++ case RESERVE: ++ case SEND_DIAGNOSTIC: ++ // Fall through ++ ++ default: ++ unknown_cmnd: ++ fsg->data_size_from_cmnd = 0; ++ sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]); ++ if ((reply = check_command(fsg, fsg->cmnd_size, ++ DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) { ++ fsg->curlun->sense_data = SS_INVALID_COMMAND; ++ reply = -EINVAL; ++ } ++ break; ++ } ++ up_read(&fsg->filesem); ++ ++ if (reply == -EINTR || signal_pending(current)) ++ return -EINTR; ++ ++ /* Set up the single reply buffer for finish_reply() */ ++ if (reply == -EINVAL) ++ reply = 0; // Error reply length ++ if (reply >= 0 && fsg->data_dir == DATA_DIR_TO_HOST) { ++ reply = min((u32) reply, fsg->data_size_from_cmnd); ++ bh->inreq->length = reply; ++ bh->state = BUF_STATE_FULL; ++ fsg->residue -= reply; ++ } // Otherwise it's already set ++ ++ return 0; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) ++{ ++ struct usb_request *req = bh->outreq; ++ struct bulk_cb_wrap *cbw = req->buf; ++ ++ /* Was this a real packet? Should it be ignored? */ ++ if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) ++ return -EINVAL; ++ ++ /* Is the CBW valid? */ ++ if (req->actual != US_BULK_CB_WRAP_LEN || ++ cbw->Signature != cpu_to_le32( ++ US_BULK_CB_SIGN)) { ++ DBG(fsg, "invalid CBW: len %u sig 0x%x\n", ++ req->actual, ++ le32_to_cpu(cbw->Signature)); ++ ++ /* The Bulk-only spec says we MUST stall the IN endpoint ++ * (6.6.1), so it's unavoidable. It also says we must ++ * retain this state until the next reset, but there's ++ * no way to tell the controller driver it should ignore ++ * Clear-Feature(HALT) requests. ++ * ++ * We aren't required to halt the OUT endpoint; instead ++ * we can simply accept and discard any data received ++ * until the next reset. */ ++ wedge_bulk_in_endpoint(fsg); ++ set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); ++ return -EINVAL; ++ } ++ ++ /* Is the CBW meaningful? */ ++ if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || ++ cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { ++ DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " ++ "cmdlen %u\n", ++ cbw->Lun, cbw->Flags, cbw->Length); ++ ++ /* We can do anything we want here, so let's stall the ++ * bulk pipes if we are allowed to. */ ++ if (mod_data.can_stall) { ++ fsg_set_halt(fsg, fsg->bulk_out); ++ halt_bulk_in_endpoint(fsg); ++ } ++ return -EINVAL; ++ } ++ ++ /* Save the command for later */ ++ fsg->cmnd_size = cbw->Length; ++ memcpy(fsg->cmnd, cbw->CDB, fsg->cmnd_size); ++ if (cbw->Flags & US_BULK_FLAG_IN) ++ fsg->data_dir = DATA_DIR_TO_HOST; ++ else ++ fsg->data_dir = DATA_DIR_FROM_HOST; ++ fsg->data_size = le32_to_cpu(cbw->DataTransferLength); ++ if (fsg->data_size == 0) ++ fsg->data_dir = DATA_DIR_NONE; ++ fsg->lun = cbw->Lun; ++ fsg->tag = cbw->Tag; ++ return 0; ++} ++ ++ ++static int get_next_command(struct fsg_dev *fsg) ++{ ++ struct fsg_buffhd *bh; ++ int rc = 0; ++ ++ if (transport_is_bbb()) { ++ ++ /* Wait for the next buffer to become available */ ++ bh = fsg->next_buffhd_to_fill; ++ while (bh->state != BUF_STATE_EMPTY) { ++ rc = sleep_thread(fsg); ++ if (rc) ++ return rc; ++ } ++ ++ /* Queue a request to read a Bulk-only CBW */ ++ set_bulk_out_req_length(fsg, bh, US_BULK_CB_WRAP_LEN); ++ start_transfer(fsg, fsg->bulk_out, bh->outreq, ++ &bh->outreq_busy, &bh->state); ++ ++ /* We will drain the buffer in software, which means we ++ * can reuse it for the next filling. No need to advance ++ * next_buffhd_to_fill. */ ++ ++ /* Wait for the CBW to arrive */ ++ while (bh->state != BUF_STATE_FULL) { ++ rc = sleep_thread(fsg); ++ if (rc) ++ return rc; ++ } ++ smp_rmb(); ++ rc = received_cbw(fsg, bh); ++ bh->state = BUF_STATE_EMPTY; ++ ++ } else { // USB_PR_CB or USB_PR_CBI ++ ++ /* Wait for the next command to arrive */ ++ while (fsg->cbbuf_cmnd_size == 0) { ++ rc = sleep_thread(fsg); ++ if (rc) ++ return rc; ++ } ++ ++ /* Is the previous status interrupt request still busy? ++ * The host is allowed to skip reading the status, ++ * so we must cancel it. */ ++ if (fsg->intreq_busy) ++ usb_ep_dequeue(fsg->intr_in, fsg->intreq); ++ ++ /* Copy the command and mark the buffer empty */ ++ fsg->data_dir = DATA_DIR_UNKNOWN; ++ spin_lock_irq(&fsg->lock); ++ fsg->cmnd_size = fsg->cbbuf_cmnd_size; ++ memcpy(fsg->cmnd, fsg->cbbuf_cmnd, fsg->cmnd_size); ++ fsg->cbbuf_cmnd_size = 0; ++ spin_unlock_irq(&fsg->lock); ++ ++ /* Use LUN from the command */ ++ fsg->lun = fsg->cmnd[1] >> 5; ++ } ++ ++ /* Update current lun */ ++ if (fsg->lun >= 0 && fsg->lun < fsg->nluns) ++ fsg->curlun = &fsg->luns[fsg->lun]; ++ else ++ fsg->curlun = NULL; ++ ++ return rc; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep, ++ const struct usb_endpoint_descriptor *d) ++{ ++ int rc; ++ ++ ep->driver_data = fsg; ++ ep->desc = d; ++ rc = usb_ep_enable(ep); ++ if (rc) ++ ERROR(fsg, "can't enable %s, result %d\n", ep->name, rc); ++ return rc; ++} ++ ++static int alloc_request(struct fsg_dev *fsg, struct usb_ep *ep, ++ struct usb_request **preq) ++{ ++ *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); ++ if (*preq) ++ return 0; ++ ERROR(fsg, "can't allocate request for %s\n", ep->name); ++ return -ENOMEM; ++} ++ ++/* ++ * Reset interface setting and re-init endpoint state (toggle etc). ++ * Call with altsetting < 0 to disable the interface. The only other ++ * available altsetting is 0, which enables the interface. ++ */ ++static int do_set_interface(struct fsg_dev *fsg, int altsetting) ++{ ++ int rc = 0; ++ int i; ++ const struct usb_endpoint_descriptor *d; ++ ++ if (fsg->running) ++ DBG(fsg, "reset interface\n"); ++ ++reset: ++ /* Deallocate the requests */ ++ for (i = 0; i < fsg_num_buffers; ++i) { ++ struct fsg_buffhd *bh = &fsg->buffhds[i]; ++ ++ if (bh->inreq) { ++ usb_ep_free_request(fsg->bulk_in, bh->inreq); ++ bh->inreq = NULL; ++ } ++ if (bh->outreq) { ++ usb_ep_free_request(fsg->bulk_out, bh->outreq); ++ bh->outreq = NULL; ++ } ++ } ++ if (fsg->intreq) { ++ usb_ep_free_request(fsg->intr_in, fsg->intreq); ++ fsg->intreq = NULL; ++ } ++ ++ /* Disable the endpoints */ ++ if (fsg->bulk_in_enabled) { ++ usb_ep_disable(fsg->bulk_in); ++ fsg->bulk_in_enabled = 0; ++ } ++ if (fsg->bulk_out_enabled) { ++ usb_ep_disable(fsg->bulk_out); ++ fsg->bulk_out_enabled = 0; ++ } ++ if (fsg->intr_in_enabled) { ++ usb_ep_disable(fsg->intr_in); ++ fsg->intr_in_enabled = 0; ++ } ++ ++ fsg->running = 0; ++ if (altsetting < 0 || rc != 0) ++ return rc; ++ ++ DBG(fsg, "set interface %d\n", altsetting); ++ ++ /* Enable the endpoints */ ++ d = fsg_ep_desc(fsg->gadget, ++ &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc, ++ &fsg_ss_bulk_in_desc); ++ if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) ++ goto reset; ++ fsg->bulk_in_enabled = 1; ++ ++ d = fsg_ep_desc(fsg->gadget, ++ &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc, ++ &fsg_ss_bulk_out_desc); ++ if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) ++ goto reset; ++ fsg->bulk_out_enabled = 1; ++ fsg->bulk_out_maxpacket = usb_endpoint_maxp(d); ++ clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); ++ ++ if (transport_is_cbi()) { ++ d = fsg_ep_desc(fsg->gadget, ++ &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc, ++ &fsg_ss_intr_in_desc); ++ if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) ++ goto reset; ++ fsg->intr_in_enabled = 1; ++ } ++ ++ /* Allocate the requests */ ++ for (i = 0; i < fsg_num_buffers; ++i) { ++ struct fsg_buffhd *bh = &fsg->buffhds[i]; ++ ++ if ((rc = alloc_request(fsg, fsg->bulk_in, &bh->inreq)) != 0) ++ goto reset; ++ if ((rc = alloc_request(fsg, fsg->bulk_out, &bh->outreq)) != 0) ++ goto reset; ++ bh->inreq->buf = bh->outreq->buf = bh->buf; ++ bh->inreq->context = bh->outreq->context = bh; ++ bh->inreq->complete = bulk_in_complete; ++ bh->outreq->complete = bulk_out_complete; ++ } ++ if (transport_is_cbi()) { ++ if ((rc = alloc_request(fsg, fsg->intr_in, &fsg->intreq)) != 0) ++ goto reset; ++ fsg->intreq->complete = intr_in_complete; ++ } ++ ++ fsg->running = 1; ++ for (i = 0; i < fsg->nluns; ++i) ++ fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; ++ return rc; ++} ++ ++ ++/* ++ * Change our operational configuration. This code must agree with the code ++ * that returns config descriptors, and with interface altsetting code. ++ * ++ * It's also responsible for power management interactions. Some ++ * configurations might not work with our current power sources. ++ * For now we just assume the gadget is always self-powered. ++ */ ++static int do_set_config(struct fsg_dev *fsg, u8 new_config) ++{ ++ int rc = 0; ++ ++ /* Disable the single interface */ ++ if (fsg->config != 0) { ++ DBG(fsg, "reset config\n"); ++ fsg->config = 0; ++ rc = do_set_interface(fsg, -1); ++ } ++ ++ /* Enable the interface */ ++ if (new_config != 0) { ++ fsg->config = new_config; ++ if ((rc = do_set_interface(fsg, 0)) != 0) ++ fsg->config = 0; // Reset on errors ++ else ++ INFO(fsg, "%s config #%d\n", ++ usb_speed_string(fsg->gadget->speed), ++ fsg->config); ++ } ++ return rc; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void handle_exception(struct fsg_dev *fsg) ++{ ++ siginfo_t info; ++ int sig; ++ int i; ++ int num_active; ++ struct fsg_buffhd *bh; ++ enum fsg_state old_state; ++ u8 new_config; ++ struct fsg_lun *curlun; ++ unsigned int exception_req_tag; ++ int rc; ++ ++ /* Clear the existing signals. Anything but SIGUSR1 is converted ++ * into a high-priority EXIT exception. */ ++ for (;;) { ++ sig = dequeue_signal_lock(current, ¤t->blocked, &info); ++ if (!sig) ++ break; ++ if (sig != SIGUSR1) { ++ if (fsg->state < FSG_STATE_EXIT) ++ DBG(fsg, "Main thread exiting on signal\n"); ++ raise_exception(fsg, FSG_STATE_EXIT); ++ } ++ } ++ ++ /* Cancel all the pending transfers */ ++ if (fsg->intreq_busy) ++ usb_ep_dequeue(fsg->intr_in, fsg->intreq); ++ for (i = 0; i < fsg_num_buffers; ++i) { ++ bh = &fsg->buffhds[i]; ++ if (bh->inreq_busy) ++ usb_ep_dequeue(fsg->bulk_in, bh->inreq); ++ if (bh->outreq_busy) ++ usb_ep_dequeue(fsg->bulk_out, bh->outreq); ++ } ++ ++ /* Wait until everything is idle */ ++ for (;;) { ++ num_active = fsg->intreq_busy; ++ for (i = 0; i < fsg_num_buffers; ++i) { ++ bh = &fsg->buffhds[i]; ++ num_active += bh->inreq_busy + bh->outreq_busy; ++ } ++ if (num_active == 0) ++ break; ++ if (sleep_thread(fsg)) ++ return; ++ } ++ ++ /* Clear out the controller's fifos */ ++ if (fsg->bulk_in_enabled) ++ usb_ep_fifo_flush(fsg->bulk_in); ++ if (fsg->bulk_out_enabled) ++ usb_ep_fifo_flush(fsg->bulk_out); ++ if (fsg->intr_in_enabled) ++ usb_ep_fifo_flush(fsg->intr_in); ++ ++ /* Reset the I/O buffer states and pointers, the SCSI ++ * state, and the exception. Then invoke the handler. */ ++ spin_lock_irq(&fsg->lock); ++ ++ for (i = 0; i < fsg_num_buffers; ++i) { ++ bh = &fsg->buffhds[i]; ++ bh->state = BUF_STATE_EMPTY; ++ } ++ fsg->next_buffhd_to_fill = fsg->next_buffhd_to_drain = ++ &fsg->buffhds[0]; ++ ++ exception_req_tag = fsg->exception_req_tag; ++ new_config = fsg->new_config; ++ old_state = fsg->state; ++ ++ if (old_state == FSG_STATE_ABORT_BULK_OUT) ++ fsg->state = FSG_STATE_STATUS_PHASE; ++ else { ++ for (i = 0; i < fsg->nluns; ++i) { ++ curlun = &fsg->luns[i]; ++ curlun->prevent_medium_removal = 0; ++ curlun->sense_data = curlun->unit_attention_data = ++ SS_NO_SENSE; ++ curlun->sense_data_info = 0; ++ curlun->info_valid = 0; ++ } ++ fsg->state = FSG_STATE_IDLE; ++ } ++ spin_unlock_irq(&fsg->lock); ++ ++ /* Carry out any extra actions required for the exception */ ++ switch (old_state) { ++ default: ++ break; ++ ++ case FSG_STATE_ABORT_BULK_OUT: ++ send_status(fsg); ++ spin_lock_irq(&fsg->lock); ++ if (fsg->state == FSG_STATE_STATUS_PHASE) ++ fsg->state = FSG_STATE_IDLE; ++ spin_unlock_irq(&fsg->lock); ++ break; ++ ++ case FSG_STATE_RESET: ++ /* In case we were forced against our will to halt a ++ * bulk endpoint, clear the halt now. (The SuperH UDC ++ * requires this.) */ ++ if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) ++ usb_ep_clear_halt(fsg->bulk_in); ++ ++ if (transport_is_bbb()) { ++ if (fsg->ep0_req_tag == exception_req_tag) ++ ep0_queue(fsg); // Complete the status stage ++ ++ } else if (transport_is_cbi()) ++ send_status(fsg); // Status by interrupt pipe ++ ++ /* Technically this should go here, but it would only be ++ * a waste of time. Ditto for the INTERFACE_CHANGE and ++ * CONFIG_CHANGE cases. */ ++ // for (i = 0; i < fsg->nluns; ++i) ++ // fsg->luns[i].unit_attention_data = SS_RESET_OCCURRED; ++ break; ++ ++ case FSG_STATE_INTERFACE_CHANGE: ++ rc = do_set_interface(fsg, 0); ++ if (fsg->ep0_req_tag != exception_req_tag) ++ break; ++ if (rc != 0) // STALL on errors ++ fsg_set_halt(fsg, fsg->ep0); ++ else // Complete the status stage ++ ep0_queue(fsg); ++ break; ++ ++ case FSG_STATE_CONFIG_CHANGE: ++ rc = do_set_config(fsg, new_config); ++ if (fsg->ep0_req_tag != exception_req_tag) ++ break; ++ if (rc != 0) // STALL on errors ++ fsg_set_halt(fsg, fsg->ep0); ++ else // Complete the status stage ++ ep0_queue(fsg); ++ break; ++ ++ case FSG_STATE_DISCONNECT: ++ for (i = 0; i < fsg->nluns; ++i) ++ fsg_lun_fsync_sub(fsg->luns + i); ++ do_set_config(fsg, 0); // Unconfigured state ++ break; ++ ++ case FSG_STATE_EXIT: ++ case FSG_STATE_TERMINATED: ++ do_set_config(fsg, 0); // Free resources ++ spin_lock_irq(&fsg->lock); ++ fsg->state = FSG_STATE_TERMINATED; // Stop the thread ++ spin_unlock_irq(&fsg->lock); ++ break; ++ } ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int fsg_main_thread(void *fsg_) ++{ ++ struct fsg_dev *fsg = fsg_; ++ ++ /* Allow the thread to be killed by a signal, but set the signal mask ++ * to block everything but INT, TERM, KILL, and USR1. */ ++ allow_signal(SIGINT); ++ allow_signal(SIGTERM); ++ allow_signal(SIGKILL); ++ allow_signal(SIGUSR1); ++ ++ /* Allow the thread to be frozen */ ++ set_freezable(); ++ ++ /* Arrange for userspace references to be interpreted as kernel ++ * pointers. That way we can pass a kernel pointer to a routine ++ * that expects a __user pointer and it will work okay. */ ++ set_fs(get_ds()); ++ ++ /* The main loop */ ++ while (fsg->state != FSG_STATE_TERMINATED) { ++ if (exception_in_progress(fsg) || signal_pending(current)) { ++ handle_exception(fsg); ++ continue; ++ } ++ ++ if (!fsg->running) { ++ sleep_thread(fsg); ++ continue; ++ } ++ ++ if (get_next_command(fsg)) ++ continue; ++ ++ spin_lock_irq(&fsg->lock); ++ if (!exception_in_progress(fsg)) ++ fsg->state = FSG_STATE_DATA_PHASE; ++ spin_unlock_irq(&fsg->lock); ++ ++ if (do_scsi_command(fsg) || finish_reply(fsg)) ++ continue; ++ ++ spin_lock_irq(&fsg->lock); ++ if (!exception_in_progress(fsg)) ++ fsg->state = FSG_STATE_STATUS_PHASE; ++ spin_unlock_irq(&fsg->lock); ++ ++ if (send_status(fsg)) ++ continue; ++ ++ spin_lock_irq(&fsg->lock); ++ if (!exception_in_progress(fsg)) ++ fsg->state = FSG_STATE_IDLE; ++ spin_unlock_irq(&fsg->lock); ++ } ++ ++ spin_lock_irq(&fsg->lock); ++ fsg->thread_task = NULL; ++ spin_unlock_irq(&fsg->lock); ++ ++ /* If we are exiting because of a signal, unregister the ++ * gadget driver. */ ++ if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) ++ usb_gadget_unregister_driver(&fsg_driver); ++ ++ /* Let the unbind and cleanup routines know the thread has exited */ ++ complete_and_exit(&fsg->thread_notifier, 0); ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++ ++/* The write permissions and store_xxx pointers are set in fsg_bind() */ ++static DEVICE_ATTR(ro, 0444, fsg_show_ro, NULL); ++static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, NULL); ++static DEVICE_ATTR(file, 0444, fsg_show_file, NULL); ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void fsg_release(struct kref *ref) ++{ ++ struct fsg_dev *fsg = container_of(ref, struct fsg_dev, ref); ++ ++ kfree(fsg->luns); ++ kfree(fsg); ++} ++ ++static void lun_release(struct device *dev) ++{ ++ struct rw_semaphore *filesem = dev_get_drvdata(dev); ++ struct fsg_dev *fsg = ++ container_of(filesem, struct fsg_dev, filesem); ++ ++ kref_put(&fsg->ref, fsg_release); ++} ++ ++static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) ++{ ++ struct fsg_dev *fsg = get_gadget_data(gadget); ++ int i; ++ struct fsg_lun *curlun; ++ struct usb_request *req = fsg->ep0req; ++ ++ DBG(fsg, "unbind\n"); ++ clear_bit(REGISTERED, &fsg->atomic_bitflags); ++ ++ /* If the thread isn't already dead, tell it to exit now */ ++ if (fsg->state != FSG_STATE_TERMINATED) { ++ raise_exception(fsg, FSG_STATE_EXIT); ++ wait_for_completion(&fsg->thread_notifier); ++ ++ /* The cleanup routine waits for this completion also */ ++ complete(&fsg->thread_notifier); ++ } ++ ++ /* Unregister the sysfs attribute files and the LUNs */ ++ for (i = 0; i < fsg->nluns; ++i) { ++ curlun = &fsg->luns[i]; ++ if (curlun->registered) { ++ device_remove_file(&curlun->dev, &dev_attr_nofua); ++ device_remove_file(&curlun->dev, &dev_attr_ro); ++ device_remove_file(&curlun->dev, &dev_attr_file); ++ fsg_lun_close(curlun); ++ device_unregister(&curlun->dev); ++ curlun->registered = 0; ++ } ++ } ++ ++ /* Free the data buffers */ ++ for (i = 0; i < fsg_num_buffers; ++i) ++ kfree(fsg->buffhds[i].buf); ++ ++ /* Free the request and buffer for endpoint 0 */ ++ if (req) { ++ kfree(req->buf); ++ usb_ep_free_request(fsg->ep0, req); ++ } ++ ++ set_gadget_data(gadget, NULL); ++} ++ ++ ++static int __init check_parameters(struct fsg_dev *fsg) ++{ ++ int prot; ++ int gcnum; ++ ++ /* Store the default values */ ++ mod_data.transport_type = USB_PR_BULK; ++ mod_data.transport_name = "Bulk-only"; ++ mod_data.protocol_type = USB_SC_SCSI; ++ mod_data.protocol_name = "Transparent SCSI"; ++ ++ /* Some peripheral controllers are known not to be able to ++ * halt bulk endpoints correctly. If one of them is present, ++ * disable stalls. ++ */ ++ if (gadget_is_at91(fsg->gadget)) ++ mod_data.can_stall = 0; ++ ++ if (mod_data.release == 0xffff) { // Parameter wasn't set ++ gcnum = usb_gadget_controller_number(fsg->gadget); ++ if (gcnum >= 0) ++ mod_data.release = 0x0300 + gcnum; ++ else { ++ WARNING(fsg, "controller '%s' not recognized\n", ++ fsg->gadget->name); ++ mod_data.release = 0x0399; ++ } ++ } ++ ++ prot = simple_strtol(mod_data.protocol_parm, NULL, 0); ++ ++#ifdef CONFIG_USB_FILE_STORAGE_TEST ++ if (strnicmp(mod_data.transport_parm, "BBB", 10) == 0) { ++ ; // Use default setting ++ } else if (strnicmp(mod_data.transport_parm, "CB", 10) == 0) { ++ mod_data.transport_type = USB_PR_CB; ++ mod_data.transport_name = "Control-Bulk"; ++ } else if (strnicmp(mod_data.transport_parm, "CBI", 10) == 0) { ++ mod_data.transport_type = USB_PR_CBI; ++ mod_data.transport_name = "Control-Bulk-Interrupt"; ++ } else { ++ ERROR(fsg, "invalid transport: %s\n", mod_data.transport_parm); ++ return -EINVAL; ++ } ++ ++ if (strnicmp(mod_data.protocol_parm, "SCSI", 10) == 0 || ++ prot == USB_SC_SCSI) { ++ ; // Use default setting ++ } else if (strnicmp(mod_data.protocol_parm, "RBC", 10) == 0 || ++ prot == USB_SC_RBC) { ++ mod_data.protocol_type = USB_SC_RBC; ++ mod_data.protocol_name = "RBC"; ++ } else if (strnicmp(mod_data.protocol_parm, "8020", 4) == 0 || ++ strnicmp(mod_data.protocol_parm, "ATAPI", 10) == 0 || ++ prot == USB_SC_8020) { ++ mod_data.protocol_type = USB_SC_8020; ++ mod_data.protocol_name = "8020i (ATAPI)"; ++ } else if (strnicmp(mod_data.protocol_parm, "QIC", 3) == 0 || ++ prot == USB_SC_QIC) { ++ mod_data.protocol_type = USB_SC_QIC; ++ mod_data.protocol_name = "QIC-157"; ++ } else if (strnicmp(mod_data.protocol_parm, "UFI", 10) == 0 || ++ prot == USB_SC_UFI) { ++ mod_data.protocol_type = USB_SC_UFI; ++ mod_data.protocol_name = "UFI"; ++ } else if (strnicmp(mod_data.protocol_parm, "8070", 4) == 0 || ++ prot == USB_SC_8070) { ++ mod_data.protocol_type = USB_SC_8070; ++ mod_data.protocol_name = "8070i"; ++ } else { ++ ERROR(fsg, "invalid protocol: %s\n", mod_data.protocol_parm); ++ return -EINVAL; ++ } ++ ++ mod_data.buflen &= PAGE_CACHE_MASK; ++ if (mod_data.buflen <= 0) { ++ ERROR(fsg, "invalid buflen\n"); ++ return -ETOOSMALL; ++ } ++ ++#endif /* CONFIG_USB_FILE_STORAGE_TEST */ ++ ++ /* Serial string handling. ++ * On a real device, the serial string would be loaded ++ * from permanent storage. */ ++ if (mod_data.serial) { ++ const char *ch; ++ unsigned len = 0; ++ ++ /* Sanity check : ++ * The CB[I] specification limits the serial string to ++ * 12 uppercase hexadecimal characters. ++ * BBB need at least 12 uppercase hexadecimal characters, ++ * with a maximum of 126. */ ++ for (ch = mod_data.serial; *ch; ++ch) { ++ ++len; ++ if ((*ch < '0' || *ch > '9') && ++ (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */ ++ WARNING(fsg, ++ "Invalid serial string character: %c\n", ++ *ch); ++ goto no_serial; ++ } ++ } ++ if (len > 126 || ++ (mod_data.transport_type == USB_PR_BULK && len < 12) || ++ (mod_data.transport_type != USB_PR_BULK && len > 12)) { ++ WARNING(fsg, "Invalid serial string length!\n"); ++ goto no_serial; ++ } ++ fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial; ++ } else { ++ WARNING(fsg, "No serial-number string provided!\n"); ++ no_serial: ++ device_desc.iSerialNumber = 0; ++ } ++ ++ return 0; ++} ++ ++ ++static int __init fsg_bind(struct usb_gadget *gadget) ++{ ++ struct fsg_dev *fsg = the_fsg; ++ int rc; ++ int i; ++ struct fsg_lun *curlun; ++ struct usb_ep *ep; ++ struct usb_request *req; ++ char *pathbuf, *p; ++ ++ fsg->gadget = gadget; ++ set_gadget_data(gadget, fsg); ++ fsg->ep0 = gadget->ep0; ++ fsg->ep0->driver_data = fsg; ++ ++ if ((rc = check_parameters(fsg)) != 0) ++ goto out; ++ ++ if (mod_data.removable) { // Enable the store_xxx attributes ++ dev_attr_file.attr.mode = 0644; ++ dev_attr_file.store = fsg_store_file; ++ if (!mod_data.cdrom) { ++ dev_attr_ro.attr.mode = 0644; ++ dev_attr_ro.store = fsg_store_ro; ++ } ++ } ++ ++ /* Only for removable media? */ ++ dev_attr_nofua.attr.mode = 0644; ++ dev_attr_nofua.store = fsg_store_nofua; ++ ++ /* Find out how many LUNs there should be */ ++ i = mod_data.nluns; ++ if (i == 0) ++ i = max(mod_data.num_filenames, 1u); ++ if (i > FSG_MAX_LUNS) { ++ ERROR(fsg, "invalid number of LUNs: %d\n", i); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ /* Create the LUNs, open their backing files, and register the ++ * LUN devices in sysfs. */ ++ fsg->luns = kzalloc(i * sizeof(struct fsg_lun), GFP_KERNEL); ++ if (!fsg->luns) { ++ rc = -ENOMEM; ++ goto out; ++ } ++ fsg->nluns = i; ++ ++ for (i = 0; i < fsg->nluns; ++i) { ++ curlun = &fsg->luns[i]; ++ curlun->cdrom = !!mod_data.cdrom; ++ curlun->ro = mod_data.cdrom || mod_data.ro[i]; ++ curlun->initially_ro = curlun->ro; ++ curlun->removable = mod_data.removable; ++ curlun->nofua = mod_data.nofua[i]; ++ curlun->dev.release = lun_release; ++ curlun->dev.parent = &gadget->dev; ++ curlun->dev.driver = &fsg_driver.driver; ++ dev_set_drvdata(&curlun->dev, &fsg->filesem); ++ dev_set_name(&curlun->dev,"%s-lun%d", ++ dev_name(&gadget->dev), i); ++ ++ kref_get(&fsg->ref); ++ rc = device_register(&curlun->dev); ++ if (rc) { ++ INFO(fsg, "failed to register LUN%d: %d\n", i, rc); ++ put_device(&curlun->dev); ++ goto out; ++ } ++ curlun->registered = 1; ++ ++ rc = device_create_file(&curlun->dev, &dev_attr_ro); ++ if (rc) ++ goto out; ++ rc = device_create_file(&curlun->dev, &dev_attr_nofua); ++ if (rc) ++ goto out; ++ rc = device_create_file(&curlun->dev, &dev_attr_file); ++ if (rc) ++ goto out; ++ ++ if (mod_data.file[i] && *mod_data.file[i]) { ++ rc = fsg_lun_open(curlun, mod_data.file[i]); ++ if (rc) ++ goto out; ++ } else if (!mod_data.removable) { ++ ERROR(fsg, "no file given for LUN%d\n", i); ++ rc = -EINVAL; ++ goto out; ++ } ++ } ++ ++ /* Find all the endpoints we will use */ ++ usb_ep_autoconfig_reset(gadget); ++ ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); ++ if (!ep) ++ goto autoconf_fail; ++ ep->driver_data = fsg; // claim the endpoint ++ fsg->bulk_in = ep; ++ ++ ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); ++ if (!ep) ++ goto autoconf_fail; ++ ep->driver_data = fsg; // claim the endpoint ++ fsg->bulk_out = ep; ++ ++ if (transport_is_cbi()) { ++ ep = usb_ep_autoconfig(gadget, &fsg_fs_intr_in_desc); ++ if (!ep) ++ goto autoconf_fail; ++ ep->driver_data = fsg; // claim the endpoint ++ fsg->intr_in = ep; ++ } ++ ++ /* Fix up the descriptors */ ++ device_desc.idVendor = cpu_to_le16(mod_data.vendor); ++ device_desc.idProduct = cpu_to_le16(mod_data.product); ++ device_desc.bcdDevice = cpu_to_le16(mod_data.release); ++ ++ i = (transport_is_cbi() ? 3 : 2); // Number of endpoints ++ fsg_intf_desc.bNumEndpoints = i; ++ fsg_intf_desc.bInterfaceSubClass = mod_data.protocol_type; ++ fsg_intf_desc.bInterfaceProtocol = mod_data.transport_type; ++ fsg_fs_function[i + FSG_FS_FUNCTION_PRE_EP_ENTRIES] = NULL; ++ ++ if (gadget_is_dualspeed(gadget)) { ++ fsg_hs_function[i + FSG_HS_FUNCTION_PRE_EP_ENTRIES] = NULL; ++ ++ /* Assume endpoint addresses are the same for both speeds */ ++ fsg_hs_bulk_in_desc.bEndpointAddress = ++ fsg_fs_bulk_in_desc.bEndpointAddress; ++ fsg_hs_bulk_out_desc.bEndpointAddress = ++ fsg_fs_bulk_out_desc.bEndpointAddress; ++ fsg_hs_intr_in_desc.bEndpointAddress = ++ fsg_fs_intr_in_desc.bEndpointAddress; ++ } ++ ++ if (gadget_is_superspeed(gadget)) { ++ unsigned max_burst; ++ ++ fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL; ++ ++ /* Calculate bMaxBurst, we know packet size is 1024 */ ++ max_burst = min_t(unsigned, mod_data.buflen / 1024, 15); ++ ++ /* Assume endpoint addresses are the same for both speeds */ ++ fsg_ss_bulk_in_desc.bEndpointAddress = ++ fsg_fs_bulk_in_desc.bEndpointAddress; ++ fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; ++ ++ fsg_ss_bulk_out_desc.bEndpointAddress = ++ fsg_fs_bulk_out_desc.bEndpointAddress; ++ fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; ++ } ++ ++ if (gadget_is_otg(gadget)) ++ fsg_otg_desc.bmAttributes |= USB_OTG_HNP; ++ ++ rc = -ENOMEM; ++ ++ /* Allocate the request and buffer for endpoint 0 */ ++ fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL); ++ if (!req) ++ goto out; ++ req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL); ++ if (!req->buf) ++ goto out; ++ req->complete = ep0_complete; ++ ++ /* Allocate the data buffers */ ++ for (i = 0; i < fsg_num_buffers; ++i) { ++ struct fsg_buffhd *bh = &fsg->buffhds[i]; ++ ++ /* Allocate for the bulk-in endpoint. We assume that ++ * the buffer will also work with the bulk-out (and ++ * interrupt-in) endpoint. */ ++ bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL); ++ if (!bh->buf) ++ goto out; ++ bh->next = bh + 1; ++ } ++ fsg->buffhds[fsg_num_buffers - 1].next = &fsg->buffhds[0]; ++ ++ /* This should reflect the actual gadget power source */ ++ usb_gadget_set_selfpowered(gadget); ++ ++ snprintf(fsg_string_manufacturer, sizeof fsg_string_manufacturer, ++ "%s %s with %s", ++ init_utsname()->sysname, init_utsname()->release, ++ gadget->name); ++ ++ fsg->thread_task = kthread_create(fsg_main_thread, fsg, ++ "file-storage-gadget"); ++ if (IS_ERR(fsg->thread_task)) { ++ rc = PTR_ERR(fsg->thread_task); ++ goto out; ++ } ++ ++ INFO(fsg, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); ++ INFO(fsg, "NOTE: This driver is deprecated. " ++ "Consider using g_mass_storage instead.\n"); ++ INFO(fsg, "Number of LUNs=%d\n", fsg->nluns); ++ ++ pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); ++ for (i = 0; i < fsg->nluns; ++i) { ++ curlun = &fsg->luns[i]; ++ if (fsg_lun_is_open(curlun)) { ++ p = NULL; ++ if (pathbuf) { ++ p = d_path(&curlun->filp->f_path, ++ pathbuf, PATH_MAX); ++ if (IS_ERR(p)) ++ p = NULL; ++ } ++ LINFO(curlun, "ro=%d, nofua=%d, file: %s\n", ++ curlun->ro, curlun->nofua, (p ? p : "(error)")); ++ } ++ } ++ kfree(pathbuf); ++ ++ DBG(fsg, "transport=%s (x%02x)\n", ++ mod_data.transport_name, mod_data.transport_type); ++ DBG(fsg, "protocol=%s (x%02x)\n", ++ mod_data.protocol_name, mod_data.protocol_type); ++ DBG(fsg, "VendorID=x%04x, ProductID=x%04x, Release=x%04x\n", ++ mod_data.vendor, mod_data.product, mod_data.release); ++ DBG(fsg, "removable=%d, stall=%d, cdrom=%d, buflen=%u\n", ++ mod_data.removable, mod_data.can_stall, ++ mod_data.cdrom, mod_data.buflen); ++ DBG(fsg, "I/O thread pid: %d\n", task_pid_nr(fsg->thread_task)); ++ ++ set_bit(REGISTERED, &fsg->atomic_bitflags); ++ ++ /* Tell the thread to start working */ ++ wake_up_process(fsg->thread_task); ++ return 0; ++ ++autoconf_fail: ++ ERROR(fsg, "unable to autoconfigure all endpoints\n"); ++ rc = -ENOTSUPP; ++ ++out: ++ fsg->state = FSG_STATE_TERMINATED; // The thread is dead ++ fsg_unbind(gadget); ++ complete(&fsg->thread_notifier); ++ return rc; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void fsg_suspend(struct usb_gadget *gadget) ++{ ++ struct fsg_dev *fsg = get_gadget_data(gadget); ++ ++ DBG(fsg, "suspend\n"); ++ set_bit(SUSPENDED, &fsg->atomic_bitflags); ++} ++ ++static void fsg_resume(struct usb_gadget *gadget) ++{ ++ struct fsg_dev *fsg = get_gadget_data(gadget); ++ ++ DBG(fsg, "resume\n"); ++ clear_bit(SUSPENDED, &fsg->atomic_bitflags); ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct usb_gadget_driver fsg_driver = { ++ .max_speed = USB_SPEED_SUPER, ++ .function = (char *) fsg_string_product, ++ .unbind = fsg_unbind, ++ .disconnect = fsg_disconnect, ++ .setup = fsg_setup, ++ .suspend = fsg_suspend, ++ .resume = fsg_resume, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ // .release = ... ++ // .suspend = ... ++ // .resume = ... ++ }, ++}; ++ ++ ++static int __init fsg_alloc(void) ++{ ++ struct fsg_dev *fsg; ++ ++ fsg = kzalloc(sizeof *fsg + ++ fsg_num_buffers * sizeof *(fsg->buffhds), GFP_KERNEL); ++ ++ if (!fsg) ++ return -ENOMEM; ++ spin_lock_init(&fsg->lock); ++ init_rwsem(&fsg->filesem); ++ kref_init(&fsg->ref); ++ init_completion(&fsg->thread_notifier); ++ ++ the_fsg = fsg; ++ return 0; ++} ++ ++ ++static int __init fsg_init(void) ++{ ++ int rc; ++ struct fsg_dev *fsg; ++ ++ rc = fsg_num_buffers_validate(); ++ if (rc != 0) ++ return rc; ++ ++ if ((rc = fsg_alloc()) != 0) ++ return rc; ++ fsg = the_fsg; ++ if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0) ++ kref_put(&fsg->ref, fsg_release); ++ return rc; ++} ++module_init(fsg_init); ++ ++ ++static void __exit fsg_cleanup(void) ++{ ++ struct fsg_dev *fsg = the_fsg; ++ ++ /* Unregister the driver iff the thread hasn't already done so */ ++ if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) ++ usb_gadget_unregister_driver(&fsg_driver); ++ ++ /* Wait for the thread to finish up */ ++ wait_for_completion(&fsg->thread_notifier); ++ ++ kref_put(&fsg->ref, fsg_release); ++} ++module_exit(fsg_cleanup); +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 344d5e2..0937bde 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -663,6 +663,19 @@ config USB_HWA_HCD + To compile this driver a module, choose M here: the module + will be called "hwa-hc". + ++config USB_DWCOTG ++ tristate "Synopsis DWC host support" ++ depends on USB ++ help ++ The Synopsis DWC controller is a dual-role ++ host/peripheral/OTG ("On The Go") USB controllers. ++ ++ Enable this option to support this IP in host controller mode. ++ If unsure, say N. ++ ++ To compile this driver as a module, choose M here: the ++ modules built will be called dwc_otg and dwc_common_port. ++ + config USB_IMX21_HCD + tristate "i.MX21 HCD support" + depends on ARM && ARCH_MXC +diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile +index 4fb73c1..76d97de 100644 +--- a/drivers/usb/host/Makefile ++++ b/drivers/usb/host/Makefile +@@ -47,6 +47,8 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o + obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o + obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o + obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o ++ ++obj-$(CONFIG_USB_DWCOTG) += dwc_otg/ dwc_common_port/ + obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o + obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o + obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o +diff --git a/drivers/usb/host/dwc_common_port/Makefile b/drivers/usb/host/dwc_common_port/Makefile +new file mode 100644 +index 0000000..63e3485 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/Makefile +@@ -0,0 +1,58 @@ ++# ++# Makefile for DWC_common library ++# ++ ++ifneq ($(KERNELRELEASE),) ++ ++EXTRA_CFLAGS += -DDWC_LINUX ++#EXTRA_CFLAGS += -DDEBUG ++#EXTRA_CFLAGS += -DDWC_DEBUG_REGS ++#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY ++ ++EXTRA_CFLAGS += -DDWC_LIBMODULE ++EXTRA_CFLAGS += -DDWC_CCLIB ++#EXTRA_CFLAGS += -DDWC_CRYPTOLIB ++EXTRA_CFLAGS += -DDWC_NOTIFYLIB ++EXTRA_CFLAGS += -DDWC_UTFLIB ++ ++obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o ++dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ ++ dwc_crypto.o dwc_notifier.o \ ++ dwc_common_linux.o dwc_mem.o ++ ++kernrelwd := $(subst ., ,$(KERNELRELEASE)) ++kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) ++ ++ifneq ($(kernrel3),2.6.20) ++# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually ++EXTRA_CFLAGS += $(CPPFLAGS) ++endif ++ ++else ++ ++#ifeq ($(KDIR),) ++#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) ++#endif ++ ++ifeq ($(ARCH),) ++$(error Must give "ARCH=" on command line or in environment. Also, if \ ++ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-") ++endif ++ ++ifeq ($(DOXYGEN),) ++DOXYGEN := doxygen ++endif ++ ++default: ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++endif ++ ++clean: ++ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ +diff --git a/drivers/usb/host/dwc_common_port/Makefile.fbsd b/drivers/usb/host/dwc_common_port/Makefile.fbsd +new file mode 100644 +index 0000000..45db991 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/Makefile.fbsd +@@ -0,0 +1,17 @@ ++CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include ++CFLAGS += -DDWC_FREEBSD ++CFLAGS += -DDEBUG ++#CFLAGS += -DDWC_DEBUG_REGS ++#CFLAGS += -DDWC_DEBUG_MEMORY ++ ++#CFLAGS += -DDWC_LIBMODULE ++#CFLAGS += -DDWC_CCLIB ++#CFLAGS += -DDWC_CRYPTOLIB ++#CFLAGS += -DDWC_NOTIFYLIB ++#CFLAGS += -DDWC_UTFLIB ++ ++KMOD = dwc_common_port_lib ++SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \ ++ dwc_common_fbsd.c dwc_mem.c ++ ++.include +diff --git a/drivers/usb/host/dwc_common_port/Makefile.linux b/drivers/usb/host/dwc_common_port/Makefile.linux +new file mode 100644 +index 0000000..961df3f +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/Makefile.linux +@@ -0,0 +1,49 @@ ++# ++# Makefile for DWC_common library ++# ++ifneq ($(KERNELRELEASE),) ++ ++EXTRA_CFLAGS += -DDWC_LINUX ++#EXTRA_CFLAGS += -DDEBUG ++#EXTRA_CFLAGS += -DDWC_DEBUG_REGS ++#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY ++ ++EXTRA_CFLAGS += -DDWC_LIBMODULE ++EXTRA_CFLAGS += -DDWC_CCLIB ++EXTRA_CFLAGS += -DDWC_CRYPTOLIB ++EXTRA_CFLAGS += -DDWC_NOTIFYLIB ++EXTRA_CFLAGS += -DDWC_UTFLIB ++ ++obj-m := dwc_common_port_lib.o ++dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ ++ dwc_crypto.o dwc_notifier.o \ ++ dwc_common_linux.o dwc_mem.o ++ ++else ++ ++ifeq ($(KDIR),) ++$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) ++endif ++ ++ifeq ($(ARCH),) ++$(error Must give "ARCH=" on command line or in environment. Also, if \ ++ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-") ++endif ++ ++ifeq ($(DOXYGEN),) ++DOXYGEN := doxygen ++endif ++ ++default: ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++endif ++ ++clean: ++ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ +diff --git a/drivers/usb/host/dwc_common_port/changes.txt b/drivers/usb/host/dwc_common_port/changes.txt +new file mode 100644 +index 0000000..f6839f9 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/changes.txt +@@ -0,0 +1,174 @@ ++ ++dwc_read_reg32() and friends now take an additional parameter, a pointer to an ++IO context struct. The IO context struct should live in an os-dependent struct ++in your driver. As an example, the dwc_usb3 driver has an os-dependent struct ++named 'os_dep' embedded in the main device struct. So there these calls look ++like this: ++ ++ dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg); ++ ++ dwc_write_reg32(&usb3_dev->os_dep.ioctx, ++ &pcd->dev_global_regs->dcfg, 0); ++ ++Note that for the existing Linux driver ports, it is not necessary to actually ++define the 'ioctx' member in the os-dependent struct. Since Linux does not ++require an IO context, its macros for dwc_read_reg32() and friends do not ++use the context pointer, so it is optimized away by the compiler. But it is ++necessary to add the pointer parameter to all of the call sites, to be ready ++for any future ports (such as FreeBSD) which do require an IO context. ++ ++ ++Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now ++take an additional parameter, a pointer to a memory context. Examples: ++ ++ addr = dwc_alloc(&usb3_dev->os_dep.memctx, size); ++ ++ dwc_free(&usb3_dev->os_dep.memctx, addr); ++ ++Again, for the Linux ports, it is not necessary to actually define the memctx ++member, but it is necessary to add the pointer parameter to all of the call ++sites. ++ ++ ++Same for dwc_dma_alloc() and dwc_dma_free(). Examples: ++ ++ virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr); ++ ++ dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr); ++ ++ ++Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples: ++ ++ mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx); ++ ++ dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex); ++ ++ ++Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples: ++ ++ lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx); ++ ++ dwc_spinlock_free(&usb3_dev->osdep.splctx, lock); ++ ++ ++Same for dwc_timer_alloc(). Example: ++ ++ timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1", ++ cb_func, cb_data); ++ ++ ++Same for dwc_waitq_alloc(). Example: ++ ++ waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx); ++ ++ ++Same for dwc_thread_run(). Example: ++ ++ thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func, ++ "dwc_usb3_thd1", data); ++ ++ ++Same for dwc_workq_alloc(). Example: ++ ++ workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1"); ++ ++ ++Same for dwc_task_alloc(). Example: ++ ++ task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1", ++ cb_func, cb_data); ++ ++ ++In addition to the context pointer additions, a few core functions have had ++other changes made to their parameters: ++ ++The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore() ++has been changed from a uint64_t to a dwc_irqflags_t. ++ ++dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the ++FreeBSD equivalent of that function requires it. ++ ++And, in addition to the context pointer, dwc_task_alloc() also adds a ++'char *name' parameter, to be consistent with dwc_thread_run() and ++dwc_workq_alloc(), and because the FreeBSD equivalent of that function ++requires a unique name. ++ ++ ++Here is a complete list of the core functions that now take a pointer to a ++context as their first parameter: ++ ++ dwc_read_reg32 ++ dwc_read_reg64 ++ dwc_write_reg32 ++ dwc_write_reg64 ++ dwc_modify_reg32 ++ dwc_modify_reg64 ++ dwc_alloc ++ dwc_alloc_atomic ++ dwc_strdup ++ dwc_free ++ dwc_dma_alloc ++ dwc_dma_free ++ dwc_mutex_alloc ++ dwc_mutex_free ++ dwc_spinlock_alloc ++ dwc_spinlock_free ++ dwc_timer_alloc ++ dwc_waitq_alloc ++ dwc_thread_run ++ dwc_workq_alloc ++ dwc_task_alloc Also adds a 'char *name' as its 2nd parameter ++ ++And here are the core functions that have other changes to their parameters: ++ ++ dwc_spinlock_irqsave 'flags' param is now a 'dwc_irqflags_t *' ++ dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t' ++ dwc_thread_should_stop Adds a 'dwc_thread_t *' parameter ++ ++ ++ ++The changes to the core functions also require some of the other library ++functions to change: ++ ++ dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx' ++ (for memory allocation) as the 1st param and a 'void *mtxctx' ++ (for mutex allocation) as the 2nd param. ++ ++ dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(), ++ dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a ++ 'void *memctx' as the 1st param. ++ ++ dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a ++ 'void *memctx' as the 1st param. ++ ++ dwc_modpow() now takes a 'void *memctx' as the 1st param. ++ ++ dwc_alloc_notification_manager() now takes a 'void *memctx' as the ++ 1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd ++ param, and also now returns an integer value that is non-zero if ++ allocation of its data structures or work queue fails. ++ ++ dwc_register_notifier() now takes a 'void *memctx' as the 1st param. ++ ++ dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first ++ param, and also now returns an integer value that is non-zero if ++ allocation of its data structures fails. ++ ++ ++ ++Other miscellaneous changes: ++ ++The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to ++DWC_DEBUG_MEMORY and DWC_DEBUG_REGS. ++ ++The following #define's have been added to allow selectively compiling library ++features: ++ ++ DWC_CCLIB ++ DWC_CRYPTOLIB ++ DWC_NOTIFYLIB ++ DWC_UTFLIB ++ ++A DWC_LIBMODULE #define has also been added. If this is not defined, then the ++module code in dwc_common_linux.c is not compiled in. This allows linking the ++library code directly into a driver module, instead of as a standalone module. +diff --git a/drivers/usb/host/dwc_common_port/doc/doxygen.cfg b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg +new file mode 100644 +index 0000000..605b9dab +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg +@@ -0,0 +1,270 @@ ++# Doxyfile 1.4.5 ++ ++#--------------------------------------------------------------------------- ++# Project related configuration options ++#--------------------------------------------------------------------------- ++PROJECT_NAME = "Synopsys DWC Portability and Common Library for UWB" ++PROJECT_NUMBER = ++OUTPUT_DIRECTORY = doc ++CREATE_SUBDIRS = NO ++OUTPUT_LANGUAGE = English ++BRIEF_MEMBER_DESC = YES ++REPEAT_BRIEF = YES ++ABBREVIATE_BRIEF = "The $name class" \ ++ "The $name widget" \ ++ "The $name file" \ ++ is \ ++ provides \ ++ specifies \ ++ contains \ ++ represents \ ++ a \ ++ an \ ++ the ++ALWAYS_DETAILED_SEC = YES ++INLINE_INHERITED_MEMB = NO ++FULL_PATH_NAMES = NO ++STRIP_FROM_PATH = .. ++STRIP_FROM_INC_PATH = ++SHORT_NAMES = NO ++JAVADOC_AUTOBRIEF = YES ++MULTILINE_CPP_IS_BRIEF = NO ++DETAILS_AT_TOP = YES ++INHERIT_DOCS = YES ++SEPARATE_MEMBER_PAGES = NO ++TAB_SIZE = 8 ++ALIASES = ++OPTIMIZE_OUTPUT_FOR_C = YES ++OPTIMIZE_OUTPUT_JAVA = NO ++BUILTIN_STL_SUPPORT = NO ++DISTRIBUTE_GROUP_DOC = NO ++SUBGROUPING = NO ++#--------------------------------------------------------------------------- ++# Build related configuration options ++#--------------------------------------------------------------------------- ++EXTRACT_ALL = NO ++EXTRACT_PRIVATE = NO ++EXTRACT_STATIC = YES ++EXTRACT_LOCAL_CLASSES = NO ++EXTRACT_LOCAL_METHODS = NO ++HIDE_UNDOC_MEMBERS = NO ++HIDE_UNDOC_CLASSES = NO ++HIDE_FRIEND_COMPOUNDS = NO ++HIDE_IN_BODY_DOCS = NO ++INTERNAL_DOCS = NO ++CASE_SENSE_NAMES = YES ++HIDE_SCOPE_NAMES = NO ++SHOW_INCLUDE_FILES = NO ++INLINE_INFO = YES ++SORT_MEMBER_DOCS = NO ++SORT_BRIEF_DOCS = NO ++SORT_BY_SCOPE_NAME = NO ++GENERATE_TODOLIST = YES ++GENERATE_TESTLIST = YES ++GENERATE_BUGLIST = YES ++GENERATE_DEPRECATEDLIST= YES ++ENABLED_SECTIONS = ++MAX_INITIALIZER_LINES = 30 ++SHOW_USED_FILES = YES ++SHOW_DIRECTORIES = YES ++FILE_VERSION_FILTER = ++#--------------------------------------------------------------------------- ++# configuration options related to warning and progress messages ++#--------------------------------------------------------------------------- ++QUIET = YES ++WARNINGS = YES ++WARN_IF_UNDOCUMENTED = NO ++WARN_IF_DOC_ERROR = YES ++WARN_NO_PARAMDOC = YES ++WARN_FORMAT = "$file:$line: $text" ++WARN_LOGFILE = ++#--------------------------------------------------------------------------- ++# configuration options related to the input files ++#--------------------------------------------------------------------------- ++INPUT = . ++FILE_PATTERNS = *.c \ ++ *.cc \ ++ *.cxx \ ++ *.cpp \ ++ *.c++ \ ++ *.d \ ++ *.java \ ++ *.ii \ ++ *.ixx \ ++ *.ipp \ ++ *.i++ \ ++ *.inl \ ++ *.h \ ++ *.hh \ ++ *.hxx \ ++ *.hpp \ ++ *.h++ \ ++ *.idl \ ++ *.odl \ ++ *.cs \ ++ *.php \ ++ *.php3 \ ++ *.inc \ ++ *.m \ ++ *.mm \ ++ *.dox \ ++ *.py \ ++ *.C \ ++ *.CC \ ++ *.C++ \ ++ *.II \ ++ *.I++ \ ++ *.H \ ++ *.HH \ ++ *.H++ \ ++ *.CS \ ++ *.PHP \ ++ *.PHP3 \ ++ *.M \ ++ *.MM \ ++ *.PY ++RECURSIVE = NO ++EXCLUDE = ++EXCLUDE_SYMLINKS = NO ++EXCLUDE_PATTERNS = ++EXAMPLE_PATH = ++EXAMPLE_PATTERNS = * ++EXAMPLE_RECURSIVE = NO ++IMAGE_PATH = ++INPUT_FILTER = ++FILTER_PATTERNS = ++FILTER_SOURCE_FILES = NO ++#--------------------------------------------------------------------------- ++# configuration options related to source browsing ++#--------------------------------------------------------------------------- ++SOURCE_BROWSER = NO ++INLINE_SOURCES = NO ++STRIP_CODE_COMMENTS = YES ++REFERENCED_BY_RELATION = YES ++REFERENCES_RELATION = YES ++USE_HTAGS = NO ++VERBATIM_HEADERS = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the alphabetical class index ++#--------------------------------------------------------------------------- ++ALPHABETICAL_INDEX = NO ++COLS_IN_ALPHA_INDEX = 5 ++IGNORE_PREFIX = ++#--------------------------------------------------------------------------- ++# configuration options related to the HTML output ++#--------------------------------------------------------------------------- ++GENERATE_HTML = YES ++HTML_OUTPUT = html ++HTML_FILE_EXTENSION = .html ++HTML_HEADER = ++HTML_FOOTER = ++HTML_STYLESHEET = ++HTML_ALIGN_MEMBERS = YES ++GENERATE_HTMLHELP = NO ++CHM_FILE = ++HHC_LOCATION = ++GENERATE_CHI = NO ++BINARY_TOC = NO ++TOC_EXPAND = NO ++DISABLE_INDEX = NO ++ENUM_VALUES_PER_LINE = 4 ++GENERATE_TREEVIEW = YES ++TREEVIEW_WIDTH = 250 ++#--------------------------------------------------------------------------- ++# configuration options related to the LaTeX output ++#--------------------------------------------------------------------------- ++GENERATE_LATEX = NO ++LATEX_OUTPUT = latex ++LATEX_CMD_NAME = latex ++MAKEINDEX_CMD_NAME = makeindex ++COMPACT_LATEX = NO ++PAPER_TYPE = a4wide ++EXTRA_PACKAGES = ++LATEX_HEADER = ++PDF_HYPERLINKS = NO ++USE_PDFLATEX = NO ++LATEX_BATCHMODE = NO ++LATEX_HIDE_INDICES = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the RTF output ++#--------------------------------------------------------------------------- ++GENERATE_RTF = NO ++RTF_OUTPUT = rtf ++COMPACT_RTF = NO ++RTF_HYPERLINKS = NO ++RTF_STYLESHEET_FILE = ++RTF_EXTENSIONS_FILE = ++#--------------------------------------------------------------------------- ++# configuration options related to the man page output ++#--------------------------------------------------------------------------- ++GENERATE_MAN = NO ++MAN_OUTPUT = man ++MAN_EXTENSION = .3 ++MAN_LINKS = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the XML output ++#--------------------------------------------------------------------------- ++GENERATE_XML = NO ++XML_OUTPUT = xml ++XML_SCHEMA = ++XML_DTD = ++XML_PROGRAMLISTING = YES ++#--------------------------------------------------------------------------- ++# configuration options for the AutoGen Definitions output ++#--------------------------------------------------------------------------- ++GENERATE_AUTOGEN_DEF = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the Perl module output ++#--------------------------------------------------------------------------- ++GENERATE_PERLMOD = NO ++PERLMOD_LATEX = NO ++PERLMOD_PRETTY = YES ++PERLMOD_MAKEVAR_PREFIX = ++#--------------------------------------------------------------------------- ++# Configuration options related to the preprocessor ++#--------------------------------------------------------------------------- ++ENABLE_PREPROCESSING = YES ++MACRO_EXPANSION = NO ++EXPAND_ONLY_PREDEF = NO ++SEARCH_INCLUDES = YES ++INCLUDE_PATH = ++INCLUDE_FILE_PATTERNS = ++PREDEFINED = DEBUG DEBUG_MEMORY ++EXPAND_AS_DEFINED = ++SKIP_FUNCTION_MACROS = YES ++#--------------------------------------------------------------------------- ++# Configuration::additions related to external references ++#--------------------------------------------------------------------------- ++TAGFILES = ++GENERATE_TAGFILE = ++ALLEXTERNALS = NO ++EXTERNAL_GROUPS = YES ++PERL_PATH = /usr/bin/perl ++#--------------------------------------------------------------------------- ++# Configuration options related to the dot tool ++#--------------------------------------------------------------------------- ++CLASS_DIAGRAMS = YES ++HIDE_UNDOC_RELATIONS = YES ++HAVE_DOT = NO ++CLASS_GRAPH = YES ++COLLABORATION_GRAPH = YES ++GROUP_GRAPHS = YES ++UML_LOOK = NO ++TEMPLATE_RELATIONS = NO ++INCLUDE_GRAPH = NO ++INCLUDED_BY_GRAPH = YES ++CALL_GRAPH = NO ++GRAPHICAL_HIERARCHY = YES ++DIRECTORY_GRAPH = YES ++DOT_IMAGE_FORMAT = png ++DOT_PATH = ++DOTFILE_DIRS = ++MAX_DOT_GRAPH_DEPTH = 1000 ++DOT_TRANSPARENT = NO ++DOT_MULTI_TARGETS = NO ++GENERATE_LEGEND = YES ++DOT_CLEANUP = YES ++#--------------------------------------------------------------------------- ++# Configuration::additions related to the search engine ++#--------------------------------------------------------------------------- ++SEARCHENGINE = NO +diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.c b/drivers/usb/host/dwc_common_port/dwc_cc.c +new file mode 100644 +index 0000000..613c901 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_cc.c +@@ -0,0 +1,532 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $ ++ * $Revision: #4 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621692 $ ++ * ++ * Synopsys Portability Library Software 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. ++ * ========================================================================= */ ++#ifdef DWC_CCLIB ++ ++#include "dwc_cc.h" ++ ++typedef struct dwc_cc ++{ ++ uint32_t uid; ++ uint8_t chid[16]; ++ uint8_t cdid[16]; ++ uint8_t ck[16]; ++ uint8_t *name; ++ uint8_t length; ++ DWC_CIRCLEQ_ENTRY(dwc_cc) list_entry; ++} dwc_cc_t; ++ ++DWC_CIRCLEQ_HEAD(context_list, dwc_cc); ++ ++/** The main structure for CC management. */ ++struct dwc_cc_if ++{ ++ dwc_mutex_t *mutex; ++ char *filename; ++ ++ unsigned is_host:1; ++ ++ dwc_notifier_t *notifier; ++ ++ struct context_list list; ++}; ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ DWC_PRINTF("%s: ", name); ++ for (i=0; ilength = length; ++ cc->name = dwc_alloc(mem_ctx, length); ++ if (!cc->name) { ++ dwc_free(mem_ctx, cc); ++ return NULL; ++ } ++ ++ DWC_MEMCPY(cc->name, name, length); ++ } ++ ++ return cc; ++} ++ ++static void free_cc(void *mem_ctx, dwc_cc_t *cc) ++{ ++ if (cc->name) { ++ dwc_free(mem_ctx, cc->name); ++ } ++ dwc_free(mem_ctx, cc); ++} ++ ++static uint32_t next_uid(dwc_cc_if_t *cc_if) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (cc->uid > uid) { ++ uid = cc->uid; ++ } ++ } ++ ++ if (uid == 0) { ++ uid = 255; ++ } ++ ++ return uid + 1; ++} ++ ++static dwc_cc_t *cc_find(dwc_cc_if_t *cc_if, uint32_t uid) ++{ ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (cc->uid == uid) { ++ return cc; ++ } ++ } ++ return NULL; ++} ++ ++static unsigned int cc_data_size(dwc_cc_if_t *cc_if) ++{ ++ unsigned int size = 0; ++ dwc_cc_t *cc; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ size += (48 + 1); ++ if (cc->name) { ++ size += cc->length; ++ } ++ } ++ return size; ++} ++ ++static uint32_t cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (DWC_MEMCMP(cc->chid, chid, 16) == 0) { ++ uid = cc->uid; ++ break; ++ } ++ } ++ return uid; ++} ++static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) ++{ ++ uint32_t uid = 0; ++ dwc_cc_t *cc; ++ ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ if (DWC_MEMCMP(cc->cdid, cdid, 16) == 0) { ++ uid = cc->uid; ++ break; ++ } ++ } ++ return uid; ++} ++ ++/* Internal cc_add */ ++static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ dwc_cc_t *cc; ++ uint32_t uid; ++ ++ if (cc_if->is_host) { ++ uid = cc_match_cdid(cc_if, cdid); ++ } ++ else { ++ uid = cc_match_chid(cc_if, chid); ++ } ++ ++ if (uid) { ++ DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); ++ cc = cc_find(cc_if, uid); ++ } ++ else { ++ cc = alloc_cc(mem_ctx, name, length); ++ cc->uid = next_uid(cc_if); ++ DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry); ++ } ++ ++ DWC_MEMCPY(&(cc->chid[0]), chid, 16); ++ DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); ++ DWC_MEMCPY(&(cc->ck[0]), ck, 16); ++ ++ DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); ++ dump_bytes("CHID", cc->chid, 16); ++ dump_bytes("CDID", cc->cdid, 16); ++ dump_bytes("CK", cc->ck, 16); ++ return cc->uid; ++} ++ ++/* Internal cc_clear */ ++static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) ++{ ++ while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) { ++ dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list); ++ DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); ++ free_cc(mem_ctx, cc); ++ } ++} ++ ++dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ dwc_notifier_t *notifier, unsigned is_host) ++{ ++ dwc_cc_if_t *cc_if = NULL; ++ ++ /* Allocate a common_cc_if structure */ ++ cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t)); ++ ++ if (!cc_if) ++ return NULL; ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++ DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex); ++#else ++ cc_if->mutex = dwc_mutex_alloc(mtx_ctx); ++#endif ++ if (!cc_if->mutex) { ++ dwc_free(mem_ctx, cc_if); ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT(&cc_if->list); ++ cc_if->is_host = is_host; ++ cc_if->notifier = notifier; ++ return cc_if; ++} ++ ++void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if) ++{ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++ DWC_MUTEX_FREE(cc_if->mutex); ++#else ++ dwc_mutex_free(mtx_ctx, cc_if->mutex); ++#endif ++ cc_clear(mem_ctx, cc_if); ++ dwc_free(mem_ctx, cc_if); ++} ++ ++static void cc_changed(dwc_cc_if_t *cc_if) ++{ ++ if (cc_if->notifier) { ++ dwc_notify(cc_if->notifier, DWC_CC_LIST_CHANGED_NOTIFICATION, cc_if); ++ } ++} ++ ++void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) ++{ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc_clear(mem_ctx, cc_if); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ cc_changed(cc_if); ++} ++ ++int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ uint32_t uid; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ cc_changed(cc_if); ++ ++ return uid; ++} ++ ++void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++{ ++ dwc_cc_t* cc; ++ ++ DWC_DEBUGC("Change connection context %d", id); ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (!cc) { ++ DWC_ERROR("Uid %d not found in cc list\n", id); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ ++ if (chid) { ++ DWC_MEMCPY(&(cc->chid[0]), chid, 16); ++ } ++ if (cdid) { ++ DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); ++ } ++ if (ck) { ++ DWC_MEMCPY(&(cc->ck[0]), ck, 16); ++ } ++ ++ if (name) { ++ if (cc->name) { ++ dwc_free(mem_ctx, cc->name); ++ } ++ cc->name = dwc_alloc(mem_ctx, length); ++ if (!cc->name) { ++ DWC_ERROR("Out of memory in dwc_cc_change()\n"); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ cc->length = length; ++ DWC_MEMCPY(cc->name, name, length); ++ } ++ ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ cc_changed(cc_if); ++ ++ DWC_DEBUGC("Changed connection context id=%d\n", id); ++ dump_bytes("New CHID", cc->chid, 16); ++ dump_bytes("New CDID", cc->cdid, 16); ++ dump_bytes("New CK", cc->ck, 16); ++} ++ ++void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id) ++{ ++ dwc_cc_t *cc; ++ ++ DWC_DEBUGC("Removing connection context %d", id); ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (!cc) { ++ DWC_ERROR("Uid %d not found in cc list\n", id); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; ++ } ++ ++ DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ free_cc(mem_ctx, cc); ++ ++ cc_changed(cc_if); ++} ++ ++uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length) ++{ ++ uint8_t *buf, *x; ++ uint8_t zero = 0; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ *length = cc_data_size(cc_if); ++ if (!(*length)) { ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return NULL; ++ } ++ ++ DWC_DEBUGC("Creating data for saving (length=%d)", *length); ++ ++ buf = dwc_alloc(mem_ctx, *length); ++ if (!buf) { ++ *length = 0; ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return NULL; ++ } ++ ++ x = buf; ++ DWC_CIRCLEQ_FOREACH(cc, &cc_if->list, list_entry) { ++ DWC_MEMCPY(x, cc->chid, 16); ++ x += 16; ++ DWC_MEMCPY(x, cc->cdid, 16); ++ x += 16; ++ DWC_MEMCPY(x, cc->ck, 16); ++ x += 16; ++ if (cc->name) { ++ DWC_MEMCPY(x, &cc->length, 1); ++ x += 1; ++ DWC_MEMCPY(x, cc->name, cc->length); ++ x += cc->length; ++ } ++ else { ++ DWC_MEMCPY(x, &zero, 1); ++ x += 1; ++ } ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return buf; ++} ++ ++void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length) ++{ ++ uint8_t name_length; ++ uint8_t *name; ++ uint8_t *chid; ++ uint8_t *cdid; ++ uint8_t *ck; ++ uint32_t i = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc_clear(mem_ctx, cc_if); ++ ++ while (i < length) { ++ chid = &data[i]; ++ i += 16; ++ cdid = &data[i]; ++ i += 16; ++ ck = &data[i]; ++ i += 16; ++ ++ name_length = data[i]; ++ i ++; ++ ++ if (name_length) { ++ name = &data[i]; ++ i += name_length; ++ } ++ else { ++ name = NULL; ++ } ++ ++ /* check to see if we haven't overflown the buffer */ ++ if (i > length) { ++ DWC_ERROR("Data format error while attempting to load CCs " ++ "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length); ++ break; ++ } ++ ++ cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length); ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ cc_changed(cc_if); ++} ++ ++uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid) ++{ ++ uint32_t uid = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_match_chid(cc_if, chid); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return uid; ++} ++uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) ++{ ++ uint32_t uid = 0; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ uid = cc_match_cdid(cc_if, cdid); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return uid; ++} ++ ++uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *ck = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ ck = cc->ck; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return ck; ++ ++} ++ ++uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ retval = cc->chid; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ retval = cc->cdid; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length) ++{ ++ uint8_t *retval = NULL; ++ dwc_cc_t *cc; ++ ++ DWC_MUTEX_LOCK(cc_if->mutex); ++ *length = 0; ++ cc = cc_find(cc_if, id); ++ if (cc) { ++ *length = cc->length; ++ retval = cc->name; ++ } ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ ++ return retval; ++} ++ ++#endif /* DWC_CCLIB */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.h b/drivers/usb/host/dwc_common_port/dwc_cc.h +new file mode 100644 +index 0000000..6b2bbaf +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_cc.h +@@ -0,0 +1,225 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $ ++ * $Revision: #4 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software 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_CC_H_ ++#define _DWC_CC_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file defines the Context Context library. ++ * ++ * The main data structure is dwc_cc_if_t which is returned by either the ++ * dwc_cc_if_alloc function or returned by the module to the user via a provided ++ * function. The data structure is opaque and should only be manipulated via the ++ * functions provied in this API. ++ * ++ * It manages a list of connection contexts and operations can be performed to ++ * add, remove, query, search, and change, those contexts. Additionally, ++ * a dwc_notifier_t object can be requested from the manager so that ++ * the user can be notified whenever the context list has changed. ++ */ ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++#include "dwc_notifier.h" ++ ++ ++/* Notifications */ ++#define DWC_CC_LIST_CHANGED_NOTIFICATION "DWC_CC_LIST_CHANGED_NOTIFICATION" ++ ++struct dwc_cc_if; ++typedef struct dwc_cc_if dwc_cc_if_t; ++ ++ ++/** @name Connection Context Operations */ ++/** @{ */ ++ ++/** This function allocates memory for a dwc_cc_if_t structure, initializes ++ * fields to default values, and returns a pointer to the structure or NULL on ++ * error. */ ++extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ dwc_notifier_t *notifier, unsigned is_host); ++ ++/** Frees the memory for the specified CC structure allocated from ++ * dwc_cc_if_alloc(). */ ++extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if); ++ ++/** Removes all contexts from the connection context list */ ++extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if); ++ ++/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list. ++ * If a CHID already exists, the CK and name are overwritten. Statistics are ++ * not overwritten. ++ * ++ * @param cc_if The cc_if structure. ++ * @param chid A pointer to the 16-byte CHID. This value will be copied. ++ * @param ck A pointer to the 16-byte CK. This value will be copied. ++ * @param cdid A pointer to the 16-byte CDID. This value will be copied. ++ * @param name An optional host friendly name as defined in the association model ++ * spec. Must be a UTF16-LE unicode string. Can be NULL to indicated no name. ++ * @param length The length othe unicode string. ++ * @return A unique identifier used to refer to this context that is valid for ++ * as long as this context is still in the list. */ ++extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, ++ uint8_t length); ++ ++/** Changes the CHID, CK, CDID, or Name values of a connection context in the ++ * list, preserving any accumulated statistics. This would typically be called ++ * if the host decideds to change the context with a SET_CONNECTION request. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @param chid A pointer to the 16-byte CHID. This value will be copied. NULL ++ * indicates no change. ++ * @param cdid A pointer to the 16-byte CDID. This value will be copied. NULL ++ * indicates no change. ++ * @param ck A pointer to the 16-byte CK. This value will be copied. NULL ++ * indicates no change. ++ * @param name Host friendly name UTF16-LE. NULL indicates no change. ++ * @param length Length of name. */ ++extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, ++ uint8_t *chid, uint8_t *cdid, uint8_t *ck, ++ uint8_t *name, uint8_t length); ++ ++/** Remove the specified connection context. ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context to remove. */ ++extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Get a binary block of data for the connection context list and attributes. ++ * This data can be used by the OS specific driver to save the connection ++ * context list into non-volatile memory. ++ * ++ * @param cc_if The cc_if structure. ++ * @param length Return the length of the data buffer. ++ * @return A pointer to the data buffer. The memory for this buffer should be ++ * freed with DWC_FREE() after use. */ ++extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, ++ unsigned int *length); ++ ++/** Restore the connection context list from the binary data that was previously ++ * returned from a call to dwc_cc_data_for_save. This can be used by the OS specific ++ * driver to load a connection context list from non-volatile memory. ++ * ++ * @param cc_if The cc_if structure. ++ * @param data The data bytes as returned from dwc_cc_data_for_save. ++ * @param length The length of the data. */ ++extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, ++ uint8_t *data, unsigned int length); ++ ++/** Find the connection context from the specified CHID. ++ * ++ * @param cc_if The cc_if structure. ++ * @param chid A pointer to the CHID data. ++ * @return A non-zero identifier of the connection context if the CHID matches. ++ * Otherwise returns 0. */ ++extern uint32_t dwc_cc_match_chid(dwc_cc_if_t *cc_if, uint8_t *chid); ++ ++/** Find the connection context from the specified CDID. ++ * ++ * @param cc_if The cc_if structure. ++ * @param cdid A pointer to the CDID data. ++ * @return A non-zero identifier of the connection context if the CHID matches. ++ * Otherwise returns 0. */ ++extern uint32_t dwc_cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid); ++ ++/** Retrieve the CK from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CK data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_ck(dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Retrieve the CHID from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CHID data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_chid(dwc_cc_if_t *cc_if, int32_t id); ++ ++/** Retrieve the CDID from the specified connection context. ++ * ++ * @param cc_if The cc_if structure. ++ * @param id The identifier of the connection context. ++ * @return A pointer to the CDID data. The memory does not need to be freed. */ ++extern uint8_t *dwc_cc_cdid(dwc_cc_if_t *cc_if, int32_t id); ++ ++extern uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length); ++ ++/** Checks a buffer for non-zero. ++ * @param id A pointer to a 16 byte buffer. ++ * @return true if the 16 byte value is non-zero. */ ++static inline unsigned dwc_assoc_is_not_zero_id(uint8_t *id) { ++ int i; ++ for (i=0; i<16; i++) { ++ if (id[i]) return 1; ++ } ++ return 0; ++} ++ ++/** Checks a buffer for zero. ++ * @param id A pointer to a 16 byte buffer. ++ * @return true if the 16 byte value is zero. */ ++static inline unsigned dwc_assoc_is_zero_id(uint8_t *id) { ++ return !dwc_assoc_is_not_zero_id(id); ++} ++ ++/** Prints an ASCII representation for the 16-byte chid, cdid, or ck, into ++ * buffer. */ ++static inline int dwc_print_id_string(char *buffer, uint8_t *id) { ++ char *ptr = buffer; ++ int i; ++ for (i=0; i<16; i++) { ++ ptr += DWC_SPRINTF(ptr, "%02x", id[i]); ++ if (i < 15) { ++ ptr += DWC_SPRINTF(ptr, " "); ++ } ++ } ++ return ptr - buffer; ++} ++ ++/** @} */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_CC_H_ */ ++ +diff --git a/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c +new file mode 100644 +index 0000000..6dd04b5 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c +@@ -0,0 +1,1308 @@ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++#ifdef DWC_CCLIB ++# include "dwc_cc.h" ++#endif ++ ++#ifdef DWC_CRYPTOLIB ++# include "dwc_modpow.h" ++# include "dwc_dh.h" ++# include "dwc_crypto.h" ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++# include "dwc_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */ ++ ++ ++/* MISC */ ++ ++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ bcopy(src, dest, size); ++ return dest; ++} ++ ++int DWC_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int DWC_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int DWC_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int DWC_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *DWC_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *DWC_STRDUP(char const *str) ++{ ++ int len = DWC_STRLEN(str) + 1; ++ char *new = DWC_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ DWC_MEMCPY(new, str, len); ++ return new; ++} ++ ++int DWC_ATOI(char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = strtol(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int DWC_ATOUI(char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef DWC_UTFLIB ++/* From usbstring.c */ ++ ++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++ ++#endif /* DWC_UTFLIB */ ++ ++ ++/* dwc_debug.h */ ++ ++dwc_bool_t DWC_IN_IRQ(void) ++{ ++// return in_irq(); ++ return 0; ++} ++ ++dwc_bool_t DWC_IN_BH(void) ++{ ++// return in_softirq(); ++ return 0; ++} ++ ++void DWC_VPRINTF(char *format, va_list args) ++{ ++ vprintf(format, args); ++} ++ ++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void DWC_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int DWC_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int DWC_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __DWC_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __DWC_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void DWC_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++// BUG_ON(1); ??? ++} ++ ++#ifdef DEBUG ++void __DWC_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* dwc_mem.h */ ++ ++#if 0 ++dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (dwc_pool_t *)pool; ++} ++ ++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++ return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr); ++} ++ ++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) ++{ ++ if (error) ++ return; ++ *(bus_addr_t *)arg = segs[0].ds_addr; ++} ++ ++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; ++ int error; ++ ++ error = bus_dma_tag_create( ++#if __FreeBSD_version >= 700000 ++ bus_get_dma_tag(dma->dev), /* parent */ ++#else ++ NULL, /* parent */ ++#endif ++ 4, 0, /* alignment, bounds */ ++ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ ++ BUS_SPACE_MAXADDR, /* highaddr */ ++ NULL, NULL, /* filter, filterarg */ ++ size, /* maxsize */ ++ 1, /* nsegments */ ++ size, /* maxsegsize */ ++ 0, /* flags */ ++ NULL, /* lockfunc */ ++ NULL, /* lockarg */ ++ &dma->dma_tag); ++ if (error) { ++ device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n", ++ __func__, error); ++ goto fail_0; ++ } ++ ++ error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr, ++ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); ++ if (error) { ++ device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n", ++ __func__, (uintmax_t)size, error); ++ goto fail_1; ++ } ++ ++ dma->dma_paddr = 0; ++ error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size, ++ dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT); ++ if (error || dma->dma_paddr == 0) { ++ device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n", ++ __func__, error); ++ goto fail_2; ++ } ++ ++ *dma_addr = dma->dma_paddr; ++ return dma->dma_vaddr; ++ ++fail_2: ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++fail_1: ++ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); ++ bus_dma_tag_destroy(dma->dma_tag); ++fail_0: ++ dma->dma_map = NULL; ++ dma->dma_tag = NULL; ++ ++ return NULL; ++} ++ ++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) ++{ ++ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; ++ ++ if (dma->dma_tag == NULL) ++ return; ++ if (dma->dma_map != NULL) { ++ bus_dmamap_sync(dma->dma_tag, dma->dma_map, ++ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); ++ dma->dma_map = NULL; ++ } ++ ++ bus_dma_tag_destroy(dma->dma_tag); ++ dma->dma_tag = NULL; ++} ++ ++void *__DWC_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); ++} ++ ++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); ++} ++ ++void __DWC_FREE(void *mem_ctx, void *addr) ++{ ++ free(addr, M_DEVBUF); ++} ++ ++ ++#ifdef DWC_CRYPTOLIB ++/* dwc_crypto.h */ ++ ++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ DWC_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t DWC_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_4(io->iot, io->ioh, ior); ++} ++ ++#if 0 ++uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_8(io->iot, io->ioh, ior); ++} ++#endif ++ ++void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, value); ++} ++ ++#if 0 ++void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, value); ++} ++#endif ++ ++void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, ++ uint32_t set_mask) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, ++ (bus_space_read_4(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++ ++#if 0 ++void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, ++ uint64_t set_mask) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, ++ (bus_space_read_8(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++#endif ++ ++ ++/* Locking */ ++ ++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) ++{ ++ struct mtx *sl = DWC_ALLOC(sizeof(*sl)); ++ ++ if (!sl) { ++ DWC_ERROR("Cannot allocate memory for spinlock"); ++ return NULL; ++ } ++ ++ mtx_init(sl, "dw3spn", NULL, MTX_SPIN); ++ return (dwc_spinlock_t *)sl; ++} ++ ++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) ++{ ++ struct mtx *sl = (struct mtx *)lock; ++ ++ mtx_destroy(sl); ++ DWC_FREE(sl); ++} ++ ++void DWC_SPINLOCK(dwc_spinlock_t *lock) ++{ ++ mtx_lock_spin((struct mtx *)lock); // ??? ++} ++ ++void DWC_SPINUNLOCK(dwc_spinlock_t *lock) ++{ ++ mtx_unlock_spin((struct mtx *)lock); // ??? ++} ++ ++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) ++{ ++ mtx_lock_spin((struct mtx *)lock); ++} ++ ++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) ++{ ++ mtx_unlock_spin((struct mtx *)lock); ++} ++ ++dwc_mutex_t *DWC_MUTEX_ALLOC(void) ++{ ++ struct mtx *m; ++ dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx)); ++ ++ if (!mutex) { ++ DWC_ERROR("Cannot allocate memory for mutex"); ++ return NULL; ++ } ++ ++ m = (struct mtx *)mutex; ++ mtx_init(m, "dw3mtx", NULL, MTX_DEF); ++ return mutex; ++} ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void DWC_MUTEX_FREE(dwc_mutex_t *mutex) ++{ ++ mtx_destroy((struct mtx *)mutex); ++ DWC_FREE(mutex); ++} ++#endif ++ ++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ mtx_lock(m); ++} ++ ++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ return mtx_trylock(m); ++} ++ ++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ mtx_unlock(m); ++} ++ ++ ++/* Timing */ ++ ++void DWC_UDELAY(uint32_t usecs) ++{ ++ DELAY(usecs); ++} ++ ++void DWC_MDELAY(uint32_t msecs) ++{ ++ do { ++ DELAY(1000); ++ } while (--msecs); ++} ++ ++void DWC_MSLEEP(uint32_t msecs) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ pause("dw3slp", tvtohz(&tv)); ++} ++ ++uint32_t DWC_TIME(void) ++{ ++ struct timeval tv; ++ ++ microuptime(&tv); // or getmicrouptime? (less precise, but faster) ++ return tv.tv_sec * 1000 + tv.tv_usec / 1000; ++} ++ ++ ++/* Timers */ ++ ++struct dwc_timer { ++ struct callout t; ++ char *name; ++ dwc_spinlock_t *lock; ++ dwc_timer_callback_t cb; ++ void *data; ++}; ++ ++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) ++{ ++ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ DWC_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ callout_init(&t->t, 1); ++ ++ t->name = DWC_STRDUP(name); ++ if (!t->name) { ++ DWC_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = DWC_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ DWC_ERROR("Cannot allocate memory for lock"); ++ goto no_lock; ++ } ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ DWC_FREE(t->name); ++ no_name: ++ DWC_FREE(t); ++ ++ return NULL; ++} ++ ++void DWC_TIMER_FREE(dwc_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++ DWC_SPINLOCK_FREE(timer->lock); ++ DWC_FREE(timer->name); ++ DWC_FREE(timer); ++} ++ ++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data); ++} ++ ++void DWC_TIMER_CANCEL(dwc_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct dwc_waitq { ++ struct mtx lock; ++ int abort; ++}; ++ ++dwc_waitq_t *DWC_WAITQ_ALLOC(void) ++{ ++ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue"); ++ return NULL; ++ } ++ ++ mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF); ++ wq->abort = 0; ++ ++ return wq; ++} ++ ++void DWC_WAITQ_FREE(dwc_waitq_t *wq) ++{ ++ mtx_destroy(&wq->lock); ++ DWC_FREE(wq); ++} ++ ++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) ++{ ++// intrmask_t ipl; ++ int result = 0; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++// splx(ipl); ++ result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout ++// ipl = splbio(); ++ } ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -DWC_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -DWC_E_ABORT; ++ ++ } else if (wq->abort) { ++ result = -DWC_E_ABORT; ++ ++ } else { ++ result = 0; ++ } ++ ++ wq->abort = 0; ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++ return result; ++} ++ ++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ struct timeval tv, tv1, tv2; ++// intrmask_t ipl; ++ int result = 0; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++// splx(ipl); ++ getmicrouptime(&tv1); ++ result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv)); ++ getmicrouptime(&tv2); ++// ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ result = -DWC_E_ABORT; ++ } else { ++ tv2.tv_usec -= tv1.tv_usec; ++ if (tv2.tv_usec < 0) { ++ tv2.tv_usec += 1000000; ++ tv2.tv_sec--; ++ } ++ ++ tv2.tv_sec -= tv1.tv_sec; ++ result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; ++ result = msecs - result; ++ if (result <= 0) ++ result = 1; ++ } ++ } else if (result == ERESTART) { // signaled - restart ++ result = -DWC_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -DWC_E_ABORT; ++ ++ } else { // timed out ++ result = -DWC_E_TIMEOUT; ++ } ++ ++ wq->abort = 0; ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++ return result; ++} ++ ++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) ++{ ++ wakeup(wq); ++} ++ ++void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++{ ++// intrmask_t ipl; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ wq->abort = 1; ++ wakeup(wq); ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++} ++ ++ ++/* Threading */ ++ ++struct dwc_thread { ++ struct proc *proc; ++ int abort; ++}; ++ ++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) ++{ ++ int retval; ++ dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread)); ++ ++ if (!thread) { ++ return NULL; ++ } ++ ++ thread->abort = 0; ++ retval = kthread_create((void (*)(void *))func, data, &thread->proc, ++ RFPROC | RFNOWAIT, 0, "%s", name); ++ if (retval) { ++ DWC_FREE(thread); ++ return NULL; ++ } ++ ++ return thread; ++} ++ ++int DWC_THREAD_STOP(dwc_thread_t *thread) ++{ ++ int retval; ++ ++ thread->abort = 1; ++ retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz); ++ ++ if (retval == 0) { ++ /* DWC_THREAD_EXIT() will free the thread struct */ ++ return 0; ++ } ++ ++ /* NOTE: We leak the thread struct if thread doesn't die */ ++ ++ if (retval == EWOULDBLOCK) { ++ return -DWC_E_TIMEOUT; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread) ++{ ++ return thread->abort; ++} ++ ++void DWC_THREAD_EXIT(dwc_thread_t *thread) ++{ ++ wakeup(&thread->abort); ++ DWC_FREE(thread); ++ kthread_exit(0); ++} ++ ++ ++/* tasklets ++ - Runs in interrupt context (cannot sleep) ++ - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ] ++ - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ] ++ */ ++struct dwc_tasklet { ++ struct task t; ++ dwc_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(void *data, int pending) // what to do with pending ??? ++{ ++ dwc_tasklet_t *task = (dwc_tasklet_t *)data; ++ ++ task->cb(task->data); ++} ++ ++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) ++{ ++ dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task)); ++ ++ if (task) { ++ task->cb = cb; ++ task->data = data; ++ TASK_INIT(&task->t, 0, tasklet_callback, task); ++ } else { ++ DWC_ERROR("Cannot allocate memory for tasklet"); ++ } ++ ++ return task; ++} ++ ++void DWC_TASK_FREE(dwc_tasklet_t *task) ++{ ++ taskqueue_drain(taskqueue_fast, &task->t); // ??? ++ DWC_FREE(task); ++} ++ ++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) ++{ ++ /* Uses predefined system queue */ ++ taskqueue_enqueue_fast(taskqueue_fast, &task->t); ++} ++ ++ ++/* workqueues ++ - Runs in process context (can sleep) ++ */ ++typedef struct work_container { ++ dwc_work_callback_t cb; ++ void *data; ++ dwc_workq_t *wq; ++ char *name; ++ int hz; ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_ENTRY(work_container) entry; ++#endif ++ struct task task; ++} work_container_t; ++ ++#ifdef DEBUG ++DWC_CIRCLEQ_HEAD(work_container_queue, work_container); ++#endif ++ ++struct dwc_workq { ++ struct taskqueue *taskq; ++ dwc_spinlock_t *lock; ++ dwc_waitq_t *waitq; ++ int pending; ++ ++#ifdef DEBUG ++ struct work_container_queue entries; ++#endif ++}; ++ ++static void do_work(void *data, int pending) // what to do with pending ??? ++{ ++ work_container_t *container = (work_container_t *)data; ++ dwc_workq_t *wq = container->wq; ++ dwc_irqflags_t flags; ++ ++ if (container->hz) { ++ pause("dw3wrk", container->hz); ++ } ++ ++ container->cb(container->data); ++ DWC_DEBUG("Work done: %s, container=%p", container->name, container); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); ++#endif ++ if (container->name) ++ DWC_FREE(container->name); ++ DWC_FREE(container); ++ wq->pending--; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ dwc_workq_t *workq = (dwc_workq_t *)data; ++ ++ return workq->pending == 0; ++} ++ ++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) ++{ ++ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++dwc_workq_t *DWC_WORKQ_ALLOC(char *name) ++{ ++ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for workqueue"); ++ return NULL; ++ } ++ ++ wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq); ++ if (!wq->taskq) { ++ DWC_ERROR("Cannot allocate memory for taskqueue"); ++ goto no_taskq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = DWC_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ DWC_ERROR("Cannot allocate memory for spinlock"); ++ goto no_lock; ++ } ++ ++ wq->waitq = DWC_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue"); ++ goto no_waitq; ++ } ++ ++ taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk"); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INIT(&wq->entries); ++#endif ++ return wq; ++ ++ no_waitq: ++ DWC_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ taskqueue_free(wq->taskq); ++ no_taskq: ++ DWC_FREE(wq); ++ ++ return NULL; ++} ++ ++void DWC_WORKQ_FREE(dwc_workq_t *wq) ++{ ++#ifdef DEBUG ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++ if (wq->pending != 0) { ++ struct work_container *container; ++ ++ DWC_ERROR("Destroying work queue with pending work"); ++ ++ DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) { ++ DWC_ERROR("Work %s still pending", container->name); ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++#endif ++ DWC_WAITQ_FREE(wq->waitq); ++ DWC_SPINLOCK_FREE(wq->lock); ++ taskqueue_free(wq->taskq); ++ DWC_FREE(wq); ++} ++ ++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ container->hz = 0; ++ ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ ++ TASK_INIT(&container->task, 0, do_work, container); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ taskqueue_enqueue_fast(wq->taskq, &container->task); ++} ++ ++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ struct timeval tv; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ container->hz = tvtohz(&tv); ++ ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ ++ TASK_INIT(&container->task, 0, do_work, container); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ taskqueue_enqueue_fast(wq->taskq, &container->task); ++} ++ ++int DWC_WORKQ_PENDING(dwc_workq_t *wq) ++{ ++ return wq->pending; ++} +diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c +new file mode 100644 +index 0000000..f00a9ff +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c +@@ -0,0 +1,1421 @@ ++#include ++#include ++#include ++#include ++ ++#ifdef DWC_CCLIB ++# include "dwc_cc.h" ++#endif ++ ++#ifdef DWC_CRYPTOLIB ++# include "dwc_modpow.h" ++# include "dwc_dh.h" ++# include "dwc_crypto.h" ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++# include "dwc_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the Linux kernel implementation of the DWC platform library. */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++#else ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++ ++/* MISC */ ++ ++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ return memmove(dest, src, size); ++} ++ ++int DWC_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int DWC_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int DWC_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int DWC_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *DWC_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *DWC_STRDUP(char const *str) ++{ ++ int len = DWC_STRLEN(str) + 1; ++ char *new = DWC_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ DWC_MEMCPY(new, str, len); ++ return new; ++} ++ ++int DWC_ATOI(const char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtol(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int DWC_ATOUI(const char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef DWC_UTFLIB ++/* From usbstring.c */ ++ ++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++#endif /* DWC_UTFLIB */ ++ ++ ++/* dwc_debug.h */ ++ ++dwc_bool_t DWC_IN_IRQ(void) ++{ ++ return in_irq(); ++} ++ ++dwc_bool_t DWC_IN_BH(void) ++{ ++ return in_softirq(); ++} ++ ++void DWC_VPRINTF(char *format, va_list args) ++{ ++ vprintk(format, args); ++} ++ ++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void DWC_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int DWC_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int DWC_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __DWC_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_WARNING); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __DWC_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_ERR); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void DWC_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_ERR); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++ BUG_ON(1); ++} ++ ++#ifdef DEBUG ++void __DWC_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_DEBUG); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* dwc_mem.h */ ++ ++#if 0 ++dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (dwc_pool_t *)pool; ++} ++ ++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++} ++ ++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++#ifdef xxCOSIM /* Only works for 32-bit cosim */ ++ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); ++#else ++ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); ++#endif ++ if (!buf) { ++ return NULL; ++ } ++ ++ memset(buf, 0, (size_t)size); ++ return buf; ++} ++ ++void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); ++ if (!buf) { ++ return NULL; ++ } ++ memset(buf, 0, (size_t)size); ++ return buf; ++} ++ ++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) ++{ ++ dma_free_coherent(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++void *__DWC_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return kzalloc(size, GFP_KERNEL); ++} ++ ++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return kzalloc(size, GFP_ATOMIC); ++} ++ ++void __DWC_FREE(void *mem_ctx, void *addr) ++{ ++ kfree(addr); ++} ++ ++ ++#ifdef DWC_CRYPTOLIB ++/* dwc_crypto.h */ ++ ++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ DWC_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t DWC_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t DWC_READ_REG32(uint32_t volatile *reg) ++{ ++ return readl(reg); ++} ++ ++#if 0 ++uint64_t DWC_READ_REG64(uint64_t volatile *reg) ++{ ++} ++#endif ++ ++void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value) ++{ ++ writel(value, reg); ++} ++ ++#if 0 ++void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value) ++{ ++} ++#endif ++ ++void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) ++{ ++ writel((readl(reg) & ~clear_mask) | set_mask, reg); ++} ++ ++#if 0 ++void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask) ++{ ++} ++#endif ++ ++ ++/* Locking */ ++ ++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) ++{ ++ spinlock_t *sl = (spinlock_t *)1; ++ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ sl = DWC_ALLOC(sizeof(*sl)); ++ if (!sl) { ++ DWC_ERROR("Cannot allocate memory for spinlock\n"); ++ return NULL; ++ } ++ ++ spin_lock_init(sl); ++#endif ++ return (dwc_spinlock_t *)sl; ++} ++ ++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ DWC_FREE(lock); ++#endif ++} ++ ++void DWC_SPINLOCK(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_lock((spinlock_t *)lock); ++#endif ++} ++ ++void DWC_SPINUNLOCK(dwc_spinlock_t *lock) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_unlock((spinlock_t *)lock); ++#endif ++} ++ ++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) ++{ ++ dwc_irqflags_t f; ++ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_lock_irqsave((spinlock_t *)lock, f); ++#else ++ local_irq_save(f); ++#endif ++ *flags = f; ++} ++ ++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) ++{ ++#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) ++ spin_unlock_irqrestore((spinlock_t *)lock, flags); ++#else ++ local_irq_restore(flags); ++#endif ++} ++ ++dwc_mutex_t *DWC_MUTEX_ALLOC(void) ++{ ++ struct mutex *m; ++ dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); ++ ++ if (!mutex) { ++ DWC_ERROR("Cannot allocate memory for mutex\n"); ++ return NULL; ++ } ++ ++ m = (struct mutex *)mutex; ++ mutex_init(m); ++ return mutex; ++} ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void DWC_MUTEX_FREE(dwc_mutex_t *mutex) ++{ ++ mutex_destroy((struct mutex *)mutex); ++ DWC_FREE(mutex); ++} ++#endif ++ ++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ mutex_lock(m); ++} ++ ++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ return mutex_trylock(m); ++} ++ ++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) ++{ ++ struct mutex *m = (struct mutex *)mutex; ++ mutex_unlock(m); ++} ++ ++ ++/* Timing */ ++ ++void DWC_UDELAY(uint32_t usecs) ++{ ++ udelay(usecs); ++} ++ ++void DWC_MDELAY(uint32_t msecs) ++{ ++ mdelay(msecs); ++} ++ ++void DWC_MSLEEP(uint32_t msecs) ++{ ++ msleep(msecs); ++} ++ ++uint32_t DWC_TIME(void) ++{ ++ return jiffies_to_msecs(jiffies); ++} ++ ++ ++/* Timers */ ++ ++struct dwc_timer { ++ struct timer_list *t; ++ char *name; ++ dwc_timer_callback_t cb; ++ void *data; ++ uint8_t scheduled; ++ dwc_spinlock_t *lock; ++}; ++ ++static void timer_callback(unsigned long data) ++{ ++ dwc_timer_t *timer = (dwc_timer_t *)data; ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ timer->scheduled = 0; ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++ DWC_DEBUGC("Timer %s callback", timer->name); ++ timer->cb(timer->data); ++} ++ ++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) ++{ ++ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ DWC_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ t->t = DWC_ALLOC(sizeof(*t->t)); ++ if (!t->t) { ++ DWC_ERROR("Cannot allocate memory for timer->t"); ++ goto no_timer; ++ } ++ ++ t->name = DWC_STRDUP(name); ++ if (!t->name) { ++ DWC_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = DWC_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ DWC_ERROR("Cannot allocate memory for lock"); ++ goto no_lock; ++ } ++ ++ t->scheduled = 0; ++ t->t->base = &boot_tvec_bases; ++ t->t->expires = jiffies; ++ setup_timer(t->t, timer_callback, (unsigned long)t); ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ DWC_FREE(t->name); ++ no_name: ++ DWC_FREE(t->t); ++ no_timer: ++ DWC_FREE(t); ++ return NULL; ++} ++ ++void DWC_TIMER_FREE(dwc_timer_t *timer) ++{ ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (timer->scheduled) { ++ del_timer(timer->t); ++ timer->scheduled = 0; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++ DWC_SPINLOCK_FREE(timer->lock); ++ DWC_FREE(timer->t); ++ DWC_FREE(timer->name); ++ DWC_FREE(timer); ++} ++ ++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) ++{ ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (!timer->scheduled) { ++ timer->scheduled = 1; ++ DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time); ++ timer->t->expires = jiffies + msecs_to_jiffies(time); ++ add_timer(timer->t); ++ } else { ++ DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time); ++ mod_timer(timer->t, jiffies + msecs_to_jiffies(time)); ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++} ++ ++void DWC_TIMER_CANCEL(dwc_timer_t *timer) ++{ ++ del_timer(timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct dwc_waitq { ++ wait_queue_head_t queue; ++ int abort; ++}; ++ ++dwc_waitq_t *DWC_WAITQ_ALLOC(void) ++{ ++ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue\n"); ++ return NULL; ++ } ++ ++ init_waitqueue_head(&wq->queue); ++ wq->abort = 0; ++ return wq; ++} ++ ++void DWC_WAITQ_FREE(dwc_waitq_t *wq) ++{ ++ DWC_FREE(wq); ++} ++ ++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) ++{ ++ int result = wait_event_interruptible(wq->queue, ++ cond(data) || wq->abort); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -DWC_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -DWC_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result == 0) { ++ return 0; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ int32_t tmsecs; ++ int result = wait_event_interruptible_timeout(wq->queue, ++ cond(data) || wq->abort, ++ msecs_to_jiffies(msecs)); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -DWC_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -DWC_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result > 0) { ++ tmsecs = jiffies_to_msecs(result); ++ if (!tmsecs) { ++ return 1; ++ } ++ ++ return tmsecs; ++ } ++ ++ if (result == 0) { ++ return -DWC_E_TIMEOUT; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) ++{ ++ wq->abort = 0; ++ wake_up_interruptible(&wq->queue); ++} ++ ++void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++{ ++ wq->abort = 1; ++ wake_up_interruptible(&wq->queue); ++} ++ ++ ++/* Threading */ ++ ++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) ++{ ++ struct task_struct *thread = kthread_run(func, data, name); ++ ++ if (thread == ERR_PTR(-ENOMEM)) { ++ return NULL; ++ } ++ ++ return (dwc_thread_t *)thread; ++} ++ ++int DWC_THREAD_STOP(dwc_thread_t *thread) ++{ ++ return kthread_stop((struct task_struct *)thread); ++} ++ ++dwc_bool_t DWC_THREAD_SHOULD_STOP(void) ++{ ++ return kthread_should_stop(); ++} ++ ++ ++/* tasklets ++ - run in interrupt context (cannot sleep) ++ - each tasklet runs on a single CPU ++ - different tasklets can be running simultaneously on different CPUs ++ */ ++struct dwc_tasklet { ++ struct tasklet_struct t; ++ dwc_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(unsigned long data) ++{ ++ dwc_tasklet_t *t = (dwc_tasklet_t *)data; ++ t->cb(t->data); ++} ++ ++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) ++{ ++ dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (t) { ++ t->cb = cb; ++ t->data = data; ++ tasklet_init(&t->t, tasklet_callback, (unsigned long)t); ++ } else { ++ DWC_ERROR("Cannot allocate memory for tasklet\n"); ++ } ++ ++ return t; ++} ++ ++void DWC_TASK_FREE(dwc_tasklet_t *task) ++{ ++ DWC_FREE(task); ++} ++ ++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) ++{ ++ tasklet_schedule(&task->t); ++} ++ ++ ++/* workqueues ++ - run in process context (can sleep) ++ */ ++typedef struct work_container { ++ dwc_work_callback_t cb; ++ void *data; ++ dwc_workq_t *wq; ++ char *name; ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_ENTRY(work_container) entry; ++#endif ++ struct delayed_work work; ++} work_container_t; ++ ++#ifdef DEBUG ++DWC_CIRCLEQ_HEAD(work_container_queue, work_container); ++#endif ++ ++struct dwc_workq { ++ struct workqueue_struct *wq; ++ dwc_spinlock_t *lock; ++ dwc_waitq_t *waitq; ++ int pending; ++ ++#ifdef DEBUG ++ struct work_container_queue entries; ++#endif ++}; ++ ++static void do_work(struct work_struct *work) ++{ ++ dwc_irqflags_t flags; ++ struct delayed_work *dw = container_of(work, struct delayed_work, work); ++ work_container_t *container = container_of(dw, struct work_container, work); ++ dwc_workq_t *wq = container->wq; ++ ++ container->cb(container->data); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); ++#endif ++ DWC_DEBUGC("Work done: %s, container=%p", container->name, container); ++ if (container->name) { ++ DWC_FREE(container->name); ++ } ++ DWC_FREE(container); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending--; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ dwc_workq_t *workq = (dwc_workq_t *)data; ++ return workq->pending == 0; ++} ++ ++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) ++{ ++ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++dwc_workq_t *DWC_WORKQ_ALLOC(char *name) ++{ ++ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ return NULL; ++ } ++ ++ wq->wq = create_singlethread_workqueue(name); ++ if (!wq->wq) { ++ goto no_wq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = DWC_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ goto no_lock; ++ } ++ ++ wq->waitq = DWC_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ goto no_waitq; ++ } ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INIT(&wq->entries); ++#endif ++ return wq; ++ ++ no_waitq: ++ DWC_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ destroy_workqueue(wq->wq); ++ no_wq: ++ DWC_FREE(wq); ++ ++ return NULL; ++} ++ ++void DWC_WORKQ_FREE(dwc_workq_t *wq) ++{ ++#ifdef DEBUG ++ if (wq->pending != 0) { ++ struct work_container *wc; ++ DWC_ERROR("Destroying work queue with pending work"); ++ DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { ++ DWC_ERROR("Work %s still pending", wc->name); ++ } ++ } ++#endif ++ destroy_workqueue(wq->wq); ++ DWC_SPINLOCK_FREE(wq->lock); ++ DWC_WAITQ_FREE(wq->waitq); ++ DWC_FREE(wq); ++} ++ ++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name\n"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container); ++ INIT_WORK(&container->work.work, do_work); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_work(wq->wq, &container->work.work); ++} ++ ++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name\n"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container); ++ INIT_DELAYED_WORK(&container->work, do_work); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); ++} ++ ++int DWC_WORKQ_PENDING(dwc_workq_t *wq) ++{ ++ return wq->pending; ++} ++ ++ ++#ifdef DWC_LIBMODULE ++ ++#ifdef DWC_CCLIB ++/* CC */ ++EXPORT_SYMBOL(dwc_cc_if_alloc); ++EXPORT_SYMBOL(dwc_cc_if_free); ++EXPORT_SYMBOL(dwc_cc_clear); ++EXPORT_SYMBOL(dwc_cc_add); ++EXPORT_SYMBOL(dwc_cc_remove); ++EXPORT_SYMBOL(dwc_cc_change); ++EXPORT_SYMBOL(dwc_cc_data_for_save); ++EXPORT_SYMBOL(dwc_cc_restore_from_data); ++EXPORT_SYMBOL(dwc_cc_match_chid); ++EXPORT_SYMBOL(dwc_cc_match_cdid); ++EXPORT_SYMBOL(dwc_cc_ck); ++EXPORT_SYMBOL(dwc_cc_chid); ++EXPORT_SYMBOL(dwc_cc_cdid); ++EXPORT_SYMBOL(dwc_cc_name); ++#endif /* DWC_CCLIB */ ++ ++#ifdef DWC_CRYPTOLIB ++# ifndef CONFIG_MACH_IPMATE ++/* Modpow */ ++EXPORT_SYMBOL(dwc_modpow); ++ ++/* DH */ ++EXPORT_SYMBOL(dwc_dh_modpow); ++EXPORT_SYMBOL(dwc_dh_derive_keys); ++EXPORT_SYMBOL(dwc_dh_pk); ++# endif /* CONFIG_MACH_IPMATE */ ++ ++/* Crypto */ ++EXPORT_SYMBOL(dwc_wusb_aes_encrypt); ++EXPORT_SYMBOL(dwc_wusb_cmf); ++EXPORT_SYMBOL(dwc_wusb_prf); ++EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce); ++EXPORT_SYMBOL(dwc_wusb_gen_nonce); ++EXPORT_SYMBOL(dwc_wusb_gen_key); ++EXPORT_SYMBOL(dwc_wusb_gen_mic); ++#endif /* DWC_CRYPTOLIB */ ++ ++/* Notification */ ++#ifdef DWC_NOTIFYLIB ++EXPORT_SYMBOL(dwc_alloc_notification_manager); ++EXPORT_SYMBOL(dwc_free_notification_manager); ++EXPORT_SYMBOL(dwc_register_notifier); ++EXPORT_SYMBOL(dwc_unregister_notifier); ++EXPORT_SYMBOL(dwc_add_observer); ++EXPORT_SYMBOL(dwc_remove_observer); ++EXPORT_SYMBOL(dwc_notify); ++#endif ++ ++/* Memory Debugging Routines */ ++#ifdef DWC_DEBUG_MEMORY ++EXPORT_SYMBOL(dwc_alloc_debug); ++EXPORT_SYMBOL(dwc_alloc_atomic_debug); ++EXPORT_SYMBOL(dwc_free_debug); ++EXPORT_SYMBOL(dwc_dma_alloc_debug); ++EXPORT_SYMBOL(dwc_dma_free_debug); ++#endif ++ ++EXPORT_SYMBOL(DWC_MEMSET); ++EXPORT_SYMBOL(DWC_MEMCPY); ++EXPORT_SYMBOL(DWC_MEMMOVE); ++EXPORT_SYMBOL(DWC_MEMCMP); ++EXPORT_SYMBOL(DWC_STRNCMP); ++EXPORT_SYMBOL(DWC_STRCMP); ++EXPORT_SYMBOL(DWC_STRLEN); ++EXPORT_SYMBOL(DWC_STRCPY); ++EXPORT_SYMBOL(DWC_STRDUP); ++EXPORT_SYMBOL(DWC_ATOI); ++EXPORT_SYMBOL(DWC_ATOUI); ++ ++#ifdef DWC_UTFLIB ++EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE); ++#endif /* DWC_UTFLIB */ ++ ++EXPORT_SYMBOL(DWC_IN_IRQ); ++EXPORT_SYMBOL(DWC_IN_BH); ++EXPORT_SYMBOL(DWC_VPRINTF); ++EXPORT_SYMBOL(DWC_VSNPRINTF); ++EXPORT_SYMBOL(DWC_PRINTF); ++EXPORT_SYMBOL(DWC_SPRINTF); ++EXPORT_SYMBOL(DWC_SNPRINTF); ++EXPORT_SYMBOL(__DWC_WARN); ++EXPORT_SYMBOL(__DWC_ERROR); ++EXPORT_SYMBOL(DWC_EXCEPTION); ++ ++#ifdef DEBUG ++EXPORT_SYMBOL(__DWC_DEBUG); ++#endif ++ ++EXPORT_SYMBOL(__DWC_DMA_ALLOC); ++EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__DWC_DMA_FREE); ++EXPORT_SYMBOL(__DWC_ALLOC); ++EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__DWC_FREE); ++ ++#ifdef DWC_CRYPTOLIB ++EXPORT_SYMBOL(DWC_RANDOM_BYTES); ++EXPORT_SYMBOL(DWC_AES_CBC); ++EXPORT_SYMBOL(DWC_SHA256); ++EXPORT_SYMBOL(DWC_HMAC_SHA256); ++#endif ++ ++EXPORT_SYMBOL(DWC_CPU_TO_LE32); ++EXPORT_SYMBOL(DWC_CPU_TO_BE32); ++EXPORT_SYMBOL(DWC_LE32_TO_CPU); ++EXPORT_SYMBOL(DWC_BE32_TO_CPU); ++EXPORT_SYMBOL(DWC_CPU_TO_LE16); ++EXPORT_SYMBOL(DWC_CPU_TO_BE16); ++EXPORT_SYMBOL(DWC_LE16_TO_CPU); ++EXPORT_SYMBOL(DWC_BE16_TO_CPU); ++EXPORT_SYMBOL(DWC_READ_REG32); ++EXPORT_SYMBOL(DWC_WRITE_REG32); ++EXPORT_SYMBOL(DWC_MODIFY_REG32); ++ ++#if 0 ++EXPORT_SYMBOL(DWC_READ_REG64); ++EXPORT_SYMBOL(DWC_WRITE_REG64); ++EXPORT_SYMBOL(DWC_MODIFY_REG64); ++#endif ++ ++EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC); ++EXPORT_SYMBOL(DWC_SPINLOCK_FREE); ++EXPORT_SYMBOL(DWC_SPINLOCK); ++EXPORT_SYMBOL(DWC_SPINUNLOCK); ++EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE); ++EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE); ++EXPORT_SYMBOL(DWC_MUTEX_ALLOC); ++ ++#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES)) ++EXPORT_SYMBOL(DWC_MUTEX_FREE); ++#endif ++ ++EXPORT_SYMBOL(DWC_MUTEX_LOCK); ++EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK); ++EXPORT_SYMBOL(DWC_MUTEX_UNLOCK); ++EXPORT_SYMBOL(DWC_UDELAY); ++EXPORT_SYMBOL(DWC_MDELAY); ++EXPORT_SYMBOL(DWC_MSLEEP); ++EXPORT_SYMBOL(DWC_TIME); ++EXPORT_SYMBOL(DWC_TIMER_ALLOC); ++EXPORT_SYMBOL(DWC_TIMER_FREE); ++EXPORT_SYMBOL(DWC_TIMER_SCHEDULE); ++EXPORT_SYMBOL(DWC_TIMER_CANCEL); ++EXPORT_SYMBOL(DWC_WAITQ_ALLOC); ++EXPORT_SYMBOL(DWC_WAITQ_FREE); ++EXPORT_SYMBOL(DWC_WAITQ_WAIT); ++EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT); ++EXPORT_SYMBOL(DWC_WAITQ_TRIGGER); ++EXPORT_SYMBOL(DWC_WAITQ_ABORT); ++EXPORT_SYMBOL(DWC_THREAD_RUN); ++EXPORT_SYMBOL(DWC_THREAD_STOP); ++EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP); ++EXPORT_SYMBOL(DWC_TASK_ALLOC); ++EXPORT_SYMBOL(DWC_TASK_FREE); ++EXPORT_SYMBOL(DWC_TASK_SCHEDULE); ++EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE); ++EXPORT_SYMBOL(DWC_WORKQ_ALLOC); ++EXPORT_SYMBOL(DWC_WORKQ_FREE); ++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE); ++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED); ++EXPORT_SYMBOL(DWC_WORKQ_PENDING); ++ ++static int dwc_common_port_init_module(void) ++{ ++ int result = 0; ++ ++ printk(KERN_DEBUG "Module dwc_common_port init\n" ); ++ ++#ifdef DWC_DEBUG_MEMORY ++ result = dwc_memory_debug_start(NULL); ++ if (result) { ++ printk(KERN_ERR ++ "dwc_memory_debug_start() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++ result = dwc_alloc_notification_manager(NULL, NULL); ++ if (result) { ++ printk(KERN_ERR ++ "dwc_alloc_notification_manager() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ return result; ++} ++ ++static void dwc_common_port_exit_module(void) ++{ ++ printk(KERN_DEBUG "Module dwc_common_port exit\n" ); ++ ++#ifdef DWC_NOTIFYLIB ++ dwc_free_notification_manager(); ++#endif ++ ++#ifdef DWC_DEBUG_MEMORY ++ dwc_memory_debug_stop(); ++#endif ++} ++ ++module_init(dwc_common_port_init_module); ++module_exit(dwc_common_port_exit_module); ++ ++MODULE_DESCRIPTION("DWC Common Library - Portable version"); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE ("GPL"); ++ ++#endif /* DWC_LIBMODULE */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c +new file mode 100644 +index 0000000..49b07e1 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c +@@ -0,0 +1,1275 @@ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++#ifdef DWC_CCLIB ++# include "dwc_cc.h" ++#endif ++ ++#ifdef DWC_CRYPTOLIB ++# include "dwc_modpow.h" ++# include "dwc_dh.h" ++# include "dwc_crypto.h" ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++# include "dwc_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */ ++ ++ ++/* MISC */ ++ ++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ bcopy(src, dest, size); ++ return dest; ++} ++ ++int DWC_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int DWC_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int DWC_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int DWC_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *DWC_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *DWC_STRDUP(char const *str) ++{ ++ int len = DWC_STRLEN(str) + 1; ++ char *new = DWC_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ DWC_MEMCPY(new, str, len); ++ return new; ++} ++ ++int DWC_ATOI(char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul' ++ * should be equivalent on 2's complement machines ++ */ ++ *value = strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int DWC_ATOUI(char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef DWC_UTFLIB ++/* From usbstring.c */ ++ ++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++ ++#endif /* DWC_UTFLIB */ ++ ++ ++/* dwc_debug.h */ ++ ++dwc_bool_t DWC_IN_IRQ(void) ++{ ++// return in_irq(); ++ return 0; ++} ++ ++dwc_bool_t DWC_IN_BH(void) ++{ ++// return in_softirq(); ++ return 0; ++} ++ ++void DWC_VPRINTF(char *format, va_list args) ++{ ++ vprintf(format, args); ++} ++ ++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void DWC_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int DWC_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int DWC_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __DWC_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __DWC_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void DWC_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++// BUG_ON(1); ??? ++} ++ ++#ifdef DEBUG ++void __DWC_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* dwc_mem.h */ ++ ++#if 0 ++dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (dwc_pool_t *)pool; ++} ++ ++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++ return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr); ++} ++ ++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; ++ int error; ++ ++ error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs, ++ sizeof(dma->segs) / sizeof(dma->segs[0]), ++ &dma->nsegs, BUS_DMA_NOWAIT); ++ if (error) { ++ printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__, ++ (uintmax_t)size, error); ++ goto fail_0; ++ } ++ ++ error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size, ++ (caddr_t *)&dma->dma_vaddr, ++ BUS_DMA_NOWAIT | BUS_DMA_COHERENT); ++ if (error) { ++ printf("%s: bus_dmamem_map failed: %d\n", __func__, error); ++ goto fail_1; ++ } ++ ++ error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0, ++ BUS_DMA_NOWAIT, &dma->dma_map); ++ if (error) { ++ printf("%s: bus_dmamap_create failed: %d\n", __func__, error); ++ goto fail_2; ++ } ++ ++ error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, ++ size, NULL, BUS_DMA_NOWAIT); ++ if (error) { ++ printf("%s: bus_dmamap_load failed: %d\n", __func__, error); ++ goto fail_3; ++ } ++ ++ dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr; ++ *dma_addr = dma->dma_paddr; ++ return dma->dma_vaddr; ++ ++fail_3: ++ bus_dmamap_destroy(dma->dma_tag, dma->dma_map); ++fail_2: ++ bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size); ++fail_1: ++ bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs); ++fail_0: ++ dma->dma_map = NULL; ++ dma->dma_vaddr = NULL; ++ dma->nsegs = 0; ++ ++ return NULL; ++} ++ ++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) ++{ ++ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; ++ ++ if (dma->dma_map != NULL) { ++ bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size, ++ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++ bus_dmamap_destroy(dma->dma_tag, dma->dma_map); ++ bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size); ++ bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs); ++ dma->dma_paddr = 0; ++ dma->dma_map = NULL; ++ dma->dma_vaddr = NULL; ++ dma->nsegs = 0; ++ } ++} ++ ++void *__DWC_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); ++} ++ ++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); ++} ++ ++void __DWC_FREE(void *mem_ctx, void *addr) ++{ ++ free(addr, M_DEVBUF); ++} ++ ++ ++#ifdef DWC_CRYPTOLIB ++/* dwc_crypto.h */ ++ ++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ DWC_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t DWC_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_4(io->iot, io->ioh, ior); ++} ++ ++#if 0 ++uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_8(io->iot, io->ioh, ior); ++} ++#endif ++ ++void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, value); ++} ++ ++#if 0 ++void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, value); ++} ++#endif ++ ++void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, ++ uint32_t set_mask) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, ++ (bus_space_read_4(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++ ++#if 0 ++void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, ++ uint64_t set_mask) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, ++ (bus_space_read_8(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++#endif ++ ++ ++/* Locking */ ++ ++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) ++{ ++ struct simplelock *sl = DWC_ALLOC(sizeof(*sl)); ++ ++ if (!sl) { ++ DWC_ERROR("Cannot allocate memory for spinlock"); ++ return NULL; ++ } ++ ++ simple_lock_init(sl); ++ return (dwc_spinlock_t *)sl; ++} ++ ++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) ++{ ++ struct simplelock *sl = (struct simplelock *)lock; ++ ++ DWC_FREE(sl); ++} ++ ++void DWC_SPINLOCK(dwc_spinlock_t *lock) ++{ ++ simple_lock((struct simplelock *)lock); ++} ++ ++void DWC_SPINUNLOCK(dwc_spinlock_t *lock) ++{ ++ simple_unlock((struct simplelock *)lock); ++} ++ ++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) ++{ ++ simple_lock((struct simplelock *)lock); ++ *flags = splbio(); ++} ++ ++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) ++{ ++ splx(flags); ++ simple_unlock((struct simplelock *)lock); ++} ++ ++dwc_mutex_t *DWC_MUTEX_ALLOC(void) ++{ ++ dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock)); ++ ++ if (!mutex) { ++ DWC_ERROR("Cannot allocate memory for mutex"); ++ return NULL; ++ } ++ ++ lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0); ++ return mutex; ++} ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void DWC_MUTEX_FREE(dwc_mutex_t *mutex) ++{ ++ DWC_FREE(mutex); ++} ++#endif ++ ++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) ++{ ++ lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL); ++} ++ ++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) ++{ ++ int status; ++ ++ status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL); ++ return status == 0; ++} ++ ++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) ++{ ++ lockmgr((struct lock *)mutex, LK_RELEASE, NULL); ++} ++ ++ ++/* Timing */ ++ ++void DWC_UDELAY(uint32_t usecs) ++{ ++ DELAY(usecs); ++} ++ ++void DWC_MDELAY(uint32_t msecs) ++{ ++ do { ++ DELAY(1000); ++ } while (--msecs); ++} ++ ++void DWC_MSLEEP(uint32_t msecs) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ tsleep(&tv, 0, "dw3slp", tvtohz(&tv)); ++} ++ ++uint32_t DWC_TIME(void) ++{ ++ struct timeval tv; ++ ++ microuptime(&tv); // or getmicrouptime? (less precise, but faster) ++ return tv.tv_sec * 1000 + tv.tv_usec / 1000; ++} ++ ++ ++/* Timers */ ++ ++struct dwc_timer { ++ struct callout t; ++ char *name; ++ dwc_spinlock_t *lock; ++ dwc_timer_callback_t cb; ++ void *data; ++}; ++ ++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) ++{ ++ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ DWC_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ callout_init(&t->t); ++ ++ t->name = DWC_STRDUP(name); ++ if (!t->name) { ++ DWC_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = DWC_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ DWC_ERROR("Cannot allocate memory for timer->lock"); ++ goto no_lock; ++ } ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ DWC_FREE(t->name); ++ no_name: ++ DWC_FREE(t); ++ ++ return NULL; ++} ++ ++void DWC_TIMER_FREE(dwc_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++ DWC_SPINLOCK_FREE(timer->lock); ++ DWC_FREE(timer->name); ++ DWC_FREE(timer); ++} ++ ++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data); ++} ++ ++void DWC_TIMER_CANCEL(dwc_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct dwc_waitq { ++ struct simplelock lock; ++ int abort; ++}; ++ ++dwc_waitq_t *DWC_WAITQ_ALLOC(void) ++{ ++ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue"); ++ return NULL; ++ } ++ ++ simple_lock_init(&wq->lock); ++ wq->abort = 0; ++ ++ return wq; ++} ++ ++void DWC_WAITQ_FREE(dwc_waitq_t *wq) ++{ ++ DWC_FREE(wq); ++} ++ ++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) ++{ ++ int ipl; ++ int result = 0; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++ splx(ipl); ++ result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout ++ ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ wq->abort = 0; ++ result = -DWC_E_ABORT; ++ } else { ++ result = 0; ++ } ++ ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ } else { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -DWC_E_RESTART; ++ } else { // signaled - must be EINTR ++ result = -DWC_E_ABORT; ++ } ++ } ++ ++ return result; ++} ++ ++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ struct timeval tv, tv1, tv2; ++ int ipl; ++ int result = 0; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++ splx(ipl); ++ getmicrouptime(&tv1); ++ result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock); ++ getmicrouptime(&tv2); ++ ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ result = -DWC_E_ABORT; ++ } else { ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ tv2.tv_usec -= tv1.tv_usec; ++ if (tv2.tv_usec < 0) { ++ tv2.tv_usec += 1000000; ++ tv2.tv_sec--; ++ } ++ ++ tv2.tv_sec -= tv1.tv_sec; ++ result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; ++ result = msecs - result; ++ if (result <= 0) ++ result = 1; ++ } ++ } else { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -DWC_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -DWC_E_ABORT; ++ ++ } else { // timed out ++ result = -DWC_E_TIMEOUT; ++ } ++ } ++ ++ return result; ++} ++ ++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) ++{ ++ wakeup(wq); ++} ++ ++void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++{ ++ int ipl; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ wq->abort = 1; ++ wakeup(wq); ++ splx(ipl); ++ simple_unlock(&wq->lock); ++} ++ ++ ++/* Threading */ ++ ++struct dwc_thread { ++ struct proc *proc; ++ int abort; ++}; ++ ++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) ++{ ++ int retval; ++ dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread)); ++ ++ if (!thread) { ++ return NULL; ++ } ++ ++ thread->abort = 0; ++ retval = kthread_create1((void (*)(void *))func, data, &thread->proc, ++ "%s", name); ++ if (retval) { ++ DWC_FREE(thread); ++ return NULL; ++ } ++ ++ return thread; ++} ++ ++int DWC_THREAD_STOP(dwc_thread_t *thread) ++{ ++ int retval; ++ ++ thread->abort = 1; ++ retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz); ++ ++ if (retval == 0) { ++ /* DWC_THREAD_EXIT() will free the thread struct */ ++ return 0; ++ } ++ ++ /* NOTE: We leak the thread struct if thread doesn't die */ ++ ++ if (retval == EWOULDBLOCK) { ++ return -DWC_E_TIMEOUT; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread) ++{ ++ return thread->abort; ++} ++ ++void DWC_THREAD_EXIT(dwc_thread_t *thread) ++{ ++ wakeup(&thread->abort); ++ DWC_FREE(thread); ++ kthread_exit(0); ++} ++ ++/* tasklets ++ - Runs in interrupt context (cannot sleep) ++ - Each tasklet runs on a single CPU ++ - Different tasklets can be running simultaneously on different CPUs ++ [ On NetBSD there is no corresponding mechanism, drivers don't have bottom- ++ halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ] ++ */ ++struct dwc_tasklet { ++ dwc_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(void *data) ++{ ++ dwc_tasklet_t *task = (dwc_tasklet_t *)data; ++ ++ task->cb(task->data); ++} ++ ++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) ++{ ++ dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task)); ++ ++ if (task) { ++ task->cb = cb; ++ task->data = data; ++ } else { ++ DWC_ERROR("Cannot allocate memory for tasklet"); ++ } ++ ++ return task; ++} ++ ++void DWC_TASK_FREE(dwc_tasklet_t *task) ++{ ++ DWC_FREE(task); ++} ++ ++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) ++{ ++ tasklet_callback(task); ++} ++ ++ ++/* workqueues ++ - Runs in process context (can sleep) ++ */ ++typedef struct work_container { ++ dwc_work_callback_t cb; ++ void *data; ++ dwc_workq_t *wq; ++ char *name; ++ int hz; ++ struct work task; ++} work_container_t; ++ ++struct dwc_workq { ++ struct workqueue *taskq; ++ dwc_spinlock_t *lock; ++ dwc_waitq_t *waitq; ++ int pending; ++ struct work_container *container; ++}; ++ ++static void do_work(struct work *task, void *data) ++{ ++ dwc_workq_t *wq = (dwc_workq_t *)data; ++ work_container_t *container = wq->container; ++ dwc_irqflags_t flags; ++ ++ if (container->hz) { ++ tsleep(container, 0, "dw3wrk", container->hz); ++ } ++ ++ container->cb(container->data); ++ DWC_DEBUG("Work done: %s, container=%p", container->name, container); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ if (container->name) ++ DWC_FREE(container->name); ++ DWC_FREE(container); ++ wq->pending--; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ dwc_workq_t *workq = (dwc_workq_t *)data; ++ ++ return workq->pending == 0; ++} ++ ++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) ++{ ++ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++dwc_workq_t *DWC_WORKQ_ALLOC(char *name) ++{ ++ int result; ++ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for workqueue"); ++ return NULL; ++ } ++ ++ result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/, ++ IPL_BIO, 0); ++ if (result) { ++ DWC_ERROR("Cannot create workqueue"); ++ goto no_taskq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = DWC_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ DWC_ERROR("Cannot allocate memory for spinlock"); ++ goto no_lock; ++ } ++ ++ wq->waitq = DWC_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue"); ++ goto no_waitq; ++ } ++ ++ return wq; ++ ++ no_waitq: ++ DWC_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ workqueue_destroy(wq->taskq); ++ no_taskq: ++ DWC_FREE(wq); ++ ++ return NULL; ++} ++ ++void DWC_WORKQ_FREE(dwc_workq_t *wq) ++{ ++#ifdef DEBUG ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++ if (wq->pending != 0) { ++ struct work_container *container = wq->container; ++ ++ DWC_ERROR("Destroying work queue with pending work"); ++ ++ if (container && container->name) { ++ DWC_ERROR("Work %s still pending", container->name); ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++#endif ++ DWC_WAITQ_FREE(wq->waitq); ++ DWC_SPINLOCK_FREE(wq->lock); ++ workqueue_destroy(wq->taskq); ++ DWC_FREE(wq); ++} ++ ++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ container->hz = 0; ++ wq->container = container; ++ ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ workqueue_enqueue(wq->taskq, &container->task); ++} ++ ++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ struct timeval tv; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ container->hz = tvtohz(&tv); ++ wq->container = container; ++ ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ workqueue_enqueue(wq->taskq, &container->task); ++} ++ ++int DWC_WORKQ_PENDING(dwc_workq_t *wq) ++{ ++ return wq->pending; ++} +diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.c b/drivers/usb/host/dwc_common_port/dwc_crypto.c +new file mode 100644 +index 0000000..3b03532 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c +@@ -0,0 +1,308 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $ ++ * $Revision: #5 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software 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. ++ * ========================================================================= */ ++ ++/** @file ++ * This file contains the WUSB cryptographic routines. ++ */ ++ ++#ifdef DWC_CRYPTOLIB ++ ++#include "dwc_crypto.h" ++#include "usb.h" ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ DWC_PRINTF("%s: ", name); ++ for (i=0; idst == src, then the bytes will be encrypted ++ * in-place. ++ * ++ * @return 0 on success, negative error code on error. ++ */ ++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst) ++{ ++ u8 block_t[16]; ++ DWC_MEMSET(block_t, 0, 16); ++ ++ return DWC_AES_CBC(src, 16, key, 16, block_t, dst); ++} ++ ++/** ++ * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec. ++ * This function takes a data string and returns the encrypted CBC ++ * Counter-mode MIC. ++ * ++ * @param key The 128-bit symmetric key. ++ * @param nonce The CCM nonce. ++ * @param label The unique 14-byte ASCII text label. ++ * @param bytes The byte array to be encrypted. ++ * @param len Length of the byte array. ++ * @param result Byte array to receive the 8-byte encrypted MIC. ++ */ ++void dwc_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ u8 block_m[16]; ++ u8 block_x[16]; ++ u8 block_t[8]; ++ int idx, blkNum; ++ u16 la = (u16)(len + 14); ++ ++ /* Set the AES-128 key */ ++ //dwc_aes_setkey(tfm, key, 16); ++ ++ /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */ ++ block_m[0] = 0x59; ++ for (idx = 0; idx < 13; idx++) ++ block_m[idx + 1] = nonce[idx]; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Produce the CBC IV */ ++ dwc_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_m, "CBC IV in: ", "\n", 0); ++ show_block(block_x, "CBC IV out:", "\n", 0); ++ ++ /* Fill block B1 from l(a) = Blen + 14, and A */ ++ block_x[0] ^= (u8)(la >> 8); ++ block_x[1] ^= (u8)la; ++ for (idx = 0; idx < 14; idx++) ++ block_x[idx + 2] ^= label[idx]; ++ show_block(block_x, "After xor: ", "b1\n", 16); ++ ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "b1\n", 16); ++ ++ idx = 0; ++ blkNum = 0; ++ ++ /* Fill remaining blocks with B */ ++ while (len-- > 0) { ++ block_x[idx] ^= *bytes++; ++ if (++idx >= 16) { ++ idx = 0; ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ blkNum++; ++ } ++ } ++ ++ /* Handle partial last block */ ++ if (idx > 0) { ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ } ++ ++ /* Save the MIC tag */ ++ DWC_MEMCPY(block_t, block_x, 8); ++ show_block(block_t, "MIC tag : ", NULL, 8); ++ ++ /* Fill block A0 from flags = 0x01, N, and counter = 0 */ ++ block_m[0] = 0x01; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Encrypt the counter */ ++ dwc_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_x, "CTR[MIC] : ", NULL, 8); ++ ++ /* XOR with MIC tag */ ++ for (idx = 0; idx < 8; idx++) { ++ block_t[idx] ^= block_x[idx]; ++ } ++ ++ /* Return result to caller */ ++ DWC_MEMCPY(result, block_t, 8); ++ show_block(result, "CCM-MIC : ", NULL, 8); ++ ++} ++ ++/** ++ * The PRF function described in section 6.5 of the WUSB spec. This function ++ * concatenates MIC values returned from dwc_cmf() to create a value of ++ * the requested length. ++ * ++ * @param prf_len Length of the PRF function in bits (64, 128, or 256). ++ * @param key, nonce, label, bytes, len Same as for dwc_cmf(). ++ * @param result Byte array to receive the result. ++ */ ++void dwc_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result) ++{ ++ int i; ++ ++ nonce[0] = 0; ++ for (i = 0; i < prf_len >> 6; i++, nonce[0]++) { ++ dwc_wusb_cmf(key, nonce, label, bytes, len, result); ++ result += 8; ++ } ++} ++ ++/** ++ * Fills in CCM Nonce per the WUSB spec. ++ * ++ * @param[in] haddr Host address. ++ * @param[in] daddr Device address. ++ * @param[in] tkid Session Key(PTK) identifier. ++ * @param[out] nonce Pointer to where the CCM Nonce output is to be written. ++ */ ++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce) ++{ ++ ++ DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr); ++ ++ DWC_MEMSET(&nonce[0], 0, 16); ++ ++ DWC_MEMCPY(&nonce[6], tkid, 3); ++ nonce[9] = daddr & 0xFF; ++ nonce[10] = (daddr >> 8) & 0xFF; ++ nonce[11] = haddr & 0xFF; ++ nonce[12] = (haddr >> 8) & 0xFF; ++ ++ dump_bytes("CCM nonce", nonce, 16); ++} ++ ++/** ++ * Generates a 16-byte cryptographic-grade random number for the Host/Device ++ * Nonce. ++ */ ++void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce) ++{ ++ uint8_t inonce[16]; ++ uint32_t temp[4]; ++ ++ /* Fill in the Nonce */ ++ DWC_MEMSET(&inonce[0], 0, sizeof(inonce)); ++ inonce[9] = addr & 0xFF; ++ inonce[10] = (addr >> 8) & 0xFF; ++ inonce[11] = inonce[9]; ++ inonce[12] = inonce[10]; ++ ++ /* Collect "randomness samples" */ ++ DWC_RANDOM_BYTES((uint8_t *)temp, 16); ++ ++ dwc_wusb_prf_128((uint8_t *)temp, nonce, ++ "Random Numbers", (uint8_t *)temp, sizeof(temp), ++ nonce); ++} ++ ++/** ++ * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the ++ * WUSB spec. ++ * ++ * @param[in] ccm_nonce Pointer to CCM Nonce. ++ * @param[in] mk Master Key to derive the session from ++ * @param[in] hnonce Pointer to Host Nonce. ++ * @param[in] dnonce Pointer to Device Nonce. ++ * @param[out] kck Pointer to where the KCK output is to be written. ++ * @param[out] ptk Pointer to where the PTK output is to be written. ++ */ ++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce, ++ uint8_t *dnonce, uint8_t *kck, uint8_t *ptk) ++{ ++ uint8_t idata[32]; ++ uint8_t odata[32]; ++ ++ dump_bytes("ck", mk, 16); ++ dump_bytes("hnonce", hnonce, 16); ++ dump_bytes("dnonce", dnonce, 16); ++ ++ /* The data is the HNonce and DNonce concatenated */ ++ DWC_MEMCPY(&idata[0], hnonce, 16); ++ DWC_MEMCPY(&idata[16], dnonce, 16); ++ ++ dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata); ++ ++ /* Low 16 bytes of the result is the KCK, high 16 is the PTK */ ++ DWC_MEMCPY(kck, &odata[0], 16); ++ DWC_MEMCPY(ptk, &odata[16], 16); ++ ++ dump_bytes("kck", kck, 16); ++ dump_bytes("ptk", ptk, 16); ++} ++ ++/** ++ * Generates the Message Integrity Code over the Handshake data per the ++ * WUSB spec. ++ * ++ * @param ccm_nonce Pointer to CCM Nonce. ++ * @param kck Pointer to Key Confirmation Key. ++ * @param data Pointer to Handshake data to be checked. ++ * @param mic Pointer to where the MIC output is to be written. ++ */ ++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck, ++ uint8_t *data, uint8_t *mic) ++{ ++ ++ dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC", ++ data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic); ++} ++ ++#endif /* DWC_CRYPTOLIB */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.h b/drivers/usb/host/dwc_common_port/dwc_crypto.h +new file mode 100644 +index 0000000..26fcddc +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h +@@ -0,0 +1,111 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software 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_CRYPTO_H_ ++#define _DWC_CRYPTO_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file contains declarations for the WUSB Cryptographic routines as ++ * defined in the WUSB spec. They are only to be used internally by the DWC UWB ++ * modules. ++ */ ++ ++#include "dwc_os.h" ++ ++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst); ++ ++void dwc_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result); ++void dwc_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result); ++ ++/** ++ * The PRF-64 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(64, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-128 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(128, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-256 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(256, key, nonce, label, bytes, len, result); ++} ++ ++ ++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce); ++void dwc_wusb_gen_nonce(uint16_t addr, ++ uint8_t *nonce); ++ ++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, ++ uint8_t *hnonce, uint8_t *dnonce, ++ uint8_t *kck, uint8_t *ptk); ++ ++ ++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t ++ *kck, uint8_t *data, uint8_t *mic); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_CRYPTO_H_ */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_dh.c b/drivers/usb/host/dwc_common_port/dwc_dh.c +new file mode 100644 +index 0000000..997f753 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_dh.c +@@ -0,0 +1,291 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software 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. ++ * ========================================================================= */ ++#ifdef DWC_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "dwc_dh.h" ++#include "dwc_modpow.h" ++ ++#ifdef DEBUG ++/* This function prints out a buffer in the format described in the Association ++ * Model specification. */ ++static void dh_dump(char *str, void *_num, int len) ++{ ++ uint8_t *num = _num; ++ int i; ++ DWC_PRINTF("%s\n", str); ++ for (i = 0; i < len; i ++) { ++ DWC_PRINTF("%02x", num[i]); ++ if (((i + 1) % 2) == 0) DWC_PRINTF(" "); ++ if (((i + 1) % 26) == 0) DWC_PRINTF("\n"); ++ } ++ ++ DWC_PRINTF("\n"); ++} ++#else ++#define dh_dump(_x...) do {; } while(0) ++#endif ++ ++/* Constant g value */ ++static __u32 dh_g[] = { ++ 0x02000000, ++}; ++ ++/* Constant p value */ ++static __u32 dh_p[] = { ++ 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A, ++ 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2, ++ 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4, ++ 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1, ++ 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520, ++ 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E, ++ 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895, ++ 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004, ++ 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6, ++ 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9, ++ 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA, ++ 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF, ++}; ++ ++static void dh_swap_bytes(void *_in, void *_out, uint32_t len) ++{ ++ uint8_t *in = _in; ++ uint8_t *out = _out; ++ int i; ++ for (i=0; inext = (link); \ ++ (link)->prev = (link); \ ++} while (0) ++ ++#define DWC_LIST_FIRST(link) ((link)->next) ++#define DWC_LIST_LAST(link) ((link)->prev) ++#define DWC_LIST_END(link) (link) ++#define DWC_LIST_NEXT(link) ((link)->next) ++#define DWC_LIST_PREV(link) ((link)->prev) ++#define DWC_LIST_EMPTY(link) \ ++ (DWC_LIST_FIRST(link) == DWC_LIST_END(link)) ++#define DWC_LIST_ENTRY(link, type, field) \ ++ (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field)) ++ ++#if 0 ++#define DWC_LIST_INSERT_HEAD(list, link) do { \ ++ (link)->next = (list)->next; \ ++ (link)->prev = (list); \ ++ (list)->next->prev = (link); \ ++ (list)->next = (link); \ ++} while (0) ++ ++#define DWC_LIST_INSERT_TAIL(list, link) do { \ ++ (link)->next = (list); \ ++ (link)->prev = (list)->prev; \ ++ (list)->prev->next = (link); \ ++ (list)->prev = (link); \ ++} while (0) ++#else ++#define DWC_LIST_INSERT_HEAD(list, link) do { \ ++ dwc_list_link_t *__next__ = (list)->next; \ ++ __next__->prev = (link); \ ++ (link)->next = __next__; \ ++ (link)->prev = (list); \ ++ (list)->next = (link); \ ++} while (0) ++ ++#define DWC_LIST_INSERT_TAIL(list, link) do { \ ++ dwc_list_link_t *__prev__ = (list)->prev; \ ++ (list)->prev = (link); \ ++ (link)->next = (list); \ ++ (link)->prev = __prev__; \ ++ __prev__->next = (link); \ ++} while (0) ++#endif ++ ++#if 0 ++static inline void __list_add(struct list_head *new, ++ struct list_head *prev, ++ struct list_head *next) ++{ ++ next->prev = new; ++ new->next = next; ++ new->prev = prev; ++ prev->next = new; ++} ++ ++static inline void list_add(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head, head->next); ++} ++ ++static inline void list_add_tail(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head->prev, head); ++} ++ ++static inline void __list_del(struct list_head * prev, struct list_head * next) ++{ ++ next->prev = prev; ++ prev->next = next; ++} ++ ++static inline void list_del(struct list_head *entry) ++{ ++ __list_del(entry->prev, entry->next); ++ entry->next = LIST_POISON1; ++ entry->prev = LIST_POISON2; ++} ++#endif ++ ++#define DWC_LIST_REMOVE(link) do { \ ++ (link)->next->prev = (link)->prev; \ ++ (link)->prev->next = (link)->next; \ ++} while (0) ++ ++#define DWC_LIST_REMOVE_INIT(link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INIT(link); \ ++} while (0) ++ ++#define DWC_LIST_MOVE_HEAD(list, link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INSERT_HEAD(list, link); \ ++} while (0) ++ ++#define DWC_LIST_MOVE_TAIL(list, link) do { \ ++ DWC_LIST_REMOVE(link); \ ++ DWC_LIST_INSERT_TAIL(list, link); \ ++} while (0) ++ ++#define DWC_LIST_FOREACH(var, list) \ ++ for((var) = DWC_LIST_FIRST(list); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = DWC_LIST_NEXT(var)) ++ ++#define DWC_LIST_FOREACH_SAFE(var, var2, list) \ ++ for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = (var2), (var2) = DWC_LIST_NEXT(var2)) ++ ++#define DWC_LIST_FOREACH_REVERSE(var, list) \ ++ for((var) = DWC_LIST_LAST(list); \ ++ (var) != DWC_LIST_END(list); \ ++ (var) = DWC_LIST_PREV(var)) ++ ++/* ++ * Singly-linked List definitions. ++ */ ++#define DWC_SLIST_HEAD(name, type) \ ++struct name { \ ++ struct type *slh_first; /* first element */ \ ++} ++ ++#define DWC_SLIST_HEAD_INITIALIZER(head) \ ++ { NULL } ++ ++#define DWC_SLIST_ENTRY(type) \ ++struct { \ ++ struct type *sle_next; /* next element */ \ ++} ++ ++/* ++ * Singly-linked List access methods. ++ */ ++#define DWC_SLIST_FIRST(head) ((head)->slh_first) ++#define DWC_SLIST_END(head) NULL ++#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) ++#define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next) ++ ++#define DWC_SLIST_FOREACH(var, head, field) \ ++ for((var) = SLIST_FIRST(head); \ ++ (var) != SLIST_END(head); \ ++ (var) = SLIST_NEXT(var, field)) ++ ++#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ ++ for((varp) = &SLIST_FIRST((head)); \ ++ ((var) = *(varp)) != SLIST_END(head); \ ++ (varp) = &SLIST_NEXT((var), field)) ++ ++/* ++ * Singly-linked List functions. ++ */ ++#define DWC_SLIST_INIT(head) { \ ++ SLIST_FIRST(head) = SLIST_END(head); \ ++} ++ ++#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ ++ (elm)->field.sle_next = (slistelm)->field.sle_next; \ ++ (slistelm)->field.sle_next = (elm); \ ++} while (0) ++ ++#define DWC_SLIST_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.sle_next = (head)->slh_first; \ ++ (head)->slh_first = (elm); \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE_NEXT(head, elm, field) do { \ ++ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE_HEAD(head, field) do { \ ++ (head)->slh_first = (head)->slh_first->field.sle_next; \ ++} while (0) ++ ++#define DWC_SLIST_REMOVE(head, elm, type, field) do { \ ++ if ((head)->slh_first == (elm)) { \ ++ SLIST_REMOVE_HEAD((head), field); \ ++ } \ ++ else { \ ++ struct type *curelm = (head)->slh_first; \ ++ while( curelm->field.sle_next != (elm) ) \ ++ curelm = curelm->field.sle_next; \ ++ curelm->field.sle_next = \ ++ curelm->field.sle_next->field.sle_next; \ ++ } \ ++} while (0) ++ ++/* ++ * Simple queue definitions. ++ */ ++#define DWC_SIMPLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *sqh_first; /* first element */ \ ++ struct type **sqh_last; /* addr of last next element */ \ ++} ++ ++#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).sqh_first } ++ ++#define DWC_SIMPLEQ_ENTRY(type) \ ++struct { \ ++ struct type *sqe_next; /* next element */ \ ++} ++ ++/* ++ * Simple queue access methods. ++ */ ++#define DWC_SIMPLEQ_FIRST(head) ((head)->sqh_first) ++#define DWC_SIMPLEQ_END(head) NULL ++#define DWC_SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) ++#define DWC_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) ++ ++#define DWC_SIMPLEQ_FOREACH(var, head, field) \ ++ for((var) = SIMPLEQ_FIRST(head); \ ++ (var) != SIMPLEQ_END(head); \ ++ (var) = SIMPLEQ_NEXT(var, field)) ++ ++/* ++ * Simple queue functions. ++ */ ++#define DWC_SIMPLEQ_INIT(head) do { \ ++ (head)->sqh_first = NULL; \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (head)->sqh_first = (elm); \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.sqe_next = NULL; \ ++ *(head)->sqh_last = (elm); \ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++} while (0) ++ ++#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ ++ (head)->sqh_last = &(elm)->field.sqe_next; \ ++ (listelm)->field.sqe_next = (elm); \ ++} while (0) ++ ++#define DWC_SIMPLEQ_REMOVE_HEAD(head, field) do { \ ++ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ ++ (head)->sqh_last = &(head)->sqh_first; \ ++} while (0) ++ ++/* ++ * Tail queue definitions. ++ */ ++#define DWC_TAILQ_HEAD(name, type) \ ++struct name { \ ++ struct type *tqh_first; /* first element */ \ ++ struct type **tqh_last; /* addr of last next element */ \ ++} ++ ++#define DWC_TAILQ_HEAD_INITIALIZER(head) \ ++ { NULL, &(head).tqh_first } ++ ++#define DWC_TAILQ_ENTRY(type) \ ++struct { \ ++ struct type *tqe_next; /* next element */ \ ++ struct type **tqe_prev; /* address of previous next element */ \ ++} ++ ++/* ++ * tail queue access methods ++ */ ++#define DWC_TAILQ_FIRST(head) ((head)->tqh_first) ++#define DWC_TAILQ_END(head) NULL ++#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) ++#define DWC_TAILQ_LAST(head, headname) \ ++ (*(((struct headname *)((head)->tqh_last))->tqh_last)) ++/* XXX */ ++#define DWC_TAILQ_PREV(elm, headname, field) \ ++ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) ++#define DWC_TAILQ_EMPTY(head) \ ++ (TAILQ_FIRST(head) == TAILQ_END(head)) ++ ++#define DWC_TAILQ_FOREACH(var, head, field) \ ++ for((var) = TAILQ_FIRST(head); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_NEXT(var, field)) ++ ++#define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ ++ for((var) = TAILQ_LAST(head, headname); \ ++ (var) != TAILQ_END(head); \ ++ (var) = TAILQ_PREV(var, headname, field)) ++ ++/* ++ * Tail queue functions. ++ */ ++#define DWC_TAILQ_INIT(head) do { \ ++ (head)->tqh_first = NULL; \ ++ (head)->tqh_last = &(head)->tqh_first; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_HEAD(head, elm, field) do { \ ++ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ ++ (head)->tqh_first->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (head)->tqh_first = (elm); \ ++ (elm)->field.tqe_prev = &(head)->tqh_first; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.tqe_next = NULL; \ ++ (elm)->field.tqe_prev = (head)->tqh_last; \ ++ *(head)->tqh_last = (elm); \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ &(elm)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm)->field.tqe_next; \ ++ (listelm)->field.tqe_next = (elm); \ ++ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ ++ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ ++ (elm)->field.tqe_next = (listelm); \ ++ *(listelm)->field.tqe_prev = (elm); \ ++ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_REMOVE(head, elm, field) do { \ ++ if (((elm)->field.tqe_next) != NULL) \ ++ (elm)->field.tqe_next->field.tqe_prev = \ ++ (elm)->field.tqe_prev; \ ++ else \ ++ (head)->tqh_last = (elm)->field.tqe_prev; \ ++ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ ++} while (0) ++ ++#define DWC_TAILQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ ++ (elm2)->field.tqe_next->field.tqe_prev = \ ++ &(elm2)->field.tqe_next; \ ++ else \ ++ (head)->tqh_last = &(elm2)->field.tqe_next; \ ++ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ ++ *(elm2)->field.tqe_prev = (elm2); \ ++} while (0) ++ ++/* ++ * Circular queue definitions. ++ */ ++#define DWC_CIRCLEQ_HEAD(name, type) \ ++struct name { \ ++ struct type *cqh_first; /* first element */ \ ++ struct type *cqh_last; /* last element */ \ ++} ++ ++#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ ++ { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) } ++ ++#define DWC_CIRCLEQ_ENTRY(type) \ ++struct { \ ++ struct type *cqe_next; /* next element */ \ ++ struct type *cqe_prev; /* previous element */ \ ++} ++ ++/* ++ * Circular queue access methods ++ */ ++#define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first) ++#define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last) ++#define DWC_CIRCLEQ_END(head) ((void *)(head)) ++#define DWC_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) ++#define DWC_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) ++#define DWC_CIRCLEQ_EMPTY(head) \ ++ (DWC_CIRCLEQ_FIRST(head) == DWC_CIRCLEQ_END(head)) ++ ++#define DWC_CIRCLEQ_EMPTY_ENTRY(elm, field) (((elm)->field.cqe_next == NULL) && ((elm)->field.cqe_prev == NULL)) ++ ++#define DWC_CIRCLEQ_FOREACH(var, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = DWC_CIRCLEQ_NEXT(var, field)) ++ ++#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field)) ++ ++#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ ++ for((var) = DWC_CIRCLEQ_LAST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) = DWC_CIRCLEQ_PREV(var, field)) ++ ++/* ++ * Circular queue functions. ++ */ ++#define DWC_CIRCLEQ_INIT(head) do { \ ++ (head)->cqh_first = DWC_CIRCLEQ_END(head); \ ++ (head)->cqh_last = DWC_CIRCLEQ_END(head); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ ++ (elm)->field.cqe_next = NULL; \ ++ (elm)->field.cqe_prev = NULL; \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ ++ (elm)->field.cqe_prev = (listelm); \ ++ if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ ++ (listelm)->field.cqe_next = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ ++ (elm)->field.cqe_next = (listelm); \ ++ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ ++ if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ ++ (listelm)->field.cqe_prev = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ ++ (elm)->field.cqe_next = (head)->cqh_first; \ ++ (elm)->field.cqe_prev = DWC_CIRCLEQ_END(head); \ ++ if ((head)->cqh_last == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm); \ ++ else \ ++ (head)->cqh_first->field.cqe_prev = (elm); \ ++ (head)->cqh_first = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ ++ (elm)->field.cqe_next = DWC_CIRCLEQ_END(head); \ ++ (elm)->field.cqe_prev = (head)->cqh_last; \ ++ if ((head)->cqh_first == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm); \ ++ else \ ++ (head)->cqh_last->field.cqe_next = (elm); \ ++ (head)->cqh_last = (elm); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ ++ if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_last = (elm)->field.cqe_prev; \ ++ else \ ++ (elm)->field.cqe_next->field.cqe_prev = \ ++ (elm)->field.cqe_prev; \ ++ if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ (head)->cqh_first = (elm)->field.cqe_next; \ ++ else \ ++ (elm)->field.cqe_prev->field.cqe_next = \ ++ (elm)->field.cqe_next; \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ ++ DWC_CIRCLEQ_REMOVE(head, elm, field); \ ++ DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ ++} while (0) ++ ++#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ ++ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ ++ DWC_CIRCLEQ_END(head)) \ ++ (head).cqh_last = (elm2); \ ++ else \ ++ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ ++ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ ++ DWC_CIRCLEQ_END(head)) \ ++ (head).cqh_first = (elm2); \ ++ else \ ++ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ ++} while (0) ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LIST_H_ */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_mem.c b/drivers/usb/host/dwc_common_port/dwc_mem.c +new file mode 100644 +index 0000000..ad645ff +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_mem.c +@@ -0,0 +1,245 @@ ++/* Memory Debugging */ ++#ifdef DWC_DEBUG_MEMORY ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++struct allocation { ++ void *addr; ++ void *ctx; ++ char *func; ++ int line; ++ uint32_t size; ++ int dma; ++ DWC_CIRCLEQ_ENTRY(allocation) entry; ++}; ++ ++DWC_CIRCLEQ_HEAD(allocation_queue, allocation); ++ ++struct allocation_manager { ++ void *mem_ctx; ++ struct allocation_queue allocations; ++ ++ /* statistics */ ++ int num; ++ int num_freed; ++ int num_active; ++ uint32_t total; ++ uint32_t cur; ++ uint32_t max; ++}; ++ ++static struct allocation_manager *manager = NULL; ++ ++static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr, ++ int dma) ++{ ++ struct allocation *a; ++ ++ DWC_ASSERT(manager != NULL, "manager not allocated"); ++ ++ a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a)); ++ if (!a) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1); ++ if (!a->func) { ++ __DWC_FREE(manager->mem_ctx, a); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1); ++ a->addr = addr; ++ a->ctx = ctx; ++ a->line = line; ++ a->size = size; ++ a->dma = dma; ++ DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry); ++ ++ /* Update stats */ ++ manager->num++; ++ manager->num_active++; ++ manager->total += size; ++ manager->cur += size; ++ ++ if (manager->max < manager->cur) { ++ manager->max = manager->cur; ++ } ++ ++ return 0; ++} ++ ++static struct allocation *find_allocation(void *ctx, void *addr) ++{ ++ struct allocation *a; ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ if (a->ctx == ctx && a->addr == addr) { ++ return a; ++ } ++ } ++ ++ return NULL; ++} ++ ++static void free_allocation(void *ctx, void *addr, char const *func, int line) ++{ ++ struct allocation *a = find_allocation(ctx, addr); ++ ++ if (!a) { ++ DWC_ASSERT(0, ++ "Free of address %p that was never allocated or already freed %s:%d", ++ addr, func, line); ++ return; ++ } ++ ++ DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry); ++ ++ manager->num_active--; ++ manager->num_freed++; ++ manager->cur -= a->size; ++ __DWC_FREE(manager->mem_ctx, a->func); ++ __DWC_FREE(manager->mem_ctx, a); ++} ++ ++int dwc_memory_debug_start(void *mem_ctx) ++{ ++ DWC_ASSERT(manager == NULL, "Memory debugging has already started\n"); ++ ++ if (manager) { ++ return -DWC_E_BUSY; ++ } ++ ++ manager = __DWC_ALLOC(mem_ctx, sizeof(*manager)); ++ if (!manager) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INIT(&manager->allocations); ++ manager->mem_ctx = mem_ctx; ++ manager->num = 0; ++ manager->num_freed = 0; ++ manager->num_active = 0; ++ manager->total = 0; ++ manager->cur = 0; ++ manager->max = 0; ++ ++ return 0; ++} ++ ++void dwc_memory_debug_stop(void) ++{ ++ struct allocation *a; ++ ++ dwc_memory_debug_report(); ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line); ++ free_allocation(a->ctx, a->addr, NULL, -1); ++ } ++ ++ __DWC_FREE(manager->mem_ctx, manager); ++} ++ ++void dwc_memory_debug_report(void) ++{ ++ struct allocation *a; ++ ++ DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n"); ++ DWC_PRINTF("Num Allocations = %d\n", manager->num); ++ DWC_PRINTF("Freed = %d\n", manager->num_freed); ++ DWC_PRINTF("Active = %d\n", manager->num_active); ++ DWC_PRINTF("Current Memory Used = %d\n", manager->cur); ++ DWC_PRINTF("Total Memory Used = %d\n", manager->total); ++ DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max); ++ DWC_PRINTF("Unfreed allocations:\n"); ++ ++ DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { ++ DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", ++ a->addr, a->size, a->func, a->line, a->dma); ++ } ++} ++ ++/* The replacement functions */ ++void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line) ++{ ++ void *addr = __DWC_ALLOC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __DWC_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, ++ int line) ++{ ++ void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __DWC_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line) ++{ ++ free_allocation(mem_ctx, addr, func, line); ++ __DWC_FREE(mem_ctx, addr); ++} ++ ++void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line) ++{ ++ void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, ++ dwc_dma_t *dma_addr, char const *func, int line) ++{ ++ void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ ++ return addr; ++} ++ ++void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ dwc_dma_t dma_addr, char const *func, int line) ++{ ++ free_allocation(dma_ctx, virt_addr, func, line); ++ __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++#endif /* DWC_DEBUG_MEMORY */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.c b/drivers/usb/host/dwc_common_port/dwc_modpow.c +new file mode 100644 +index 0000000..b7c456b +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c +@@ -0,0 +1,636 @@ ++/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows. ++ * ++ * PuTTY is copyright 1997-2007 Simon Tatham. ++ * ++ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian ++ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, ++ * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus ++ * Kuhn, and CORE SDI S.A. ++ * ++ * Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation files ++ * (the "Software"), to deal in the Software without restriction, ++ * including without limitation the rights to use, copy, modify, merge, ++ * publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, ++ * subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE ++ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF ++ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#ifdef DWC_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "dwc_modpow.h" ++ ++#define BIGNUM_INT_MASK 0xFFFFFFFFUL ++#define BIGNUM_TOP_BIT 0x80000000UL ++#define BIGNUM_INT_BITS 32 ++ ++ ++static void *snmalloc(void *mem_ctx, size_t n, size_t size) ++{ ++ void *p; ++ size *= n; ++ if (size == 0) size = 1; ++ p = dwc_alloc(mem_ctx, size); ++ return p; ++} ++ ++#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type))) ++#define sfree dwc_free ++ ++/* ++ * Usage notes: ++ * * Do not call the DIVMOD_WORD macro with expressions such as array ++ * subscripts, as some implementations object to this (see below). ++ * * Note that none of the division methods below will cope if the ++ * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful ++ * to avoid this case. ++ * If this condition occurs, in the case of the x86 DIV instruction, ++ * an overflow exception will occur, which (according to a correspondent) ++ * will manifest on Windows as something like ++ * 0xC0000095: Integer overflow ++ * The C variant won't give the right answer, either. ++ */ ++ ++#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) ++ ++#if defined __GNUC__ && defined __i386__ ++#define DIVMOD_WORD(q, r, hi, lo, w) \ ++ __asm__("div %2" : \ ++ "=d" (r), "=a" (q) : \ ++ "r" (w), "d" (hi), "a" (lo)) ++#else ++#define DIVMOD_WORD(q, r, hi, lo, w) do { \ ++ BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ ++ q = n / w; \ ++ r = n % w; \ ++} while (0) ++#endif ++ ++// q = n / w; ++// r = n % w; ++ ++#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8) ++ ++#define BIGNUM_INTERNAL ++ ++static Bignum newbn(void *mem_ctx, int length) ++{ ++ Bignum b = snewn(mem_ctx, length + 1, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ DWC_MEMSET(b, 0, (length + 1) * sizeof(*b)); ++ b[0] = length; ++ return b; ++} ++ ++void freebn(void *mem_ctx, Bignum b) ++{ ++ /* ++ * Burn the evidence, just in case. ++ */ ++ DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1)); ++ sfree(mem_ctx, b); ++} ++ ++/* ++ * Compute c = a * b. ++ * Input is in the first len words of a and b. ++ * Result is returned in the first 2*len words of c. ++ */ ++static void internal_mul(BignumInt *a, BignumInt *b, ++ BignumInt *c, int len) ++{ ++ int i, j; ++ BignumDblInt t; ++ ++ for (j = 0; j < 2 * len; j++) ++ c[j] = 0; ++ ++ for (i = len - 1; i >= 0; i--) { ++ t = 0; ++ for (j = len - 1; j >= 0; j--) { ++ t += MUL_WORD(a[i], (BignumDblInt) b[j]); ++ t += (BignumDblInt) c[i + j + 1]; ++ c[i + j + 1] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ c[i] = (BignumInt) t; ++ } ++} ++ ++static void internal_add_shifted(BignumInt *number, ++ unsigned n, int shift) ++{ ++ int word = 1 + (shift / BIGNUM_INT_BITS); ++ int bshift = shift % BIGNUM_INT_BITS; ++ BignumDblInt addend; ++ ++ addend = (BignumDblInt)n << bshift; ++ ++ while (addend) { ++ addend += number[word]; ++ number[word] = (BignumInt) addend & BIGNUM_INT_MASK; ++ addend >>= BIGNUM_INT_BITS; ++ word++; ++ } ++} ++ ++/* ++ * Compute a = a % m. ++ * Input in first alen words of a and first mlen words of m. ++ * Output in first alen words of a ++ * (of which first alen-mlen words will be zero). ++ * The MSW of m MUST have its high bit set. ++ * Quotient is accumulated in the `quotient' array, which is a Bignum ++ * rather than the internal bigendian format. Quotient parts are shifted ++ * left by `qshift' before adding into quot. ++ */ ++static void internal_mod(BignumInt *a, int alen, ++ BignumInt *m, int mlen, ++ BignumInt *quot, int qshift) ++{ ++ BignumInt m0, m1; ++ unsigned int h; ++ int i, k; ++ ++ m0 = m[0]; ++ if (mlen > 1) ++ m1 = m[1]; ++ else ++ m1 = 0; ++ ++ for (i = 0; i <= alen - mlen; i++) { ++ BignumDblInt t; ++ unsigned int q, r, c, ai1; ++ ++ if (i == 0) { ++ h = 0; ++ } else { ++ h = a[i - 1]; ++ a[i - 1] = 0; ++ } ++ ++ if (i == alen - 1) ++ ai1 = 0; ++ else ++ ai1 = a[i + 1]; ++ ++ /* Find q = h:a[i] / m0 */ ++ if (h >= m0) { ++ /* ++ * Special case. ++ * ++ * To illustrate it, suppose a BignumInt is 8 bits, and ++ * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then ++ * our initial division will be 0xA123 / 0xA1, which ++ * will give a quotient of 0x100 and a divide overflow. ++ * However, the invariants in this division algorithm ++ * are not violated, since the full number A1:23:... is ++ * _less_ than the quotient prefix A1:B2:... and so the ++ * following correction loop would have sorted it out. ++ * ++ * In this situation we set q to be the largest ++ * quotient we _can_ stomach (0xFF, of course). ++ */ ++ q = BIGNUM_INT_MASK; ++ } else { ++ /* Macro doesn't want an array subscript expression passed ++ * into it (see definition), so use a temporary. */ ++ BignumInt tmplo = a[i]; ++ DIVMOD_WORD(q, r, h, tmplo, m0); ++ ++ /* Refine our estimate of q by looking at ++ h:a[i]:a[i+1] / m0:m1 */ ++ t = MUL_WORD(m1, q); ++ if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) { ++ q--; ++ t -= m1; ++ r = (r + m0) & BIGNUM_INT_MASK; /* overflow? */ ++ if (r >= (BignumDblInt) m0 && ++ t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--; ++ } ++ } ++ ++ /* Subtract q * m from a[i...] */ ++ c = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t = MUL_WORD(q, m[k]); ++ t += c; ++ c = (unsigned)(t >> BIGNUM_INT_BITS); ++ if ((BignumInt) t > a[i + k]) ++ c++; ++ a[i + k] -= (BignumInt) t; ++ } ++ ++ /* Add back m in case of borrow */ ++ if (c != h) { ++ t = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t += m[k]; ++ t += a[i + k]; ++ a[i + k] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ q--; ++ } ++ if (quot) ++ internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i)); ++ } ++} ++ ++/* ++ * Compute p % mod. ++ * The most significant word of mod MUST be non-zero. ++ * We assume that the result array is the same size as the mod array. ++ * We optionally write out a quotient if `quotient' is non-NULL. ++ * We can avoid writing out the result if `result' is NULL. ++ */ ++void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient) ++{ ++ BignumInt *n, *m; ++ int mshift; ++ int plen, mlen, i, j; ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ plen = p[0]; ++ /* Ensure plen > mlen */ ++ if (plen <= mlen) ++ plen = mlen + 1; ++ ++ /* Allocate n of size plen, copy p to n */ ++ n = snewn(mem_ctx, plen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ for (j = 0; j < plen; j++) ++ n[j] = 0; ++ for (j = 1; j <= (int)p[0]; j++) ++ n[plen - j] = p[j]; ++ ++ /* Main computation */ ++ internal_mod(n, plen, m, mlen, quotient, mshift); ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = plen - mlen - 1; i < plen - 1; i++) ++ n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ n[plen - 1] = n[plen - 1] << mshift; ++ internal_mod(n, plen, m, mlen, quotient, 0); ++ for (i = plen - 1; i >= plen - mlen; i--) ++ n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ if (result) { ++ for (i = 1; i <= (int)result[0]; i++) { ++ int j = plen - i; ++ result[i] = j >= 0 ? n[j] : 0; ++ } ++ } ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < plen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++} ++ ++/* ++ * Simple remainder. ++ */ ++Bignum bigmod(void *mem_ctx, Bignum a, Bignum b) ++{ ++ Bignum r = newbn(mem_ctx, b[0]); ++ bigdivmod(mem_ctx, a, b, r, NULL); ++ return r; ++} ++ ++/* ++ * Compute (base ^ exp) % mod. ++ */ ++Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod) ++{ ++ BignumInt *a, *b, *n, *m; ++ int mshift; ++ int mlen, i, j; ++ Bignum base, result; ++ ++ /* ++ * The most significant word of mod needs to be non-zero. It ++ * should already be, but let's make sure. ++ */ ++ //assert(mod[mod[0]] != 0); ++ ++ /* ++ * Make sure the base is smaller than the modulus, by reducing ++ * it modulo the modulus if not. ++ */ ++ base = bigmod(mem_ctx, base_in, mod); ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = ++ (m[i] << mshift) | (m[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ /* Allocate n of size mlen, copy base to n */ ++ n = snewn(mem_ctx, mlen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ i = mlen - base[0]; ++ for (j = 0; j < i; j++) ++ n[j] = 0; ++ for (j = 0; j < base[0]; j++) ++ n[i + j] = base[base[0] - j]; ++ ++ /* Allocate a and b of size 2*mlen. Set a = 1 */ ++ a = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!a) ++ //abort(); /* FIXME */ ++ b = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ a[2 * mlen - 1] = 1; ++ ++ /* Skip leading zero bits of exp. */ ++ i = 0; ++ j = BIGNUM_INT_BITS - 1; ++ while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) { ++ j--; ++ if (j < 0) { ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ } ++ ++ /* Main computation */ ++ while (i < exp[0]) { ++ while (j >= 0) { ++ internal_mul(a + mlen, a + mlen, b, mlen); ++ internal_mod(b, mlen * 2, m, mlen, NULL, 0); ++ if ((exp[exp[0] - i] & (1 << j)) != 0) { ++ internal_mul(b + mlen, n, a, mlen); ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ } else { ++ BignumInt *t; ++ t = a; ++ a = b; ++ b = t; ++ } ++ j--; ++ } ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = mlen - 1; i < 2 * mlen - 1; i++) ++ a[i] = ++ (a[i] << mshift) | (a[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ a[2 * mlen - 1] = a[2 * mlen - 1] << mshift; ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ for (i = 2 * mlen - 1; i >= mlen; i--) ++ a[i] = ++ (a[i] >> mshift) | (a[i - 1] << ++ (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ result = newbn(mem_ctx, mod[0]); ++ for (i = 0; i < mlen; i++) ++ result[result[0] - i] = a[i + mlen]; ++ while (result[0] > 1 && result[result[0]] == 0) ++ result[0]--; ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ sfree(mem_ctx, a); ++ for (i = 0; i < 2 * mlen; i++) ++ b[i] = 0; ++ sfree(mem_ctx, b); ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < mlen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++ ++ freebn(mem_ctx, base); ++ ++ return result; ++} ++ ++ ++#ifdef UNITTEST ++ ++static __u32 dh_p[] = { ++ 96, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++ 0xA93AD2CA, ++ 0x4B82D120, ++ 0xE0FD108E, ++ 0x43DB5BFC, ++ 0x74E5AB31, ++ 0x08E24FA0, ++ 0xBAD946E2, ++ 0x770988C0, ++ 0x7A615D6C, ++ 0xBBE11757, ++ 0x177B200C, ++ 0x521F2B18, ++ 0x3EC86A64, ++ 0xD8760273, ++ 0xD98A0864, ++ 0xF12FFA06, ++ 0x1AD2EE6B, ++ 0xCEE3D226, ++ 0x4A25619D, ++ 0x1E8C94E0, ++ 0xDB0933D7, ++ 0xABF5AE8C, ++ 0xA6E1E4C7, ++ 0xB3970F85, ++ 0x5D060C7D, ++ 0x8AEA7157, ++ 0x58DBEF0A, ++ 0xECFB8504, ++ 0xDF1CBA64, ++ 0xA85521AB, ++ 0x04507A33, ++ 0xAD33170D, ++ 0x8AAAC42D, ++ 0x15728E5A, ++ 0x98FA0510, ++ 0x15D22618, ++ 0xEA956AE5, ++ 0x3995497C, ++ 0x95581718, ++ 0xDE2BCBF6, ++ 0x6F4C52C9, ++ 0xB5C55DF0, ++ 0xEC07A28F, ++ 0x9B2783A2, ++ 0x180E8603, ++ 0xE39E772C, ++ 0x2E36CE3B, ++ 0x32905E46, ++ 0xCA18217C, ++ 0xF1746C08, ++ 0x4ABC9804, ++ 0x670C354E, ++ 0x7096966D, ++ 0x9ED52907, ++ 0x208552BB, ++ 0x1C62F356, ++ 0xDCA3AD96, ++ 0x83655D23, ++ 0xFD24CF5F, ++ 0x69163FA8, ++ 0x1C55D39A, ++ 0x98DA4836, ++ 0xA163BF05, ++ 0xC2007CB8, ++ 0xECE45B3D, ++ 0x49286651, ++ 0x7C4B1FE6, ++ 0xAE9F2411, ++ 0x5A899FA5, ++ 0xEE386BFB, ++ 0xF406B7ED, ++ 0x0BFF5CB6, ++ 0xA637ED6B, ++ 0xF44C42E9, ++ 0x625E7EC6, ++ 0xE485B576, ++ 0x6D51C245, ++ 0x4FE1356D, ++ 0xF25F1437, ++ 0x302B0A6D, ++ 0xCD3A431B, ++ 0xEF9519B3, ++ 0x8E3404DD, ++ 0x514A0879, ++ 0x3B139B22, ++ 0x020BBEA6, ++ 0x8A67CC74, ++ 0x29024E08, ++ 0x80DC1CD1, ++ 0xC4C6628B, ++ 0x2168C234, ++ 0xC90FDAA2, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++}; ++ ++static __u32 dh_a[] = { ++ 8, ++ 0xdf367516, ++ 0x86459caa, ++ 0xe2d459a4, ++ 0xd910dae0, ++ 0x8a8b5e37, ++ 0x67ab31c6, ++ 0xf0b55ea9, ++ 0x440051d6, ++}; ++ ++static __u32 dh_b[] = { ++ 8, ++ 0xded92656, ++ 0xe07a048a, ++ 0x6fa452cd, ++ 0x2df89d30, ++ 0xc75f1b0f, ++ 0x8ce3578f, ++ 0x7980a324, ++ 0x5daec786, ++}; ++ ++static __u32 dh_g[] = { ++ 1, ++ 2, ++}; ++ ++int main(void) ++{ ++ int i; ++ __u32 *k; ++ k = dwc_modpow(NULL, dh_g, dh_a, dh_p); ++ ++ printf("\n\n"); ++ for (i=0; i> 16; ++ printf("%04x %04x ", m, l); ++ if (!((i + 1)%13)) printf("\n"); ++ } ++ printf("\n\n"); ++ ++ if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) { ++ printf("PASS\n\n"); ++ } ++ else { ++ printf("FAIL\n\n"); ++ } ++ ++} ++ ++#endif /* UNITTEST */ ++ ++#endif /* CONFIG_MACH_IPMATE */ ++ ++#endif /*DWC_CRYPTOLIB */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.h b/drivers/usb/host/dwc_common_port/dwc_modpow.h +new file mode 100644 +index 0000000..64f00c2 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h +@@ -0,0 +1,34 @@ ++/* ++ * dwc_modpow.h ++ * See dwc_modpow.c for license and changes ++ */ ++#ifndef _DWC_MODPOW_H ++#define _DWC_MODPOW_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "dwc_os.h" ++ ++/** @file ++ * ++ * This file defines the module exponentiation function which is only used ++ * internally by the DWC UWB modules for calculation of PKs during numeric ++ * association. The routine is taken from the PUTTY, an open source terminal ++ * emulator. The PUTTY License is preserved in the dwc_modpow.c file. ++ * ++ */ ++ ++typedef uint32_t BignumInt; ++typedef uint64_t BignumDblInt; ++typedef BignumInt *Bignum; ++ ++/* Compute modular exponentiaion */ ++extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _LINUX_BIGNUM_H */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.c b/drivers/usb/host/dwc_common_port/dwc_notifier.c +new file mode 100644 +index 0000000..8b3772a +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c +@@ -0,0 +1,319 @@ ++#ifdef DWC_NOTIFYLIB ++ ++#include "dwc_notifier.h" ++#include "dwc_list.h" ++ ++typedef struct dwc_observer { ++ void *observer; ++ dwc_notifier_callback_t callback; ++ void *data; ++ char *notification; ++ DWC_CIRCLEQ_ENTRY(dwc_observer) list_entry; ++} observer_t; ++ ++DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer); ++ ++typedef struct dwc_notifier { ++ void *mem_ctx; ++ void *object; ++ struct observer_queue observers; ++ DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry; ++} notifier_t; ++ ++DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier); ++ ++typedef struct manager { ++ void *mem_ctx; ++ void *wkq_ctx; ++ dwc_workq_t *wq; ++// dwc_mutex_t *mutex; ++ struct notifier_queue notifiers; ++} manager_t; ++ ++static manager_t *manager = NULL; ++ ++static int create_manager(void *mem_ctx, void *wkq_ctx) ++{ ++ manager = dwc_alloc(mem_ctx, sizeof(manager_t)); ++ if (!manager) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INIT(&manager->notifiers); ++ ++ manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ"); ++ if (!manager->wq) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ return 0; ++} ++ ++static void free_manager(void) ++{ ++ dwc_workq_free(manager->wq); ++ ++ /* All notifiers must have unregistered themselves before this module ++ * can be removed. Hitting this assertion indicates a programmer ++ * error. */ ++ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), ++ "Notification manager being freed before all notifiers have been removed"); ++ dwc_free(manager->mem_ctx, manager); ++} ++ ++#ifdef DEBUG ++static void dump_manager(void) ++{ ++ notifier_t *n; ++ observer_t *o; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_DEBUG("List of all notifiers and observers:\n"); ++ DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { ++ DWC_DEBUG("Notifier %p has observers:\n", n->object); ++ DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) { ++ DWC_DEBUG(" %p watching %s\n", o->observer, o->notification); ++ } ++ } ++} ++#else ++#define dump_manager(...) ++#endif ++ ++static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification, ++ dwc_notifier_callback_t callback, void *data) ++{ ++ observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t)); ++ ++ if (!new_observer) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry); ++ new_observer->observer = observer; ++ new_observer->notification = notification; ++ new_observer->callback = callback; ++ new_observer->data = data; ++ return new_observer; ++} ++ ++static void free_observer(void *mem_ctx, observer_t *observer) ++{ ++ dwc_free(mem_ctx, observer); ++} ++ ++static notifier_t *alloc_notifier(void *mem_ctx, void *object) ++{ ++ notifier_t *notifier; ++ ++ if (!object) { ++ return NULL; ++ } ++ ++ notifier = dwc_alloc(mem_ctx, sizeof(notifier_t)); ++ if (!notifier) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INIT(¬ifier->observers); ++ DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry); ++ ++ notifier->mem_ctx = mem_ctx; ++ notifier->object = object; ++ return notifier; ++} ++ ++static void free_notifier(notifier_t *notifier) ++{ ++ observer_t *observer; ++ ++ DWC_CIRCLEQ_FOREACH(observer, ¬ifier->observers, list_entry) { ++ free_observer(notifier->mem_ctx, observer); ++ } ++ ++ dwc_free(notifier->mem_ctx, notifier); ++} ++ ++static notifier_t *find_notifier(void *object) ++{ ++ notifier_t *notifier; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ if (!object) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) { ++ if (notifier->object == object) { ++ return notifier; ++ } ++ } ++ ++ return NULL; ++} ++ ++int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx) ++{ ++ return create_manager(mem_ctx, wkq_ctx); ++} ++ ++void dwc_free_notification_manager(void) ++{ ++ free_manager(); ++} ++ ++dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object) ++{ ++ notifier_t *notifier; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ notifier = find_notifier(object); ++ if (notifier) { ++ DWC_ERROR("Notifier %p is already registered\n", object); ++ return NULL; ++ } ++ ++ notifier = alloc_notifier(mem_ctx, object); ++ if (!notifier) { ++ return NULL; ++ } ++ ++ DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); ++ ++ DWC_INFO("Notifier %p registered", object); ++ dump_manager(); ++ ++ return notifier; ++} ++ ++void dwc_unregister_notifier(dwc_notifier_t *notifier) ++{ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ if (!DWC_CIRCLEQ_EMPTY(¬ifier->observers)) { ++ observer_t *o; ++ ++ DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object); ++ DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { ++ DWC_DEBUGC(" %p watching %s\n", o->observer, o->notification); ++ } ++ ++ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers), ++ "Notifier %p has active observers when removing", notifier); ++ } ++ ++ DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry); ++ free_notifier(notifier); ++ ++ DWC_INFO("Notifier unregistered"); ++ dump_manager(); ++} ++ ++/* Add an observer to observe the notifier for a particular state, event, or notification. */ ++int dwc_add_observer(void *observer, void *object, char *notification, ++ dwc_notifier_callback_t callback, void *data) ++{ ++ notifier_t *notifier = find_notifier(object); ++ observer_t *new_observer; ++ ++ if (!notifier) { ++ DWC_ERROR("Notifier %p is not found when adding observer\n", object); ++ return -DWC_E_INVALID; ++ } ++ ++ new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data); ++ if (!new_observer) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_CIRCLEQ_INSERT_TAIL(¬ifier->observers, new_observer, list_entry); ++ ++ DWC_INFO("Added observer %p to notifier %p observing notification %s, callback=%p, data=%p", ++ observer, object, notification, callback, data); ++ ++ dump_manager(); ++ return 0; ++} ++ ++int dwc_remove_observer(void *observer) ++{ ++ notifier_t *n; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { ++ observer_t *o; ++ observer_t *o2; ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) { ++ if (o->observer == observer) { ++ DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry); ++ DWC_INFO("Removing observer %p from notifier %p watching notification %s:", ++ o->observer, n->object, o->notification); ++ free_observer(n->mem_ctx, o); ++ } ++ } ++ } ++ ++ dump_manager(); ++ return 0; ++} ++ ++typedef struct callback_data { ++ void *mem_ctx; ++ dwc_notifier_callback_t cb; ++ void *observer; ++ void *data; ++ void *object; ++ char *notification; ++ void *notification_data; ++} cb_data_t; ++ ++static void cb_task(void *data) ++{ ++ cb_data_t *cb = (cb_data_t *)data; ++ ++ cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data); ++ dwc_free(cb->mem_ctx, cb); ++} ++ ++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data) ++{ ++ observer_t *o; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ ++ DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { ++ int len = DWC_STRLEN(notification); ++ ++ if (DWC_STRLEN(o->notification) != len) { ++ continue; ++ } ++ ++ if (DWC_STRNCMP(o->notification, notification, len) == 0) { ++ cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t)); ++ ++ if (!cb_data) { ++ DWC_ERROR("Failed to allocate callback data\n"); ++ return; ++ } ++ ++ cb_data->mem_ctx = notifier->mem_ctx; ++ cb_data->cb = o->callback; ++ cb_data->observer = o->observer; ++ cb_data->data = o->data; ++ cb_data->object = notifier->object; ++ cb_data->notification = notification; ++ cb_data->notification_data = notification_data; ++ DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification); ++ DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data, ++ "Notify callback from %p for Notification %s, to observer %p", ++ cb_data->object, notification, cb_data->observer); ++ } ++ } ++} ++ ++#endif /* DWC_NOTIFYLIB */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.h b/drivers/usb/host/dwc_common_port/dwc_notifier.h +new file mode 100644 +index 0000000..4a8cdfe +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h +@@ -0,0 +1,122 @@ ++ ++#ifndef __DWC_NOTIFIER_H__ ++#define __DWC_NOTIFIER_H__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "dwc_os.h" ++ ++/** @file ++ * ++ * A simple implementation of the Observer pattern. Any "module" can ++ * register as an observer or notifier. The notion of "module" is abstract and ++ * can mean anything used to identify either an observer or notifier. Usually ++ * it will be a pointer to a data structure which contains some state, ie an ++ * object. ++ * ++ * Before any notifiers can be added, the global notification manager must be ++ * brought up with dwc_alloc_notification_manager(). ++ * dwc_free_notification_manager() will bring it down and free all resources. ++ * These would typically be called upon module load and unload. The ++ * notification manager is a single global instance that handles all registered ++ * observable modules and observers so this should be done only once. ++ * ++ * A module can be observable by using Notifications to publicize some general ++ * information about it's state or operation. It does not care who listens, or ++ * even if anyone listens, or what they do with the information. The observable ++ * modules do not need to know any information about it's observers or their ++ * interface, or their state or data. ++ * ++ * Any module can register to emit Notifications. It should publish a list of ++ * notifications that it can emit and their behavior, such as when they will get ++ * triggered, and what information will be provided to the observer. Then it ++ * should register itself as an observable module. See dwc_register_notifier(). ++ * ++ * Any module can observe any observable, registered module, provided it has a ++ * handle to the other module and knows what notifications to observe. See ++ * dwc_add_observer(). ++ * ++ * A function of type dwc_notifier_callback_t is called whenever a notification ++ * is triggered with one or more observers observing it. This function is ++ * called in it's own process so it may sleep or block if needed. It is ++ * guaranteed to be called sometime after the notification has occurred and will ++ * be called once per each time the notification is triggered. It will NOT be ++ * called in the same process context used to trigger the notification. ++ * ++ * @section Limitiations ++ * ++ * Keep in mind that Notifications that can be triggered in rapid sucession may ++ * schedule too many processes too handle. Be aware of this limitation when ++ * designing to use notifications, and only add notifications for appropriate ++ * observable information. ++ * ++ * Also Notification callbacks are not synchronous. If you need to synchronize ++ * the behavior between module/observer you must use other means. And perhaps ++ * that will mean Notifications are not the proper solution. ++ */ ++ ++struct dwc_notifier; ++typedef struct dwc_notifier dwc_notifier_t; ++ ++/** The callback function must be of this type. ++ * ++ * @param object This is the object that is being observed. ++ * @param notification This is the notification that was triggered. ++ * @param observer This is the observer ++ * @param notification_data This is notification-specific data that the notifier ++ * has included in this notification. The value of this should be published in ++ * the documentation of the observable module with the notifications. ++ * @param user_data This is any custom data that the observer provided when ++ * adding itself as an observer to the notification. */ ++typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, ++ void *notification_data, void *user_data); ++ ++/** Brings up the notification manager. */ ++extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx); ++/** Brings down the notification manager. */ ++extern void dwc_free_notification_manager(void); ++ ++/** This function registers an observable module. A dwc_notifier_t object is ++ * returned to the observable module. This is an opaque object that is used by ++ * the observable module to trigger notifications. This object should only be ++ * accessible to functions that are authorized to trigger notifications for this ++ * module. Observers do not need this object. */ ++extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object); ++ ++/** This function unregisters an observable module. All observers have to be ++ * removed prior to unregistration. */ ++extern void dwc_unregister_notifier(dwc_notifier_t *notifier); ++ ++/** Add a module as an observer to the observable module. The observable module ++ * needs to have previously registered with the notification manager. ++ * ++ * @param observer The observer module ++ * @param object The module to observe ++ * @param notification The notification to observe ++ * @param callback The callback function to call ++ * @param user_data Any additional user data to pass into the callback function */ ++extern int dwc_add_observer(void *observer, void *object, char *notification, ++ dwc_notifier_callback_t callback, void *user_data); ++ ++/** Removes the specified observer from all notifications that it is currently ++ * observing. */ ++extern int dwc_remove_observer(void *observer); ++ ++/** This function triggers a Notification. It should be called by the ++ * observable module, or any module or library which the observable module ++ * allows to trigger notification on it's behalf. Such as the dwc_cc_t. ++ * ++ * dwc_notify is a non-blocking function. Callbacks are scheduled called in ++ * their own process context for each trigger. Callbacks can be blocking. ++ * dwc_notify can be called from interrupt context if needed. ++ * ++ */ ++void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* __DWC_NOTIFIER_H__ */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h +new file mode 100644 +index 0000000..308ddd5 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_os.h +@@ -0,0 +1,1260 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $ ++ * $Revision: #14 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621695 $ ++ * ++ * Synopsys Portability Library Software 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_OS_H_ ++#define _DWC_OS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * DWC portability library, low level os-wrapper functions ++ * ++ */ ++ ++/* These basic types need to be defined by some OS header file or custom header ++ * file for your specific target architecture. ++ * ++ * uint8_t, int8_t, uint16_t, int16_t, uint32_t, int32_t, uint64_t, int64_t ++ * ++ * Any custom or alternate header file must be added and enabled here. ++ */ ++ ++#ifdef DWC_LINUX ++# include ++# ifdef CONFIG_DEBUG_MUTEXES ++# include ++# endif ++# include ++# include ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++# include ++#endif ++ ++ ++/** @name Primitive Types and Values */ ++ ++/** We define a boolean type for consistency. Can be either YES or NO */ ++typedef uint8_t dwc_bool_t; ++#define YES 1 ++#define NO 0 ++ ++#ifdef DWC_LINUX ++ ++/** @name Error Codes */ ++#define DWC_E_INVALID EINVAL ++#define DWC_E_NO_MEMORY ENOMEM ++#define DWC_E_NO_DEVICE ENODEV ++#define DWC_E_NOT_SUPPORTED EOPNOTSUPP ++#define DWC_E_TIMEOUT ETIMEDOUT ++#define DWC_E_BUSY EBUSY ++#define DWC_E_AGAIN EAGAIN ++#define DWC_E_RESTART ERESTART ++#define DWC_E_ABORT ECONNABORTED ++#define DWC_E_SHUTDOWN ESHUTDOWN ++#define DWC_E_NO_DATA ENODATA ++#define DWC_E_DISCONNECT ECONNRESET ++#define DWC_E_UNKNOWN EINVAL ++#define DWC_E_NO_STREAM_RES ENOSR ++#define DWC_E_COMMUNICATION ECOMM ++#define DWC_E_OVERFLOW EOVERFLOW ++#define DWC_E_PROTOCOL EPROTO ++#define DWC_E_IN_PROGRESS EINPROGRESS ++#define DWC_E_PIPE EPIPE ++#define DWC_E_IO EIO ++#define DWC_E_NO_SPACE ENOSPC ++ ++#else ++ ++/** @name Error Codes */ ++#define DWC_E_INVALID 1001 ++#define DWC_E_NO_MEMORY 1002 ++#define DWC_E_NO_DEVICE 1003 ++#define DWC_E_NOT_SUPPORTED 1004 ++#define DWC_E_TIMEOUT 1005 ++#define DWC_E_BUSY 1006 ++#define DWC_E_AGAIN 1007 ++#define DWC_E_RESTART 1008 ++#define DWC_E_ABORT 1009 ++#define DWC_E_SHUTDOWN 1010 ++#define DWC_E_NO_DATA 1011 ++#define DWC_E_DISCONNECT 2000 ++#define DWC_E_UNKNOWN 3000 ++#define DWC_E_NO_STREAM_RES 4001 ++#define DWC_E_COMMUNICATION 4002 ++#define DWC_E_OVERFLOW 4003 ++#define DWC_E_PROTOCOL 4004 ++#define DWC_E_IN_PROGRESS 4005 ++#define DWC_E_PIPE 4006 ++#define DWC_E_IO 4007 ++#define DWC_E_NO_SPACE 4008 ++ ++#endif ++ ++ ++/** @name Tracing/Logging Functions ++ * ++ * These function provide the capability to add tracing, debugging, and error ++ * messages, as well exceptions as assertions. The WUDEV uses these ++ * extensively. These could be logged to the main console, the serial port, an ++ * internal buffer, etc. These functions could also be no-op if they are too ++ * expensive on your system. By default undefining the DEBUG macro already ++ * no-ops some of these functions. */ ++ ++/** Returns non-zero if in interrupt context. */ ++extern dwc_bool_t DWC_IN_IRQ(void); ++#define dwc_in_irq DWC_IN_IRQ ++ ++/** Returns "IRQ" if DWC_IN_IRQ is true. */ ++static inline char *dwc_irq(void) { ++ return DWC_IN_IRQ() ? "IRQ" : ""; ++} ++ ++/** Returns non-zero if in bottom-half context. */ ++extern dwc_bool_t DWC_IN_BH(void); ++#define dwc_in_bh DWC_IN_BH ++ ++/** Returns "BH" if DWC_IN_BH is true. */ ++static inline char *dwc_bh(void) { ++ return DWC_IN_BH() ? "BH" : ""; ++} ++ ++/** ++ * A vprintf() clone. Just call vprintf if you've got it. ++ */ ++extern void DWC_VPRINTF(char *format, va_list args); ++#define dwc_vprintf DWC_VPRINTF ++ ++/** ++ * A vsnprintf() clone. Just call vprintf if you've got it. ++ */ ++extern int DWC_VSNPRINTF(char *str, int size, char *format, va_list args); ++#define dwc_vsnprintf DWC_VSNPRINTF ++ ++/** ++ * printf() clone. Just call printf if you've go it. ++ */ ++extern void DWC_PRINTF(char *format, ...) ++/* This provides compiler level static checking of the parameters if you're ++ * using GCC. */ ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#define dwc_printf DWC_PRINTF ++ ++/** ++ * sprintf() clone. Just call sprintf if you've got it. ++ */ ++extern int DWC_SPRINTF(char *string, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 2, 3))); ++#else ++ ; ++#endif ++#define dwc_sprintf DWC_SPRINTF ++ ++/** ++ * snprintf() clone. Just call snprintf if you've got it. ++ */ ++extern int DWC_SNPRINTF(char *string, int size, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 3, 4))); ++#else ++ ; ++#endif ++#define dwc_snprintf DWC_SNPRINTF ++ ++/** ++ * Prints a WARNING message. On systems that don't differentiate between ++ * warnings and regular log messages, just print it. Indicates that something ++ * may be wrong with the driver. Works like printf(). ++ * ++ * Use the DWC_WARN macro to call this function. ++ */ ++extern void __DWC_WARN(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++ ++/** ++ * Prints an error message. On systems that don't differentiate between errors ++ * and regular log messages, just print it. Indicates that something went wrong ++ * with the driver. Works like printf(). ++ * ++ * Use the DWC_ERROR macro to call this function. ++ */ ++extern void __DWC_ERROR(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++ ++/** ++ * Prints an exception error message and takes some user-defined action such as ++ * print out a backtrace or trigger a breakpoint. Indicates that something went ++ * abnormally wrong with the driver such as programmer error, or other ++ * exceptional condition. It should not be ignored so even on systems without ++ * printing capability, some action should be taken to notify the developer of ++ * it. Works like printf(). ++ */ ++extern void DWC_EXCEPTION(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#define dwc_exception DWC_EXCEPTION ++ ++#ifndef DWC_OTG_DEBUG_LEV ++#define DWC_OTG_DEBUG_LEV 0 ++#endif ++ ++#ifdef DEBUG ++/** ++ * Prints out a debug message. Used for logging/trace messages. ++ * ++ * Use the DWC_DEBUG macro to call this function ++ */ ++extern void __DWC_DEBUG(char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 1, 2))); ++#else ++ ; ++#endif ++#else ++#define __DWC_DEBUG printk ++#endif ++ ++/** ++ * Prints out a Debug message. ++ */ ++#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \ ++ __func__, dwc_irq(), ## _args) ++#define dwc_debug DWC_DEBUG ++/** ++ * Prints out a Debug message if enabled at compile time. ++ */ ++#if DWC_OTG_DEBUG_LEV > 0 ++#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args ) ++#else ++#define DWC_DEBUGC(_format, _args...) ++#endif ++#define dwc_debugc DWC_DEBUGC ++/** ++ * Prints out an informative message. ++ */ ++#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \ ++ dwc_irq(), ## _args) ++#define dwc_info DWC_INFO ++/** ++ * Prints out an informative message if enabled at compile time. ++ */ ++#if DWC_OTG_DEBUG_LEV > 1 ++#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args ) ++#else ++#define DWC_INFOC(_format, _args...) ++#endif ++#define dwc_infoc DWC_INFOC ++/** ++ * Prints out a warning message. ++ */ ++#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_warn DWC_WARN ++/** ++ * Prints out an error message. ++ */ ++#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_error DWC_ERROR ++ ++#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) ++#define dwc_proto_error DWC_PROTO_ERROR ++ ++#ifdef DEBUG ++/** Prints out a exception error message if the _expr expression fails. Disabled ++ * if DEBUG is not enabled. */ ++#define DWC_ASSERT(_expr, _format, _args...) do { \ ++ if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \ ++ __FILE__, __LINE__, ## _args); } \ ++ } while (0) ++#else ++#define DWC_ASSERT(_x...) ++#endif ++#define dwc_assert DWC_ASSERT ++ ++ ++/** @name Byte Ordering ++ * The following functions are for conversions between processor's byte ordering ++ * and specific ordering you want. ++ */ ++ ++/** Converts 32 bit data in CPU byte ordering to little endian. */ ++extern uint32_t DWC_CPU_TO_LE32(uint32_t *p); ++#define dwc_cpu_to_le32 DWC_CPU_TO_LE32 ++ ++/** Converts 32 bit data in CPU byte orderint to big endian. */ ++extern uint32_t DWC_CPU_TO_BE32(uint32_t *p); ++#define dwc_cpu_to_be32 DWC_CPU_TO_BE32 ++ ++/** Converts 32 bit little endian data to CPU byte ordering. */ ++extern uint32_t DWC_LE32_TO_CPU(uint32_t *p); ++#define dwc_le32_to_cpu DWC_LE32_TO_CPU ++ ++/** Converts 32 bit big endian data to CPU byte ordering. */ ++extern uint32_t DWC_BE32_TO_CPU(uint32_t *p); ++#define dwc_be32_to_cpu DWC_BE32_TO_CPU ++ ++/** Converts 16 bit data in CPU byte ordering to little endian. */ ++extern uint16_t DWC_CPU_TO_LE16(uint16_t *p); ++#define dwc_cpu_to_le16 DWC_CPU_TO_LE16 ++ ++/** Converts 16 bit data in CPU byte orderint to big endian. */ ++extern uint16_t DWC_CPU_TO_BE16(uint16_t *p); ++#define dwc_cpu_to_be16 DWC_CPU_TO_BE16 ++ ++/** Converts 16 bit little endian data to CPU byte ordering. */ ++extern uint16_t DWC_LE16_TO_CPU(uint16_t *p); ++#define dwc_le16_to_cpu DWC_LE16_TO_CPU ++ ++/** Converts 16 bit bi endian data to CPU byte ordering. */ ++extern uint16_t DWC_BE16_TO_CPU(uint16_t *p); ++#define dwc_be16_to_cpu DWC_BE16_TO_CPU ++ ++ ++/** @name Register Read/Write ++ * ++ * The following six functions should be implemented to read/write registers of ++ * 32-bit and 64-bit sizes. All modules use this to read/write register values. ++ * The reg value is a pointer to the register calculated from the void *base ++ * variable passed into the driver when it is started. */ ++ ++#ifdef DWC_LINUX ++/* Linux doesn't need any extra parameters for register read/write, so we ++ * just throw away the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t DWC_READ_REG32(uint32_t volatile *reg); ++#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_) ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t DWC_READ_REG64(uint64_t volatile *reg); ++#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_) ++ ++/** Writes to a 32-bit register. */ ++extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value); ++#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_) ++ ++/** Writes to a 64-bit register. */ ++extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value); ++#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_) ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_) ++extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_) ++ ++#endif /* DWC_LINUX */ ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++typedef struct dwc_ioctx { ++ struct device *dev; ++ bus_space_tag_t iot; ++ bus_space_handle_t ioh; ++} dwc_ioctx_t; ++ ++/** BSD needs two extra parameters for register read/write, so we pass ++ * them in using the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg); ++#define dwc_read_reg32 DWC_READ_REG32 ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg); ++#define dwc_read_reg64 DWC_READ_REG64 ++ ++/** Writes to a 32-bit register. */ ++extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value); ++#define dwc_write_reg32 DWC_WRITE_REG32 ++ ++/** Writes to a 64-bit register. */ ++extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value); ++#define dwc_write_reg64 DWC_WRITE_REG64 ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define dwc_modify_reg32 DWC_MODIFY_REG32 ++extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define dwc_modify_reg64 DWC_MODIFY_REG64 ++ ++#endif /* DWC_FREEBSD || DWC_NETBSD */ ++ ++/** @cond */ ++ ++/** @name Some convenience MACROS used internally. Define DWC_DEBUG_REGS to log the ++ * register writes. */ ++ ++#ifdef DWC_LINUX ++ ++# ifdef DWC_DEBUG_REGS ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ ++ return DWC_READ_REG32(&container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ ++ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(_container_type *container) { \ ++ return DWC_READ_REG32(&container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ ++ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ DWC_WRITE_REG32(&container->regs->_reg, data); \ ++} ++ ++# else /* DWC_DEBUG_REGS */ ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ ++ return DWC_READ_REG32(&container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ ++ DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(_container_type *container) { \ ++ return DWC_READ_REG32(&container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ ++ DWC_WRITE_REG32(&container->regs->_reg, data); \ ++} ++ ++# endif /* DWC_DEBUG_REGS */ ++ ++#endif /* DWC_LINUX */ ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++ ++# ifdef DWC_DEBUG_REGS ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# else /* DWC_DEBUG_REGS */ ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# endif /* DWC_DEBUG_REGS */ ++ ++#endif /* DWC_FREEBSD || DWC_NETBSD */ ++ ++/** @endcond */ ++ ++ ++#ifdef DWC_CRYPTOLIB ++/** @name Crypto Functions ++ * ++ * These are the low-level cryptographic functions used by the driver. */ ++ ++/** Perform AES CBC */ ++extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out); ++#define dwc_aes_cbc DWC_AES_CBC ++ ++/** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */ ++extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length); ++#define dwc_random_bytes DWC_RANDOM_BYTES ++ ++/** Perform the SHA-256 hash function */ ++extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out); ++#define dwc_sha256 DWC_SHA256 ++ ++/** Calculated the HMAC-SHA256 */ ++extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out); ++#define dwc_hmac_sha256 DWC_HMAC_SHA256 ++ ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/** @name Memory Allocation ++ * ++ * These function provide access to memory allocation. There are only 2 DMA ++ * functions and 3 Regular memory functions that need to be implemented. None ++ * of the memory debugging routines need to be implemented. The allocation ++ * routines all ZERO the contents of the memory. ++ * ++ * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering. ++ * This checks for memory leaks, keeping track of alloc/free pairs. It also ++ * keeps track of how much memory the driver is using at any given time. */ ++ ++#define DWC_PAGE_SIZE 4096 ++#define DWC_PAGE_OFFSET(addr) (((uint32_t)addr) & 0xfff) ++#define DWC_PAGE_ALIGNED(addr) ((((uint32_t)addr) & 0xfff) == 0) ++ ++#define DWC_INVALID_DMA_ADDR 0x0 ++ ++#ifdef DWC_LINUX ++/** Type for a DMA address */ ++typedef dma_addr_t dwc_dma_t; ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++typedef bus_addr_t dwc_dma_t; ++#endif ++ ++#ifdef DWC_FREEBSD ++typedef struct dwc_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} dwc_dmactx_t; ++#endif ++ ++#ifdef DWC_NETBSD ++typedef struct dwc_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_dma_segment_t segs[1]; ++ int nsegs; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} dwc_dmactx_t; ++#endif ++ ++/* @todo these functions will be added in the future */ ++#if 0 ++/** ++ * Creates a DMA pool from which you can allocate DMA buffers. Buffers ++ * allocated from this pool will be guaranteed to meet the size, alignment, and ++ * boundary requirements specified. ++ * ++ * @param[in] size Specifies the size of the buffers that will be allocated from ++ * this pool. ++ * @param[in] align Specifies the byte alignment requirements of the buffers ++ * allocated from this pool. Must be a power of 2. ++ * @param[in] boundary Specifies the N-byte boundary that buffers allocated from ++ * this pool must not cross. ++ * ++ * @returns A pointer to an internal opaque structure which is not to be ++ * accessed outside of these library functions. Use this handle to specify ++ * which pools to allocate/free DMA buffers from and also to destroy the pool, ++ * when you are done with it. ++ */ ++extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary); ++ ++/** ++ * Destroy a DMA pool. All buffers allocated from that pool must be freed first. ++ */ ++extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool); ++ ++/** ++ * Allocate a buffer from the specified DMA pool and zeros its contents. ++ */ ++extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr); ++ ++/** ++ * Free a previously allocated buffer from the DMA pool. ++ */ ++extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr); ++#endif ++ ++/** Allocates a DMA capable buffer and zeroes its contents. */ ++extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); ++ ++/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */ ++extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); ++ ++/** Frees a previously allocated buffer. */ ++extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr); ++ ++/** Allocates a block of memory and zeroes its contents. */ ++extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size); ++ ++/** Allocates a block of memory and zeroes its contents, in an atomic manner ++ * which can be used inside interrupt context. The size should be sufficiently ++ * small, a few KB at most, such that failures are not likely to occur. Can just call ++ * __DWC_ALLOC if it is atomic. */ ++extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size); ++ ++/** Frees a previously allocated buffer. */ ++extern void __DWC_FREE(void *mem_ctx, void *addr); ++ ++#ifndef DWC_DEBUG_MEMORY ++ ++#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_) ++#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_) ++#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) ++ ++# ifdef DWC_LINUX ++#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) ++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) ++#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) ++# endif ++ ++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++#define DWC_DMA_ALLOC __DWC_DMA_ALLOC ++#define DWC_DMA_FREE __DWC_DMA_FREE ++# endif ++extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line); ++ ++#else /* DWC_DEBUG_MEMORY */ ++ ++extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line); ++extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line); ++extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line); ++extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ dwc_dma_t dma_addr, char const *func, int line); ++ ++extern int dwc_memory_debug_start(void *mem_ctx); ++extern void dwc_memory_debug_stop(void); ++extern void dwc_memory_debug_report(void); ++ ++#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__) ++#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \ ++ __func__, __LINE__) ++#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) ++ ++# ifdef DWC_LINUX ++#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++#endif /* DWC_DEBUG_MEMORY */ ++ ++#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_) ++#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_) ++#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_) ++ ++#ifdef DWC_LINUX ++/* Linux doesn't need any extra parameters for DMA buffer allocation, so we ++ * just throw away the DMA context parameter. ++ */ ++#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_) ++#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_) ++#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_) ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++/** BSD needs several extra parameters for DMA buffer allocation, so we pass ++ * them in using the DMA context parameter. ++ */ ++#define dwc_dma_alloc DWC_DMA_ALLOC ++#define dwc_dma_free DWC_DMA_FREE ++#endif ++ ++ ++/** @name Memory and String Processing */ ++ ++/** memset() clone */ ++extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size); ++#define dwc_memset DWC_MEMSET ++ ++/** memcpy() clone */ ++extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size); ++#define dwc_memcpy DWC_MEMCPY ++ ++/** memmove() clone */ ++extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size); ++#define dwc_memmove DWC_MEMMOVE ++ ++/** memcmp() clone */ ++extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size); ++#define dwc_memcmp DWC_MEMCMP ++ ++/** strcmp() clone */ ++extern int DWC_STRCMP(void *s1, void *s2); ++#define dwc_strcmp DWC_STRCMP ++ ++/** strncmp() clone */ ++extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size); ++#define dwc_strncmp DWC_STRNCMP ++ ++/** strlen() clone, for NULL terminated ASCII strings */ ++extern int DWC_STRLEN(char const *str); ++#define dwc_strlen DWC_STRLEN ++ ++/** strcpy() clone, for NULL terminated ASCII strings */ ++extern char *DWC_STRCPY(char *to, const char *from); ++#define dwc_strcpy DWC_STRCPY ++ ++/** strdup() clone. If you wish to use memory allocation debugging, this ++ * implementation of strdup should use the DWC_* memory routines instead of ++ * calling a predefined strdup. Otherwise the memory allocated by this routine ++ * will not be seen by the debugging routines. */ ++extern char *DWC_STRDUP(char const *str); ++#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_) ++ ++/** NOT an atoi() clone. Read the description carefully. Returns an integer ++ * converted from the string str in base 10 unless the string begins with a "0x" ++ * in which case it is base 16. String must be a NULL terminated sequence of ++ * ASCII characters and may optionally begin with whitespace, a + or -, and a ++ * "0x" prefix if base 16. The remaining characters must be valid digits for ++ * the number and end with a NULL character. If any invalid characters are ++ * encountered or it returns with a negative error code and the results of the ++ * conversion are undefined. On sucess it returns 0. Overflow conditions are ++ * undefined. An example implementation using atoi() can be referenced from the ++ * Linux implementation. */ ++extern int DWC_ATOI(const char *str, int32_t *value); ++#define dwc_atoi DWC_ATOI ++ ++/** Same as above but for unsigned. */ ++extern int DWC_ATOUI(const char *str, uint32_t *value); ++#define dwc_atoui DWC_ATOUI ++ ++#ifdef DWC_UTFLIB ++/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */ ++extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len); ++#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE ++#endif ++ ++ ++/** @name Wait queues ++ * ++ * Wait queues provide a means of synchronizing between threads or processes. A ++ * process can block on a waitq if some condition is not true, waiting for it to ++ * become true. When the waitq is triggered all waiting process will get ++ * unblocked and the condition will be check again. Waitqs should be triggered ++ * every time a condition can potentially change.*/ ++struct dwc_waitq; ++ ++/** Type for a waitq */ ++typedef struct dwc_waitq dwc_waitq_t; ++ ++/** The type of waitq condition callback function. This is called every time ++ * condition is evaluated. */ ++typedef int (*dwc_waitq_condition_t)(void *data); ++ ++/** Allocate a waitq */ ++extern dwc_waitq_t *DWC_WAITQ_ALLOC(void); ++#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC() ++ ++/** Free a waitq */ ++extern void DWC_WAITQ_FREE(dwc_waitq_t *wq); ++#define dwc_waitq_free DWC_WAITQ_FREE ++ ++/** Check the condition and if it is false, block on the waitq. When unblocked, check the ++ * condition again. The function returns when the condition becomes true. The return value ++ * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */ ++extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data); ++#define dwc_waitq_wait DWC_WAITQ_WAIT ++ ++/** Check the condition and if it is false, block on the waitq. When unblocked, ++ * check the condition again. The function returns when the condition become ++ * true or the timeout has passed. The return value is 0 on condition true or ++ * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on ++ * error. */ ++extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs); ++#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT ++ ++/** Trigger a waitq, unblocking all processes. This should be called whenever a condition ++ * has potentially changed. */ ++extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq); ++#define dwc_waitq_trigger DWC_WAITQ_TRIGGER ++ ++/** Unblock all processes waiting on the waitq with an ABORTED result. */ ++extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq); ++#define dwc_waitq_abort DWC_WAITQ_ABORT ++ ++ ++/** @name Threads ++ * ++ * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP ++ * whenever it is woken up, and then return. The DWC_THREAD_STOP function ++ * returns the value from the thread. ++ */ ++ ++struct dwc_thread; ++ ++/** Type for a thread */ ++typedef struct dwc_thread dwc_thread_t; ++ ++/** The thread function */ ++typedef int (*dwc_thread_function_t)(void *data); ++ ++/** Create a thread and start it running the thread_function. Returns a handle ++ * to the thread */ ++extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data); ++#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_) ++ ++/** Stops a thread. Return the value returned by the thread. Or will return ++ * DWC_ABORT if the thread never started. */ ++extern int DWC_THREAD_STOP(dwc_thread_t *thread); ++#define dwc_thread_stop DWC_THREAD_STOP ++ ++/** Signifies to the thread that it must stop. */ ++#ifdef DWC_LINUX ++/* Linux doesn't need any parameters for kthread_should_stop() */ ++extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void); ++#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP() ++ ++/* No thread_exit function in Linux */ ++#define dwc_thread_exit(_thrd_) ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++/** BSD needs the thread pointer for kthread_suspend_check() */ ++extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread); ++#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP ++ ++/** The thread must call this to exit. */ ++extern void DWC_THREAD_EXIT(dwc_thread_t *thread); ++#define dwc_thread_exit DWC_THREAD_EXIT ++#endif ++ ++ ++/** @name Work queues ++ * ++ * Workqs are used to queue a callback function to be called at some later time, ++ * in another thread. */ ++struct dwc_workq; ++ ++/** Type for a workq */ ++typedef struct dwc_workq dwc_workq_t; ++ ++/** The type of the callback function to be called. */ ++typedef void (*dwc_work_callback_t)(void *data); ++ ++/** Allocate a workq */ ++extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name); ++#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_) ++ ++/** Free a workq. All work must be completed before being freed. */ ++extern void DWC_WORKQ_FREE(dwc_workq_t *workq); ++#define dwc_workq_free DWC_WORKQ_FREE ++ ++/** Schedule a callback on the workq, passing in data. The function will be ++ * scheduled at some later time. */ ++extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb, ++ void *data, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 4, 5))); ++#else ++ ; ++#endif ++#define dwc_workq_schedule DWC_WORKQ_SCHEDULE ++ ++/** Schedule a callback on the workq, that will be called until at least ++ * given number miliseconds have passed. */ ++extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++#ifdef __GNUC__ ++ __attribute__ ((format(printf, 5, 6))); ++#else ++ ; ++#endif ++#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED ++ ++/** The number of processes in the workq */ ++extern int DWC_WORKQ_PENDING(dwc_workq_t *workq); ++#define dwc_workq_pending DWC_WORKQ_PENDING ++ ++/** Blocks until all the work in the workq is complete or timed out. Returns < ++ * 0 on timeout. */ ++extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout); ++#define dwc_workq_wait_work_done DWC_WORKQ_WAIT_WORK_DONE ++ ++ ++/** @name Tasklets ++ * ++ */ ++struct dwc_tasklet; ++ ++/** Type for a tasklet */ ++typedef struct dwc_tasklet dwc_tasklet_t; ++ ++/** The type of the callback function to be called */ ++typedef void (*dwc_tasklet_callback_t)(void *data); ++ ++/** Allocates a tasklet */ ++extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data); ++#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_) ++ ++/** Frees a tasklet */ ++extern void DWC_TASK_FREE(dwc_tasklet_t *task); ++#define dwc_task_free DWC_TASK_FREE ++ ++/** Schedules a tasklet to run */ ++extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task); ++#define dwc_task_schedule DWC_TASK_SCHEDULE ++ ++ ++/** @name Timer ++ * ++ * Callbacks must be small and atomic. ++ */ ++struct dwc_timer; ++ ++/** Type for a timer */ ++typedef struct dwc_timer dwc_timer_t; ++ ++/** The type of the callback function to be called */ ++typedef void (*dwc_timer_callback_t)(void *data); ++ ++/** Allocates a timer */ ++extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data); ++#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_) ++ ++/** Frees a timer */ ++extern void DWC_TIMER_FREE(dwc_timer_t *timer); ++#define dwc_timer_free DWC_TIMER_FREE ++ ++/** Schedules the timer to run at time ms from now. And will repeat at every ++ * repeat_interval msec therafter ++ * ++ * Modifies a timer that is still awaiting execution to a new expiration time. ++ * The mod_time is added to the old time. */ ++extern void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time); ++#define dwc_timer_schedule DWC_TIMER_SCHEDULE ++ ++/** Disables the timer from execution. */ ++extern void DWC_TIMER_CANCEL(dwc_timer_t *timer); ++#define dwc_timer_cancel DWC_TIMER_CANCEL ++ ++ ++/** @name Spinlocks ++ * ++ * These locks are used when the work between the lock/unlock is atomic and ++ * short. Interrupts are also disabled during the lock/unlock and thus they are ++ * suitable to lock between interrupt/non-interrupt context. They also lock ++ * between processes if you have multiple CPUs or Preemption. If you don't have ++ * multiple CPUS or Preemption, then the you can simply implement the ++ * DWC_SPINLOCK and DWC_SPINUNLOCK to disable and enable interrupts. Because ++ * the work between the lock/unlock is atomic, the process context will never ++ * change, and so you never have to lock between processes. */ ++ ++struct dwc_spinlock; ++ ++/** Type for a spinlock */ ++typedef struct dwc_spinlock dwc_spinlock_t; ++ ++/** Type for the 'flags' argument to spinlock funtions */ ++typedef unsigned long dwc_irqflags_t; ++ ++/** Returns an initialized lock variable. This function should allocate and ++ * initialize the OS-specific data structure used for locking. This data ++ * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should ++ * be freed by the DWC_FREE_LOCK when it is no longer used. */ ++extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void); ++#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC() ++ ++/** Frees an initialized lock variable. */ ++extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock); ++#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_) ++ ++/** Disables interrupts and blocks until it acquires the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ * @param flags Unsigned long for irq flags storage. ++ */ ++extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags); ++#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE ++ ++/** Re-enables the interrupt and releases the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ * @param flags Unsigned long for irq flags storage. Must be the same as was ++ * passed into DWC_LOCK. ++ */ ++extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags); ++#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE ++ ++/** Blocks until it acquires the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ */ ++extern void DWC_SPINLOCK(dwc_spinlock_t *lock); ++#define dwc_spinlock DWC_SPINLOCK ++ ++/** Releases the lock. ++ * ++ * @param lock Pointer to the spinlock. ++ */ ++extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock); ++#define dwc_spinunlock DWC_SPINUNLOCK ++ ++ ++/** @name Mutexes ++ * ++ * Unlike spinlocks Mutexes lock only between processes and the work between the ++ * lock/unlock CAN block, therefore it CANNOT be called from interrupt context. ++ */ ++ ++struct dwc_mutex; ++ ++/** Type for a mutex */ ++typedef struct dwc_mutex dwc_mutex_t; ++ ++/* For Linux Mutex Debugging make it inline because the debugging routines use ++ * the symbol to determine recursive locking. This makes it falsely think ++ * recursive locking occurs. */ ++#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) ++#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \ ++ __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \ ++ mutex_init((struct mutex *)__mutexp); \ ++}) ++#endif ++ ++/** Allocate a mutex */ ++extern dwc_mutex_t *DWC_MUTEX_ALLOC(void); ++#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC() ++ ++/* For memory leak debugging when using Linux Mutex Debugging */ ++#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) ++#define DWC_MUTEX_FREE(__mutexp) do { \ ++ mutex_destroy((struct mutex *)__mutexp); \ ++ DWC_FREE(__mutexp); \ ++} while(0) ++#else ++/** Free a mutex */ ++extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex); ++#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_) ++#endif ++ ++/** Lock a mutex */ ++extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_lock DWC_MUTEX_LOCK ++ ++/** Non-blocking lock returns 1 on successful lock. */ ++extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK ++ ++/** Unlock a mutex */ ++extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex); ++#define dwc_mutex_unlock DWC_MUTEX_UNLOCK ++ ++ ++/** @name Time */ ++ ++/** Microsecond delay. ++ * ++ * @param usecs Microseconds to delay. ++ */ ++extern void DWC_UDELAY(uint32_t usecs); ++#define dwc_udelay DWC_UDELAY ++ ++/** Millisecond delay. ++ * ++ * @param msecs Milliseconds to delay. ++ */ ++extern void DWC_MDELAY(uint32_t msecs); ++#define dwc_mdelay DWC_MDELAY ++ ++/** Non-busy waiting. ++ * Sleeps for specified number of milliseconds. ++ * ++ * @param msecs Milliseconds to sleep. ++ */ ++extern void DWC_MSLEEP(uint32_t msecs); ++#define dwc_msleep DWC_MSLEEP ++ ++/** ++ * Returns number of milliseconds since boot. ++ */ ++extern uint32_t DWC_TIME(void); ++#define dwc_time DWC_TIME ++ ++ ++ ++ ++/* @mainpage DWC Portability and Common Library ++ * ++ * This is the documentation for the DWC Portability and Common Library. ++ * ++ * @section intro Introduction ++ * ++ * The DWC Portability library consists of wrapper calls and data structures to ++ * all low-level functions which are typically provided by the OS. The WUDEV ++ * driver uses only these functions. In order to port the WUDEV driver, only ++ * the functions in this library need to be re-implemented, with the same ++ * behavior as documented here. ++ * ++ * The Common library consists of higher level functions, which rely only on ++ * calling the functions from the DWC Portability library. These common ++ * routines are shared across modules. Some of the common libraries need to be ++ * used directly by the driver programmer when porting WUDEV. Such as the ++ * parameter and notification libraries. ++ * ++ * @section low Portability Library OS Wrapper Functions ++ * ++ * Any function starting with DWC and in all CAPS is a low-level OS-wrapper that ++ * needs to be implemented when porting, for example DWC_MUTEX_ALLOC(). All of ++ * these functions are included in the dwc_os.h file. ++ * ++ * There are many functions here covering a wide array of OS services. Please ++ * see dwc_os.h for details, and implementation notes for each function. ++ * ++ * @section common Common Library Functions ++ * ++ * Any function starting with dwc and in all lowercase is a common library ++ * routine. These functions have a portable implementation and do not need to ++ * be reimplemented when porting. The common routines can be used by any ++ * driver, and some must be used by the end user to control the drivers. For ++ * example, you must use the Parameter common library in order to set the ++ * parameters in the WUDEV module. ++ * ++ * The common libraries consist of the following: ++ * ++ * - Connection Contexts - Used internally and can be used by end-user. See dwc_cc.h ++ * - Parameters - Used internally and can be used by end-user. See dwc_params.h ++ * - Notifications - Used internally and can be used by end-user. See dwc_notifier.h ++ * - Lists - Used internally and can be used by end-user. See dwc_list.h ++ * - Memory Debugging - Used internally and can be used by end-user. See dwc_os.h ++ * - Modpow - Used internally only. See dwc_modpow.h ++ * - DH - Used internally only. See dwc_dh.h ++ * - Crypto - Used internally only. See dwc_crypto.h ++ * ++ * ++ * @section prereq Prerequistes For dwc_os.h ++ * @subsection types Data Types ++ * ++ * The dwc_os.h file assumes that several low-level data types are pre defined for the ++ * compilation environment. These data types are: ++ * ++ * - uint8_t - unsigned 8-bit data type ++ * - int8_t - signed 8-bit data type ++ * - uint16_t - unsigned 16-bit data type ++ * - int16_t - signed 16-bit data type ++ * - uint32_t - unsigned 32-bit data type ++ * - int32_t - signed 32-bit data type ++ * - uint64_t - unsigned 64-bit data type ++ * - int64_t - signed 64-bit data type ++ * ++ * Ensure that these are defined before using dwc_os.h. The easiest way to do ++ * that is to modify the top of the file to include the appropriate header. ++ * This is already done for the Linux environment. If the DWC_LINUX macro is ++ * defined, the correct header will be added. A standard header is ++ * also used for environments where standard C headers are available. ++ * ++ * @subsection stdarg Variable Arguments ++ * ++ * Variable arguments are provided by a standard C header . it is ++ * available in Both the Linux and ANSI C enviornment. An equivalent must be ++ * provided in your enviornment in order to use dwc_os.h with the debug and ++ * tracing message functionality. ++ * ++ * @subsection thread Threading ++ * ++ * WUDEV Core must be run on an operating system that provides for multiple ++ * threads/processes. Threading can be implemented in many ways, even in ++ * embedded systems without an operating system. At the bare minimum, the ++ * system should be able to start any number of processes at any time to handle ++ * special work. It need not be a pre-emptive system. Process context can ++ * change upon a call to a blocking function. The hardware interrupt context ++ * that calls the module's ISR() function must be differentiable from process ++ * context, even if your processes are impemented via a hardware interrupt. ++ * Further locking mechanism between process must exist (or be implemented), and ++ * process context must have a way to disable interrupts for a period of time to ++ * lock them out. If all of this exists, the functions in dwc_os.h related to ++ * threading should be able to be implemented with the defined behavior. ++ * ++ */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_OS_H_ */ +diff --git a/drivers/usb/host/dwc_common_port/usb.h b/drivers/usb/host/dwc_common_port/usb.h +new file mode 100644 +index 0000000..27bda82 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/usb.h +@@ -0,0 +1,946 @@ ++/* ++ * Copyright (c) 1998 The NetBSD Foundation, Inc. ++ * All rights reserved. ++ * ++ * This code is derived from software contributed to The NetBSD Foundation ++ * by Lennart Augustsson (lennart@augustsson.net) at ++ * Carlstedt Research & Technology. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. All advertising materials mentioning features or use of this software ++ * must display the following acknowledgement: ++ * This product includes software developed by the NetBSD ++ * Foundation, Inc. and its contributors. ++ * 4. Neither the name of The NetBSD Foundation nor the names of its ++ * contributors may be used to endorse or promote products derived ++ * from this software without specific prior written permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS ++ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ++ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS ++ * 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. ++ */ ++ ++/* Modified by Synopsys, Inc, 12/12/2007 */ ++ ++ ++#ifndef _USB_H_ ++#define _USB_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* ++ * The USB records contain some unaligned little-endian word ++ * components. The U[SG]ETW macros take care of both the alignment ++ * and endian problem and should always be used to access non-byte ++ * values. ++ */ ++typedef u_int8_t uByte; ++typedef u_int8_t uWord[2]; ++typedef u_int8_t uDWord[4]; ++ ++#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) ++#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff } ++#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \ ++ ((x) >> 16) & 0xff, ((x) >> 24) & 0xff } ++ ++#if 1 ++#define UGETW(w) ((w)[0] | ((w)[1] << 8)) ++#define USETW(w,v) ((w)[0] = (u_int8_t)(v), (w)[1] = (u_int8_t)((v) >> 8)) ++#define UGETDW(w) ((w)[0] | ((w)[1] << 8) | ((w)[2] << 16) | ((w)[3] << 24)) ++#define USETDW(w,v) ((w)[0] = (u_int8_t)(v), \ ++ (w)[1] = (u_int8_t)((v) >> 8), \ ++ (w)[2] = (u_int8_t)((v) >> 16), \ ++ (w)[3] = (u_int8_t)((v) >> 24)) ++#else ++/* ++ * On little-endian machines that can handle unanliged accesses ++ * (e.g. i386) these macros can be replaced by the following. ++ */ ++#define UGETW(w) (*(u_int16_t *)(w)) ++#define USETW(w,v) (*(u_int16_t *)(w) = (v)) ++#define UGETDW(w) (*(u_int32_t *)(w)) ++#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) ++#endif ++ ++/* ++ * Macros for accessing UAS IU fields, which are big-endian ++ */ ++#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l)) ++#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ ++ ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUGETW(w) (((w)[0] << 8) | (w)[1]) ++#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v)) ++#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) ++#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \ ++ (w)[1] = (u_int8_t)((v) >> 16), \ ++ (w)[2] = (u_int8_t)((v) >> 8), \ ++ (w)[3] = (u_int8_t)(v)) ++ ++#define UPACKED __attribute__((__packed__)) ++ ++typedef struct { ++ uByte bmRequestType; ++ uByte bRequest; ++ uWord wValue; ++ uWord wIndex; ++ uWord wLength; ++} UPACKED usb_device_request_t; ++ ++#define UT_GET_DIR(a) ((a) & 0x80) ++#define UT_WRITE 0x00 ++#define UT_READ 0x80 ++ ++#define UT_GET_TYPE(a) ((a) & 0x60) ++#define UT_STANDARD 0x00 ++#define UT_CLASS 0x20 ++#define UT_VENDOR 0x40 ++ ++#define UT_GET_RECIPIENT(a) ((a) & 0x1f) ++#define UT_DEVICE 0x00 ++#define UT_INTERFACE 0x01 ++#define UT_ENDPOINT 0x02 ++#define UT_OTHER 0x03 ++ ++#define UT_READ_DEVICE (UT_READ | UT_STANDARD | UT_DEVICE) ++#define UT_READ_INTERFACE (UT_READ | UT_STANDARD | UT_INTERFACE) ++#define UT_READ_ENDPOINT (UT_READ | UT_STANDARD | UT_ENDPOINT) ++#define UT_WRITE_DEVICE (UT_WRITE | UT_STANDARD | UT_DEVICE) ++#define UT_WRITE_INTERFACE (UT_WRITE | UT_STANDARD | UT_INTERFACE) ++#define UT_WRITE_ENDPOINT (UT_WRITE | UT_STANDARD | UT_ENDPOINT) ++#define UT_READ_CLASS_DEVICE (UT_READ | UT_CLASS | UT_DEVICE) ++#define UT_READ_CLASS_INTERFACE (UT_READ | UT_CLASS | UT_INTERFACE) ++#define UT_READ_CLASS_OTHER (UT_READ | UT_CLASS | UT_OTHER) ++#define UT_READ_CLASS_ENDPOINT (UT_READ | UT_CLASS | UT_ENDPOINT) ++#define UT_WRITE_CLASS_DEVICE (UT_WRITE | UT_CLASS | UT_DEVICE) ++#define UT_WRITE_CLASS_INTERFACE (UT_WRITE | UT_CLASS | UT_INTERFACE) ++#define UT_WRITE_CLASS_OTHER (UT_WRITE | UT_CLASS | UT_OTHER) ++#define UT_WRITE_CLASS_ENDPOINT (UT_WRITE | UT_CLASS | UT_ENDPOINT) ++#define UT_READ_VENDOR_DEVICE (UT_READ | UT_VENDOR | UT_DEVICE) ++#define UT_READ_VENDOR_INTERFACE (UT_READ | UT_VENDOR | UT_INTERFACE) ++#define UT_READ_VENDOR_OTHER (UT_READ | UT_VENDOR | UT_OTHER) ++#define UT_READ_VENDOR_ENDPOINT (UT_READ | UT_VENDOR | UT_ENDPOINT) ++#define UT_WRITE_VENDOR_DEVICE (UT_WRITE | UT_VENDOR | UT_DEVICE) ++#define UT_WRITE_VENDOR_INTERFACE (UT_WRITE | UT_VENDOR | UT_INTERFACE) ++#define UT_WRITE_VENDOR_OTHER (UT_WRITE | UT_VENDOR | UT_OTHER) ++#define UT_WRITE_VENDOR_ENDPOINT (UT_WRITE | UT_VENDOR | UT_ENDPOINT) ++ ++/* Requests */ ++#define UR_GET_STATUS 0x00 ++#define USTAT_STANDARD_STATUS 0x00 ++#define WUSTAT_WUSB_FEATURE 0x01 ++#define WUSTAT_CHANNEL_INFO 0x02 ++#define WUSTAT_RECEIVED_DATA 0x03 ++#define WUSTAT_MAS_AVAILABILITY 0x04 ++#define WUSTAT_CURRENT_TRANSMIT_POWER 0x05 ++#define UR_CLEAR_FEATURE 0x01 ++#define UR_SET_FEATURE 0x03 ++#define UR_SET_AND_TEST_FEATURE 0x0c ++#define UR_SET_ADDRESS 0x05 ++#define UR_GET_DESCRIPTOR 0x06 ++#define UDESC_DEVICE 0x01 ++#define UDESC_CONFIG 0x02 ++#define UDESC_STRING 0x03 ++#define UDESC_INTERFACE 0x04 ++#define UDESC_ENDPOINT 0x05 ++#define UDESC_SS_USB_COMPANION 0x30 ++#define UDESC_DEVICE_QUALIFIER 0x06 ++#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 ++#define UDESC_INTERFACE_POWER 0x08 ++#define UDESC_OTG 0x09 ++#define WUDESC_SECURITY 0x0c ++#define WUDESC_KEY 0x0d ++#define WUD_GET_KEY_INDEX(_wValue_) ((_wValue_) & 0xf) ++#define WUD_GET_KEY_TYPE(_wValue_) (((_wValue_) & 0x30) >> 4) ++#define WUD_KEY_TYPE_ASSOC 0x01 ++#define WUD_KEY_TYPE_GTK 0x02 ++#define WUD_GET_KEY_ORIGIN(_wValue_) (((_wValue_) & 0x40) >> 6) ++#define WUD_KEY_ORIGIN_HOST 0x00 ++#define WUD_KEY_ORIGIN_DEVICE 0x01 ++#define WUDESC_ENCRYPTION_TYPE 0x0e ++#define WUDESC_BOS 0x0f ++#define WUDESC_DEVICE_CAPABILITY 0x10 ++#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11 ++#define UDESC_BOS 0x0f ++#define UDESC_DEVICE_CAPABILITY 0x10 ++#define UDESC_CS_DEVICE 0x21 /* class specific */ ++#define UDESC_CS_CONFIG 0x22 ++#define UDESC_CS_STRING 0x23 ++#define UDESC_CS_INTERFACE 0x24 ++#define UDESC_CS_ENDPOINT 0x25 ++#define UDESC_HUB 0x29 ++#define UR_SET_DESCRIPTOR 0x07 ++#define UR_GET_CONFIG 0x08 ++#define UR_SET_CONFIG 0x09 ++#define UR_GET_INTERFACE 0x0a ++#define UR_SET_INTERFACE 0x0b ++#define UR_SYNCH_FRAME 0x0c ++#define WUR_SET_ENCRYPTION 0x0d ++#define WUR_GET_ENCRYPTION 0x0e ++#define WUR_SET_HANDSHAKE 0x0f ++#define WUR_GET_HANDSHAKE 0x10 ++#define WUR_SET_CONNECTION 0x11 ++#define WUR_SET_SECURITY_DATA 0x12 ++#define WUR_GET_SECURITY_DATA 0x13 ++#define WUR_SET_WUSB_DATA 0x14 ++#define WUDATA_DRPIE_INFO 0x01 ++#define WUDATA_TRANSMIT_DATA 0x02 ++#define WUDATA_TRANSMIT_PARAMS 0x03 ++#define WUDATA_RECEIVE_PARAMS 0x04 ++#define WUDATA_TRANSMIT_POWER 0x05 ++#define WUR_LOOPBACK_DATA_WRITE 0x15 ++#define WUR_LOOPBACK_DATA_READ 0x16 ++#define WUR_SET_INTERFACE_DS 0x17 ++ ++/* Feature numbers */ ++#define UF_ENDPOINT_HALT 0 ++#define UF_DEVICE_REMOTE_WAKEUP 1 ++#define UF_TEST_MODE 2 ++#define UF_DEVICE_B_HNP_ENABLE 3 ++#define UF_DEVICE_A_HNP_SUPPORT 4 ++#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 ++#define WUF_WUSB 3 ++#define WUF_TX_DRPIE 0x0 ++#define WUF_DEV_XMIT_PACKET 0x1 ++#define WUF_COUNT_PACKETS 0x2 ++#define WUF_CAPTURE_PACKETS 0x3 ++#define UF_FUNCTION_SUSPEND 0 ++#define UF_U1_ENABLE 48 ++#define UF_U2_ENABLE 49 ++#define UF_LTM_ENABLE 50 ++ ++/* Class requests from the USB 2.0 hub spec, table 11-15 */ ++#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE) ++#define UCR_CLEAR_PORT_FEATURE (0x2300 | UR_CLEAR_FEATURE) ++#define UCR_GET_HUB_DESCRIPTOR (0xa000 | UR_GET_DESCRIPTOR) ++#define UCR_GET_HUB_STATUS (0xa000 | UR_GET_STATUS) ++#define UCR_GET_PORT_STATUS (0xa300 | UR_GET_STATUS) ++#define UCR_SET_HUB_FEATURE (0x2000 | UR_SET_FEATURE) ++#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE) ++#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE) ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDescriptorSubtype; ++} UPACKED usb_descriptor_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++} UPACKED usb_descriptor_header_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++#define UD_USB_2_0 0x0200 ++#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize; ++ /* The fields below are not part of the initial descriptor. */ ++ uWord idVendor; ++ uWord idProduct; ++ uWord bcdDevice; ++ uByte iManufacturer; ++ uByte iProduct; ++ uByte iSerialNumber; ++ uByte bNumConfigurations; ++} UPACKED usb_device_descriptor_t; ++#define USB_DEVICE_DESCRIPTOR_SIZE 18 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumInterface; ++ uByte bConfigurationValue; ++ uByte iConfiguration; ++#define UC_ATT_ONE (1 << 7) /* must be set */ ++#define UC_ATT_SELFPOWER (1 << 6) /* self powered */ ++#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */ ++#define UC_ATT_BATTERY (1 << 4) /* battery powered */ ++ uByte bmAttributes; ++#define UC_BUS_POWERED 0x80 ++#define UC_SELF_POWERED 0x40 ++#define UC_REMOTE_WAKEUP 0x20 ++ uByte bMaxPower; /* max current in 2 mA units */ ++#define UC_POWER_FACTOR 2 ++} UPACKED usb_config_descriptor_t; ++#define USB_CONFIG_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bInterfaceNumber; ++ uByte bAlternateSetting; ++ uByte bNumEndpoints; ++ uByte bInterfaceClass; ++ uByte bInterfaceSubClass; ++ uByte bInterfaceProtocol; ++ uByte iInterface; ++} UPACKED usb_interface_descriptor_t; ++#define USB_INTERFACE_DESCRIPTOR_SIZE 9 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bEndpointAddress; ++#define UE_GET_DIR(a) ((a) & 0x80) ++#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7)) ++#define UE_DIR_IN 0x80 ++#define UE_DIR_OUT 0x00 ++#define UE_ADDR 0x0f ++#define UE_GET_ADDR(a) ((a) & UE_ADDR) ++ uByte bmAttributes; ++#define UE_XFERTYPE 0x03 ++#define UE_CONTROL 0x00 ++#define UE_ISOCHRONOUS 0x01 ++#define UE_BULK 0x02 ++#define UE_INTERRUPT 0x03 ++#define UE_GET_XFERTYPE(a) ((a) & UE_XFERTYPE) ++#define UE_ISO_TYPE 0x0c ++#define UE_ISO_ASYNC 0x04 ++#define UE_ISO_ADAPT 0x08 ++#define UE_ISO_SYNC 0x0c ++#define UE_GET_ISO_TYPE(a) ((a) & UE_ISO_TYPE) ++ uWord wMaxPacketSize; ++ uByte bInterval; ++} UPACKED usb_endpoint_descriptor_t; ++#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 ++ ++typedef struct ss_endpoint_companion_descriptor { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f) ++#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f)) ++#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03) ++#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03)) ++ uByte bmAttributes; ++ uWord wBytesPerInterval; ++} UPACKED ss_endpoint_companion_descriptor_t; ++#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bString[127]; ++} UPACKED usb_string_descriptor_t; ++#define USB_MAX_STRING_LEN 128 ++#define USB_LANGUAGE_TABLE 0 /* # of the string language id table */ ++ ++/* Hub specific request */ ++#define UR_GET_BUS_STATE 0x02 ++#define UR_CLEAR_TT_BUFFER 0x08 ++#define UR_RESET_TT 0x09 ++#define UR_GET_TT_STATE 0x0a ++#define UR_STOP_TT 0x0b ++ ++/* Hub features */ ++#define UHF_C_HUB_LOCAL_POWER 0 ++#define UHF_C_HUB_OVER_CURRENT 1 ++#define UHF_PORT_CONNECTION 0 ++#define UHF_PORT_ENABLE 1 ++#define UHF_PORT_SUSPEND 2 ++#define UHF_PORT_OVER_CURRENT 3 ++#define UHF_PORT_RESET 4 ++#define UHF_PORT_L1 5 ++#define UHF_PORT_POWER 8 ++#define UHF_PORT_LOW_SPEED 9 ++#define UHF_PORT_HIGH_SPEED 10 ++#define UHF_C_PORT_CONNECTION 16 ++#define UHF_C_PORT_ENABLE 17 ++#define UHF_C_PORT_SUSPEND 18 ++#define UHF_C_PORT_OVER_CURRENT 19 ++#define UHF_C_PORT_RESET 20 ++#define UHF_C_PORT_L1 23 ++#define UHF_PORT_TEST 21 ++#define UHF_PORT_INDICATOR 22 ++ ++typedef struct { ++ uByte bDescLength; ++ uByte bDescriptorType; ++ uByte bNbrPorts; ++ uWord wHubCharacteristics; ++#define UHD_PWR 0x0003 ++#define UHD_PWR_GANGED 0x0000 ++#define UHD_PWR_INDIVIDUAL 0x0001 ++#define UHD_PWR_NO_SWITCH 0x0002 ++#define UHD_COMPOUND 0x0004 ++#define UHD_OC 0x0018 ++#define UHD_OC_GLOBAL 0x0000 ++#define UHD_OC_INDIVIDUAL 0x0008 ++#define UHD_OC_NONE 0x0010 ++#define UHD_TT_THINK 0x0060 ++#define UHD_TT_THINK_8 0x0000 ++#define UHD_TT_THINK_16 0x0020 ++#define UHD_TT_THINK_24 0x0040 ++#define UHD_TT_THINK_32 0x0060 ++#define UHD_PORT_IND 0x0080 ++ uByte bPwrOn2PwrGood; /* delay in 2 ms units */ ++#define UHD_PWRON_FACTOR 2 ++ uByte bHubContrCurrent; ++ uByte DeviceRemovable[32]; /* max 255 ports */ ++#define UHD_NOT_REMOV(desc, i) \ ++ (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1) ++ /* deprecated */ uByte PortPowerCtrlMask[1]; ++} UPACKED usb_hub_descriptor_t; ++#define USB_HUB_DESCRIPTOR_SIZE 9 /* includes deprecated PortPowerCtrlMask */ ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord bcdUSB; ++ uByte bDeviceClass; ++ uByte bDeviceSubClass; ++ uByte bDeviceProtocol; ++ uByte bMaxPacketSize0; ++ uByte bNumConfigurations; ++ uByte bReserved; ++} UPACKED usb_device_qualifier_t; ++#define USB_DEVICE_QUALIFIER_SIZE 10 ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bmAttributes; ++#define UOTG_SRP 0x01 ++#define UOTG_HNP 0x02 ++} UPACKED usb_otg_descriptor_t; ++ ++/* OTG feature selectors */ ++#define UOTG_B_HNP_ENABLE 3 ++#define UOTG_A_HNP_SUPPORT 4 ++#define UOTG_A_ALT_HNP_SUPPORT 5 ++ ++typedef struct { ++ uWord wStatus; ++/* Device status flags */ ++#define UDS_SELF_POWERED 0x0001 ++#define UDS_REMOTE_WAKEUP 0x0002 ++/* Endpoint status flags */ ++#define UES_HALT 0x0001 ++} UPACKED usb_status_t; ++ ++typedef struct { ++ uWord wHubStatus; ++#define UHS_LOCAL_POWER 0x0001 ++#define UHS_OVER_CURRENT 0x0002 ++ uWord wHubChange; ++} UPACKED usb_hub_status_t; ++ ++typedef struct { ++ uWord wPortStatus; ++#define UPS_CURRENT_CONNECT_STATUS 0x0001 ++#define UPS_PORT_ENABLED 0x0002 ++#define UPS_SUSPEND 0x0004 ++#define UPS_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_RESET 0x0010 ++#define UPS_PORT_POWER 0x0100 ++#define UPS_LOW_SPEED 0x0200 ++#define UPS_HIGH_SPEED 0x0400 ++#define UPS_PORT_TEST 0x0800 ++#define UPS_PORT_INDICATOR 0x1000 ++ uWord wPortChange; ++#define UPS_C_CONNECT_STATUS 0x0001 ++#define UPS_C_PORT_ENABLED 0x0002 ++#define UPS_C_SUSPEND 0x0004 ++#define UPS_C_OVERCURRENT_INDICATOR 0x0008 ++#define UPS_C_PORT_RESET 0x0010 ++} UPACKED usb_port_status_t; ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* Device class codes */ ++#define UDCLASS_IN_INTERFACE 0x00 ++#define UDCLASS_COMM 0x02 ++#define UDCLASS_HUB 0x09 ++#define UDSUBCLASS_HUB 0x00 ++#define UDPROTO_FSHUB 0x00 ++#define UDPROTO_HSHUBSTT 0x01 ++#define UDPROTO_HSHUBMTT 0x02 ++#define UDCLASS_DIAGNOSTIC 0xdc ++#define UDCLASS_WIRELESS 0xe0 ++#define UDSUBCLASS_RF 0x01 ++#define UDPROTO_BLUETOOTH 0x01 ++#define UDCLASS_VENDOR 0xff ++ ++/* Interface class codes */ ++#define UICLASS_UNSPEC 0x00 ++ ++#define UICLASS_AUDIO 0x01 ++#define UISUBCLASS_AUDIOCONTROL 1 ++#define UISUBCLASS_AUDIOSTREAM 2 ++#define UISUBCLASS_MIDISTREAM 3 ++ ++#define UICLASS_CDC 0x02 /* communication */ ++#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 ++#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 ++#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 ++#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 ++#define UISUBCLASS_CAPI_CONTROLMODEL 5 ++#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 ++#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 ++#define UIPROTO_CDC_AT 1 ++ ++#define UICLASS_HID 0x03 ++#define UISUBCLASS_BOOT 1 ++#define UIPROTO_BOOT_KEYBOARD 1 ++ ++#define UICLASS_PHYSICAL 0x05 ++ ++#define UICLASS_IMAGE 0x06 ++ ++#define UICLASS_PRINTER 0x07 ++#define UISUBCLASS_PRINTER 1 ++#define UIPROTO_PRINTER_UNI 1 ++#define UIPROTO_PRINTER_BI 2 ++#define UIPROTO_PRINTER_1284 3 ++ ++#define UICLASS_MASS 0x08 ++#define UISUBCLASS_RBC 1 ++#define UISUBCLASS_SFF8020I 2 ++#define UISUBCLASS_QIC157 3 ++#define UISUBCLASS_UFI 4 ++#define UISUBCLASS_SFF8070I 5 ++#define UISUBCLASS_SCSI 6 ++#define UIPROTO_MASS_CBI_I 0 ++#define UIPROTO_MASS_CBI 1 ++#define UIPROTO_MASS_BBB_OLD 2 /* Not in the spec anymore */ ++#define UIPROTO_MASS_BBB 80 /* 'P' for the Iomega Zip drive */ ++ ++#define UICLASS_HUB 0x09 ++#define UISUBCLASS_HUB 0 ++#define UIPROTO_FSHUB 0 ++#define UIPROTO_HSHUBSTT 0 /* Yes, same as previous */ ++#define UIPROTO_HSHUBMTT 1 ++ ++#define UICLASS_CDC_DATA 0x0a ++#define UISUBCLASS_DATA 0 ++#define UIPROTO_DATA_ISDNBRI 0x30 /* Physical iface */ ++#define UIPROTO_DATA_HDLC 0x31 /* HDLC */ ++#define UIPROTO_DATA_TRANSPARENT 0x32 /* Transparent */ ++#define UIPROTO_DATA_Q921M 0x50 /* Management for Q921 */ ++#define UIPROTO_DATA_Q921 0x51 /* Data for Q921 */ ++#define UIPROTO_DATA_Q921TM 0x52 /* TEI multiplexer for Q921 */ ++#define UIPROTO_DATA_V42BIS 0x90 /* Data compression */ ++#define UIPROTO_DATA_Q931 0x91 /* Euro-ISDN */ ++#define UIPROTO_DATA_V120 0x92 /* V.24 rate adaption */ ++#define UIPROTO_DATA_CAPI 0x93 /* CAPI 2.0 commands */ ++#define UIPROTO_DATA_HOST_BASED 0xfd /* Host based driver */ ++#define UIPROTO_DATA_PUF 0xfe /* see Prot. Unit Func. Desc.*/ ++#define UIPROTO_DATA_VENDOR 0xff /* Vendor specific */ ++ ++#define UICLASS_SMARTCARD 0x0b ++ ++/*#define UICLASS_FIRM_UPD 0x0c*/ ++ ++#define UICLASS_SECURITY 0x0d ++ ++#define UICLASS_DIAGNOSTIC 0xdc ++ ++#define UICLASS_WIRELESS 0xe0 ++#define UISUBCLASS_RF 0x01 ++#define UIPROTO_BLUETOOTH 0x01 ++ ++#define UICLASS_APPL_SPEC 0xfe ++#define UISUBCLASS_FIRMWARE_DOWNLOAD 1 ++#define UISUBCLASS_IRDA 2 ++#define UIPROTO_IRDA 0 ++ ++#define UICLASS_VENDOR 0xff ++ ++#define USB_HUB_MAX_DEPTH 5 ++ ++/* ++ * Minimum time a device needs to be powered down to go through ++ * a power cycle. XXX Are these time in the spec? ++ */ ++#define USB_POWER_DOWN_TIME 200 /* ms */ ++#define USB_PORT_POWER_DOWN_TIME 100 /* ms */ ++ ++#if 0 ++/* These are the values from the spec. */ ++#define USB_PORT_RESET_DELAY 10 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_RESET_RECOVERY 10 /* ms */ ++#define USB_PORT_POWERUP_DELAY 100 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 2 /* ms */ ++#define USB_RESUME_DELAY (20*5) /* ms */ ++#define USB_RESUME_WAIT 10 /* ms */ ++#define USB_RESUME_RECOVERY 10 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 0 /* ms */ ++#else ++/* Allow for marginal (i.e. non-conforming) devices. */ ++#define USB_PORT_RESET_DELAY 50 /* ms */ ++#define USB_PORT_ROOT_RESET_DELAY 250 /* ms */ ++#define USB_PORT_RESET_RECOVERY 250 /* ms */ ++#define USB_PORT_POWERUP_DELAY 300 /* ms */ ++#define USB_SET_ADDRESS_SETTLE 10 /* ms */ ++#define USB_RESUME_DELAY (50*5) /* ms */ ++#define USB_RESUME_WAIT 50 /* ms */ ++#define USB_RESUME_RECOVERY 50 /* ms */ ++#define USB_EXTRA_POWER_UP_TIME 20 /* ms */ ++#endif ++ ++#define USB_MIN_POWER 100 /* mA */ ++#define USB_MAX_POWER 500 /* mA */ ++ ++#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ ++ ++#define USB_UNCONFIG_NO 0 ++#define USB_UNCONFIG_INDEX (-1) ++ ++/*** ioctl() related stuff ***/ ++ ++struct usb_ctl_request { ++ int ucr_addr; ++ usb_device_request_t ucr_request; ++ void *ucr_data; ++ int ucr_flags; ++#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */ ++ int ucr_actlen; /* actual length transferred */ ++}; ++ ++struct usb_alt_interface { ++ int uai_config_index; ++ int uai_interface_index; ++ int uai_alt_no; ++}; ++ ++#define USB_CURRENT_CONFIG_INDEX (-1) ++#define USB_CURRENT_ALT_INDEX (-1) ++ ++struct usb_config_desc { ++ int ucd_config_index; ++ usb_config_descriptor_t ucd_desc; ++}; ++ ++struct usb_interface_desc { ++ int uid_config_index; ++ int uid_interface_index; ++ int uid_alt_index; ++ usb_interface_descriptor_t uid_desc; ++}; ++ ++struct usb_endpoint_desc { ++ int ued_config_index; ++ int ued_interface_index; ++ int ued_alt_index; ++ int ued_endpoint_index; ++ usb_endpoint_descriptor_t ued_desc; ++}; ++ ++struct usb_full_desc { ++ int ufd_config_index; ++ u_int ufd_size; ++ u_char *ufd_data; ++}; ++ ++struct usb_string_desc { ++ int usd_string_index; ++ int usd_language_id; ++ usb_string_descriptor_t usd_desc; ++}; ++ ++struct usb_ctl_report_desc { ++ int ucrd_size; ++ u_char ucrd_data[1024]; /* filled data size will vary */ ++}; ++ ++typedef struct { u_int32_t cookie; } usb_event_cookie_t; ++ ++#define USB_MAX_DEVNAMES 4 ++#define USB_MAX_DEVNAMELEN 16 ++struct usb_device_info { ++ u_int8_t udi_bus; ++ u_int8_t udi_addr; /* device address */ ++ usb_event_cookie_t udi_cookie; ++ char udi_product[USB_MAX_STRING_LEN]; ++ char udi_vendor[USB_MAX_STRING_LEN]; ++ char udi_release[8]; ++ u_int16_t udi_productNo; ++ u_int16_t udi_vendorNo; ++ u_int16_t udi_releaseNo; ++ u_int8_t udi_class; ++ u_int8_t udi_subclass; ++ u_int8_t udi_protocol; ++ u_int8_t udi_config; ++ u_int8_t udi_speed; ++#define USB_SPEED_UNKNOWN 0 ++#define USB_SPEED_LOW 1 ++#define USB_SPEED_FULL 2 ++#define USB_SPEED_HIGH 3 ++#define USB_SPEED_VARIABLE 4 ++#define USB_SPEED_SUPER 5 ++ int udi_power; /* power consumption in mA, 0 if selfpowered */ ++ int udi_nports; ++ char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; ++ u_int8_t udi_ports[16];/* hub only: addresses of devices on ports */ ++#define USB_PORT_ENABLED 0xff ++#define USB_PORT_SUSPENDED 0xfe ++#define USB_PORT_POWERED 0xfd ++#define USB_PORT_DISABLED 0xfc ++}; ++ ++struct usb_ctl_report { ++ int ucr_report; ++ u_char ucr_data[1024]; /* filled data size will vary */ ++}; ++ ++struct usb_device_stats { ++ u_long uds_requests[4]; /* indexed by transfer type UE_* */ ++}; ++ ++#define WUSB_MIN_IE 0x80 ++#define WUSB_WCTA_IE 0x80 ++#define WUSB_WCONNECTACK_IE 0x81 ++#define WUSB_WHOSTINFO_IE 0x82 ++#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3) ++#define WUHI_CA_RECONN 0x00 ++#define WUHI_CA_LIMITED 0x01 ++#define WUHI_CA_ALL 0x03 ++#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3) ++#define WUSB_WCHCHANGEANNOUNCE_IE 0x83 ++#define WUSB_WDEV_DISCONNECT_IE 0x84 ++#define WUSB_WHOST_DISCONNECT_IE 0x85 ++#define WUSB_WRELEASE_CHANNEL_IE 0x86 ++#define WUSB_WWORK_IE 0x87 ++#define WUSB_WCHANNEL_STOP_IE 0x88 ++#define WUSB_WDEV_KEEPALIVE_IE 0x89 ++#define WUSB_WISOCH_DISCARD_IE 0x8A ++#define WUSB_WRESETDEVICE_IE 0x8B ++#define WUSB_WXMIT_PACKET_ADJUST_IE 0x8C ++#define WUSB_MAX_IE 0x8C ++ ++/* Device Notification Types */ ++ ++#define WUSB_DN_MIN 0x01 ++#define WUSB_DN_CONNECT 0x01 ++# define WUSB_DA_OLDCONN 0x00 ++# define WUSB_DA_NEWCONN 0x01 ++# define WUSB_DA_SELF_BEACON 0x02 ++# define WUSB_DA_DIR_BEACON 0x04 ++# define WUSB_DA_NO_BEACON 0x06 ++#define WUSB_DN_DISCONNECT 0x02 ++#define WUSB_DN_EPRDY 0x03 ++#define WUSB_DN_MASAVAILCHANGED 0x04 ++#define WUSB_DN_REMOTEWAKEUP 0x05 ++#define WUSB_DN_SLEEP 0x06 ++#define WUSB_DN_ALIVE 0x07 ++#define WUSB_DN_MAX 0x07 ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */ ++typedef struct wusb_hndshk_data { ++ uByte bMessageNumber; ++ uByte bStatus; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte CDID[16]; ++ uByte Nonce[16]; ++ uByte MIC[8]; ++} UPACKED wusb_hndshk_data_t; ++#define WUSB_HANDSHAKE_LEN_FOR_MIC 38 ++ ++/* WUSB Connection Context */ ++typedef struct wusb_conn_context { ++ uByte CHID [16]; ++ uByte CDID [16]; ++ uByte CK [16]; ++} UPACKED wusb_conn_context_t; ++ ++/* WUSB Security Descriptor */ ++typedef struct wusb_security_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumEncryptionTypes; ++} UPACKED wusb_security_desc_t; ++ ++/* WUSB Encryption Type Descriptor */ ++typedef struct wusb_encrypt_type_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ ++ uByte bEncryptionType; ++#define WUETD_UNSECURE 0 ++#define WUETD_WIRED 1 ++#define WUETD_CCM_1 2 ++#define WUETD_RSA_1 3 ++ ++ uByte bEncryptionValue; ++ uByte bAuthKeyIndex; ++} UPACKED wusb_encrypt_type_desc_t; ++ ++/* WUSB Key Descriptor */ ++typedef struct wusb_key_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte KeyData[1]; /* variable length */ ++} UPACKED wusb_key_desc_t; ++ ++/* WUSB BOS Descriptor (Binary device Object Store) */ ++typedef struct wusb_bos_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumDeviceCaps; ++} UPACKED wusb_bos_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 ++typedef struct usb_dev_cap_20_ext_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_20_EXT_LPM 0x02 ++ uDWord bmAttributes; ++} UPACKED usb_dev_cap_20_ext_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_SS_USB 0x03 ++typedef struct usb_dev_cap_ss_usb { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_DC_SS_USB_LTM_CAPABLE 0x02 ++ uByte bmAttributes; ++#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 ++#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 ++#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 ++#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 ++ uWord wSpeedsSupported; ++ uByte bFunctionalitySupport; ++ uByte bU1DevExitLat; ++ uWord wU2DevExitLat; ++} UPACKED usb_dev_cap_ss_usb_t; ++ ++#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 ++typedef struct usb_dev_cap_container_id { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bReserved; ++ uByte containerID[16]; ++} UPACKED usb_dev_cap_container_id_t; ++ ++/* Device Capability Type Codes */ ++#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01 ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte caps[1]; /* Variable length */ ++} UPACKED wusb_dev_cap_desc_t; ++ ++/* Device Capability Descriptor */ ++typedef struct wusb_dev_cap_uwb_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bmAttributes; ++ uWord wPHYRates; /* Bitmap */ ++ uByte bmTFITXPowerInfo; ++ uByte bmFFITXPowerInfo; ++ uWord bmBandGroup; ++ uByte bReserved; ++} UPACKED wusb_dev_cap_uwb_desc_t; ++ ++/* Wireless USB Endpoint Companion Descriptor */ ++typedef struct wusb_endpoint_companion_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++ uByte bMaxSequence; ++ uWord wMaxStreamDelay; ++ uWord wOverTheAirPacketSize; ++ uByte bOverTheAirInterval; ++ uByte bmCompAttributes; ++} UPACKED wusb_endpoint_companion_desc_t; ++ ++/* Wireless USB Numeric Association M1 Data Structure */ ++typedef struct wusb_m1_data { ++ uByte version; ++ uWord langId; ++ uByte deviceFriendlyNameLength; ++ uByte sha_256_m3[32]; ++ uByte deviceFriendlyName[256]; ++} UPACKED wusb_m1_data_t; ++ ++typedef struct wusb_m2_data { ++ uByte version; ++ uWord langId; ++ uByte hostFriendlyNameLength; ++ uByte pkh[384]; ++ uByte hostFriendlyName[256]; ++} UPACKED wusb_m2_data_t; ++ ++typedef struct wusb_m3_data { ++ uByte pkd[384]; ++ uByte nd; ++} UPACKED wusb_m3_data_t; ++ ++typedef struct wusb_m4_data { ++ uDWord _attributeTypeIdAndLength_1; ++ uWord associationTypeId; ++ ++ uDWord _attributeTypeIdAndLength_2; ++ uWord associationSubTypeId; ++ ++ uDWord _attributeTypeIdAndLength_3; ++ uDWord length; ++ ++ uDWord _attributeTypeIdAndLength_4; ++ uDWord associationStatus; ++ ++ uDWord _attributeTypeIdAndLength_5; ++ uByte chid[16]; ++ ++ uDWord _attributeTypeIdAndLength_6; ++ uByte cdid[16]; ++ ++ uDWord _attributeTypeIdAndLength_7; ++ uByte bandGroups[2]; ++} UPACKED wusb_m4_data_t; ++ ++#ifdef _MSC_VER ++#include ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _USB_H_ */ +diff --git a/drivers/usb/host/dwc_otg/Makefile b/drivers/usb/host/dwc_otg/Makefile +new file mode 100644 +index 0000000..c4c6e4e +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/Makefile +@@ -0,0 +1,80 @@ ++# ++# Makefile for DWC_otg Highspeed USB controller driver ++# ++ ++ifneq ($(KERNELRELEASE),) ++ ++# Use the BUS_INTERFACE variable to compile the software for either ++# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus. ++ifeq ($(BUS_INTERFACE),) ++# BUS_INTERFACE = -DPCI_INTERFACE ++# BUS_INTERFACE = -DLM_INTERFACE ++ BUS_INTERFACE = -DPLATFORM_INTERFACE ++endif ++ ++#EXTRA_CFLAGS += -DDEBUG ++#EXTRA_CFLAGS += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs ++ ++# Use one of the following flags to compile the software in host-only or ++# device-only mode. ++#EXTRA_CFLAGS += -DDWC_HOST_ONLY ++#EXTRA_CFLAGS += -DDWC_DEVICE_ONLY ++ ++EXTRA_CFLAGS += -Dlinux -DDWC_HS_ELECT_TST ++#EXTRA_CFLAGS += -DDWC_EN_ISOC ++EXTRA_CFLAGS += -I$(obj)/../dwc_common_port ++#EXTRA_CFLAGS += -I$(PORTLIB) ++EXTRA_CFLAGS += -DDWC_LINUX ++EXTRA_CFLAGS += $(CFI) ++EXTRA_CFLAGS += $(BUS_INTERFACE) ++#EXTRA_CFLAGS += -DDWC_DEV_SRPCAP ++ ++obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o ++ ++dwc_otg-objs := dwc_otg_driver.o dwc_otg_attr.o ++dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o ++dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o ++dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o ++dwc_otg-objs += dwc_otg_adp.o ++ifneq ($(CFI),) ++dwc_otg-objs += dwc_otg_cfi.o ++endif ++ ++kernrelwd := $(subst ., ,$(KERNELRELEASE)) ++kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) ++ ++ifneq ($(kernrel3),2.6.20) ++EXTRA_CFLAGS += $(CPPFLAGS) ++endif ++ ++else ++ ++PWD := $(shell pwd) ++PORTLIB := $(PWD)/../dwc_common_port ++ ++# Command paths ++CTAGS := $(CTAGS) ++DOXYGEN := $(DOXYGEN) ++ ++default: portlib ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: default ++ $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install ++ $(MAKE) -C$(KDIR) M=$(PWD) modules_install ++ ++portlib: ++ $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ cp $(PORTLIB)/Module.symvers $(PWD)/ ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++ ++clean: ++ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers ++ ++endif +diff --git a/drivers/usb/host/dwc_otg/doc/doxygen.cfg b/drivers/usb/host/dwc_otg/doc/doxygen.cfg +new file mode 100644 +index 0000000..537c676 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg +@@ -0,0 +1,224 @@ ++# Doxyfile 1.3.9.1 ++ ++#--------------------------------------------------------------------------- ++# Project related configuration options ++#--------------------------------------------------------------------------- ++PROJECT_NAME = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver" ++PROJECT_NUMBER = v3.00a ++OUTPUT_DIRECTORY = ./doc/ ++CREATE_SUBDIRS = NO ++OUTPUT_LANGUAGE = English ++BRIEF_MEMBER_DESC = YES ++REPEAT_BRIEF = YES ++ABBREVIATE_BRIEF = "The $name class" \ ++ "The $name widget" \ ++ "The $name file" \ ++ is \ ++ provides \ ++ specifies \ ++ contains \ ++ represents \ ++ a \ ++ an \ ++ the ++ALWAYS_DETAILED_SEC = NO ++INLINE_INHERITED_MEMB = NO ++FULL_PATH_NAMES = NO ++STRIP_FROM_PATH = ++STRIP_FROM_INC_PATH = ++SHORT_NAMES = NO ++JAVADOC_AUTOBRIEF = YES ++MULTILINE_CPP_IS_BRIEF = NO ++INHERIT_DOCS = YES ++DISTRIBUTE_GROUP_DOC = NO ++TAB_SIZE = 8 ++ALIASES = ++OPTIMIZE_OUTPUT_FOR_C = YES ++OPTIMIZE_OUTPUT_JAVA = NO ++SUBGROUPING = YES ++#--------------------------------------------------------------------------- ++# Build related configuration options ++#--------------------------------------------------------------------------- ++EXTRACT_ALL = NO ++EXTRACT_PRIVATE = YES ++EXTRACT_STATIC = YES ++EXTRACT_LOCAL_CLASSES = YES ++EXTRACT_LOCAL_METHODS = NO ++HIDE_UNDOC_MEMBERS = NO ++HIDE_UNDOC_CLASSES = NO ++HIDE_FRIEND_COMPOUNDS = NO ++HIDE_IN_BODY_DOCS = NO ++INTERNAL_DOCS = NO ++CASE_SENSE_NAMES = NO ++HIDE_SCOPE_NAMES = NO ++SHOW_INCLUDE_FILES = YES ++INLINE_INFO = YES ++SORT_MEMBER_DOCS = NO ++SORT_BRIEF_DOCS = NO ++SORT_BY_SCOPE_NAME = NO ++GENERATE_TODOLIST = YES ++GENERATE_TESTLIST = YES ++GENERATE_BUGLIST = YES ++GENERATE_DEPRECATEDLIST= YES ++ENABLED_SECTIONS = ++MAX_INITIALIZER_LINES = 30 ++SHOW_USED_FILES = YES ++SHOW_DIRECTORIES = YES ++#--------------------------------------------------------------------------- ++# configuration options related to warning and progress messages ++#--------------------------------------------------------------------------- ++QUIET = YES ++WARNINGS = YES ++WARN_IF_UNDOCUMENTED = NO ++WARN_IF_DOC_ERROR = YES ++WARN_FORMAT = "$file:$line: $text" ++WARN_LOGFILE = ++#--------------------------------------------------------------------------- ++# configuration options related to the input files ++#--------------------------------------------------------------------------- ++INPUT = . ++FILE_PATTERNS = *.c \ ++ *.h \ ++ ./linux/*.c \ ++ ./linux/*.h ++RECURSIVE = NO ++EXCLUDE = ./test/ \ ++ ./dwc_otg/.AppleDouble/ ++EXCLUDE_SYMLINKS = YES ++EXCLUDE_PATTERNS = *.mod.* ++EXAMPLE_PATH = ++EXAMPLE_PATTERNS = * ++EXAMPLE_RECURSIVE = NO ++IMAGE_PATH = ++INPUT_FILTER = ++FILTER_PATTERNS = ++FILTER_SOURCE_FILES = NO ++#--------------------------------------------------------------------------- ++# configuration options related to source browsing ++#--------------------------------------------------------------------------- ++SOURCE_BROWSER = YES ++INLINE_SOURCES = NO ++STRIP_CODE_COMMENTS = YES ++REFERENCED_BY_RELATION = NO ++REFERENCES_RELATION = NO ++VERBATIM_HEADERS = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the alphabetical class index ++#--------------------------------------------------------------------------- ++ALPHABETICAL_INDEX = NO ++COLS_IN_ALPHA_INDEX = 5 ++IGNORE_PREFIX = ++#--------------------------------------------------------------------------- ++# configuration options related to the HTML output ++#--------------------------------------------------------------------------- ++GENERATE_HTML = YES ++HTML_OUTPUT = html ++HTML_FILE_EXTENSION = .html ++HTML_HEADER = ++HTML_FOOTER = ++HTML_STYLESHEET = ++HTML_ALIGN_MEMBERS = YES ++GENERATE_HTMLHELP = NO ++CHM_FILE = ++HHC_LOCATION = ++GENERATE_CHI = NO ++BINARY_TOC = NO ++TOC_EXPAND = NO ++DISABLE_INDEX = NO ++ENUM_VALUES_PER_LINE = 4 ++GENERATE_TREEVIEW = YES ++TREEVIEW_WIDTH = 250 ++#--------------------------------------------------------------------------- ++# configuration options related to the LaTeX output ++#--------------------------------------------------------------------------- ++GENERATE_LATEX = NO ++LATEX_OUTPUT = latex ++LATEX_CMD_NAME = latex ++MAKEINDEX_CMD_NAME = makeindex ++COMPACT_LATEX = NO ++PAPER_TYPE = a4wide ++EXTRA_PACKAGES = ++LATEX_HEADER = ++PDF_HYPERLINKS = NO ++USE_PDFLATEX = NO ++LATEX_BATCHMODE = NO ++LATEX_HIDE_INDICES = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the RTF output ++#--------------------------------------------------------------------------- ++GENERATE_RTF = NO ++RTF_OUTPUT = rtf ++COMPACT_RTF = NO ++RTF_HYPERLINKS = NO ++RTF_STYLESHEET_FILE = ++RTF_EXTENSIONS_FILE = ++#--------------------------------------------------------------------------- ++# configuration options related to the man page output ++#--------------------------------------------------------------------------- ++GENERATE_MAN = NO ++MAN_OUTPUT = man ++MAN_EXTENSION = .3 ++MAN_LINKS = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the XML output ++#--------------------------------------------------------------------------- ++GENERATE_XML = NO ++XML_OUTPUT = xml ++XML_SCHEMA = ++XML_DTD = ++XML_PROGRAMLISTING = YES ++#--------------------------------------------------------------------------- ++# configuration options for the AutoGen Definitions output ++#--------------------------------------------------------------------------- ++GENERATE_AUTOGEN_DEF = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the Perl module output ++#--------------------------------------------------------------------------- ++GENERATE_PERLMOD = NO ++PERLMOD_LATEX = NO ++PERLMOD_PRETTY = YES ++PERLMOD_MAKEVAR_PREFIX = ++#--------------------------------------------------------------------------- ++# Configuration options related to the preprocessor ++#--------------------------------------------------------------------------- ++ENABLE_PREPROCESSING = YES ++MACRO_EXPANSION = YES ++EXPAND_ONLY_PREDEF = YES ++SEARCH_INCLUDES = YES ++INCLUDE_PATH = ++INCLUDE_FILE_PATTERNS = ++PREDEFINED = DEVICE_ATTR DWC_EN_ISOC ++EXPAND_AS_DEFINED = DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW DWC_OTG_DEVICE_ATTR_BITFIELD_STORE DWC_OTG_DEVICE_ATTR_BITFIELD_RW DWC_OTG_DEVICE_ATTR_BITFIELD_RO DWC_OTG_DEVICE_ATTR_REG_SHOW DWC_OTG_DEVICE_ATTR_REG_STORE DWC_OTG_DEVICE_ATTR_REG32_RW DWC_OTG_DEVICE_ATTR_REG32_RO DWC_EN_ISOC ++SKIP_FUNCTION_MACROS = NO ++#--------------------------------------------------------------------------- ++# Configuration::additions related to external references ++#--------------------------------------------------------------------------- ++TAGFILES = ++GENERATE_TAGFILE = ++ALLEXTERNALS = NO ++EXTERNAL_GROUPS = YES ++PERL_PATH = /usr/bin/perl ++#--------------------------------------------------------------------------- ++# Configuration options related to the dot tool ++#--------------------------------------------------------------------------- ++CLASS_DIAGRAMS = YES ++HIDE_UNDOC_RELATIONS = YES ++HAVE_DOT = NO ++CLASS_GRAPH = YES ++COLLABORATION_GRAPH = YES ++UML_LOOK = NO ++TEMPLATE_RELATIONS = NO ++INCLUDE_GRAPH = YES ++INCLUDED_BY_GRAPH = YES ++CALL_GRAPH = NO ++GRAPHICAL_HIERARCHY = YES ++DOT_IMAGE_FORMAT = png ++DOT_PATH = ++DOTFILE_DIRS = ++MAX_DOT_GRAPH_DEPTH = 1000 ++GENERATE_LEGEND = YES ++DOT_CLEANUP = YES ++#--------------------------------------------------------------------------- ++# Configuration::additions related to the search engine ++#--------------------------------------------------------------------------- ++SEARCHENGINE = NO +diff --git a/drivers/usb/host/dwc_otg/dummy_audio.c b/drivers/usb/host/dwc_otg/dummy_audio.c +new file mode 100644 +index 0000000..530ac8b +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dummy_audio.c +@@ -0,0 +1,1575 @@ ++/* ++ * zero.c -- Gadget Zero, for USB development ++ * ++ * Copyright (C) 2003-2004 David Brownell ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions, and the following disclaimer, ++ * without modification. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The names of the above-listed copyright holders may not be used ++ * to endorse or promote products derived from this software without ++ * specific prior written permission. ++ * ++ * ALTERNATIVELY, this software may be distributed under the terms of the ++ * GNU General Public License ("GPL") as published by the Free Software ++ * Foundation, either version 2 of that License or (at your option) any ++ * later version. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS ++ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ++ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ++ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR ++ * CONTRIBUTORS 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. ++ */ ++ ++ ++/* ++ * Gadget Zero only needs two bulk endpoints, and is an example of how you ++ * can write a hardware-agnostic gadget driver running inside a USB device. ++ * ++ * Hardware details are visible (see CONFIG_USB_ZERO_* below) but don't ++ * affect most of the driver. ++ * ++ * Use it with the Linux host/master side "usbtest" driver to get a basic ++ * functional test of your device-side usb stack, or with "usb-skeleton". ++ * ++ * It supports two similar configurations. One sinks whatever the usb host ++ * writes, and in return sources zeroes. The other loops whatever the host ++ * writes back, so the host can read it. Module options include: ++ * ++ * buflen=N default N=4096, buffer size used ++ * qlen=N default N=32, how many buffers in the loopback queue ++ * loopdefault default false, list loopback config first ++ * ++ * Many drivers will only have one configuration, letting them be much ++ * simpler if they also don't support high speed operation (like this ++ * driver does). ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++# include ++#else ++# include ++#endif ++ ++#include ++ ++ ++/*-------------------------------------------------------------------------*/ ++/*-------------------------------------------------------------------------*/ ++ ++ ++static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++ ++ ++/** ++ * usb_gadget_get_string - fill out a string descriptor ++ * @table: of c strings encoded using UTF-8 ++ * @id: string id, from low byte of wValue in get string descriptor ++ * @buf: at least 256 bytes ++ * ++ * Finds the UTF-8 string matching the ID, and converts it into a ++ * string descriptor in utf16-le. ++ * Returns length of descriptor (always even) or negative errno ++ * ++ * If your driver needs stings in multiple languages, you'll probably ++ * "switch (wIndex) { ... }" in your ep0 string descriptor logic, ++ * using this routine after choosing which set of UTF-8 strings to use. ++ * Note that US-ASCII is a strict subset of UTF-8; any string bytes with ++ * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1 ++ * characters (which are also widely used in C strings). ++ */ ++int ++usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) ++{ ++ struct usb_string *s; ++ int len; ++ ++ /* descriptor 0 has the language id */ ++ if (id == 0) { ++ buf [0] = 4; ++ buf [1] = USB_DT_STRING; ++ buf [2] = (u8) table->language; ++ buf [3] = (u8) (table->language >> 8); ++ return 4; ++ } ++ for (s = table->strings; s && s->s; s++) ++ if (s->id == id) ++ break; ++ ++ /* unrecognized: stall. */ ++ if (!s || !s->s) ++ return -EINVAL; ++ ++ /* string descriptors have length, tag, then UTF16-LE text */ ++ len = min ((size_t) 126, strlen (s->s)); ++ memset (buf + 2, 0, 2 * len); /* zero all the bytes */ ++ len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len); ++ if (len < 0) ++ return -EINVAL; ++ buf [0] = (len + 1) * 2; ++ buf [1] = USB_DT_STRING; ++ return buf [0]; ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++/*-------------------------------------------------------------------------*/ ++ ++ ++/** ++ * usb_descriptor_fillbuf - fill buffer with descriptors ++ * @buf: Buffer to be filled ++ * @buflen: Size of buf ++ * @src: Array of descriptor pointers, terminated by null pointer. ++ * ++ * Copies descriptors into the buffer, returning the length or a ++ * negative error code if they can't all be copied. Useful when ++ * assembling descriptors for an associated set of interfaces used ++ * as part of configuring a composite device; or in other cases where ++ * sets of descriptors need to be marshaled. ++ */ ++int ++usb_descriptor_fillbuf(void *buf, unsigned buflen, ++ const struct usb_descriptor_header **src) ++{ ++ u8 *dest = buf; ++ ++ if (!src) ++ return -EINVAL; ++ ++ /* fill buffer from src[] until null descriptor ptr */ ++ for (; 0 != *src; src++) { ++ unsigned len = (*src)->bLength; ++ ++ if (len > buflen) ++ return -EINVAL; ++ memcpy(dest, *src, len); ++ buflen -= len; ++ dest += len; ++ } ++ return dest - (u8 *)buf; ++} ++ ++ ++/** ++ * usb_gadget_config_buf - builts a complete configuration descriptor ++ * @config: Header for the descriptor, including characteristics such ++ * as power requirements and number of interfaces. ++ * @desc: Null-terminated vector of pointers to the descriptors (interface, ++ * endpoint, etc) defining all functions in this device configuration. ++ * @buf: Buffer for the resulting configuration descriptor. ++ * @length: Length of buffer. If this is not big enough to hold the ++ * entire configuration descriptor, an error code will be returned. ++ * ++ * This copies descriptors into the response buffer, building a descriptor ++ * for that configuration. It returns the buffer length or a negative ++ * status code. The config.wTotalLength field is set to match the length ++ * of the result, but other descriptor fields (including power usage and ++ * interface count) must be set by the caller. ++ * ++ * Gadget drivers could use this when constructing a config descriptor ++ * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the ++ * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed. ++ */ ++int usb_gadget_config_buf( ++ const struct usb_config_descriptor *config, ++ void *buf, ++ unsigned length, ++ const struct usb_descriptor_header **desc ++) ++{ ++ struct usb_config_descriptor *cp = buf; ++ int len; ++ ++ /* config descriptor first */ ++ if (length < USB_DT_CONFIG_SIZE || !desc) ++ return -EINVAL; ++ *cp = *config; ++ ++ /* then interface/endpoint/class/vendor/... */ ++ len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, ++ length - USB_DT_CONFIG_SIZE, desc); ++ if (len < 0) ++ return len; ++ len += USB_DT_CONFIG_SIZE; ++ if (len > 0xffff) ++ return -EINVAL; ++ ++ /* patch up the config descriptor */ ++ cp->bLength = USB_DT_CONFIG_SIZE; ++ cp->bDescriptorType = USB_DT_CONFIG; ++ cp->wTotalLength = cpu_to_le16(len); ++ cp->bmAttributes |= USB_CONFIG_ATT_ONE; ++ return len; ++} ++ ++/*-------------------------------------------------------------------------*/ ++/*-------------------------------------------------------------------------*/ ++ ++ ++#define RBUF_LEN (1024*1024) ++static int rbuf_start; ++static int rbuf_len; ++static __u8 rbuf[RBUF_LEN]; ++ ++/*-------------------------------------------------------------------------*/ ++ ++#define DRIVER_VERSION "St Patrick's Day 2004" ++ ++static const char shortname [] = "zero"; ++static const char longname [] = "YAMAHA YST-MS35D USB Speaker "; ++ ++static const char source_sink [] = "source and sink data"; ++static const char loopback [] = "loop input to output"; ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * driver assumes self-powered hardware, and ++ * has no way for users to trigger remote wakeup. ++ * ++ * this version autoconfigures as much as possible, ++ * which is reasonable for most "bulk-only" drivers. ++ */ ++static const char *EP_IN_NAME; /* source */ ++static const char *EP_OUT_NAME; /* sink */ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* big enough to hold our biggest descriptor */ ++#define USB_BUFSIZ 512 ++ ++struct zero_dev { ++ spinlock_t lock; ++ struct usb_gadget *gadget; ++ struct usb_request *req; /* for control responses */ ++ ++ /* when configured, we have one of two configs: ++ * - source data (in to host) and sink it (out from host) ++ * - or loop it back (out from host back in to host) ++ */ ++ u8 config; ++ struct usb_ep *in_ep, *out_ep; ++ ++ /* autoresume timer */ ++ struct timer_list resume; ++}; ++ ++#define xprintk(d,level,fmt,args...) \ ++ dev_printk(level , &(d)->gadget->dev , fmt , ## args) ++ ++#ifdef DEBUG ++#define DBG(dev,fmt,args...) \ ++ xprintk(dev , KERN_DEBUG , fmt , ## args) ++#else ++#define DBG(dev,fmt,args...) \ ++ do { } while (0) ++#endif /* DEBUG */ ++ ++#ifdef VERBOSE ++#define VDBG DBG ++#else ++#define VDBG(dev,fmt,args...) \ ++ do { } while (0) ++#endif /* VERBOSE */ ++ ++#define ERROR(dev,fmt,args...) \ ++ xprintk(dev , KERN_ERR , fmt , ## args) ++#define WARN(dev,fmt,args...) \ ++ xprintk(dev , KERN_WARNING , fmt , ## args) ++#define INFO(dev,fmt,args...) \ ++ xprintk(dev , KERN_INFO , fmt , ## args) ++ ++/*-------------------------------------------------------------------------*/ ++ ++static unsigned buflen = 4096; ++static unsigned qlen = 32; ++static unsigned pattern = 0; ++ ++module_param (buflen, uint, S_IRUGO|S_IWUSR); ++module_param (qlen, uint, S_IRUGO|S_IWUSR); ++module_param (pattern, uint, S_IRUGO|S_IWUSR); ++ ++/* ++ * if it's nonzero, autoresume says how many seconds to wait ++ * before trying to wake up the host after suspend. ++ */ ++static unsigned autoresume = 0; ++module_param (autoresume, uint, 0); ++ ++/* ++ * Normally the "loopback" configuration is second (index 1) so ++ * it's not the default. Here's where to change that order, to ++ * work better with hosts where config changes are problematic. ++ * Or controllers (like superh) that only support one config. ++ */ ++static int loopdefault = 0; ++ ++module_param (loopdefault, bool, S_IRUGO|S_IWUSR); ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* Thanks to NetChip Technologies for donating this product ID. ++ * ++ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! ++ * Instead: allocate your own, using normal USB-IF procedures. ++ */ ++#ifndef CONFIG_USB_ZERO_HNPTEST ++#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ ++#define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */ ++#else ++#define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */ ++#define DRIVER_PRODUCT_NUM 0xbadd ++#endif ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * DESCRIPTORS ... most are static, but strings and (full) ++ * configuration descriptors are built on demand. ++ */ ++ ++/* ++#define STRING_MANUFACTURER 25 ++#define STRING_PRODUCT 42 ++#define STRING_SERIAL 101 ++*/ ++#define STRING_MANUFACTURER 1 ++#define STRING_PRODUCT 2 ++#define STRING_SERIAL 3 ++ ++#define STRING_SOURCE_SINK 250 ++#define STRING_LOOPBACK 251 ++ ++/* ++ * This device advertises two configurations; these numbers work ++ * on a pxa250 as well as more flexible hardware. ++ */ ++#define CONFIG_SOURCE_SINK 3 ++#define CONFIG_LOOPBACK 2 ++ ++/* ++static struct usb_device_descriptor ++device_desc = { ++ .bLength = sizeof device_desc, ++ .bDescriptorType = USB_DT_DEVICE, ++ ++ .bcdUSB = __constant_cpu_to_le16 (0x0200), ++ .bDeviceClass = USB_CLASS_VENDOR_SPEC, ++ ++ .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM), ++ .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM), ++ .iManufacturer = STRING_MANUFACTURER, ++ .iProduct = STRING_PRODUCT, ++ .iSerialNumber = STRING_SERIAL, ++ .bNumConfigurations = 2, ++}; ++*/ ++static struct usb_device_descriptor ++device_desc = { ++ .bLength = sizeof device_desc, ++ .bDescriptorType = USB_DT_DEVICE, ++ .bcdUSB = __constant_cpu_to_le16 (0x0100), ++ .bDeviceClass = USB_CLASS_PER_INTERFACE, ++ .bDeviceSubClass = 0, ++ .bDeviceProtocol = 0, ++ .bMaxPacketSize0 = 64, ++ .bcdDevice = __constant_cpu_to_le16 (0x0100), ++ .idVendor = __constant_cpu_to_le16 (0x0499), ++ .idProduct = __constant_cpu_to_le16 (0x3002), ++ .iManufacturer = STRING_MANUFACTURER, ++ .iProduct = STRING_PRODUCT, ++ .iSerialNumber = STRING_SERIAL, ++ .bNumConfigurations = 1, ++}; ++ ++static struct usb_config_descriptor ++z_config = { ++ .bLength = sizeof z_config, ++ .bDescriptorType = USB_DT_CONFIG, ++ ++ /* compute wTotalLength on the fly */ ++ .bNumInterfaces = 2, ++ .bConfigurationValue = 1, ++ .iConfiguration = 0, ++ .bmAttributes = 0x40, ++ .bMaxPower = 0, /* self-powered */ ++}; ++ ++ ++static struct usb_otg_descriptor ++otg_descriptor = { ++ .bLength = sizeof otg_descriptor, ++ .bDescriptorType = USB_DT_OTG, ++ ++ .bmAttributes = USB_OTG_SRP, ++}; ++ ++/* one interface in each configuration */ ++#ifdef CONFIG_USB_GADGET_DUALSPEED ++ ++/* ++ * usb 2.0 devices need to expose both high speed and full speed ++ * descriptors, unless they only run at full speed. ++ * ++ * that means alternate endpoint descriptors (bigger packets) ++ * and a "device qualifier" ... plus more construction options ++ * for the config descriptor. ++ */ ++ ++static struct usb_qualifier_descriptor ++dev_qualifier = { ++ .bLength = sizeof dev_qualifier, ++ .bDescriptorType = USB_DT_DEVICE_QUALIFIER, ++ ++ .bcdUSB = __constant_cpu_to_le16 (0x0200), ++ .bDeviceClass = USB_CLASS_VENDOR_SPEC, ++ ++ .bNumConfigurations = 2, ++}; ++ ++ ++struct usb_cs_as_general_descriptor { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ ++ __u8 bDescriptorSubType; ++ __u8 bTerminalLink; ++ __u8 bDelay; ++ __u16 wFormatTag; ++} __attribute__ ((packed)); ++ ++struct usb_cs_as_format_descriptor { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ ++ __u8 bDescriptorSubType; ++ __u8 bFormatType; ++ __u8 bNrChannels; ++ __u8 bSubframeSize; ++ __u8 bBitResolution; ++ __u8 bSamfreqType; ++ __u8 tLowerSamFreq[3]; ++ __u8 tUpperSamFreq[3]; ++} __attribute__ ((packed)); ++ ++static const struct usb_interface_descriptor ++z_audio_control_if_desc = { ++ .bLength = sizeof z_audio_control_if_desc, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 0, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = 0x1, ++ .bInterfaceProtocol = 0, ++ .iInterface = 0, ++}; ++ ++static const struct usb_interface_descriptor ++z_audio_if_desc = { ++ .bLength = sizeof z_audio_if_desc, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 1, ++ .bAlternateSetting = 0, ++ .bNumEndpoints = 0, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = 0x2, ++ .bInterfaceProtocol = 0, ++ .iInterface = 0, ++}; ++ ++static const struct usb_interface_descriptor ++z_audio_if_desc2 = { ++ .bLength = sizeof z_audio_if_desc, ++ .bDescriptorType = USB_DT_INTERFACE, ++ .bInterfaceNumber = 1, ++ .bAlternateSetting = 1, ++ .bNumEndpoints = 1, ++ .bInterfaceClass = USB_CLASS_AUDIO, ++ .bInterfaceSubClass = 0x2, ++ .bInterfaceProtocol = 0, ++ .iInterface = 0, ++}; ++ ++static const struct usb_cs_as_general_descriptor ++z_audio_cs_as_if_desc = { ++ .bLength = 7, ++ .bDescriptorType = 0x24, ++ ++ .bDescriptorSubType = 0x01, ++ .bTerminalLink = 0x01, ++ .bDelay = 0x0, ++ .wFormatTag = __constant_cpu_to_le16 (0x0001) ++}; ++ ++ ++static const struct usb_cs_as_format_descriptor ++z_audio_cs_as_format_desc = { ++ .bLength = 0xe, ++ .bDescriptorType = 0x24, ++ ++ .bDescriptorSubType = 2, ++ .bFormatType = 1, ++ .bNrChannels = 1, ++ .bSubframeSize = 1, ++ .bBitResolution = 8, ++ .bSamfreqType = 0, ++ .tLowerSamFreq = {0x7e, 0x13, 0x00}, ++ .tUpperSamFreq = {0xe2, 0xd6, 0x00}, ++}; ++ ++static const struct usb_endpoint_descriptor ++z_iso_ep = { ++ .bLength = 0x09, ++ .bDescriptorType = 0x05, ++ .bEndpointAddress = 0x04, ++ .bmAttributes = 0x09, ++ .wMaxPacketSize = 0x0038, ++ .bInterval = 0x01, ++ .bRefresh = 0x00, ++ .bSynchAddress = 0x00, ++}; ++ ++static char z_iso_ep2[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; ++ ++// 9 bytes ++static char z_ac_interface_header_desc[] = ++{ 0x09, 0x24, 0x01, 0x00, 0x01, 0x2b, 0x00, 0x01, 0x01 }; ++ ++// 12 bytes ++static char z_0[] = {0x0c, 0x24, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, ++ 0x03, 0x00, 0x00, 0x00}; ++// 13 bytes ++static char z_1[] = {0x0d, 0x24, 0x06, 0x02, 0x01, 0x02, 0x15, 0x00, ++ 0x02, 0x00, 0x02, 0x00, 0x00}; ++// 9 bytes ++static char z_2[] = {0x09, 0x24, 0x03, 0x03, 0x01, 0x03, 0x00, 0x02, ++ 0x00}; ++ ++static char za_0[] = {0x09, 0x04, 0x01, 0x02, 0x01, 0x01, 0x02, 0x00, ++ 0x00}; ++ ++static char za_1[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; ++ ++static char za_2[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x01, 0x08, 0x00, ++ 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00}; ++ ++static char za_3[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00, ++ 0x00}; ++ ++static char za_4[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; ++ ++static char za_5[] = {0x09, 0x04, 0x01, 0x03, 0x01, 0x01, 0x02, 0x00, ++ 0x00}; ++ ++static char za_6[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; ++ ++static char za_7[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x02, 0x10, 0x00, ++ 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00}; ++ ++static char za_8[] = {0x09, 0x05, 0x04, 0x09, 0x70, 0x00, 0x01, 0x00, ++ 0x00}; ++ ++static char za_9[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; ++ ++static char za_10[] = {0x09, 0x04, 0x01, 0x04, 0x01, 0x01, 0x02, 0x00, ++ 0x00}; ++ ++static char za_11[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; ++ ++static char za_12[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, ++ 0x73, 0x13, 0x00, 0xe2, 0xd6, 0x00}; ++ ++static char za_13[] = {0x09, 0x05, 0x04, 0x09, 0xe0, 0x00, 0x01, 0x00, ++ 0x00}; ++ ++static char za_14[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; ++ ++static char za_15[] = {0x09, 0x04, 0x01, 0x05, 0x01, 0x01, 0x02, 0x00, ++ 0x00}; ++ ++static char za_16[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; ++ ++static char za_17[] = {0x0e, 0x24, 0x02, 0x01, 0x01, 0x03, 0x14, 0x00, ++ 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00}; ++ ++static char za_18[] = {0x09, 0x05, 0x04, 0x09, 0xa8, 0x00, 0x01, 0x00, ++ 0x00}; ++ ++static char za_19[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; ++ ++static char za_20[] = {0x09, 0x04, 0x01, 0x06, 0x01, 0x01, 0x02, 0x00, ++ 0x00}; ++ ++static char za_21[] = {0x07, 0x24, 0x01, 0x01, 0x00, 0x01, 0x00}; ++ ++static char za_22[] = {0x0e, 0x24, 0x02, 0x01, 0x02, 0x03, 0x14, 0x00, ++ 0x7e, 0x13, 0x00, 0xe2, 0xd6, 0x00}; ++ ++static char za_23[] = {0x09, 0x05, 0x04, 0x09, 0x50, 0x01, 0x01, 0x00, ++ 0x00}; ++ ++static char za_24[] = {0x07, 0x25, 0x01, 0x00, 0x02, 0x00, 0x02}; ++ ++ ++ ++static const struct usb_descriptor_header *z_function [] = { ++ (struct usb_descriptor_header *) &z_audio_control_if_desc, ++ (struct usb_descriptor_header *) &z_ac_interface_header_desc, ++ (struct usb_descriptor_header *) &z_0, ++ (struct usb_descriptor_header *) &z_1, ++ (struct usb_descriptor_header *) &z_2, ++ (struct usb_descriptor_header *) &z_audio_if_desc, ++ (struct usb_descriptor_header *) &z_audio_if_desc2, ++ (struct usb_descriptor_header *) &z_audio_cs_as_if_desc, ++ (struct usb_descriptor_header *) &z_audio_cs_as_format_desc, ++ (struct usb_descriptor_header *) &z_iso_ep, ++ (struct usb_descriptor_header *) &z_iso_ep2, ++ (struct usb_descriptor_header *) &za_0, ++ (struct usb_descriptor_header *) &za_1, ++ (struct usb_descriptor_header *) &za_2, ++ (struct usb_descriptor_header *) &za_3, ++ (struct usb_descriptor_header *) &za_4, ++ (struct usb_descriptor_header *) &za_5, ++ (struct usb_descriptor_header *) &za_6, ++ (struct usb_descriptor_header *) &za_7, ++ (struct usb_descriptor_header *) &za_8, ++ (struct usb_descriptor_header *) &za_9, ++ (struct usb_descriptor_header *) &za_10, ++ (struct usb_descriptor_header *) &za_11, ++ (struct usb_descriptor_header *) &za_12, ++ (struct usb_descriptor_header *) &za_13, ++ (struct usb_descriptor_header *) &za_14, ++ (struct usb_descriptor_header *) &za_15, ++ (struct usb_descriptor_header *) &za_16, ++ (struct usb_descriptor_header *) &za_17, ++ (struct usb_descriptor_header *) &za_18, ++ (struct usb_descriptor_header *) &za_19, ++ (struct usb_descriptor_header *) &za_20, ++ (struct usb_descriptor_header *) &za_21, ++ (struct usb_descriptor_header *) &za_22, ++ (struct usb_descriptor_header *) &za_23, ++ (struct usb_descriptor_header *) &za_24, ++ NULL, ++}; ++ ++/* maxpacket and other transfer characteristics vary by speed. */ ++#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) ++ ++#else ++ ++/* if there's no high speed support, maxpacket doesn't change. */ ++#define ep_desc(g,hs,fs) fs ++ ++#endif /* !CONFIG_USB_GADGET_DUALSPEED */ ++ ++static char manufacturer [40]; ++//static char serial [40]; ++static char serial [] = "Ser 00 em"; ++ ++/* static strings, in UTF-8 */ ++static struct usb_string strings [] = { ++ { STRING_MANUFACTURER, manufacturer, }, ++ { STRING_PRODUCT, longname, }, ++ { STRING_SERIAL, serial, }, ++ { STRING_LOOPBACK, loopback, }, ++ { STRING_SOURCE_SINK, source_sink, }, ++ { } /* end of list */ ++}; ++ ++static struct usb_gadget_strings stringtab = { ++ .language = 0x0409, /* en-us */ ++ .strings = strings, ++}; ++ ++/* ++ * config descriptors are also handcrafted. these must agree with code ++ * that sets configurations, and with code managing interfaces and their ++ * altsettings. other complexity may come from: ++ * ++ * - high speed support, including "other speed config" rules ++ * - multiple configurations ++ * - interfaces with alternate settings ++ * - embedded class or vendor-specific descriptors ++ * ++ * this handles high speed, and has a second config that could as easily ++ * have been an alternate interface setting (on most hardware). ++ * ++ * NOTE: to demonstrate (and test) more USB capabilities, this driver ++ * should include an altsetting to test interrupt transfers, including ++ * high bandwidth modes at high speed. (Maybe work like Intel's test ++ * device?) ++ */ ++static int ++config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index) ++{ ++ int len; ++ const struct usb_descriptor_header **function; ++ ++ function = z_function; ++ len = usb_gadget_config_buf (&z_config, buf, USB_BUFSIZ, function); ++ if (len < 0) ++ return len; ++ ((struct usb_config_descriptor *) buf)->bDescriptorType = type; ++ return len; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct usb_request * ++alloc_ep_req (struct usb_ep *ep, unsigned length) ++{ ++ struct usb_request *req; ++ ++ req = usb_ep_alloc_request (ep, GFP_ATOMIC); ++ if (req) { ++ req->length = length; ++ req->buf = usb_ep_alloc_buffer (ep, length, ++ &req->dma, GFP_ATOMIC); ++ if (!req->buf) { ++ usb_ep_free_request (ep, req); ++ req = NULL; ++ } ++ } ++ return req; ++} ++ ++static void free_ep_req (struct usb_ep *ep, struct usb_request *req) ++{ ++ if (req->buf) ++ usb_ep_free_buffer (ep, req->buf, req->dma, req->length); ++ usb_ep_free_request (ep, req); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* optionally require specific source/sink data patterns */ ++ ++static int ++check_read_data ( ++ struct zero_dev *dev, ++ struct usb_ep *ep, ++ struct usb_request *req ++) ++{ ++ unsigned i; ++ u8 *buf = req->buf; ++ ++ for (i = 0; i < req->actual; i++, buf++) { ++ switch (pattern) { ++ /* all-zeroes has no synchronization issues */ ++ case 0: ++ if (*buf == 0) ++ continue; ++ break; ++ /* mod63 stays in sync with short-terminated transfers, ++ * or otherwise when host and gadget agree on how large ++ * each usb transfer request should be. resync is done ++ * with set_interface or set_config. ++ */ ++ case 1: ++ if (*buf == (u8)(i % 63)) ++ continue; ++ break; ++ } ++ ERROR (dev, "bad OUT byte, buf [%d] = %d\n", i, *buf); ++ usb_ep_set_halt (ep); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void zero_reset_config (struct zero_dev *dev) ++{ ++ if (dev->config == 0) ++ return; ++ ++ DBG (dev, "reset config\n"); ++ ++ /* just disable endpoints, forcing completion of pending i/o. ++ * all our completion handlers free their requests in this case. ++ */ ++ if (dev->in_ep) { ++ usb_ep_disable (dev->in_ep); ++ dev->in_ep = NULL; ++ } ++ if (dev->out_ep) { ++ usb_ep_disable (dev->out_ep); ++ dev->out_ep = NULL; ++ } ++ dev->config = 0; ++ del_timer (&dev->resume); ++} ++ ++#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos)) ++ ++static void ++zero_isoc_complete (struct usb_ep *ep, struct usb_request *req) ++{ ++ struct zero_dev *dev = ep->driver_data; ++ int status = req->status; ++ int i, j; ++ ++ switch (status) { ++ ++ case 0: /* normal completion? */ ++ //printk ("\nzero ---------------> isoc normal completion %d bytes\n", req->actual); ++ for (i=0, j=rbuf_start; iactual; i++) { ++ //printk ("%02x ", ((__u8*)req->buf)[i]); ++ rbuf[j] = ((__u8*)req->buf)[i]; ++ j++; ++ if (j >= RBUF_LEN) j=0; ++ } ++ rbuf_start = j; ++ //printk ("\n\n"); ++ ++ if (rbuf_len < RBUF_LEN) { ++ rbuf_len += req->actual; ++ if (rbuf_len > RBUF_LEN) { ++ rbuf_len = RBUF_LEN; ++ } ++ } ++ ++ break; ++ ++ /* this endpoint is normally active while we're configured */ ++ case -ECONNABORTED: /* hardware forced ep reset */ ++ case -ECONNRESET: /* request dequeued */ ++ case -ESHUTDOWN: /* disconnect from host */ ++ VDBG (dev, "%s gone (%d), %d/%d\n", ep->name, status, ++ req->actual, req->length); ++ if (ep == dev->out_ep) ++ check_read_data (dev, ep, req); ++ free_ep_req (ep, req); ++ return; ++ ++ case -EOVERFLOW: /* buffer overrun on read means that ++ * we didn't provide a big enough ++ * buffer. ++ */ ++ default: ++#if 1 ++ DBG (dev, "%s complete --> %d, %d/%d\n", ep->name, ++ status, req->actual, req->length); ++#endif ++ case -EREMOTEIO: /* short read */ ++ break; ++ } ++ ++ status = usb_ep_queue (ep, req, GFP_ATOMIC); ++ if (status) { ++ ERROR (dev, "kill %s: resubmit %d bytes --> %d\n", ++ ep->name, req->length, status); ++ usb_ep_set_halt (ep); ++ /* FIXME recover later ... somehow */ ++ } ++} ++ ++static struct usb_request * ++zero_start_isoc_ep (struct usb_ep *ep, int gfp_flags) ++{ ++ struct usb_request *req; ++ int status; ++ ++ req = alloc_ep_req (ep, 512); ++ if (!req) ++ return NULL; ++ ++ req->complete = zero_isoc_complete; ++ ++ status = usb_ep_queue (ep, req, gfp_flags); ++ if (status) { ++ struct zero_dev *dev = ep->driver_data; ++ ++ ERROR (dev, "start %s --> %d\n", ep->name, status); ++ free_ep_req (ep, req); ++ req = NULL; ++ } ++ ++ return req; ++} ++ ++/* change our operational config. this code must agree with the code ++ * that returns config descriptors, and altsetting code. ++ * ++ * it's also responsible for power management interactions. some ++ * configurations might not work with our current power sources. ++ * ++ * note that some device controller hardware will constrain what this ++ * code can do, perhaps by disallowing more than one configuration or ++ * by limiting configuration choices (like the pxa2xx). ++ */ ++static int ++zero_set_config (struct zero_dev *dev, unsigned number, int gfp_flags) ++{ ++ int result = 0; ++ struct usb_gadget *gadget = dev->gadget; ++ const struct usb_endpoint_descriptor *d; ++ struct usb_ep *ep; ++ ++ if (number == dev->config) ++ return 0; ++ ++ zero_reset_config (dev); ++ ++ gadget_for_each_ep (ep, gadget) { ++ ++ if (strcmp (ep->name, "ep4") == 0) { ++ ++ d = (struct usb_endpoint_descripter *)&za_23; // isoc ep desc for audio i/f alt setting 6 ++ result = usb_ep_enable (ep, d); ++ ++ if (result == 0) { ++ ep->driver_data = dev; ++ dev->in_ep = ep; ++ ++ if (zero_start_isoc_ep (ep, gfp_flags) != 0) { ++ ++ dev->in_ep = ep; ++ continue; ++ } ++ ++ usb_ep_disable (ep); ++ result = -EIO; ++ } ++ } ++ ++ } ++ ++ dev->config = number; ++ return result; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void zero_setup_complete (struct usb_ep *ep, struct usb_request *req) ++{ ++ if (req->status || req->actual != req->length) ++ DBG ((struct zero_dev *) ep->driver_data, ++ "setup complete --> %d, %d/%d\n", ++ req->status, req->actual, req->length); ++} ++ ++/* ++ * The setup() callback implements all the ep0 functionality that's ++ * not handled lower down, in hardware or the hardware driver (like ++ * device and endpoint feature flags, and their status). It's all ++ * housekeeping for the gadget function we're implementing. Most of ++ * the work is in config-specific setup. ++ */ ++static int ++zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ++{ ++ struct zero_dev *dev = get_gadget_data (gadget); ++ struct usb_request *req = dev->req; ++ int value = -EOPNOTSUPP; ++ ++ /* usually this stores reply data in the pre-allocated ep0 buffer, ++ * but config change events will reconfigure hardware. ++ */ ++ req->zero = 0; ++ switch (ctrl->bRequest) { ++ ++ case USB_REQ_GET_DESCRIPTOR: ++ ++ switch (ctrl->wValue >> 8) { ++ ++ case USB_DT_DEVICE: ++ value = min (ctrl->wLength, (u16) sizeof device_desc); ++ memcpy (req->buf, &device_desc, value); ++ break; ++#ifdef CONFIG_USB_GADGET_DUALSPEED ++ case USB_DT_DEVICE_QUALIFIER: ++ if (!gadget->is_dualspeed) ++ break; ++ value = min (ctrl->wLength, (u16) sizeof dev_qualifier); ++ memcpy (req->buf, &dev_qualifier, value); ++ break; ++ ++ case USB_DT_OTHER_SPEED_CONFIG: ++ if (!gadget->is_dualspeed) ++ break; ++ // FALLTHROUGH ++#endif /* CONFIG_USB_GADGET_DUALSPEED */ ++ case USB_DT_CONFIG: ++ value = config_buf (gadget, req->buf, ++ ctrl->wValue >> 8, ++ ctrl->wValue & 0xff); ++ if (value >= 0) ++ value = min (ctrl->wLength, (u16) value); ++ break; ++ ++ case USB_DT_STRING: ++ /* wIndex == language code. ++ * this driver only handles one language, you can ++ * add string tables for other languages, using ++ * any UTF-8 characters ++ */ ++ value = usb_gadget_get_string (&stringtab, ++ ctrl->wValue & 0xff, req->buf); ++ if (value >= 0) { ++ value = min (ctrl->wLength, (u16) value); ++ } ++ break; ++ } ++ break; ++ ++ /* currently two configs, two speeds */ ++ case USB_REQ_SET_CONFIGURATION: ++ if (ctrl->bRequestType != 0) ++ goto unknown; ++ ++ spin_lock (&dev->lock); ++ value = zero_set_config (dev, ctrl->wValue, GFP_ATOMIC); ++ spin_unlock (&dev->lock); ++ break; ++ case USB_REQ_GET_CONFIGURATION: ++ if (ctrl->bRequestType != USB_DIR_IN) ++ goto unknown; ++ *(u8 *)req->buf = dev->config; ++ value = min (ctrl->wLength, (u16) 1); ++ break; ++ ++ /* until we add altsetting support, or other interfaces, ++ * only 0/0 are possible. pxa2xx only supports 0/0 (poorly) ++ * and already killed pending endpoint I/O. ++ */ ++ case USB_REQ_SET_INTERFACE: ++ ++ if (ctrl->bRequestType != USB_RECIP_INTERFACE) ++ goto unknown; ++ spin_lock (&dev->lock); ++ if (dev->config) { ++ u8 config = dev->config; ++ ++ /* resets interface configuration, forgets about ++ * previous transaction state (queued bufs, etc) ++ * and re-inits endpoint state (toggle etc) ++ * no response queued, just zero status == success. ++ * if we had more than one interface we couldn't ++ * use this "reset the config" shortcut. ++ */ ++ zero_reset_config (dev); ++ zero_set_config (dev, config, GFP_ATOMIC); ++ value = 0; ++ } ++ spin_unlock (&dev->lock); ++ break; ++ case USB_REQ_GET_INTERFACE: ++ if ((ctrl->bRequestType == 0x21) && (ctrl->wIndex == 0x02)) { ++ value = ctrl->wLength; ++ break; ++ } ++ else { ++ if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) ++ goto unknown; ++ if (!dev->config) ++ break; ++ if (ctrl->wIndex != 0) { ++ value = -EDOM; ++ break; ++ } ++ *(u8 *)req->buf = 0; ++ value = min (ctrl->wLength, (u16) 1); ++ } ++ break; ++ ++ /* ++ * These are the same vendor-specific requests supported by ++ * Intel's USB 2.0 compliance test devices. We exceed that ++ * device spec by allowing multiple-packet requests. ++ */ ++ case 0x5b: /* control WRITE test -- fill the buffer */ ++ if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) ++ goto unknown; ++ if (ctrl->wValue || ctrl->wIndex) ++ break; ++ /* just read that many bytes into the buffer */ ++ if (ctrl->wLength > USB_BUFSIZ) ++ break; ++ value = ctrl->wLength; ++ break; ++ case 0x5c: /* control READ test -- return the buffer */ ++ if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) ++ goto unknown; ++ if (ctrl->wValue || ctrl->wIndex) ++ break; ++ /* expect those bytes are still in the buffer; send back */ ++ if (ctrl->wLength > USB_BUFSIZ ++ || ctrl->wLength != req->length) ++ break; ++ value = ctrl->wLength; ++ break; ++ ++ case 0x01: // SET_CUR ++ case 0x02: ++ case 0x03: ++ case 0x04: ++ case 0x05: ++ value = ctrl->wLength; ++ break; ++ case 0x81: ++ switch (ctrl->wValue) { ++ case 0x0201: ++ case 0x0202: ++ ((u8*)req->buf)[0] = 0x00; ++ ((u8*)req->buf)[1] = 0xe3; ++ break; ++ case 0x0300: ++ case 0x0500: ++ ((u8*)req->buf)[0] = 0x00; ++ break; ++ } ++ //((u8*)req->buf)[0] = 0x81; ++ //((u8*)req->buf)[1] = 0x81; ++ value = ctrl->wLength; ++ break; ++ case 0x82: ++ switch (ctrl->wValue) { ++ case 0x0201: ++ case 0x0202: ++ ((u8*)req->buf)[0] = 0x00; ++ ((u8*)req->buf)[1] = 0xc3; ++ break; ++ case 0x0300: ++ case 0x0500: ++ ((u8*)req->buf)[0] = 0x00; ++ break; ++ } ++ //((u8*)req->buf)[0] = 0x82; ++ //((u8*)req->buf)[1] = 0x82; ++ value = ctrl->wLength; ++ break; ++ case 0x83: ++ switch (ctrl->wValue) { ++ case 0x0201: ++ case 0x0202: ++ ((u8*)req->buf)[0] = 0x00; ++ ((u8*)req->buf)[1] = 0x00; ++ break; ++ case 0x0300: ++ ((u8*)req->buf)[0] = 0x60; ++ break; ++ case 0x0500: ++ ((u8*)req->buf)[0] = 0x18; ++ break; ++ } ++ //((u8*)req->buf)[0] = 0x83; ++ //((u8*)req->buf)[1] = 0x83; ++ value = ctrl->wLength; ++ break; ++ case 0x84: ++ switch (ctrl->wValue) { ++ case 0x0201: ++ case 0x0202: ++ ((u8*)req->buf)[0] = 0x00; ++ ((u8*)req->buf)[1] = 0x01; ++ break; ++ case 0x0300: ++ case 0x0500: ++ ((u8*)req->buf)[0] = 0x08; ++ break; ++ } ++ //((u8*)req->buf)[0] = 0x84; ++ //((u8*)req->buf)[1] = 0x84; ++ value = ctrl->wLength; ++ break; ++ case 0x85: ++ ((u8*)req->buf)[0] = 0x85; ++ ((u8*)req->buf)[1] = 0x85; ++ value = ctrl->wLength; ++ break; ++ ++ ++ default: ++unknown: ++ printk("unknown control req%02x.%02x v%04x i%04x l%d\n", ++ ctrl->bRequestType, ctrl->bRequest, ++ ctrl->wValue, ctrl->wIndex, ctrl->wLength); ++ } ++ ++ /* respond with data transfer before status phase? */ ++ if (value >= 0) { ++ req->length = value; ++ req->zero = value < ctrl->wLength ++ && (value % gadget->ep0->maxpacket) == 0; ++ value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC); ++ if (value < 0) { ++ DBG (dev, "ep_queue < 0 --> %d\n", value); ++ req->status = 0; ++ zero_setup_complete (gadget->ep0, req); ++ } ++ } ++ ++ /* device either stalls (value < 0) or reports success */ ++ return value; ++} ++ ++static void ++zero_disconnect (struct usb_gadget *gadget) ++{ ++ struct zero_dev *dev = get_gadget_data (gadget); ++ unsigned long flags; ++ ++ spin_lock_irqsave (&dev->lock, flags); ++ zero_reset_config (dev); ++ ++ /* a more significant application might have some non-usb ++ * activities to quiesce here, saving resources like power ++ * or pushing the notification up a network stack. ++ */ ++ spin_unlock_irqrestore (&dev->lock, flags); ++ ++ /* next we may get setup() calls to enumerate new connections; ++ * or an unbind() during shutdown (including removing module). ++ */ ++} ++ ++static void ++zero_autoresume (unsigned long _dev) ++{ ++ struct zero_dev *dev = (struct zero_dev *) _dev; ++ int status; ++ ++ /* normally the host would be woken up for something ++ * more significant than just a timer firing... ++ */ ++ if (dev->gadget->speed != USB_SPEED_UNKNOWN) { ++ status = usb_gadget_wakeup (dev->gadget); ++ DBG (dev, "wakeup --> %d\n", status); ++ } ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void ++zero_unbind (struct usb_gadget *gadget) ++{ ++ struct zero_dev *dev = get_gadget_data (gadget); ++ ++ DBG (dev, "unbind\n"); ++ ++ /* we've already been disconnected ... no i/o is active */ ++ if (dev->req) ++ free_ep_req (gadget->ep0, dev->req); ++ del_timer_sync (&dev->resume); ++ kfree (dev); ++ set_gadget_data (gadget, NULL); ++} ++ ++static int ++zero_bind (struct usb_gadget *gadget) ++{ ++ struct zero_dev *dev; ++ //struct usb_ep *ep; ++ ++ printk("binding\n"); ++ /* ++ * DRIVER POLICY CHOICE: you may want to do this differently. ++ * One thing to avoid is reusing a bcdDevice revision code ++ * with different host-visible configurations or behavior ++ * restrictions -- using ep1in/ep2out vs ep1out/ep3in, etc ++ */ ++ //device_desc.bcdDevice = __constant_cpu_to_le16 (0x0201); ++ ++ ++ /* ok, we made sense of the hardware ... */ ++ dev = kmalloc (sizeof *dev, SLAB_KERNEL); ++ if (!dev) ++ return -ENOMEM; ++ memset (dev, 0, sizeof *dev); ++ spin_lock_init (&dev->lock); ++ dev->gadget = gadget; ++ set_gadget_data (gadget, dev); ++ ++ /* preallocate control response and buffer */ ++ dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); ++ if (!dev->req) ++ goto enomem; ++ dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ, ++ &dev->req->dma, GFP_KERNEL); ++ if (!dev->req->buf) ++ goto enomem; ++ ++ dev->req->complete = zero_setup_complete; ++ ++ device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; ++ ++#ifdef CONFIG_USB_GADGET_DUALSPEED ++ /* assume ep0 uses the same value for both speeds ... */ ++ dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; ++ ++ /* and that all endpoints are dual-speed */ ++ //hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; ++ //hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; ++#endif ++ ++ usb_gadget_set_selfpowered (gadget); ++ ++ init_timer (&dev->resume); ++ dev->resume.function = zero_autoresume; ++ dev->resume.data = (unsigned long) dev; ++ ++ gadget->ep0->driver_data = dev; ++ ++ INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname); ++ INFO (dev, "using %s, OUT %s IN %s\n", gadget->name, ++ EP_OUT_NAME, EP_IN_NAME); ++ ++ snprintf (manufacturer, sizeof manufacturer, ++ UTS_SYSNAME " " UTS_RELEASE " with %s", ++ gadget->name); ++ ++ return 0; ++ ++enomem: ++ zero_unbind (gadget); ++ return -ENOMEM; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void ++zero_suspend (struct usb_gadget *gadget) ++{ ++ struct zero_dev *dev = get_gadget_data (gadget); ++ ++ if (gadget->speed == USB_SPEED_UNKNOWN) ++ return; ++ ++ if (autoresume) { ++ mod_timer (&dev->resume, jiffies + (HZ * autoresume)); ++ DBG (dev, "suspend, wakeup in %d seconds\n", autoresume); ++ } else ++ DBG (dev, "suspend\n"); ++} ++ ++static void ++zero_resume (struct usb_gadget *gadget) ++{ ++ struct zero_dev *dev = get_gadget_data (gadget); ++ ++ DBG (dev, "resume\n"); ++ del_timer (&dev->resume); ++} ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static struct usb_gadget_driver zero_driver = { ++#ifdef CONFIG_USB_GADGET_DUALSPEED ++ .speed = USB_SPEED_HIGH, ++#else ++ .speed = USB_SPEED_FULL, ++#endif ++ .function = (char *) longname, ++ .bind = zero_bind, ++ .unbind = zero_unbind, ++ ++ .setup = zero_setup, ++ .disconnect = zero_disconnect, ++ ++ .suspend = zero_suspend, ++ .resume = zero_resume, ++ ++ .driver = { ++ .name = (char *) shortname, ++ // .shutdown = ... ++ // .suspend = ... ++ // .resume = ... ++ }, ++}; ++ ++MODULE_AUTHOR ("David Brownell"); ++MODULE_LICENSE ("Dual BSD/GPL"); ++ ++static struct proc_dir_entry *pdir, *pfile; ++ ++static int isoc_read_data (char *page, char **start, ++ off_t off, int count, ++ int *eof, void *data) ++{ ++ int i; ++ static int c = 0; ++ static int done = 0; ++ static int s = 0; ++ ++/* ++ printk ("\ncount: %d\n", count); ++ printk ("rbuf_start: %d\n", rbuf_start); ++ printk ("rbuf_len: %d\n", rbuf_len); ++ printk ("off: %d\n", off); ++ printk ("start: %p\n\n", *start); ++*/ ++ if (done) { ++ c = 0; ++ done = 0; ++ *eof = 1; ++ return 0; ++ } ++ ++ if (c == 0) { ++ if (rbuf_len == RBUF_LEN) ++ s = rbuf_start; ++ else s = 0; ++ } ++ ++ for (i=0; i= rbuf_len) { ++ *eof = 1; ++ done = 1; ++ } ++ ++ ++ return i; ++} ++ ++static int __init init (void) ++{ ++ ++ int retval = 0; ++ ++ pdir = proc_mkdir("isoc_test", NULL); ++ if(pdir == NULL) { ++ retval = -ENOMEM; ++ printk("Error creating dir\n"); ++ goto done; ++ } ++ pdir->owner = THIS_MODULE; ++ ++ pfile = create_proc_read_entry("isoc_data", ++ 0444, pdir, ++ isoc_read_data, ++ NULL); ++ if (pfile == NULL) { ++ retval = -ENOMEM; ++ printk("Error creating file\n"); ++ goto no_file; ++ } ++ pfile->owner = THIS_MODULE; ++ ++ return usb_gadget_register_driver (&zero_driver); ++ ++ no_file: ++ remove_proc_entry("isoc_data", NULL); ++ done: ++ return retval; ++} ++module_init (init); ++ ++static void __exit cleanup (void) ++{ ++ ++ usb_gadget_unregister_driver (&zero_driver); ++ ++ remove_proc_entry("isoc_data", pdir); ++ remove_proc_entry("isoc_test", NULL); ++} ++module_exit (cleanup); +diff --git a/drivers/usb/host/dwc_otg/dwc_cfi_common.h b/drivers/usb/host/dwc_otg/dwc_cfi_common.h +new file mode 100644 +index 0000000..be56af4 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h +@@ -0,0 +1,142 @@ ++/* ========================================================================== ++ * 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_CFI_COMMON_H__) ++#define __DWC_CFI_COMMON_H__ ++ ++//#include ++ ++/** ++ * @file ++ * ++ * This file contains the CFI specific common constants, interfaces ++ * (functions and macros) and structures for Linux. No PCD specific ++ * data structure or definition is to be included in this file. ++ * ++ */ ++ ++/** This is a request for all Core Features */ ++#define VEN_CORE_GET_FEATURES 0xB1 ++ ++/** This is a request to get the value of a specific Core Feature */ ++#define VEN_CORE_GET_FEATURE 0xB2 ++ ++/** This command allows the host to set the value of a specific Core Feature */ ++#define VEN_CORE_SET_FEATURE 0xB3 ++ ++/** This command allows the host to set the default values of ++ * either all or any specific Core Feature ++ */ ++#define VEN_CORE_RESET_FEATURES 0xB4 ++ ++/** This command forces the PCD to write the deferred values of a Core Features */ ++#define VEN_CORE_ACTIVATE_FEATURES 0xB5 ++ ++/** This request reads a DWORD value from a register at the specified offset */ ++#define VEN_CORE_READ_REGISTER 0xB6 ++ ++/** This request writes a DWORD value into a register at the specified offset */ ++#define VEN_CORE_WRITE_REGISTER 0xB7 ++ ++/** This structure is the header of the Core Features dataset returned to ++ * the Host ++ */ ++struct cfi_all_features_header { ++/** The features header structure length is */ ++#define CFI_ALL_FEATURES_HDR_LEN 8 ++ /** ++ * The total length of the features dataset returned to the Host ++ */ ++ uint16_t wTotalLen; ++ ++ /** ++ * CFI version number inBinary-Coded Decimal (i.e., 1.00 is 100H). ++ * This field identifies the version of the CFI Specification with which ++ * the device is compliant. ++ */ ++ uint16_t wVersion; ++ ++ /** The ID of the Core */ ++ uint16_t wCoreID; ++#define CFI_CORE_ID_UDC 1 ++#define CFI_CORE_ID_OTG 2 ++#define CFI_CORE_ID_WUDEV 3 ++ ++ /** Number of features returned by VEN_CORE_GET_FEATURES request */ ++ uint16_t wNumFeatures; ++} UPACKED; ++ ++typedef struct cfi_all_features_header cfi_all_features_header_t; ++ ++/** This structure is a header of the Core Feature descriptor dataset returned to ++ * the Host after the VEN_CORE_GET_FEATURES request ++ */ ++struct cfi_feature_desc_header { ++#define CFI_FEATURE_DESC_HDR_LEN 8 ++ ++ /** The feature ID */ ++ uint16_t wFeatureID; ++ ++ /** Length of this feature descriptor in bytes - including the ++ * length of the feature name string ++ */ ++ uint16_t wLength; ++ ++ /** The data length of this feature in bytes */ ++ uint16_t wDataLength; ++ ++ /** ++ * Attributes of this features ++ * D0: Access rights ++ * 0 - Read/Write ++ * 1 - Read only ++ */ ++ uint8_t bmAttributes; ++#define CFI_FEATURE_ATTR_RO 1 ++#define CFI_FEATURE_ATTR_RW 0 ++ ++ /** Length of the feature name in bytes */ ++ uint8_t bNameLen; ++ ++ /** The feature name buffer */ ++ //uint8_t *name; ++} UPACKED; ++ ++typedef struct cfi_feature_desc_header cfi_feature_desc_header_t; ++ ++/** ++ * This structure describes a NULL terminated string referenced by its id field. ++ * It is very similar to usb_string structure but has the id field type set to 16-bit. ++ */ ++struct cfi_string { ++ uint16_t id; ++ const uint8_t *s; ++}; ++typedef struct cfi_string cfi_string_t; ++ ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.c b/drivers/usb/host/dwc_otg/dwc_otg_adp.c +new file mode 100644 +index 0000000..0877472 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.c +@@ -0,0 +1,854 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $ ++ * $Revision: #12 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ ++ * ++ * 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. ++ * ========================================================================== */ ++ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_adp.h" ++ ++/** @file ++ * ++ * This file contains the most of the Attach Detect Protocol implementation for ++ * the driver to support OTG Rev2.0. ++ * ++ */ ++ ++void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = value; ++ adpctl.b.ar = 0x2; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++} ++ ++/** ++ * Function is called to read ADP registers ++ */ ++uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = 0; ++ adpctl.b.ar = 0x1; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to read ADPCTL register and filter Write-clear bits ++ */ ++uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 0; ++ adpctl.b.adp_prb_int = 0; ++ adpctl.b.adp_tmout_int = 0; ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to write ADP registers ++ */ ++void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr, ++ uint32_t set) ++{ ++ dwc_otg_adp_write_reg(core_if, ++ (dwc_otg_adp_read_reg(core_if) & (~clr)) | set); ++} ++ ++static void adp_sense_timeout(void *ptr) ++{ ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ core_if->adp.sense_timer_started = 0; ++ DWC_PRINTF("ADP SENSE TIMEOUT\n"); ++ if (core_if->adp_enable) { ++ dwc_otg_adp_sense_stop(core_if); ++ dwc_otg_adp_probe_start(core_if); ++ } ++} ++ ++/** ++ * This function is called when the ADP vbus timer expires. Timeout is 1.1s. ++ */ ++static void adp_vbuson_timeout(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__); ++ if (core_if) { ++ core_if->adp.vbuson_timer_started = 0; ++ /* Turn off vbus */ ++ hprt0.b.prtpwr = 1; ++ DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0); ++ gpwrdn.d32 = 0; ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ /* Enable Wakeup Logic */ ++// gpwrdn.b.wkupactiv = 1; ++ gpwrdn.b.pmuactv = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ /* Suspend the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ /* Switch on VDD */ ++// gpwrdn.b.wkupactiv = 1; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pwrdnrstn = 1; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ } else { ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_otg_adp_probe_start(core_if); ++ dwc_otg_dump_global_registers(core_if); ++ dwc_otg_dump_host_registers(core_if); ++ } ++ ++} ++ ++/** ++ * Start the ADP Initial Probe timer to detect if Port Connected interrupt is ++ * not asserted within 1.1 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.vbuson_timer_started = 1; ++ if (core_if->adp.vbuson_timer) ++ { ++ DWC_PRINTF("SCHEDULING VBUSON TIMER\n"); ++ /* 1.1 secs + 60ms necessary for cil_hcd_start*/ ++ DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160); ++ } else { ++ DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer); ++ } ++} ++ ++#if 0 ++/** ++ * Masks all DWC OTG core interrupts ++ * ++ */ ++static void mask_all_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ++ /* Mask Host Interrupts */ ++ ++ /* Clear and disable HCINTs */ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0); ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF); ++ ++ } ++ ++ /* Clear and disable HAINT */ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000); ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF); ++ ++ /* Mask Device Interrupts */ ++ if (!core_if->multiproc_int_enable) { ++ /* Clear and disable IN Endpoint interrupts */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepint, 0xFFFFFFFF); ++ } ++ ++ /* Clear and disable OUT Endpoint interrupts */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0); ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> ++ doepint, 0xFFFFFFFF); ++ } ++ ++ /* Clear and disable DAINT */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint, ++ 0xFFFFFFFF); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0); ++ } else { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[i], 0); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepint, 0xFFFFFFFF); ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[i], 0); ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> ++ doepint, 0xFFFFFFFF); ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ 0); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint, ++ 0xFFFFFFFF); ++ ++ } ++ ++ /* Disable interrupts */ ++ ahbcfg.b.glblintrmsk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Clear any pending OTG Interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF); ++} ++ ++/** ++ * Unmask Port Connection Detected interrupt ++ * ++ */ ++static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 }; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++} ++#endif ++ ++/** ++ * Starts the ADP Probing ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl = {.d32 = 0}; ++ gpwrdn_data_t gpwrdn; ++#if 0 ++ adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1, ++ .b.adp_sns_int = 1, b.adp_tmout_int}; ++#endif ++ dwc_otg_disable_global_interrupts(core_if); ++ DWC_PRINTF("ADP Probe Start\n"); ++ core_if->adp.probe_enabled = 1; ++ ++ adpctl.b.adpres = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ } ++ ++ adpctl.d32 = 0; ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* In Host mode unmask SRP detected interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.sts_chngint_msk = 1; ++ if (!gpwrdn.b.idsts) { ++ gpwrdn.b.srp_det_msk = 1; ++ } ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ adpctl.b.adp_tmout_int_msk = 1; ++ adpctl.b.adp_prb_int_msk = 1; ++ adpctl.b.prb_dschg = 1; ++ adpctl.b.prb_delta = 1; ++ adpctl.b.prb_per = 1; ++ adpctl.b.adpen = 1; ++ adpctl.b.enaprb = 1; ++ ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ DWC_PRINTF("ADP Probe Finish\n"); ++ return 0; ++} ++ ++/** ++ * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted ++ * within 3 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.sense_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ ); ++} ++ ++/** ++ * Starts the ADP Sense ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ DWC_PRINTF("ADP Sense Start\n"); ++ ++ /* Unmask ADP sense interrupt and mask all other from the core */ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adp_sns_int_msk = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ dwc_otg_disable_global_interrupts(core_if); // vahrama ++ ++ /* Set ADP reset bit*/ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adpres = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ } ++ ++ adpctl.b.adpres = 0; ++ adpctl.b.adpen = 1; ++ adpctl.b.enasns = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ dwc_otg_adp_sense_timer_start(core_if); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Probing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl; ++ DWC_PRINTF("Stop ADP probe\n"); ++ core_if->adp.probe_enabled = 0; ++ core_if->adp.probe_counter = 0; ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ ++ adpctl.b.adpen = 0; ++ adpctl.b.adp_prb_int = 1; ++ adpctl.b.adp_tmout_int = 1; ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Sensing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ core_if->adp.sense_enabled = 0; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.enasns = 0; ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Called to turn on the VBUS after initial ADP probe in host mode. ++ * If port power was already enabled in cil_hcd_start function then ++ * only schedule a timer. ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr); ++ ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ ++ dwc_otg_adp_vbuson_timer_start(core_if); ++} ++ ++/** ++ * Called right after driver is loaded ++ * to perform initial actions for ADP ++ * ++ * @param core_if the pointer to core_if structure. ++ * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN ++ */ ++void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host) ++{ ++ gpwrdn_data_t gpwrdn; ++ ++ DWC_PRINTF("ADP Initial Start\n"); ++ core_if->adp.adp_started = 1; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ dwc_otg_disable_global_interrupts(core_if); ++ if (is_host) { ++ DWC_PRINTF("HOST MODE\n"); ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ /* Initialize first ADP probe to obtain Ramp Time value */ ++ core_if->adp.initial_probe = 1; ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_PRINTF("DEVICE MODE\n"); ++ if (gotgctl.b.bsesvld == 0) { ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ DWC_PRINTF("VBUS is not valid - start ADP probe\n"); ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ core_if->adp.initial_probe = 1; ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ DWC_PRINTF("VBUS is valid - initialize core as a Device\n"); ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ dwc_otg_dump_global_registers(core_if); ++ dwc_otg_dump_dev_registers(core_if); ++ } ++ } ++} ++ ++void dwc_otg_adp_init(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.adp_started = 0; ++ core_if->adp.initial_probe = 0; ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.probe_enabled = 0; ++ core_if->adp.sense_enabled = 0; ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ core_if->adp.attached = DWC_OTG_ADP_UNKOWN; ++ /* Initialize timers */ ++ core_if->adp.sense_timer = ++ DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if); ++ core_if->adp.vbuson_timer = ++ DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if); ++ if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer) ++ { ++ DWC_ERROR("Could not allocate memory for ADP timers\n"); ++ } ++} ++ ++void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (core_if->adp.probe_enabled) ++ dwc_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ dwc_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ DWC_TIMER_FREE(core_if->adp.sense_timer); ++ DWC_TIMER_FREE(core_if->adp.vbuson_timer); ++} ++ ++///////////////////////////////////////////////////////////////////// ++////////////// ADP Interrupt Handlers /////////////////////////////// ++///////////////////////////////////////////////////////////////////// ++/** ++ * This function sets Ramp Timer values ++ */ ++static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ if (core_if->adp.probe_timer_values[0] == -1) { ++ core_if->adp.probe_timer_values[0] = val; ++ core_if->adp.probe_timer_values[1] = -1; ++ return 1; ++ } else { ++ core_if->adp.probe_timer_values[1] = ++ core_if->adp.probe_timer_values[0]; ++ core_if->adp.probe_timer_values[0] = val; ++ return 0; ++ } ++} ++ ++/** ++ * This function compares Ramp Timer values ++ */ ++static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t diff; ++ if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1]) ++ diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1]; ++ else ++ diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0]; ++ if(diff < 2) { ++ return 0; ++ } else { ++ return 1; ++ } ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn, temp; ++ adpctl.d32 = val; ++ ++ temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ core_if->adp.probe_counter++; ++ core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (adpctl.b.rtim == 0 && !temp.b.idsts){ ++ DWC_PRINTF("RTIM value is 0\n"); ++ goto exit; ++ } ++ if (set_timer_value(core_if, adpctl.b.rtim) && ++ core_if->adp.initial_probe) { ++ core_if->adp.initial_probe = 0; ++ dwc_otg_adp_probe_stop(core_if); ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* ++ * Turn on VBUS after initial ADP probe. ++ */ ++ core_if->op_state = A_HOST; ++ dwc_otg_enable_global_interrupts(core_if); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_start(core_if); ++ dwc_otg_adp_turnon_vbus(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ } else { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ dwc_otg_enable_global_interrupts(core_if); ++ dwc_otg_initiate_srp(core_if); ++ } ++ } else if (core_if->adp.probe_counter > 2){ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (compare_timer_values(core_if)) { ++ DWC_PRINTF("Difference in timer values !!! \n"); ++// core_if->adp.attached = DWC_OTG_ADP_ATTACHED; ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* Disable Interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (!gotgctl.b.bsesvld) { ++ dwc_otg_initiate_srp(core_if); ++ } ++ } ++ } ++ if (core_if->power_down == 2) { ++ if (gpwrdn.b.bsessvld) { ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++ } ++exit: ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_prb_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function hadles ADP Sense Interrupt ++ */ ++static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ /* Stop ADP Sense timer */ ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ ++ /* Restart ADP Sense timer */ ++ dwc_otg_adp_sense_timer_start(core_if); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ adpctl.d32 = val; ++ set_timer_value(core_if, adpctl.b.rtim); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * ADP Interrupt handler. ++ * ++ */ ++int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ adpctl_data_t adpctl = {.d32 = 0}; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32); ++ ++ if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) { ++ DWC_PRINTF("ADP Sense interrupt\n"); ++ retval |= dwc_otg_adp_handle_sns_intr(core_if); ++ } ++ if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) { ++ DWC_PRINTF("ADP timeout interrupt\n"); ++ retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32); ++ } ++ if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) { ++ DWC_PRINTF("ADP Probe interrupt\n"); ++ adpctl.b.adp_prb_int = 1; ++ retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32); ++ } ++ ++// dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0); ++ //dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ DWC_PRINTF("RETURN FROM ADP ISR\n"); ++ ++ return retval; ++} ++ ++/** ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if) ++{ ++ ++#ifndef DWC_HOST_ONLY ++ hprt0_data_t hprt0; ++ gpwrdn_data_t gpwrdn; ++ DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n"); ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /* check which value is for device mode and which for Host mode */ ++ if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */ ++ DWC_PRINTF("SRP: Host mode\n"); ++ ++ if (core_if->adp_enable) { ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } else { ++ DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__); ++ if (core_if->adp_enable) { ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 0; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++#endif ++ return 1; ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.h b/drivers/usb/host/dwc_otg/dwc_otg_adp.h +new file mode 100644 +index 0000000..d8c3f85 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.h +@@ -0,0 +1,80 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $ ++ * $Revision: #7 $ ++ * $Date: 2011/10/24 $ ++ * $Change: 1871159 $ ++ * ++ * 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_ADP_H__ ++#define __DWC_OTG_ADP_H__ ++ ++/** ++ * @file ++ * ++ * This file contains the Attach Detect Protocol interfaces and defines ++ * (functions) and structures for Linux. ++ * ++ */ ++ ++#define DWC_OTG_ADP_UNATTACHED 0 ++#define DWC_OTG_ADP_ATTACHED 1 ++#define DWC_OTG_ADP_UNKOWN 2 ++ ++typedef struct dwc_otg_adp { ++ uint32_t adp_started; ++ uint32_t initial_probe; ++ int32_t probe_timer_values[2]; ++ uint32_t probe_enabled; ++ uint32_t sense_enabled; ++ dwc_timer_t *sense_timer; ++ uint32_t sense_timer_started; ++ dwc_timer_t *vbuson_timer; ++ uint32_t vbuson_timer_started; ++ uint32_t attached; ++ uint32_t probe_counter; ++ uint32_t gpwrdn; ++} dwc_otg_adp_t; ++ ++/** ++ * Attach Detect Protocol functions ++ */ ++ ++extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value); ++extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); ++extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if); ++extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if); ++extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if); ++ ++#endif //__DWC_OTG_ADP_H__ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c +new file mode 100644 +index 0000000..95eb7f8 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c +@@ -0,0 +1,1210 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $ ++ * $Revision: #44 $ ++ * $Date: 2010/11/29 $ ++ * $Change: 1636033 $ ++ * ++ * 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. The Linux driver attributes ++ * feature will be used to provide the Linux Diagnostic ++ * Interface. These attributes are accessed through sysfs. ++ */ ++ ++/** @page "Linux Module Attributes" ++ * ++ * The Linux module attributes feature is used to provide the Linux ++ * Diagnostic Interface. These attributes are accessed through sysfs. ++ * The diagnostic interface will provide access to the controller for ++ * bringing up the hardware and testing. ++ ++ The following table shows the attributes. ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
Name Description Access
mode Returns the current mode: 0 for device mode, 1 for host mode Read
hnpcapable Gets or sets the "HNP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value. Read/Write
srpcapable Gets or sets the "SRP-capable" bit in the Core USB Configuraton Register. ++ Read returns the current value. Read/Write
hsic_connect Gets or sets the "HSIC-Connect" bit in the GLPMCFG Register. ++ Read returns the current value. Read/Write
inv_sel_hsic Gets or sets the "Invert Select HSIC" bit in the GLPMFG Register. ++ Read returns the current value. Read/Write
hnp Initiates the Host Negotiation Protocol. Read returns the status. Read/Write
srp Initiates the Session Request Protocol. Read returns the status. Read/Write
buspower Gets or sets the Power State of the bus (0 - Off or 1 - On) Read/Write
bussuspend Suspends the USB bus. Read/Write
busconnected Gets the connection status of the bus Read
gotgctl Gets or sets the Core Control Status Register. Read/Write
gusbcfg Gets or sets the Core USB Configuration Register Read/Write
grxfsiz Gets or sets the Receive FIFO Size Register Read/Write
gnptxfsiz Gets or sets the non-periodic Transmit Size Register Read/Write
gpvndctl Gets or sets the PHY Vendor Control Register Read/Write
ggpio Gets the value in the lower 16-bits of the General Purpose IO Register ++ or sets the upper 16 bits. Read/Write
guid Gets or sets the value of the User ID Register Read/Write
gsnpsid Gets the value of the Synopsys ID Regester Read
devspeed Gets or sets the device speed setting in the DCFG register Read/Write
enumspeed Gets the device enumeration Speed. Read
hptxfsiz Gets the value of the Host Periodic Transmit FIFO Read
hprt0 Gets or sets the value in the Host Port Control and Status Register Read/Write
regoffset Sets the register offset for the next Register Access Read/Write
regvalue Gets or sets the value of the register at the offset in the regoffset attribute. Read/Write
remote_wakeup On read, shows the status of Remote Wakeup. On write, initiates a remote ++ wakeup of the host. When bit 0 is 1 and Remote Wakeup is enabled, the Remote ++ Wakeup signalling bit in the Device Control Register is set for 1 ++ milli-second. Read/Write
rem_wakeup_pwrdn On read, shows the status core - hibernated or not. On write, initiates ++ a remote wakeup of the device from Hibernation. Read/Write
mode_ch_tim_en This bit is used to enable or disable the host core to wait for 200 PHY ++ clock cycles at the end of Resume to change the opmode signal to the PHY to 00 ++ after Suspend or LPM. Read/Write
fr_interval On read, shows the value of HFIR Frame Interval. On write, dynamically ++ reload HFIR register during runtime. The application can write a value to this ++ register only after the Port Enable bit of the Host Port Control and Status ++ register (HPRT.PrtEnaPort) has been set Read/Write
disconnect_us On read, shows the status of disconnect_device_us. On write, sets disconnect_us ++ which causes soft disconnect for 100us. Applicable only for device mode of operation. Read/Write
regdump Dumps the contents of core registers. Read
spramdump Dumps the contents of core registers. Read
hcddump Dumps the current HCD state. Read
hcd_frrem Shows the average value of the Frame Remaining ++ field in the Host Frame Number/Frame Remaining register when an SOF interrupt ++ occurs. This can be used to determine the average interrupt latency. Also ++ shows the average Frame Remaining value for start_transfer and the "a" and ++ "b" sample points. The "a" and "b" sample points may be used during debugging ++ bto determine how long it takes to execute a section of the HCD code. Read
rd_reg_test Displays the time required to read the GNPTXFSIZ register many times ++ (the output shows the number of times the register is read). ++ Read
wr_reg_test Displays the time required to write the GNPTXFSIZ register many times ++ (the output shows the number of times the register is written). ++ Read
lpm_response Gets or sets lpm_response mode. Applicable only in device mode. ++ Write
sleep_status Shows sleep status of device. ++ Read
++ ++ Example usage: ++ To get the current mode: ++ cat /sys/devices/lm0/mode ++ ++ To power down the USB: ++ echo 0 > /sys/devices/lm0/buspower ++ */ ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_os.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_attr.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_hcd_if.h" ++ ++/* ++ * MACROs for defining sysfs attribute ++ */ ++#ifdef LM_INTERFACE ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ ++ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ ++ uint32_t val; \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ ++ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ ++ uint32_t set = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ ++ return count; \ ++} ++ ++#elif defined(PCI_INTERFACE) ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ ++ uint32_t val; \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ ++ uint32_t set = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ ++ return count; \ ++} ++ ++#elif defined(PLATFORM_INTERFACE) ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct platform_device *platform_dev = \ ++ container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \ ++ uint32_t val; \ ++ DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \ ++ __func__, _dev, platform_dev, otg_dev); \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \ ++ uint32_t set = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_(otg_dev->core_if, set);\ ++ return count; \ ++} ++#endif ++ ++/* ++ * MACROs for defining sysfs attribute for 32-bit registers ++ */ ++#ifdef LM_INTERFACE ++#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ ++ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ ++ uint32_t val; \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); \ ++ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); \ ++ uint32_t val = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ ++ return count; \ ++} ++#elif defined(PCI_INTERFACE) ++#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ ++ uint32_t val; \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); \ ++ uint32_t val = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ ++ return count; \ ++} ++ ++#elif defined(PLATFORM_INTERFACE) ++#include "dwc_otg_dbg.h" ++#define DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_show (struct device *_dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \ ++ uint32_t val; \ ++ DWC_PRINTF("%s(%p) -> platform_dev %p, otg_dev %p\n", \ ++ __func__, _dev, platform_dev, otg_dev); \ ++ val = dwc_otg_get_##_otg_attr_name_ (otg_dev->core_if); \ ++ return sprintf (buf, "%s = 0x%08x\n", _string_, val); \ ++} ++#define DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++static ssize_t _otg_attr_name_##_store (struct device *_dev, struct device_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ struct platform_device *platform_dev = container_of(_dev, struct platform_device, dev); \ ++ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); \ ++ uint32_t val = simple_strtoul(buf, NULL, 16); \ ++ dwc_otg_set_##_otg_attr_name_ (otg_dev->core_if, val); \ ++ return count; \ ++} ++ ++#endif ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_STORE(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); ++ ++#define DWC_OTG_DEVICE_ATTR_BITFIELD_RO(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); ++ ++#define DWC_OTG_DEVICE_ATTR_REG32_RW(_otg_attr_name_,_addr_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_STORE(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0644,_otg_attr_name_##_show,_otg_attr_name_##_store); ++ ++#define DWC_OTG_DEVICE_ATTR_REG32_RO(_otg_attr_name_,_addr_,_string_) \ ++DWC_OTG_DEVICE_ATTR_REG_SHOW(_otg_attr_name_,_string_) \ ++DEVICE_ATTR(_otg_attr_name_,0444,_otg_attr_name_##_show,NULL); ++ ++/** @name Functions for Show/Store of Attributes */ ++/**@{*/ ++ ++/** ++ * Helper function returning the otg_device structure of the given device ++ */ ++static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev) ++{ ++ dwc_otg_device_t *otg_dev; ++ DWC_OTG_GETDRVDEV(otg_dev, _dev); ++ return otg_dev; ++} ++ ++/** ++ * Show the register offset of the Register Access. ++ */ ++static ssize_t regoffset_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", ++ otg_dev->os_dep.reg_offset); ++} ++ ++/** ++ * Set the register offset for the next Register Access Read/Write ++ */ ++static ssize_t regoffset_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t offset = simple_strtoul(buf, NULL, 16); ++#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE) ++ if (offset < SZ_256K) { ++#elif defined(PCI_INTERFACE) ++ if (offset < 0x00040000) { ++#endif ++ otg_dev->os_dep.reg_offset = offset; ++ } else { ++ dev_err(_dev, "invalid offset\n"); ++ } ++ ++ return count; ++} ++ ++DEVICE_ATTR(regoffset, S_IRUGO | S_IWUSR, regoffset_show, regoffset_store); ++ ++/** ++ * Show the value of the register at the offset in the reg_offset ++ * attribute. ++ */ ++static ssize_t regvalue_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t val; ++ volatile uint32_t *addr; ++ ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ val = DWC_READ_REG32(addr); ++ return snprintf(buf, ++ sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, ++ "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset, ++ val); ++ } else { ++ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset); ++ return sprintf(buf, "invalid offset\n"); ++ } ++} ++ ++/** ++ * Store the value in the register at the offset in the reg_offset ++ * attribute. ++ * ++ */ ++static ssize_t regvalue_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ volatile uint32_t *addr; ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val); ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { ++ /* Calculate the address */ ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ DWC_WRITE_REG32(addr, val); ++ } else { ++ dev_err(_dev, "Invalid Register Offset (0x%08x)\n", ++ otg_dev->os_dep.reg_offset); ++ } ++ return count; ++} ++ ++DEVICE_ATTR(regvalue, S_IRUGO | S_IWUSR, regvalue_show, regvalue_store); ++ ++/* ++ * Attributes ++ */ ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC"); ++ ++//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(buspower,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); ++//DWC_OTG_DEVICE_ATTR_BITFIELD_RW(bussuspend,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<8),8,"Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(busconnected, "Bus Connected"); ++ ++DWC_OTG_DEVICE_ATTR_REG32_RW(gotgctl, 0, "GOTGCTL"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gusbcfg, ++ &(otg_dev->core_if->core_global_regs->gusbcfg), ++ "GUSBCFG"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(grxfsiz, ++ &(otg_dev->core_if->core_global_regs->grxfsiz), ++ "GRXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gnptxfsiz, ++ &(otg_dev->core_if->core_global_regs->gnptxfsiz), ++ "GNPTXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(gpvndctl, ++ &(otg_dev->core_if->core_global_regs->gpvndctl), ++ "GPVNDCTL"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(ggpio, ++ &(otg_dev->core_if->core_global_regs->ggpio), ++ "GGPIO"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(guid, &(otg_dev->core_if->core_global_regs->guid), ++ "GUID"); ++DWC_OTG_DEVICE_ATTR_REG32_RO(gsnpsid, ++ &(otg_dev->core_if->core_global_regs->gsnpsid), ++ "GSNPSID"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(devspeed, "Device Speed"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RO(enumspeed, "Device Enumeration Speed"); ++ ++DWC_OTG_DEVICE_ATTR_REG32_RO(hptxfsiz, ++ &(otg_dev->core_if->core_global_regs->hptxfsiz), ++ "HPTXFSIZ"); ++DWC_OTG_DEVICE_ATTR_REG32_RW(hprt0, otg_dev->core_if->host_if->hprt0, "HPRT0"); ++ ++/** ++ * @todo Add code to initiate the HNP. ++ */ ++/** ++ * Show the HNP status bit ++ */ ++static ssize_t hnp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "HstNegScs = 0x%x\n", ++ dwc_otg_get_hnpstatus(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HNP Request bit ++ */ ++static ssize_t hnp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_hnpreq(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(hnp, 0644, hnp_show, hnp_store); ++ ++/** ++ * @todo Add code to initiate the SRP. ++ */ ++/** ++ * Show the SRP status bit ++ */ ++static ssize_t srp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "SesReqScs = 0x%x\n", ++ dwc_otg_get_srpstatus(otg_dev->core_if)); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif ++} ++ ++/** ++ * Set the SRP Request bit ++ */ ++static ssize_t srp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ dwc_otg_pcd_initiate_srp(otg_dev->pcd); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(srp, 0644, srp_show, srp_store); ++ ++/** ++ * @todo Need to do more for power on/off? ++ */ ++/** ++ * Show the Bus Power status ++ */ ++static ssize_t buspower_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "Bus Power = 0x%x\n", ++ dwc_otg_get_prtpower(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Bus Power status ++ */ ++static ssize_t buspower_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t on = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_prtpower(otg_dev->core_if, on); ++ return count; ++} ++ ++DEVICE_ATTR(buspower, 0644, buspower_show, buspower_store); ++ ++/** ++ * @todo Need to do more for suspend? ++ */ ++/** ++ * Show the Bus Suspend status ++ */ ++static ssize_t bussuspend_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "Bus Suspend = 0x%x\n", ++ dwc_otg_get_prtsuspend(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Bus Suspend status ++ */ ++static ssize_t bussuspend_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_prtsuspend(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); ++ ++/** ++ * Show the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n", ++ dwc_otg_get_mode_ch_tim(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_mode_ch_tim(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store); ++ ++/** ++ * Show the value of HFIR Frame Interval bitfield ++ */ ++static ssize_t fr_interval_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "Frame Interval = 0x%x\n", ++ dwc_otg_get_fr_interval(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HFIR Frame Interval value ++ */ ++static ssize_t fr_interval_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t in = simple_strtoul(buf, NULL, 10); ++ dwc_otg_set_fr_interval(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store); ++ ++/** ++ * Show the status of Remote Wakeup. ++ */ ++static ssize_t remote_wakeup_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ ++ return sprintf(buf, ++ "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n", ++ dwc_otg_get_remotewakesig(otg_dev->core_if), ++ dwc_otg_pcd_get_rmwkup_enable(otg_dev->pcd), ++ dwc_otg_get_lpm_remotewakeenabled(otg_dev->core_if)); ++#else ++ return sprintf(buf, "Host Only Mode!\n"); ++#endif /* DWC_HOST_ONLY */ ++} ++ ++/** ++ * Initiate a remote wakeup of the host. The Device control register ++ * Remote Wakeup Signal bit is written if the PCD Remote wakeup enable ++ * flag is set. ++ * ++ */ ++static ssize_t remote_wakeup_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (val & 1) { ++ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 1); ++ } else { ++ dwc_otg_pcd_remote_wakeup(otg_dev->pcd, 0); ++ } ++#endif /* DWC_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(remote_wakeup, S_IRUGO | S_IWUSR, remote_wakeup_show, ++ remote_wakeup_store); ++ ++/** ++ * Show the whether core is hibernated or not. ++ */ ++static ssize_t rem_wakeup_pwrdn_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ ++ if (dwc_otg_get_core_state(otg_dev->core_if)) { ++ DWC_PRINTF("Core is in hibernation\n"); ++ } else { ++ DWC_PRINTF("Core is not in hibernation\n"); ++ } ++#endif /* DWC_HOST_ONLY */ ++ return 0; ++} ++ ++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/** ++ * Initiate a remote wakeup of the device to exit from hibernation. ++ */ ++static ssize_t rem_wakeup_pwrdn_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show, ++ rem_wakeup_pwrdn_store); ++ ++static ssize_t disconnect_us(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ DWC_PRINTF("The Passed value is %04x\n", val); ++ ++ dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50); ++ ++#endif /* DWC_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t regdump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ ++ dwc_otg_dump_global_registers(otg_dev->core_if); ++ if (dwc_otg_is_host_mode(otg_dev->core_if)) { ++ dwc_otg_dump_host_registers(otg_dev->core_if); ++ } else { ++ dwc_otg_dump_dev_registers(otg_dev->core_if); ++ ++ } ++ return sprintf(buf, "Register Dump\n"); ++} ++ ++DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0); ++ ++/** ++ * Dump global registers and either host or device registers (depending on the ++ * current mode of the core). ++ */ ++static ssize_t spramdump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ ++ dwc_otg_dump_spram(otg_dev->core_if); ++ ++ return sprintf(buf, "SPRAM Dump\n"); ++} ++ ++DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0); ++ ++/** ++ * Dump the current hcd state. ++ */ ++static ssize_t hcddump_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_DEVICE_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ dwc_otg_hcd_dump_state(otg_dev->hcd); ++#endif /* DWC_DEVICE_ONLY */ ++ return sprintf(buf, "HCD Dump\n"); ++} ++ ++DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ */ ++static ssize_t hcd_frrem_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_DEVICE_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ ++ dwc_otg_hcd_dump_frrem(otg_dev->hcd); ++#endif /* DWC_DEVICE_ONLY */ ++ return sprintf(buf, "HCD Dump Frame Remaining\n"); ++} ++ ++DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0); ++ ++/** ++ * Displays the time required to read the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is read). ++ */ ++#define RW_REG_COUNT 10000000 ++#define MSEC_PER_JIFFIE 1000/HZ ++static ssize_t rd_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ int i; ++ int time; ++ int start_jiffies; ++ ++ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) { ++ dwc_otg_get_gnptxfsiz(otg_dev->core_if); ++ } ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to read GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0); ++ ++/** ++ * Displays the time required to write the GNPTXFSIZ register many times (the ++ * output shows the number of times the register is written). ++ */ ++static ssize_t wr_reg_test_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t reg_val; ++ int i; ++ int time; ++ int start_jiffies; ++ ++ printk("HZ %d, MSEC_PER_JIFFIE %d, loops_per_jiffy %lu\n", ++ HZ, MSEC_PER_JIFFIE, loops_per_jiffy); ++ reg_val = dwc_otg_get_gnptxfsiz(otg_dev->core_if); ++ start_jiffies = jiffies; ++ for (i = 0; i < RW_REG_COUNT; i++) { ++ dwc_otg_set_gnptxfsiz(otg_dev->core_if, reg_val); ++ } ++ time = jiffies - start_jiffies; ++ return sprintf(buf, ++ "Time to write GNPTXFSIZ reg %d times: %d msecs (%d jiffies)\n", ++ RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); ++} ++ ++DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0); ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ ++/** ++* Show the lpm_response attribute. ++*/ ++static ssize_t lpmresp_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) ++ return sprintf(buf, "** LPM is DISABLED **\n"); ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return sprintf(buf, "** Current mode is not device mode\n"); ++ } ++ return sprintf(buf, "lpm_response = %d\n", ++ dwc_otg_get_lpmresponse(otg_dev->core_if)); ++} ++ ++/** ++* Store the lpm_response attribute. ++*/ ++static ssize_t lpmresp_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ ++ if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ if (!dwc_otg_is_device_mode(otg_dev->core_if)) { ++ return 0; ++ } ++ ++ dwc_otg_set_lpmresponse(otg_dev->core_if, val); ++ return count; ++} ++ ++DEVICE_ATTR(lpm_response, S_IRUGO | S_IWUSR, lpmresp_show, lpmresp_store); ++ ++/** ++* Show the sleep_status attribute. ++*/ ++static ssize_t sleepstatus_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "Sleep Status = %d\n", ++ dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)); ++} ++ ++/** ++ * Store the sleep_status attribure. ++ */ ++static ssize_t sleepstatus_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) { ++ if (dwc_otg_is_host_mode(core_if)) { ++ ++ DWC_PRINTF("Host initiated resume\n"); ++ dwc_otg_set_prtresume(otg_dev->core_if, 1); ++ } ++ } ++ ++ return count; ++} ++ ++DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show, ++ sleepstatus_store); ++ ++#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */ ++ ++/**@}*/ ++ ++/** ++ * Create the device files ++ */ ++void dwc_otg_attr_create( ++#ifdef LM_INTERFACE ++ struct lm_device *dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *dev ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *dev ++#endif ++ ) ++{ ++ int error; ++ ++ error = device_create_file(&dev->dev, &dev_attr_regoffset); ++ error = device_create_file(&dev->dev, &dev_attr_regvalue); ++ error = device_create_file(&dev->dev, &dev_attr_mode); ++ error = device_create_file(&dev->dev, &dev_attr_hnpcapable); ++ error = device_create_file(&dev->dev, &dev_attr_srpcapable); ++ error = device_create_file(&dev->dev, &dev_attr_hsic_connect); ++ error = device_create_file(&dev->dev, &dev_attr_inv_sel_hsic); ++ error = device_create_file(&dev->dev, &dev_attr_hnp); ++ error = device_create_file(&dev->dev, &dev_attr_srp); ++ error = device_create_file(&dev->dev, &dev_attr_buspower); ++ error = device_create_file(&dev->dev, &dev_attr_bussuspend); ++ error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ error = device_create_file(&dev->dev, &dev_attr_fr_interval); ++ error = device_create_file(&dev->dev, &dev_attr_busconnected); ++ error = device_create_file(&dev->dev, &dev_attr_gotgctl); ++ error = device_create_file(&dev->dev, &dev_attr_gusbcfg); ++ error = device_create_file(&dev->dev, &dev_attr_grxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_gnptxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_gpvndctl); ++ error = device_create_file(&dev->dev, &dev_attr_ggpio); ++ error = device_create_file(&dev->dev, &dev_attr_guid); ++ error = device_create_file(&dev->dev, &dev_attr_gsnpsid); ++ error = device_create_file(&dev->dev, &dev_attr_devspeed); ++ error = device_create_file(&dev->dev, &dev_attr_enumspeed); ++ error = device_create_file(&dev->dev, &dev_attr_hptxfsiz); ++ error = device_create_file(&dev->dev, &dev_attr_hprt0); ++ error = device_create_file(&dev->dev, &dev_attr_remote_wakeup); ++ error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ error = device_create_file(&dev->dev, &dev_attr_disconnect_us); ++ error = device_create_file(&dev->dev, &dev_attr_regdump); ++ error = device_create_file(&dev->dev, &dev_attr_spramdump); ++ error = device_create_file(&dev->dev, &dev_attr_hcddump); ++ error = device_create_file(&dev->dev, &dev_attr_hcd_frrem); ++ error = device_create_file(&dev->dev, &dev_attr_rd_reg_test); ++ error = device_create_file(&dev->dev, &dev_attr_wr_reg_test); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ error = device_create_file(&dev->dev, &dev_attr_lpm_response); ++ error = device_create_file(&dev->dev, &dev_attr_sleep_status); ++#endif ++} ++ ++/** ++ * Remove the device files ++ */ ++void dwc_otg_attr_remove( ++#ifdef LM_INTERFACE ++ struct lm_device *dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *dev ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *dev ++#endif ++ ) ++{ ++ device_remove_file(&dev->dev, &dev_attr_regoffset); ++ device_remove_file(&dev->dev, &dev_attr_regvalue); ++ device_remove_file(&dev->dev, &dev_attr_mode); ++ device_remove_file(&dev->dev, &dev_attr_hnpcapable); ++ device_remove_file(&dev->dev, &dev_attr_srpcapable); ++ device_remove_file(&dev->dev, &dev_attr_hsic_connect); ++ device_remove_file(&dev->dev, &dev_attr_inv_sel_hsic); ++ device_remove_file(&dev->dev, &dev_attr_hnp); ++ device_remove_file(&dev->dev, &dev_attr_srp); ++ device_remove_file(&dev->dev, &dev_attr_buspower); ++ device_remove_file(&dev->dev, &dev_attr_bussuspend); ++ device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ device_remove_file(&dev->dev, &dev_attr_fr_interval); ++ device_remove_file(&dev->dev, &dev_attr_busconnected); ++ device_remove_file(&dev->dev, &dev_attr_gotgctl); ++ device_remove_file(&dev->dev, &dev_attr_gusbcfg); ++ device_remove_file(&dev->dev, &dev_attr_grxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_gnptxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_gpvndctl); ++ device_remove_file(&dev->dev, &dev_attr_ggpio); ++ device_remove_file(&dev->dev, &dev_attr_guid); ++ device_remove_file(&dev->dev, &dev_attr_gsnpsid); ++ device_remove_file(&dev->dev, &dev_attr_devspeed); ++ device_remove_file(&dev->dev, &dev_attr_enumspeed); ++ device_remove_file(&dev->dev, &dev_attr_hptxfsiz); ++ device_remove_file(&dev->dev, &dev_attr_hprt0); ++ device_remove_file(&dev->dev, &dev_attr_remote_wakeup); ++ device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ device_remove_file(&dev->dev, &dev_attr_disconnect_us); ++ device_remove_file(&dev->dev, &dev_attr_regdump); ++ device_remove_file(&dev->dev, &dev_attr_spramdump); ++ device_remove_file(&dev->dev, &dev_attr_hcddump); ++ device_remove_file(&dev->dev, &dev_attr_hcd_frrem); ++ device_remove_file(&dev->dev, &dev_attr_rd_reg_test); ++ device_remove_file(&dev->dev, &dev_attr_wr_reg_test); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ device_remove_file(&dev->dev, &dev_attr_lpm_response); ++ device_remove_file(&dev->dev, &dev_attr_sleep_status); ++#endif ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h +new file mode 100644 +index 0000000..fc14d94 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h +@@ -0,0 +1,89 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $ ++ * $Revision: #13 $ ++ * $Date: 2010/06/21 $ ++ * $Change: 1532021 $ ++ * ++ * 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_OTG_ATTR_H__) ++#define __DWC_OTG_ATTR_H__ ++ ++/** @file ++ * This file contains the interface to the Linux device attributes. ++ */ ++extern struct device_attribute dev_attr_regoffset; ++extern struct device_attribute dev_attr_regvalue; ++ ++extern struct device_attribute dev_attr_mode; ++extern struct device_attribute dev_attr_hnpcapable; ++extern struct device_attribute dev_attr_srpcapable; ++extern struct device_attribute dev_attr_hnp; ++extern struct device_attribute dev_attr_srp; ++extern struct device_attribute dev_attr_buspower; ++extern struct device_attribute dev_attr_bussuspend; ++extern struct device_attribute dev_attr_mode_ch_tim_en; ++extern struct device_attribute dev_attr_fr_interval; ++extern struct device_attribute dev_attr_busconnected; ++extern struct device_attribute dev_attr_gotgctl; ++extern struct device_attribute dev_attr_gusbcfg; ++extern struct device_attribute dev_attr_grxfsiz; ++extern struct device_attribute dev_attr_gnptxfsiz; ++extern struct device_attribute dev_attr_gpvndctl; ++extern struct device_attribute dev_attr_ggpio; ++extern struct device_attribute dev_attr_guid; ++extern struct device_attribute dev_attr_gsnpsid; ++extern struct device_attribute dev_attr_devspeed; ++extern struct device_attribute dev_attr_enumspeed; ++extern struct device_attribute dev_attr_hptxfsiz; ++extern struct device_attribute dev_attr_hprt0; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++extern struct device_attribute dev_attr_lpm_response; ++extern struct device_attribute devi_attr_sleep_status; ++#endif ++ ++void dwc_otg_attr_create( ++#ifdef LM_INTERFACE ++ struct lm_device *dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *dev ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *dev ++#endif ++ ); ++ ++void dwc_otg_attr_remove( ++#ifdef LM_INTERFACE ++ struct lm_device *dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *dev ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *dev ++#endif ++ ); ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.c b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c +new file mode 100644 +index 0000000..a9878d6 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c +@@ -0,0 +1,1876 @@ ++/* ========================================================================== ++ * 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * This file contains the most of the CFI(Core Feature Interface) ++ * implementation for the OTG. ++ */ ++ ++#ifdef DWC_UTE_CFI ++ ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_cfi.h" ++ ++/** This definition should actually migrate to the Portability Library */ ++#define DWC_CONSTANT_CPU_TO_LE16(x) (x) ++ ++extern dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex); ++ ++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen); ++static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, ++ struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req); ++static int cfi_set_feature_value(struct dwc_otg_pcd *pcd); ++static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static int cfi_preproc_reset(struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req); ++static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep); ++ ++static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if); ++static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue); ++static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue); ++ ++static uint8_t resize_fifos(dwc_otg_core_if_t * core_if); ++ ++/** This is the header of the all features descriptor */ ++static cfi_all_features_header_t all_props_desc_header = { ++ .wVersion = DWC_CONSTANT_CPU_TO_LE16(0x100), ++ .wCoreID = DWC_CONSTANT_CPU_TO_LE16(CFI_CORE_ID_OTG), ++ .wNumFeatures = DWC_CONSTANT_CPU_TO_LE16(9), ++}; ++ ++/** This is an array of statically allocated feature descriptors */ ++static cfi_feature_desc_header_t prop_descs[] = { ++ ++ /* FT_ID_DMA_MODE */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_MODE), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(1), ++ }, ++ ++ /* FT_ID_DMA_BUFFER_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFFER_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DMA_BUFF_ALIGN */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_BUFF_ALIGN), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_DMA_CONCAT_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CONCAT_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ //.wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DMA_CIRCULAR */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DMA_CIRCULAR), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_THRESHOLD_SETUP */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_THRESHOLD_SETUP), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(6), ++ }, ++ ++ /* FT_ID_DFIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_DFIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RO, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_TX_FIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_TX_FIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ }, ++ ++ /* FT_ID_RX_FIFO_DEPTH */ ++ { ++ .wFeatureID = DWC_CONSTANT_CPU_TO_LE16(FT_ID_RX_FIFO_DEPTH), ++ .bmAttributes = CFI_FEATURE_ATTR_RW, ++ .wDataLength = DWC_CONSTANT_CPU_TO_LE16(2), ++ } ++}; ++ ++/** The table of feature names */ ++cfi_string_t prop_name_table[] = { ++ {FT_ID_DMA_MODE, "dma_mode"}, ++ {FT_ID_DMA_BUFFER_SETUP, "buffer_setup"}, ++ {FT_ID_DMA_BUFF_ALIGN, "buffer_align"}, ++ {FT_ID_DMA_CONCAT_SETUP, "concat_setup"}, ++ {FT_ID_DMA_CIRCULAR, "buffer_circular"}, ++ {FT_ID_THRESHOLD_SETUP, "threshold_setup"}, ++ {FT_ID_DFIFO_DEPTH, "dfifo_depth"}, ++ {FT_ID_TX_FIFO_DEPTH, "txfifo_depth"}, ++ {FT_ID_RX_FIFO_DEPTH, "rxfifo_depth"}, ++ {} ++}; ++ ++/************************************************************************/ ++ ++/** ++ * Returns the name of the feature by its ID ++ * or NULL if no featute ID matches. ++ * ++ */ ++const uint8_t *get_prop_name(uint16_t prop_id, int *len) ++{ ++ cfi_string_t *pstr; ++ *len = 0; ++ ++ for (pstr = prop_name_table; pstr && pstr->s; pstr++) { ++ if (pstr->id == prop_id) { ++ *len = DWC_STRLEN(pstr->s); ++ return pstr->s; ++ } ++ } ++ return NULL; ++} ++ ++/** ++ * This function handles all CFI specific control requests. ++ * ++ * Return a negative value to stall the DCE. ++ */ ++int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl) ++{ ++ int retval = 0; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ cfiobject_t *cfi = pcd->cfi; ++ struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd); ++ uint16_t wLen = DWC_LE16_TO_CPU(&ctrl->wLength); ++ uint16_t wValue = DWC_LE16_TO_CPU(&ctrl->wValue); ++ uint16_t wIndex = DWC_LE16_TO_CPU(&ctrl->wIndex); ++ uint32_t regaddr = 0; ++ uint32_t regval = 0; ++ ++ /* Save this Control Request in the CFI object. ++ * The data field will be assigned in the data stage completion CB function. ++ */ ++ cfi->ctrl_req = *ctrl; ++ cfi->ctrl_req.data = NULL; ++ ++ cfi->need_gadget_att = 0; ++ cfi->need_status_in_complete = 0; ++ ++ switch (ctrl->bRequest) { ++ case VEN_CORE_GET_FEATURES: ++ retval = cfi_core_features_buf(cfi->buf_in.buf, CFI_IN_BUF_LEN); ++ if (retval >= 0) { ++ //dump_msg(cfi->buf_in.buf, retval); ++ ep = &pcd->ep0; ++ ++ retval = min((uint16_t) retval, wLen); ++ /* Transfer this buffer to the host through the EP0-IN EP */ ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = retval; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ } ++ retval = 0; ++ break; ++ ++ case VEN_CORE_GET_FEATURE: ++ CFI_INFO("VEN_CORE_GET_FEATURE\n"); ++ retval = cfi_get_feature_value(cfi->buf_in.buf, CFI_IN_BUF_LEN, ++ pcd, ctrl); ++ if (retval >= 0) { ++ ep = &pcd->ep0; ++ ++ retval = min((uint16_t) retval, wLen); ++ /* Transfer this buffer to the host through the EP0-IN EP */ ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = retval; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ } ++ CFI_INFO("VEN_CORE_GET_FEATURE=%d\n", retval); ++ dump_msg(cfi->buf_in.buf, retval); ++ break; ++ ++ case VEN_CORE_SET_FEATURE: ++ CFI_INFO("VEN_CORE_SET_FEATURE\n"); ++ /* Set up an XFER to get the data stage of the control request, ++ * which is the new value of the feature to be modified. ++ */ ++ ep = &pcd->ep0; ++ ep->dwc_ep.is_in = 0; ++ ep->dwc_ep.dma_addr = cfi->buf_out.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ /* Read the control write's data stage */ ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ retval = 0; ++ break; ++ ++ case VEN_CORE_RESET_FEATURES: ++ CFI_INFO("VEN_CORE_RESET_FEATURES\n"); ++ cfi->need_gadget_att = 1; ++ cfi->need_status_in_complete = 1; ++ retval = cfi_preproc_reset(pcd, ctrl); ++ CFI_INFO("VEN_CORE_RESET_FEATURES = (%d)\n", retval); ++ break; ++ ++ case VEN_CORE_ACTIVATE_FEATURES: ++ CFI_INFO("VEN_CORE_ACTIVATE_FEATURES\n"); ++ break; ++ ++ case VEN_CORE_READ_REGISTER: ++ CFI_INFO("VEN_CORE_READ_REGISTER\n"); ++ /* wValue optionally contains the HI WORD of the register offset and ++ * wIndex contains the LOW WORD of the register offset ++ */ ++ if (wValue == 0) { ++ /* @TODO - MAS - fix the access to the base field */ ++ regaddr = 0; ++ //regaddr = (uint32_t) pcd->otg_dev->os_dep.base; ++ //GET_CORE_IF(pcd)->co ++ regaddr |= wIndex; ++ } else { ++ regaddr = (wValue << 16) | wIndex; ++ } ++ ++ /* Read a 32-bit value of the memory at the regaddr */ ++ regval = DWC_READ_REG32((uint32_t *) regaddr); ++ ++ ep = &pcd->ep0; ++ dwc_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t)); ++ ep->dwc_ep.is_in = 1; ++ ep->dwc_ep.dma_addr = cfi->buf_in.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_in.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ cfi->need_gadget_att = 0; ++ retval = 0; ++ break; ++ ++ case VEN_CORE_WRITE_REGISTER: ++ CFI_INFO("VEN_CORE_WRITE_REGISTER\n"); ++ /* Set up an XFER to get the data stage of the control request, ++ * which is the new value of the register to be modified. ++ */ ++ ep = &pcd->ep0; ++ ep->dwc_ep.is_in = 0; ++ ep->dwc_ep.dma_addr = cfi->buf_out.addr; ++ ep->dwc_ep.start_xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_buff = cfi->buf_out.buf; ++ ep->dwc_ep.xfer_len = wLen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ pcd->ep0_pending = 1; ++ /* Read the control write's data stage */ ++ dwc_otg_ep0_start_transfer(coreif, &ep->dwc_ep); ++ retval = 0; ++ break; ++ ++ default: ++ retval = -DWC_E_NOT_SUPPORTED; ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function prepares the core features descriptors and copies its ++ * raw representation into the buffer . ++ * ++ * The buffer structure is as follows: ++ * all_features_header (8 bytes) ++ * features_#1 (8 bytes + feature name string length) ++ * features_#2 (8 bytes + feature name string length) ++ * ..... ++ * features_#n - where n=the total count of feature descriptors ++ */ ++static int cfi_core_features_buf(uint8_t * buf, uint16_t buflen) ++{ ++ cfi_feature_desc_header_t *prop_hdr = prop_descs; ++ cfi_feature_desc_header_t *prop; ++ cfi_all_features_header_t *all_props_hdr = &all_props_desc_header; ++ cfi_all_features_header_t *tmp; ++ uint8_t *tmpbuf = buf; ++ const uint8_t *pname = NULL; ++ int i, j, namelen = 0, totlen; ++ ++ /* Prepare and copy the core features into the buffer */ ++ CFI_INFO("%s:\n", __func__); ++ ++ tmp = (cfi_all_features_header_t *) tmpbuf; ++ *tmp = *all_props_hdr; ++ tmpbuf += CFI_ALL_FEATURES_HDR_LEN; ++ ++ j = sizeof(prop_descs) / sizeof(cfi_all_features_header_t); ++ for (i = 0; i < j; i++, prop_hdr++) { ++ pname = get_prop_name(prop_hdr->wFeatureID, &namelen); ++ prop = (cfi_feature_desc_header_t *) tmpbuf; ++ *prop = *prop_hdr; ++ ++ prop->bNameLen = namelen; ++ prop->wLength = ++ DWC_CONSTANT_CPU_TO_LE16(CFI_FEATURE_DESC_HDR_LEN + ++ namelen); ++ ++ tmpbuf += CFI_FEATURE_DESC_HDR_LEN; ++ dwc_memcpy(tmpbuf, pname, namelen); ++ tmpbuf += namelen; ++ } ++ ++ totlen = tmpbuf - buf; ++ ++ if (totlen > 0) { ++ tmp = (cfi_all_features_header_t *) buf; ++ tmp->wTotalLen = DWC_CONSTANT_CPU_TO_LE16(totlen); ++ } ++ ++ return totlen; ++} ++ ++/** ++ * This function releases all the dynamic memory in the CFI object. ++ */ ++static void cfi_release(cfiobject_t * cfiobj) ++{ ++ cfi_ep_t *cfiep; ++ dwc_list_link_t *tmp; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ if (cfiobj->buf_in.buf) { ++ DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, ++ cfiobj->buf_in.addr); ++ cfiobj->buf_in.buf = NULL; ++ } ++ ++ if (cfiobj->buf_out.buf) { ++ DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, ++ cfiobj->buf_out.addr); ++ cfiobj->buf_out.buf = NULL; ++ } ++ ++ /* Free the Buffer Setup values for each EP */ ++ //list_for_each_entry(cfiep, &cfiobj->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfiobj->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ cfi_free_ep_bs_dyn_data(cfiep); ++ } ++} ++ ++/** ++ * This function frees the dynamically allocated EP buffer setup data. ++ */ ++static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep) ++{ ++ if (cfiep->bm_sg) { ++ DWC_FREE(cfiep->bm_sg); ++ cfiep->bm_sg = NULL; ++ } ++ ++ if (cfiep->bm_align) { ++ DWC_FREE(cfiep->bm_align); ++ cfiep->bm_align = NULL; ++ } ++ ++ if (cfiep->bm_concat) { ++ if (NULL != cfiep->bm_concat->wTxBytes) { ++ DWC_FREE(cfiep->bm_concat->wTxBytes); ++ cfiep->bm_concat->wTxBytes = NULL; ++ } ++ DWC_FREE(cfiep->bm_concat); ++ cfiep->bm_concat = NULL; ++ } ++} ++ ++/** ++ * This function initializes the default values of the features ++ * for a specific endpoint and should be called only once when ++ * the EP is enabled first time. ++ */ ++static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep) ++{ ++ int retval = 0; ++ ++ cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t)); ++ if (NULL == cfiep->bm_sg) { ++ CFI_INFO("Failed to allocate memory for SG feature value\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ ++ /* For the Concatenation feature's default value we do not allocate ++ * memory for the wTxBytes field - it will be done in the set_feature_value ++ * request handler. ++ */ ++ cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t)); ++ if (NULL == cfiep->bm_concat) { ++ CFI_INFO ++ ("Failed to allocate memory for CONCATENATION feature value\n"); ++ DWC_FREE(cfiep->bm_sg); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); ++ ++ cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t)); ++ if (NULL == cfiep->bm_align) { ++ CFI_INFO ++ ("Failed to allocate memory for Alignment feature value\n"); ++ DWC_FREE(cfiep->bm_sg); ++ DWC_FREE(cfiep->bm_concat); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t)); ++ ++ return retval; ++} ++ ++/** ++ * The callback function that notifies the CFI on the activation of ++ * an endpoint in the PCD. The following steps are done in this function: ++ * ++ * Create a dynamically allocated cfi_ep_t object (a CFI wrapper to the PCD's ++ * active endpoint) ++ * Create MAX_DMA_DESCS_PER_EP count DMA Descriptors for the EP ++ * Set the Buffer Mode to standard ++ * Initialize the default values for all EP modes (SG, Circular, Concat, Align) ++ * Add the cfi_ep_t object to the list of active endpoints in the CFI object ++ */ ++static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep) ++{ ++ cfi_ep_t *cfiep; ++ int retval = -DWC_E_NOT_SUPPORTED; ++ ++ CFI_INFO("%s: epname=%s; epnum=0x%02x\n", __func__, ++ "EP_" /*ep->ep.name */ , ep->desc->bEndpointAddress); ++ /* MAS - Check whether this endpoint already is in the list */ ++ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); ++ ++ if (NULL == cfiep) { ++ /* Allocate a cfi_ep_t object */ ++ cfiep = DWC_ALLOC(sizeof(cfi_ep_t)); ++ if (NULL == cfiep) { ++ CFI_INFO ++ ("Unable to allocate memory for in function %s\n", ++ __func__); ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_memset(cfiep, 0, sizeof(cfi_ep_t)); ++ ++ /* Save the dwc_otg_pcd_ep pointer in the cfiep object */ ++ cfiep->ep = ep; ++ ++ /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */ ++ ep->dwc_ep.descs = ++ DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP * ++ sizeof(dwc_otg_dma_desc_t), ++ &ep->dwc_ep.descs_dma_addr); ++ ++ if (NULL == ep->dwc_ep.descs) { ++ DWC_FREE(cfiep); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_LIST_INIT(&cfiep->lh); ++ ++ /* Set the buffer mode to BM_STANDARD. It will be modified ++ * when building descriptors for a specific buffer mode */ ++ ep->dwc_ep.buff_mode = BM_STANDARD; ++ ++ /* Create and initialize the default values for this EP's Buffer modes */ ++ if ((retval = cfi_ep_init_defaults(pcd, cfiep)) < 0) ++ return retval; ++ ++ /* Add the cfi_ep_t object to the CFI object's list of active endpoints */ ++ DWC_LIST_INSERT_TAIL(&cfi->active_eps, &cfiep->lh); ++ retval = 0; ++ } else { /* The sought EP already is in the list */ ++ CFI_INFO("%s: The sought EP already is in the list\n", ++ __func__); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function is called when the data stage of a 3-stage Control Write request ++ * is complete. ++ * ++ */ ++static int cfi_ctrl_write_complete(struct cfiobject *cfi, ++ struct dwc_otg_pcd *pcd) ++{ ++ uint32_t addr, reg_value; ++ uint16_t wIndex, wValue; ++ uint8_t bRequest; ++ uint8_t *buf = cfi->buf_out.buf; ++ //struct usb_ctrlrequest *ctrl_req = &cfi->ctrl_req_saved; ++ struct cfi_usb_ctrlrequest *ctrl_req = &cfi->ctrl_req; ++ int retval = -DWC_E_NOT_SUPPORTED; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ bRequest = ctrl_req->bRequest; ++ wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); ++ wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); ++ ++ /* ++ * Save the pointer to the data stage in the ctrl_req's field. ++ * The request should be already saved in the command stage by now. ++ */ ++ ctrl_req->data = cfi->buf_out.buf; ++ cfi->need_status_in_complete = 0; ++ cfi->need_gadget_att = 0; ++ ++ switch (bRequest) { ++ case VEN_CORE_WRITE_REGISTER: ++ /* The buffer contains raw data of the new value for the register */ ++ reg_value = *((uint32_t *) buf); ++ if (wValue == 0) { ++ addr = 0; ++ //addr = (uint32_t) pcd->otg_dev->os_dep.base; ++ addr += wIndex; ++ } else { ++ addr = (wValue << 16) | wIndex; ++ } ++ ++ //writel(reg_value, addr); ++ ++ retval = 0; ++ cfi->need_status_in_complete = 1; ++ break; ++ ++ case VEN_CORE_SET_FEATURE: ++ /* The buffer contains raw data of the new value of the feature */ ++ retval = cfi_set_feature_value(pcd); ++ if (retval < 0) ++ return retval; ++ ++ cfi->need_status_in_complete = 1; ++ break; ++ ++ default: ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function builds the DMA descriptors for the SG buffer mode. ++ */ ++static void cfi_build_sg_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_sg_buffer_setup_t *sgval = cfiep->bm_sg; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ int i; ++ uint32_t txsize, off; ++ ++ txsize = sgval->wSize; ++ off = sgval->bOffset; ++ ++// CFI_INFO("%s: %s TXSIZE=0x%08x; OFFSET=0x%08x\n", ++// __func__, cfiep->ep->ep.name, txsize, off); ++ ++ for (i = 0; i < sgval->bCount; i++) { ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->buf = buff_addr; ++ desc->status.b.l = 0; ++ desc->status.b.ioc = 0; ++ desc->status.b.sp = 0; ++ desc->status.b.bytes = txsize; ++ desc->status.b.bs = BS_HOST_READY; ++ ++ /* Set the next address of the buffer */ ++ buff_addr += txsize + off; ++ desc_last = desc; ++ desc++; ++ } ++ ++ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ ++ desc_last->status.b.l = 1; ++ desc_last->status.b.ioc = 1; ++ desc_last->status.b.sp = ep->dwc_ep.sent_zlp; ++ /* Save the last DMA descriptor pointer */ ++ cfiep->dma_desc_last = desc_last; ++ cfiep->desc_count = sgval->bCount; ++} ++ ++/** ++ * This function builds the DMA descriptors for the Concatenation buffer mode. ++ */ ++static void cfi_build_concat_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_concat_buffer_setup_t *concatval = cfiep->bm_concat; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ struct dwc_otg_dma_desc *desc_last = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ int i; ++ uint16_t *txsize; ++ ++ txsize = concatval->wTxBytes; ++ ++ for (i = 0; i < concatval->hdr.bDescCount; i++) { ++ desc->buf = buff_addr; ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->status.b.l = 0; ++ desc->status.b.ioc = 0; ++ desc->status.b.sp = 0; ++ desc->status.b.bytes = *txsize; ++ desc->status.b.bs = BS_HOST_READY; ++ ++ txsize++; ++ /* Set the next address of the buffer */ ++ buff_addr += UGETW(ep->desc->wMaxPacketSize); ++ desc_last = desc; ++ desc++; ++ } ++ ++ /* Set the last, ioc and sp bits on the Last DMA Descriptor */ ++ desc_last->status.b.l = 1; ++ desc_last->status.b.ioc = 1; ++ desc_last->status.b.sp = ep->dwc_ep.sent_zlp; ++ cfiep->dma_desc_last = desc_last; ++ cfiep->desc_count = concatval->hdr.bDescCount; ++} ++ ++/** ++ * This function builds the DMA descriptors for the Circular buffer mode ++ */ ++static void cfi_build_circ_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ /* @todo: MAS - add implementation when this feature needs to be tested */ ++} ++ ++/** ++ * This function builds the DMA descriptors for the Alignment buffer mode ++ */ ++static void cfi_build_align_descs(struct cfiobject *cfi, cfi_ep_t * cfiep, ++ dwc_otg_pcd_request_t * req) ++{ ++ struct dwc_otg_pcd_ep *ep = cfiep->ep; ++ ddma_align_buffer_setup_t *alignval = cfiep->bm_align; ++ struct dwc_otg_dma_desc *desc = cfiep->ep->dwc_ep.descs; ++ dma_addr_t buff_addr = req->dma; ++ ++ desc->status.b.bs = BS_HOST_BUSY; ++ desc->status.b.l = 1; ++ desc->status.b.ioc = 1; ++ desc->status.b.sp = ep->dwc_ep.sent_zlp; ++ desc->status.b.bytes = req->length; ++ /* Adjust the buffer alignment */ ++ desc->buf = (buff_addr + alignval->bAlign); ++ desc->status.b.bs = BS_HOST_READY; ++ cfiep->dma_desc_last = desc; ++ cfiep->desc_count = 1; ++} ++ ++/** ++ * This function builds the DMA descriptors chain for different modes of the ++ * buffer setup of an endpoint. ++ */ ++static void cfi_build_descriptors(struct cfiobject *cfi, ++ struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep, ++ dwc_otg_pcd_request_t * req) ++{ ++ cfi_ep_t *cfiep; ++ ++ /* Get the cfiep by the dwc_otg_pcd_ep */ ++ cfiep = get_cfi_ep_by_pcd_ep(cfi, ep); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Unable to find a matching active endpoint\n", ++ __func__); ++ return; ++ } ++ ++ cfiep->xfer_len = req->length; ++ ++ /* Iterate through all the DMA descriptors */ ++ switch (cfiep->ep->dwc_ep.buff_mode) { ++ case BM_SG: ++ cfi_build_sg_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_CONCAT: ++ cfi_build_concat_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_CIRCULAR: ++ cfi_build_circ_descs(cfi, cfiep, req); ++ break; ++ ++ case BM_ALIGN: ++ cfi_build_align_descs(cfi, cfiep, req); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++/** ++ * Allocate DMA buffer for different Buffer modes. ++ */ ++static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, ++ struct dwc_otg_pcd_ep *ep, dma_addr_t * dma, ++ unsigned size, gfp_t flags) ++{ ++ return DWC_DMA_ALLOC(size, dma); ++} ++ ++/** ++ * This function initializes the CFI object. ++ */ ++int init_cfi(cfiobject_t * cfiobj) ++{ ++ CFI_INFO("%s\n", __func__); ++ ++ /* Allocate a buffer for IN XFERs */ ++ cfiobj->buf_in.buf = ++ DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); ++ if (NULL == cfiobj->buf_in.buf) { ++ CFI_INFO("Unable to allocate buffer for INs\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Allocate a buffer for OUT XFERs */ ++ cfiobj->buf_out.buf = ++ DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); ++ if (NULL == cfiobj->buf_out.buf) { ++ CFI_INFO("Unable to allocate buffer for OUT\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Initialize the callback function pointers */ ++ cfiobj->ops.release = cfi_release; ++ cfiobj->ops.ep_enable = cfi_ep_enable; ++ cfiobj->ops.ctrl_write_complete = cfi_ctrl_write_complete; ++ cfiobj->ops.build_descriptors = cfi_build_descriptors; ++ cfiobj->ops.ep_alloc_buf = cfi_ep_alloc_buf; ++ ++ /* Initialize the list of active endpoints in the CFI object */ ++ DWC_LIST_INIT(&cfiobj->active_eps); ++ ++ return 0; ++} ++ ++/** ++ * This function reads the required feature's current value into the buffer ++ * ++ * @retval: Returns negative as error, or the data length of the feature ++ */ ++static int cfi_get_feature_value(uint8_t * buf, uint16_t buflen, ++ struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ struct dwc_otg_core_if *coreif = GET_CORE_IF(pcd); ++ uint16_t dfifo, rxfifo, txfifo; ++ ++ switch (ctrl_req->wIndex) { ++ /* Whether the DDMA is enabled or not */ ++ case FT_ID_DMA_MODE: ++ *buf = (coreif->dma_enable && coreif->dma_desc_enable) ? 1 : 0; ++ retval = 1; ++ break; ++ ++ case FT_ID_DMA_BUFFER_SETUP: ++ retval = cfi_ep_get_sg_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ retval = cfi_ep_get_align_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ retval = cfi_ep_get_concat_val(buf, pcd, ctrl_req); ++ break; ++ ++ case FT_ID_DMA_CIRCULAR: ++ CFI_INFO("GetFeature value (FT_ID_DMA_CIRCULAR)\n"); ++ break; ++ ++ case FT_ID_THRESHOLD_SETUP: ++ CFI_INFO("GetFeature value (FT_ID_THRESHOLD_SETUP)\n"); ++ break; ++ ++ case FT_ID_DFIFO_DEPTH: ++ dfifo = get_dfifo_size(coreif); ++ *((uint16_t *) buf) = dfifo; ++ retval = sizeof(uint16_t); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ retval = get_txfifo_size(pcd, ctrl_req->wValue); ++ if (retval >= 0) { ++ txfifo = retval; ++ *((uint16_t *) buf) = txfifo; ++ retval = sizeof(uint16_t); ++ } ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ retval = get_rxfifo_size(coreif, ctrl_req->wValue); ++ if (retval >= 0) { ++ rxfifo = retval; ++ *((uint16_t *) buf) = rxfifo; ++ retval = sizeof(uint16_t); ++ } ++ break; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function resets the SG for the specified EP to its default value ++ */ ++static int cfi_reset_sg_val(cfi_ep_t * cfiep) ++{ ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets the Alignment for the specified EP to its default value ++ */ ++static int cfi_reset_align_val(cfi_ep_t * cfiep) ++{ ++ dwc_memset(cfiep->bm_sg, 0, sizeof(ddma_sg_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets the Concatenation for the specified EP to its default value ++ * This function will also set the value of the wTxBytes field to NULL after ++ * freeing the memory previously allocated for this field. ++ */ ++static int cfi_reset_concat_val(cfi_ep_t * cfiep) ++{ ++ /* First we need to free the wTxBytes field */ ++ if (cfiep->bm_concat->wTxBytes) { ++ DWC_FREE(cfiep->bm_concat->wTxBytes); ++ cfiep->bm_concat->wTxBytes = NULL; ++ } ++ ++ dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); ++ return 0; ++} ++ ++/** ++ * This function resets all the buffer setups of the specified endpoint ++ */ ++static int cfi_ep_reset_all_setup_vals(cfi_ep_t * cfiep) ++{ ++ cfi_reset_sg_val(cfiep); ++ cfi_reset_align_val(cfiep); ++ cfi_reset_concat_val(cfiep); ++ return 0; ++} ++ ++static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr, ++ uint8_t rx_rst, uint8_t tx_rst) ++{ ++ int retval = -DWC_E_INVALID; ++ uint16_t tx_siz[15]; ++ uint16_t rx_siz = 0; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ ++ if (rx_rst) { ++ rx_siz = params->dev_rx_fifo_size; ++ params->dev_rx_fifo_size = GET_CORE_IF(pcd)->init_rxfsiz; ++ } ++ ++ if (tx_rst) { ++ if (ep_addr == 0) { ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ tx_siz[i] = ++ core_if->core_params->dev_tx_fifo_size[i]; ++ core_if->core_params->dev_tx_fifo_size[i] = ++ core_if->init_txfsiz[i]; ++ } ++ } else { ++ ++ ep = get_ep_by_addr(pcd, ep_addr); ++ ++ if (NULL == ep) { ++ CFI_INFO ++ ("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, ep_addr); ++ return -DWC_E_INVALID; ++ } ++ ++ tx_siz[0] = ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - ++ 1]; ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = ++ GET_CORE_IF(pcd)->init_txfsiz[ep-> ++ dwc_ep.tx_fifo_num - ++ 1]; ++ } ++ } ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO ++ ("%s: Error resetting the feature Reset All(FIFO size)\n", ++ __func__); ++ if (rx_rst) { ++ params->dev_rx_fifo_size = rx_siz; ++ } ++ ++ if (tx_rst) { ++ if (ep_addr == 0) { ++ int i; ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++ i++) { ++ core_if-> ++ core_params->dev_tx_fifo_size[i] = ++ tx_siz[i]; ++ } ++ } else { ++ params->dev_tx_fifo_size[ep-> ++ dwc_ep.tx_fifo_num - ++ 1] = tx_siz[0]; ++ } ++ } ++ retval = -DWC_E_INVALID; ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_all(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ retval = cfi_handle_reset_fifo_val(pcd, addr, 1, 1); ++ if (retval < 0) { ++ return retval; ++ } ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_ep_reset_all_setup_vals(cfiep); ++ cfiep->ep->dwc_ep.buff_mode = BM_STANDARD; ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_ep_reset_all_setup_vals(cfiep); ++ cfiep->ep->dwc_ep.buff_mode = BM_STANDARD; ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Reset All\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_dma_buff_setup(struct dwc_otg_pcd *pcd, ++ uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_sg_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_sg_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Buffer Setup\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_concat_val(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_concat_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_concat_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Concatenation Value\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++} ++ ++static int cfi_handle_reset_align_val(struct dwc_otg_pcd *pcd, uint8_t addr) ++{ ++ int retval = 0; ++ cfi_ep_t *cfiep; ++ cfiobject_t *cfi = pcd->cfi; ++ dwc_list_link_t *tmp; ++ ++ /* If the EP address is known then reset the features for only that EP */ ++ if (addr) { ++ cfiep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == cfiep) { ++ CFI_INFO("%s: Error getting the EP address 0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ retval = cfi_reset_align_val(cfiep); ++ } ++ /* Otherwise (wValue == 0), reset all features of all EP's */ ++ else { ++ /* Traverse all the active EP's and reset the feature(s) value(s) */ ++ //list_for_each_entry(cfiep, &cfi->active_eps, lh) { ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ cfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ retval = cfi_reset_align_val(cfiep); ++ if (retval < 0) { ++ CFI_INFO ++ ("%s: Error resetting the feature Aliignment Value\n", ++ __func__); ++ return retval; ++ } ++ } ++ } ++ return retval; ++ ++} ++ ++static int cfi_preproc_reset(struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = 0; ++ ++ switch (req->wIndex) { ++ case 0: ++ /* Reset all features */ ++ retval = cfi_handle_reset_all(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_BUFFER_SETUP: ++ /* Reset the SG buffer setup */ ++ retval = ++ cfi_handle_reset_dma_buff_setup(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ /* Reset the Concatenation buffer setup */ ++ retval = cfi_handle_reset_concat_val(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ /* Reset the Alignment buffer setup */ ++ retval = cfi_handle_reset_align_val(pcd, req->wValue & 0xff); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ retval = ++ cfi_handle_reset_fifo_val(pcd, req->wValue & 0xff, 0, 1); ++ pcd->cfi->need_gadget_att = 0; ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ retval = cfi_handle_reset_fifo_val(pcd, 0, 1, 0); ++ pcd->cfi->need_gadget_att = 0; ++ break; ++ default: ++ break; ++ } ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the SG buffer setup. ++ */ ++static int cfi_ep_set_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ uint8_t inaddr, outaddr; ++ cfi_ep_t *epin, *epout; ++ ddma_sg_buffer_setup_t *psgval; ++ uint32_t desccount, size; ++ ++ CFI_INFO("%s\n", __func__); ++ ++ psgval = (ddma_sg_buffer_setup_t *) buf; ++ desccount = (uint32_t) psgval->bCount; ++ size = (uint32_t) psgval->wSize; ++ ++ /* Check the DMA descriptor count */ ++ if ((desccount > MAX_DMA_DESCS_PER_EP) || (desccount == 0)) { ++ CFI_INFO ++ ("%s: The count of DMA Descriptors should be between 1 and %d\n", ++ __func__, MAX_DMA_DESCS_PER_EP); ++ return -DWC_E_INVALID; ++ } ++ ++ /* Check the DMA descriptor count */ ++ ++ if (size == 0) { ++ ++ CFI_INFO("%s: The transfer size should be at least 1 byte\n", ++ __func__); ++ ++ return -DWC_E_INVALID; ++ ++ } ++ ++ inaddr = psgval->bInEndpointAddress; ++ outaddr = psgval->bOutEndpointAddress; ++ ++ epin = get_cfi_ep_by_addr(pcd->cfi, inaddr); ++ epout = get_cfi_ep_by_addr(pcd->cfi, outaddr); ++ ++ if (NULL == epin || NULL == epout) { ++ CFI_INFO ++ ("%s: Unable to get the endpoints inaddr=0x%02x outaddr=0x%02x\n", ++ __func__, inaddr, outaddr); ++ return -DWC_E_INVALID; ++ } ++ ++ epin->ep->dwc_ep.buff_mode = BM_SG; ++ dwc_memcpy(epin->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); ++ ++ epout->ep->dwc_ep.buff_mode = BM_SG; ++ dwc_memcpy(epout->bm_sg, psgval, sizeof(ddma_sg_buffer_setup_t)); ++ ++ return 0; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_ep_set_alignment_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ cfi_ep_t *ep; ++ uint8_t addr; ++ ddma_align_buffer_setup_t *palignval; ++ ++ palignval = (ddma_align_buffer_setup_t *) buf; ++ addr = palignval->bEndpointAddress; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ ++ ep->ep->dwc_ep.buff_mode = BM_ALIGN; ++ dwc_memcpy(ep->bm_align, palignval, sizeof(ddma_align_buffer_setup_t)); ++ ++ return 0; ++} ++ ++/** ++ * This function sets a new value for the Concatenation buffer setup. ++ */ ++static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd) ++{ ++ uint8_t addr; ++ cfi_ep_t *ep; ++ struct _ddma_concat_buffer_setup_hdr *pConcatValHdr; ++ uint16_t *pVals; ++ uint32_t desccount; ++ int i; ++ uint16_t mps; ++ ++ pConcatValHdr = (struct _ddma_concat_buffer_setup_hdr *)buf; ++ desccount = (uint32_t) pConcatValHdr->bDescCount; ++ pVals = (uint16_t *) (buf + BS_CONCAT_VAL_HDR_LEN); ++ ++ /* Check the DMA descriptor count */ ++ if (desccount > MAX_DMA_DESCS_PER_EP) { ++ CFI_INFO("%s: Maximum DMA Descriptor count should be %d\n", ++ __func__, MAX_DMA_DESCS_PER_EP); ++ return -DWC_E_INVALID; ++ } ++ ++ addr = pConcatValHdr->bEndpointAddress; ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, addr); ++ return -DWC_E_INVALID; ++ } ++ ++ mps = UGETW(ep->ep->desc->wMaxPacketSize); ++ ++#if 0 ++ for (i = 0; i < desccount; i++) { ++ CFI_INFO("%s: wTxSize[%d]=0x%04x\n", __func__, i, pVals[i]); ++ } ++ CFI_INFO("%s: epname=%s; mps=%d\n", __func__, ep->ep->ep.name, mps); ++#endif ++ ++ /* Check the wTxSizes to be less than or equal to the mps */ ++ for (i = 0; i < desccount; i++) { ++ if (pVals[i] > mps) { ++ CFI_INFO ++ ("%s: ERROR - the wTxSize[%d] should be <= MPS (wTxSize=%d)\n", ++ __func__, i, pVals[i]); ++ return -DWC_E_INVALID; ++ } ++ } ++ ++ ep->ep->dwc_ep.buff_mode = BM_CONCAT; ++ dwc_memcpy(ep->bm_concat, pConcatValHdr, BS_CONCAT_VAL_HDR_LEN); ++ ++ /* Free the previously allocated storage for the wTxBytes */ ++ if (ep->bm_concat->wTxBytes) { ++ DWC_FREE(ep->bm_concat->wTxBytes); ++ } ++ ++ /* Allocate a new storage for the wTxBytes field */ ++ ep->bm_concat->wTxBytes = ++ DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ if (NULL == ep->bm_concat->wTxBytes) { ++ CFI_INFO("%s: Unable to allocate memory\n", __func__); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Copy the new values into the wTxBytes filed */ ++ dwc_memcpy(ep->bm_concat->wTxBytes, buf + BS_CONCAT_VAL_HDR_LEN, ++ sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ ++ return 0; ++} ++ ++/** ++ * This function calculates the total of all FIFO sizes ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static uint16_t get_dfifo_size(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint16_t dfifo_total = 0; ++ int i; ++ ++ /* The shared RxFIFO size */ ++ dfifo_total = ++ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; ++ ++ /* Add up each TxFIFO size to the total */ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dfifo_total += params->dev_tx_fifo_size[i]; ++ } ++ ++ return dfifo_total; ++} ++ ++/** ++ * This function returns Rx FIFO size ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static int32_t get_rxfifo_size(dwc_otg_core_if_t * core_if, uint16_t wValue) ++{ ++ switch (wValue >> 8) { ++ case 0: ++ return (core_if->pwron_rxfsiz < ++ 32768) ? core_if->pwron_rxfsiz : 32768; ++ break; ++ case 1: ++ return core_if->core_params->dev_rx_fifo_size; ++ break; ++ default: ++ return -DWC_E_INVALID; ++ break; ++ } ++} ++ ++/** ++ * This function returns Tx FIFO size for IN EP ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return The total of data FIFO sizes. ++ * ++ */ ++static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_ep_by_addr(pcd, wValue & 0xff); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, wValue & 0xff); ++ return -DWC_E_INVALID; ++ } ++ ++ if (!ep->dwc_ep.is_in) { ++ CFI_INFO ++ ("%s: No Tx FIFO assingned to the Out endpoint addr=0x%02x\n", ++ __func__, wValue & 0xff); ++ return -DWC_E_INVALID; ++ } ++ ++ switch (wValue >> 8) { ++ case 0: ++ return (GET_CORE_IF(pcd)->pwron_txfsiz ++ [ep->dwc_ep.tx_fifo_num - 1] < ++ 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep-> ++ dwc_ep.tx_fifo_num ++ - 1] : 32768; ++ break; ++ case 1: ++ return GET_CORE_IF(pcd)->core_params-> ++ dev_tx_fifo_size[ep->dwc_ep.num - 1]; ++ break; ++ default: ++ return -DWC_E_INVALID; ++ break; ++ } ++} ++ ++/** ++ * This function checks if the submitted combination of ++ * device mode FIFO sizes is possible or not. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return 1 if possible, 0 otherwise. ++ * ++ */ ++static uint8_t check_fifo_sizes(dwc_otg_core_if_t * core_if) ++{ ++ uint16_t dfifo_actual = 0; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint16_t start_addr = 0; ++ int i; ++ ++ dfifo_actual = ++ params->dev_rx_fifo_size + params->dev_nperio_tx_fifo_size; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dfifo_actual += params->dev_tx_fifo_size[i]; ++ } ++ ++ if (dfifo_actual > core_if->total_fifo_size) { ++ return 0; ++ } ++ ++ if (params->dev_rx_fifo_size > 32768 || params->dev_rx_fifo_size < 16) ++ return 0; ++ ++ if (params->dev_nperio_tx_fifo_size > 32768 ++ || params->dev_nperio_tx_fifo_size < 16) ++ return 0; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ if (params->dev_tx_fifo_size[i] > 768 ++ || params->dev_tx_fifo_size[i] < 4) ++ return 0; ++ } ++ ++ if (params->dev_rx_fifo_size > core_if->pwron_rxfsiz) ++ return 0; ++ start_addr = params->dev_rx_fifo_size; ++ ++ if (params->dev_nperio_tx_fifo_size > core_if->pwron_gnptxfsiz) ++ return 0; ++ start_addr += params->dev_nperio_tx_fifo_size; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ if (params->dev_tx_fifo_size[i] > core_if->pwron_txfsiz[i]) ++ return 0; ++ start_addr += params->dev_tx_fifo_size[i]; ++ } ++ ++ return 1; ++} ++ ++/** ++ * This function resizes Device mode FIFOs ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ * @return 1 if successful, 0 otherwise ++ * ++ */ ++static uint8_t resize_fifos(dwc_otg_core_if_t * core_if) ++{ ++ int i = 0; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ uint32_t rx_fifo_size; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t txfifosize[15]; ++ ++ uint32_t rx_fsz_bak; ++ uint32_t nptxfsz_bak; ++ uint32_t txfsz_bak[15]; ++ ++ uint16_t start_address; ++ uint8_t retval = 1; ++ ++ if (!check_fifo_sizes(core_if)) { ++ return 0; ++ } ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz); ++ rx_fifo_size = params->dev_rx_fifo_size; ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); ++ ++ /* ++ * Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_tx_fifo_size array and the FIFO size registers in ++ * the dtxfsiz array run from 0 to 14. ++ */ ++ ++ /* Non-periodic Tx FIFO */ ++ nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz); ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ start_address = params->dev_rx_fifo_size; ++ nptxfifosize.b.startaddr = start_address; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ ++ start_address += nptxfifosize.b.depth; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]); ++ ++ txfifosize[i].b.depth = params->dev_tx_fifo_size[i]; ++ txfifosize[i].b.startaddr = start_address; ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfifosize[i].d32); ++ ++ start_address += txfifosize[i].b.depth; ++ } ++ ++ /** Check if register values are set correctly */ ++ if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) { ++ retval = 0; ++ } ++ ++ if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) { ++ retval = 0; ++ } ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ if (txfifosize[i].d32 != ++ DWC_READ_REG32(&global_regs->dtxfsiz[i])) { ++ retval = 0; ++ } ++ } ++ ++ /** If register values are not set correctly, reset old values */ ++ if (retval == 0) { ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak); ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfsz_bak[i]); ++ } ++ } ++ } else { ++ return 0; ++ } ++ ++ /* Flush the FIFOs */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_ep_set_tx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd) ++{ ++ int retval; ++ uint32_t fsiz; ++ uint16_t size; ++ uint16_t ep_addr; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ tx_fifo_size_setup_t *ptxfifoval; ++ ++ ptxfifoval = (tx_fifo_size_setup_t *) buf; ++ ep_addr = ptxfifoval->bEndpointAddress; ++ size = ptxfifoval->wDepth; ++ ++ ep = get_ep_by_addr(pcd, ep_addr); ++ ++ CFI_INFO ++ ("%s: Set Tx FIFO size: endpoint addr=0x%02x, depth=%d, FIFO Num=%d\n", ++ __func__, ep_addr, size, ep->dwc_ep.tx_fifo_num); ++ ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint addr=0x%02x\n", ++ __func__, ep_addr); ++ return -DWC_E_INVALID; ++ } ++ ++ fsiz = params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1]; ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = size; ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO ++ ("%s: Error setting the feature Tx FIFO Size for EP%d\n", ++ __func__, ep_addr); ++ params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = fsiz; ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the buffer Alignment setup. ++ */ ++static int cfi_set_rx_fifo_val(uint8_t * buf, dwc_otg_pcd_t * pcd) ++{ ++ int retval; ++ uint32_t fsiz; ++ uint16_t size; ++ dwc_otg_core_params_t *params = GET_CORE_IF(pcd)->core_params; ++ rx_fifo_size_setup_t *prxfifoval; ++ ++ prxfifoval = (rx_fifo_size_setup_t *) buf; ++ size = prxfifoval->wDepth; ++ ++ fsiz = params->dev_rx_fifo_size; ++ params->dev_rx_fifo_size = size; ++ ++ if (resize_fifos(GET_CORE_IF(pcd))) { ++ retval = 0; ++ } else { ++ CFI_INFO("%s: Error setting the feature Rx FIFO Size\n", ++ __func__); ++ params->dev_rx_fifo_size = fsiz; ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function reads the SG of an EP's buffer setup into the buffer buf ++ */ ++static int cfi_ep_get_sg_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ dwc_memcpy(buf, ep->bm_sg, BS_SG_VAL_DESC_LEN); ++ retval = BS_SG_VAL_DESC_LEN; ++ return retval; ++} ++ ++/** ++ * This function reads the Concatenation value of an EP's buffer mode into ++ * the buffer buf ++ */ ++static int cfi_ep_get_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ uint8_t desc_count; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ /* Copy the header to the buffer */ ++ dwc_memcpy(buf, ep->bm_concat, BS_CONCAT_VAL_HDR_LEN); ++ /* Advance the buffer pointer by the header size */ ++ buf += BS_CONCAT_VAL_HDR_LEN; ++ ++ desc_count = ep->bm_concat->hdr.bDescCount; ++ /* Copy alll the wTxBytes to the buffer */ ++ dwc_memcpy(buf, ep->bm_concat->wTxBytes, sizeof(uid16_t) * desc_count); ++ ++ retval = BS_CONCAT_VAL_HDR_LEN + sizeof(uid16_t) * desc_count; ++ return retval; ++} ++ ++/** ++ * This function reads the buffer Alignment value of an EP's buffer mode into ++ * the buffer buf ++ * ++ * @return The total number of bytes copied to the buffer or negative error code. ++ */ ++static int cfi_ep_get_align_val(uint8_t * buf, struct dwc_otg_pcd *pcd, ++ struct cfi_usb_ctrlrequest *req) ++{ ++ int retval = -DWC_E_INVALID; ++ uint8_t addr; ++ cfi_ep_t *ep; ++ ++ /* The Low Byte of the wValue contains a non-zero address of the endpoint */ ++ addr = req->wValue & 0xFF; ++ if (addr == 0) /* The address should be non-zero */ ++ return retval; ++ ++ ep = get_cfi_ep_by_addr(pcd->cfi, addr); ++ if (NULL == ep) { ++ CFI_INFO("%s: Unable to get the endpoint address(0x%02x)\n", ++ __func__, addr); ++ return retval; ++ } ++ ++ dwc_memcpy(buf, ep->bm_align, BS_ALIGN_VAL_HDR_LEN); ++ retval = BS_ALIGN_VAL_HDR_LEN; ++ ++ return retval; ++} ++ ++/** ++ * This function sets a new value for the specified feature ++ * ++ * @param pcd A pointer to the PCD object ++ * ++ * @return 0 if successful, negative error code otherwise to stall the DCE. ++ */ ++static int cfi_set_feature_value(struct dwc_otg_pcd *pcd) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ uint16_t wIndex, wValue; ++ uint8_t bRequest; ++ struct dwc_otg_core_if *coreif; ++ cfiobject_t *cfi = pcd->cfi; ++ struct cfi_usb_ctrlrequest *ctrl_req; ++ uint8_t *buf; ++ ctrl_req = &cfi->ctrl_req; ++ ++ buf = pcd->cfi->ctrl_req.data; ++ ++ coreif = GET_CORE_IF(pcd); ++ bRequest = ctrl_req->bRequest; ++ wIndex = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wIndex); ++ wValue = DWC_CONSTANT_CPU_TO_LE16(ctrl_req->wValue); ++ ++ /* See which feature is to be modified */ ++ switch (wIndex) { ++ case FT_ID_DMA_BUFFER_SETUP: ++ /* Modify the feature */ ++ if ((retval = cfi_ep_set_sg_val(buf, pcd)) < 0) ++ return retval; ++ ++ /* And send this request to the gadget */ ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_BUFF_ALIGN: ++ if ((retval = cfi_ep_set_alignment_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_CONCAT_SETUP: ++ /* Modify the feature */ ++ if ((retval = cfi_ep_set_concat_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 1; ++ break; ++ ++ case FT_ID_DMA_CIRCULAR: ++ CFI_INFO("FT_ID_DMA_CIRCULAR\n"); ++ break; ++ ++ case FT_ID_THRESHOLD_SETUP: ++ CFI_INFO("FT_ID_THRESHOLD_SETUP\n"); ++ break; ++ ++ case FT_ID_DFIFO_DEPTH: ++ CFI_INFO("FT_ID_DFIFO_DEPTH\n"); ++ break; ++ ++ case FT_ID_TX_FIFO_DEPTH: ++ CFI_INFO("FT_ID_TX_FIFO_DEPTH\n"); ++ if ((retval = cfi_ep_set_tx_fifo_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 0; ++ break; ++ ++ case FT_ID_RX_FIFO_DEPTH: ++ CFI_INFO("FT_ID_RX_FIFO_DEPTH\n"); ++ if ((retval = cfi_set_rx_fifo_val(buf, pcd)) < 0) ++ return retval; ++ cfi->need_gadget_att = 0; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif //DWC_UTE_CFI +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.h b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h +new file mode 100644 +index 0000000..cbccdab +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h +@@ -0,0 +1,320 @@ ++/* ========================================================================== ++ * 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_OTG_CFI_H__) ++#define __DWC_OTG_CFI_H__ ++ ++#include "dwc_otg_pcd.h" ++#include "dwc_cfi_common.h" ++ ++/** ++ * @file ++ * This file contains the CFI related OTG PCD specific common constants, ++ * interfaces(functions and macros) and data structures.The CFI Protocol is an ++ * optional interface for internal testing purposes that a DUT may implement to ++ * support testing of configurable features. ++ * ++ */ ++ ++struct dwc_otg_pcd; ++struct dwc_otg_pcd_ep; ++ ++/** OTG CFI Features (properties) ID constants */ ++/** This is a request for all Core Features */ ++#define FT_ID_DMA_MODE 0x0001 ++#define FT_ID_DMA_BUFFER_SETUP 0x0002 ++#define FT_ID_DMA_BUFF_ALIGN 0x0003 ++#define FT_ID_DMA_CONCAT_SETUP 0x0004 ++#define FT_ID_DMA_CIRCULAR 0x0005 ++#define FT_ID_THRESHOLD_SETUP 0x0006 ++#define FT_ID_DFIFO_DEPTH 0x0007 ++#define FT_ID_TX_FIFO_DEPTH 0x0008 ++#define FT_ID_RX_FIFO_DEPTH 0x0009 ++ ++/**********************************************************/ ++#define CFI_INFO_DEF ++ ++#ifdef CFI_INFO_DEF ++#define CFI_INFO(fmt...) DWC_PRINTF("CFI: " fmt); ++#else ++#define CFI_INFO(fmt...) ++#endif ++ ++#define min(x,y) ({ \ ++ x < y ? x : y; }) ++ ++#define max(x,y) ({ \ ++ x > y ? x : y; }) ++ ++/** ++ * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is ++ * also used for setting up a buffer for Circular DDMA. ++ */ ++struct _ddma_sg_buffer_setup { ++#define BS_SG_VAL_DESC_LEN 6 ++ /* The OUT EP address */ ++ uint8_t bOutEndpointAddress; ++ /* The IN EP address */ ++ uint8_t bInEndpointAddress; ++ /* Number of bytes to put between transfer segments (must be DWORD boundaries) */ ++ uint8_t bOffset; ++ /* The number of transfer segments (a DMA descriptors per each segment) */ ++ uint8_t bCount; ++ /* Size (in byte) of each transfer segment */ ++ uint16_t wSize; ++} __attribute__ ((packed)); ++typedef struct _ddma_sg_buffer_setup ddma_sg_buffer_setup_t; ++ ++/** Descriptor DMA Concatenation Buffer setup structure */ ++struct _ddma_concat_buffer_setup_hdr { ++#define BS_CONCAT_VAL_HDR_LEN 4 ++ /* The endpoint for which the buffer is to be set up */ ++ uint8_t bEndpointAddress; ++ /* The count of descriptors to be used */ ++ uint8_t bDescCount; ++ /* The total size of the transfer */ ++ uint16_t wSize; ++} __attribute__ ((packed)); ++typedef struct _ddma_concat_buffer_setup_hdr ddma_concat_buffer_setup_hdr_t; ++ ++/** Descriptor DMA Concatenation Buffer setup structure */ ++struct _ddma_concat_buffer_setup { ++ /* The SG header */ ++ ddma_concat_buffer_setup_hdr_t hdr; ++ ++ /* The XFER sizes pointer (allocated dynamically) */ ++ uint16_t *wTxBytes; ++} __attribute__ ((packed)); ++typedef struct _ddma_concat_buffer_setup ddma_concat_buffer_setup_t; ++ ++/** Descriptor DMA Alignment Buffer setup structure */ ++struct _ddma_align_buffer_setup { ++#define BS_ALIGN_VAL_HDR_LEN 2 ++ uint8_t bEndpointAddress; ++ uint8_t bAlign; ++} __attribute__ ((packed)); ++typedef struct _ddma_align_buffer_setup ddma_align_buffer_setup_t; ++ ++/** Transmit FIFO Size setup structure */ ++struct _tx_fifo_size_setup { ++ uint8_t bEndpointAddress; ++ uint16_t wDepth; ++} __attribute__ ((packed)); ++typedef struct _tx_fifo_size_setup tx_fifo_size_setup_t; ++ ++/** Transmit FIFO Size setup structure */ ++struct _rx_fifo_size_setup { ++ uint16_t wDepth; ++} __attribute__ ((packed)); ++typedef struct _rx_fifo_size_setup rx_fifo_size_setup_t; ++ ++/** ++ * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest ++ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer ++ * to the data returned in the data stage of a 3-stage Control Write requests. ++ */ ++struct cfi_usb_ctrlrequest { ++ uint8_t bRequestType; ++ uint8_t bRequest; ++ uint16_t wValue; ++ uint16_t wIndex; ++ uint16_t wLength; ++ uint8_t *data; ++} UPACKED; ++ ++/*---------------------------------------------------------------------------*/ ++ ++/** ++ * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures. ++ * This structure is used to store the buffer setup data for any ++ * enabled endpoint in the PCD. ++ */ ++struct cfi_ep { ++ /* Entry for the list container */ ++ dwc_list_link_t lh; ++ /* Pointer to the active PCD endpoint structure */ ++ struct dwc_otg_pcd_ep *ep; ++ /* The last descriptor in the chain of DMA descriptors of the endpoint */ ++ struct dwc_otg_dma_desc *dma_desc_last; ++ /* The SG feature value */ ++ ddma_sg_buffer_setup_t *bm_sg; ++ /* The Circular feature value */ ++ ddma_sg_buffer_setup_t *bm_circ; ++ /* The Concatenation feature value */ ++ ddma_concat_buffer_setup_t *bm_concat; ++ /* The Alignment feature value */ ++ ddma_align_buffer_setup_t *bm_align; ++ /* XFER length */ ++ uint32_t xfer_len; ++ /* ++ * Count of DMA descriptors currently used. ++ * The total should not exceed the MAX_DMA_DESCS_PER_EP value ++ * defined in the dwc_otg_cil.h ++ */ ++ uint32_t desc_count; ++}; ++typedef struct cfi_ep cfi_ep_t; ++ ++typedef struct cfi_dma_buff { ++#define CFI_IN_BUF_LEN 1024 ++#define CFI_OUT_BUF_LEN 1024 ++ dma_addr_t addr; ++ uint8_t *buf; ++} cfi_dma_buff_t; ++ ++struct cfiobject; ++ ++/** ++ * This is the interface for the CFI operations. ++ * ++ * @param ep_enable Called when any endpoint is enabled and activated. ++ * @param release Called when the CFI object is released and it needs to correctly ++ * deallocate the dynamic memory ++ * @param ctrl_write_complete Called when the data stage of the request is complete ++ */ ++typedef struct cfi_ops { ++ int (*ep_enable) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep); ++ void *(*ep_alloc_buf) (struct cfiobject * cfi, struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep, dma_addr_t * dma, ++ unsigned size, gfp_t flags); ++ void (*release) (struct cfiobject * cfi); ++ int (*ctrl_write_complete) (struct cfiobject * cfi, ++ struct dwc_otg_pcd * pcd); ++ void (*build_descriptors) (struct cfiobject * cfi, ++ struct dwc_otg_pcd * pcd, ++ struct dwc_otg_pcd_ep * ep, ++ dwc_otg_pcd_request_t * req); ++} cfi_ops_t; ++ ++struct cfiobject { ++ cfi_ops_t ops; ++ struct dwc_otg_pcd *pcd; ++ struct usb_gadget *gadget; ++ ++ /* Buffers used to send/receive CFI-related request data */ ++ cfi_dma_buff_t buf_in; ++ cfi_dma_buff_t buf_out; ++ ++ /* CFI specific Control request wrapper */ ++ struct cfi_usb_ctrlrequest ctrl_req; ++ ++ /* The list of active EP's in the PCD of type cfi_ep_t */ ++ dwc_list_link_t active_eps; ++ ++ /* This flag shall control the propagation of a specific request ++ * to the gadget's processing routines. ++ * 0 - no gadget handling ++ * 1 - the gadget needs to know about this request (w/o completing a status ++ * phase - just return a 0 to the _setup callback) ++ */ ++ uint8_t need_gadget_att; ++ ++ /* Flag indicating whether the status IN phase needs to be ++ * completed by the PCD ++ */ ++ uint8_t need_status_in_complete; ++}; ++typedef struct cfiobject cfiobject_t; ++ ++#define DUMP_MSG ++ ++#if defined(DUMP_MSG) ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ ++ start = 0; ++ while (length > 0) { ++ num = min(length, 16u); ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ DWC_SPRINTF(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ DWC_DEBUG("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function returns a pointer to cfi_ep_t object with the addr address. ++ */ ++static inline struct cfi_ep *get_cfi_ep_by_addr(struct cfiobject *cfi, ++ uint8_t addr) ++{ ++ struct cfi_ep *pcfiep; ++ dwc_list_link_t *tmp; ++ ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ ++ if (pcfiep->ep->desc->bEndpointAddress == addr) { ++ return pcfiep; ++ } ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This function returns a pointer to cfi_ep_t object that matches ++ * the dwc_otg_pcd_ep object. ++ */ ++static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi, ++ struct dwc_otg_pcd_ep *ep) ++{ ++ struct cfi_ep *pcfiep = NULL; ++ dwc_list_link_t *tmp; ++ ++ DWC_LIST_FOREACH(tmp, &cfi->active_eps) { ++ pcfiep = DWC_LIST_ENTRY(tmp, struct cfi_ep, lh); ++ if (pcfiep->ep == ep) { ++ return pcfiep; ++ } ++ } ++ return NULL; ++} ++ ++int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); ++ ++#endif /* (__DWC_OTG_CFI_H__) */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c +new file mode 100644 +index 0000000..9b67537 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c +@@ -0,0 +1,7151 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $ ++ * $Revision: #191 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * The CIL manages the memory map for the core so that the HCD and PCD ++ * don't have to do this separately. It also handles basic tasks like ++ * reading/writing the registers and data FIFOs in the controller. ++ * Some of the data access functions provide encapsulation of several ++ * operations required to perform a task, such as writing multiple ++ * registers to start a transfer. Finally, the CIL performs basic ++ * services that are not specific to either the host or device modes ++ * of operation. These services include management of the OTG Host ++ * Negotiation Protocol (HNP) and Session Request Protocol (SRP). A ++ * Diagnostic API is also provided to allow testing of the controller ++ * hardware. ++ * ++ * The Core Interface Layer has the following requirements: ++ * - Provides basic controller operations. ++ * - Minimal use of OS services. ++ * - The OS services used will be abstracted by using inline functions ++ * or macros. ++ * ++ */ ++ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++ ++static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if); ++ ++/** ++ * This function is called to initialize the DWC_otg CSR data ++ * structures. The register addresses in the device and host ++ * structures are initialized from the base address supplied by the ++ * caller. The calling function must make the OS calls to get the ++ * base address of the DWC_otg controller registers. The core_params ++ * argument holds the parameters that specify how the core should be ++ * configured. ++ * ++ * @param reg_base_addr Base address of DWC_otg core registers ++ * ++ */ ++dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) ++{ ++ dwc_otg_core_if_t *core_if = 0; ++ dwc_otg_dev_if_t *dev_if = 0; ++ dwc_otg_host_if_t *host_if = 0; ++ uint8_t *reg_base = (uint8_t *) reg_base_addr; ++ int i = 0; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr); ++ ++ core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t)); ++ ++ if (core_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, ++ "Allocation of dwc_otg_core_if_t failed\n"); ++ return 0; ++ } ++ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base; ++ ++ /* ++ * Allocate the Device Mode structures. ++ */ ++ dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t)); ++ ++ if (dev_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n"); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ dev_if->dev_global_regs = ++ (dwc_otg_device_global_regs_t *) (reg_base + ++ DWC_DEV_GLOBAL_REG_OFFSET); ++ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *) ++ (reg_base + DWC_DEV_IN_EP_REG_OFFSET + ++ (i * DWC_EP_REG_OFFSET)); ++ ++ dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *) ++ (reg_base + DWC_DEV_OUT_EP_REG_OFFSET + ++ (i * DWC_EP_REG_OFFSET)); ++ DWC_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p\n", ++ i, &dev_if->in_ep_regs[i]->diepctl); ++ DWC_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p\n", ++ i, &dev_if->out_ep_regs[i]->doepctl); ++ } ++ ++ dev_if->speed = 0; // unknown ++ ++ core_if->dev_if = dev_if; ++ ++ /* ++ * Allocate the Host Mode structures. ++ */ ++ host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t)); ++ ++ if (host_if == NULL) { ++ DWC_DEBUGPL(DBG_CIL, ++ "Allocation of dwc_otg_host_if_t failed\n"); ++ DWC_FREE(dev_if); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ 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)); ++ DWC_DEBUGPL(DBG_CILV, "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)); ++ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n", ++ i, (unsigned long)core_if->data_fifo[i]); ++ } ++ ++ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET); ++ ++ /* Initiate lx_state to L3 disconnected state */ ++ core_if->lx_state = DWC_OTG_L3; ++ /* ++ * 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); ++ ++ /* Force host mode to get HPTXFSIZ exact power on value */ ++ { ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(100); ++ core_if->hptxfsiz.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(100); ++ } ++ ++ DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg3=%08x\n", core_if->hwcfg3.d32); ++ DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); ++ ++ core_if->hcfg.d32 = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ core_if->dcfg.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ ++ DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32); ++ DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_CILV, "op_mode=%0x\n", core_if->hwcfg2.b.op_mode); ++ DWC_DEBUGPL(DBG_CILV, "arch=%0x\n", core_if->hwcfg2.b.architecture); ++ DWC_DEBUGPL(DBG_CILV, "num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep); ++ DWC_DEBUGPL(DBG_CILV, "num_host_chan=%d\n", ++ core_if->hwcfg2.b.num_host_chan); ++ DWC_DEBUGPL(DBG_CILV, "nonperio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.nonperio_tx_q_depth); ++ DWC_DEBUGPL(DBG_CILV, "host_perio_tx_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.host_perio_tx_q_depth); ++ DWC_DEBUGPL(DBG_CILV, "dev_token_q_depth=0x%0x\n", ++ core_if->hwcfg2.b.dev_token_q_depth); ++ ++ DWC_DEBUGPL(DBG_CILV, "Total FIFO SZ=%d\n", ++ core_if->hwcfg3.b.dfifo_depth); ++ DWC_DEBUGPL(DBG_CILV, "xfer_size_cntr_width=%0x\n", ++ core_if->hwcfg3.b.xfer_size_cntr_width); ++ ++ /* ++ * Set the SRP sucess bit for FS-I2c ++ */ ++ core_if->srp_success = 0; ++ core_if->srp_timer_started = 0; ++ ++ /* ++ * Create new workqueue and init works ++ */ ++ core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg"); ++ if (core_if->wq_otg == 0) { ++ DWC_WARN("DWC_WORKQ_ALLOC failed\n"); ++ DWC_FREE(host_if); ++ DWC_FREE(dev_if); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid); ++ ++ DWC_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)); ++ ++ core_if->wkp_timer = DWC_TIMER_ALLOC("Wake Up Timer", ++ w_wakeup_detected, core_if); ++ if (core_if->wkp_timer == 0) { ++ DWC_WARN("DWC_TIMER_ALLOC failed\n"); ++ DWC_FREE(host_if); ++ DWC_FREE(dev_if); ++ DWC_WORKQ_FREE(core_if->wq_otg); ++ DWC_FREE(core_if); ++ return 0; ++ } ++ ++ if (dwc_otg_setup_params(core_if)) { ++ DWC_WARN("Error while setting core params\n"); ++ } ++ ++ core_if->hibernation_suspend = 0; ++ ++ /** ADP initialization */ ++ dwc_otg_adp_init(core_if); ++ ++ return core_if; ++} ++ ++/** ++ * This function frees the structures allocated by dwc_otg_cil_init(). ++ * ++ * @param core_if The core interface pointer returned from ++ * dwc_otg_cil_init(). ++ * ++ */ ++void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); ++ ++ /* Disable all interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ dctl.b.sftdiscon = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, ++ dctl.d32); ++ } ++ ++ if (core_if->wq_otg) { ++ DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500); ++ DWC_WORKQ_FREE(core_if->wq_otg); ++ } ++ if (core_if->dev_if) { ++ DWC_FREE(core_if->dev_if); ++ } ++ if (core_if->host_if) { ++ DWC_FREE(core_if->host_if); ++ } ++ ++ /** Remove ADP Stuff */ ++ dwc_otg_adp_remove(core_if); ++ if (core_if->core_params) { ++ DWC_FREE(core_if->core_params); ++ } ++ if (core_if->wkp_timer) { ++ DWC_TIMER_FREE(core_if->wkp_timer); ++ } ++ if (core_if->srp_timer) { ++ DWC_TIMER_FREE(core_if->srp_timer); ++ } ++ DWC_FREE(core_if); ++} ++ ++/** ++ * This function enables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); ++} ++ ++/** ++ * This function disables the controller's Global Interrupt in the AHB Config ++ * register. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ahbcfg.b.glblintrmsk = 1; /* Disable interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++} ++ ++/** ++ * This function initializes the commmon interrupts, used in both ++ * device and host modes. ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ * ++ */ ++static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ /* Clear any pending OTG Interrupts */ ++ DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* ++ * Enable the interrupts in the GINTMSK. ++ */ ++ intr_mask.b.modemismatch = 1; ++ intr_mask.b.otgintr = 1; ++ ++ if (!core_if->dma_enable) { ++ intr_mask.b.rxstsqlvl = 1; ++ } ++ ++ intr_mask.b.conidstschng = 1; ++ intr_mask.b.wkupintr = 1; ++ intr_mask.b.disconnect = 0; ++ intr_mask.b.usbsuspend = 1; ++ intr_mask.b.sessreqintr = 1; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->core_params->lpm_enable) { ++ intr_mask.b.lpmtranrcvd = 1; ++ } ++#endif ++ DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32); ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Device mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of DWC_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (rem_wakeup) { ++ dwc_udelay(70); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Mask interrupts from gpwrdn */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* ++ * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1 ++ * indicates restore from remote_wakeup ++ */ ++ restore_essential_regs(core_if, rem_wakeup, 0); ++ ++ /* ++ * Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling ++ */ ++ dwc_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* ++ * Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ DWC_PRINTF("Restore Done Interrupt seen\n"); ++ break; ++ } ++ dwc_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_PRINTF("Restore Done interrupt wasn't generated here\n"); ++ } ++ } ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (!rem_wakeup) { ++ pcgcctl.d32 = 0; ++ pcgcctl.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ } ++ ++ /* Restore GUSBCFG and DCFG */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (!rem_wakeup) { ++ /* Set Device programming done bit */ ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ /* Start Remote Wakeup Signaling */ ++ dctl.d32 = core_if->dr_backup->dctl; ++ dctl.b.rmtwkupsig = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++ ++ dwc_mdelay(2); ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ dwc_otg_restore_global_regs(core_if); ++ /* Restore device global registers */ ++ dwc_otg_restore_dev_regs(core_if, rem_wakeup); ++ ++ if (rem_wakeup) { ++ dwc_mdelay(7); ++ dctl.d32 = 0; ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ } ++ ++ core_if->hibernation_suspend = 0; ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_PRINTF("Hibernation recovery completes here\n"); ++ ++ return 1; ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Host mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of DWC_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (!rem_wakeup) { ++ dwc_udelay(50); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Set Restore Essential Regs bit in PCGCCTL register */ ++ restore_essential_regs(core_if, rem_wakeup, 1); ++ ++ /* Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling */ ++ dwc_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n"); ++ break; ++ } ++ dwc_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_WARN("Restore Done interrupt wasn't generated\n"); ++ } ++ } ++ ++ /* Set the flag's value to 0 again after receiving restore done interrupt */ ++ core_if->hibernation_suspend = 0; ++ ++ /* This step is not described in functional spec but if not wait for this ++ * delay, mismatch interrupts occurred because just after restore core is ++ * in Device mode(gintsts.curmode == 0) */ ++ dwc_mdelay(100); ++ ++ /* Clear all pending interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Restore GUSBCFG and HCFG */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ core_if->hr_backup->hcfg_local); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Start the Resume operation by programming HPRT0 */ ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ DWC_PRINTF("Resume Starts Now\n"); ++ if (!reset) { // Indicates it is Resume Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtres = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ if (!rem_wakeup) ++ hprt0.b.prtres = 0; ++ /* Wait for Resume time and then program HPRT again */ ++ dwc_mdelay(100); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ } else { // Indicates it is Reset Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtrst = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Wait for Reset time and then program HPRT again */ ++ dwc_mdelay(60); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ /* Clear all interrupt status */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtconndet = 1; ++ hprt0.b.prtenchng = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ dwc_otg_restore_global_regs(core_if); ++ /* Restore host global registers */ ++ dwc_otg_restore_host_regs(core_if, reset); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_PRINTF("Hibernation recovery is complete here\n"); ++ return 0; ++} ++ ++/** Saves some register values into system memory. */ ++int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ gr = DWC_ALLOC(sizeof(*gr)); ++ if (!gr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->gr_backup = gr; ++ } ++ ++ gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz); ++ gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++#endif ++ gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl); ++ gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl); ++ gr->gdfifocfg_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ gr->dtxfsiz_local[i] = ++ DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i])); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl = %08x\n", gr->gotgctl_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg = %08x\n", gr->gahbcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg = %08x\n", gr->gusbcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz = %08x\n", gr->grxfsiz_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n", ++ gr->gnptxfsiz_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz = %08x\n", ++ gr->hptxfsiz_local); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg = %08x\n", gr->glpmcfg_local); ++#endif ++ DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl = %08x\n", gr->gi2cctl_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl = %08x\n", gr->pcgcctl_local); ++ DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg = %08x\n",gr->gdfifocfg_local); ++ ++ return 0; ++} ++ ++/** Saves GINTMSK register before setting the msk bits. */ ++int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ gr = DWC_ALLOC(sizeof(*gr)); ++ if (!gr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->gr_backup = gr; ++ } ++ ++ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ ++ return 0; ++} ++ ++int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ if (!dr) { ++ dr = DWC_ALLOC(sizeof(*dr)); ++ if (!dr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->dr_backup = dr; ++ } ++ ++ dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dr->daintmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ dr->diepmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk); ++ dr->doepmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk); ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ dr->diepctl[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ dr->dieptsiz[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz); ++ dr->diepdma[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers==============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dcfg = %08x\n", dr->dcfg); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dctl = %08x\n", dr->dctl); ++ DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk = %08x\n", ++ dr->daintmsk); ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk = %08x\n", dr->diepmsk); ++ DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk = %08x\n", dr->doepmsk); ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d] = %08x\n", i, ++ dr->diepctl[i]); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d] = %08x\n", ++ i, dr->dieptsiz[i]); ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d] = %08x\n", i, ++ dr->diepdma[i]); ++ } ++ ++ return 0; ++} ++ ++int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_host_regs_backup *hr; ++ int i; ++ ++ hr = core_if->hr_backup; ++ if (!hr) { ++ hr = DWC_ALLOC(sizeof(*hr)); ++ if (!hr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->hr_backup = hr; ++ } ++ ++ hr->hcfg_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hr->haintmsk_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ hr->hcintmsk_local[i] = ++ DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk); ++ } ++ hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0); ++ hr->hfir_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers===============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hcfg = %08x\n", ++ hr->hcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i, ++ hr->hcintmsk_local[i]); ++ } ++ DWC_DEBUGPL(DBG_ANY, "Backed up hprt0 = %08x\n", ++ hr->hprt0_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hfir = %08x\n", ++ hr->hfir_local); ++ ++ return 0; ++} ++ ++int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, ++ gr->gnptxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz, ++ gr->hptxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg, ++ gr->gdfifocfg_local); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i], ++ gr->dtxfsiz_local[i]); ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, ++ (gr->gahbcfg_local)); ++ return 0; ++} ++ ++int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup) ++{ ++ struct dwc_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ ++ if (!dr) { ++ return -DWC_E_INVALID; ++ } ++ ++ if (!rem_wakeup) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dr->dctl); ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk); ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]); ++ } ++ ++ return 0; ++} ++ ++int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset) ++{ ++ struct dwc_otg_host_regs_backup *hr; ++ int i; ++ hr = core_if->hr_backup; ++ ++ if (!hr) { ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local); ++ //if (!reset) ++ //{ ++ // DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local); ++ //} ++ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, ++ hr->haintmsk_local); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, ++ hr->hcintmsk_local[i]); ++ } ++ ++ return 0; ++} ++ ++int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ ++ /* Restore values for LPM and I2C */ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local); ++#endif ++ DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local); ++ ++ return 0; ++} ++ ++int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ /* Restore LPM and I2C registers */ ++ restore_lpm_i2c_regs(core_if); ++ ++ /* Set PCGCCTL to 0 */ ++ DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000); ++ ++ gr = core_if->gr_backup; ++ /* Load restore values for [31:14] bits */ ++ DWC_WRITE_REG32(core_if->pcgcctl, ++ ((gr->pcgcctl_local & 0xffffc000) | 0x00020000)); ++ ++ /* Umnask global Interrupt in GAHBCFG and restore it */ ++ gahbcfg.d32 = gr->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Unmask restore done interrupt */ ++ gintmsk.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++ ++ /* Restore GUSBCFG and HCFG/DCFG */ ++ gusbcfg.d32 = core_if->gr_backup->gusbcfg_local; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ ++ if (is_host) { ++ hcfg_data_t hcfg = {.d32 = 0 }; ++ hcfg.d32 = core_if->hr_backup->hcfg_local; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ /* Load restore values for [31:14] bits and set EssRegRestored bit */ ++ pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } else { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ dcfg.d32 = core_if->dr_backup->dcfg; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ if (!rmode) { ++ pcgcctl.d32 |= 0x208; ++ } ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (!rmode) ++ pcgcctl.d32 |= 0x208; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } ++ ++ return 0; ++} ++ ++/** ++ * 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; ++ } ++ ++ DWC_DEBUGPL(DBG_CIL, "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); ++} ++ ++/** ++ * Initializes the DevSpd field of the DCFG register depending on the PHY type ++ * and the enumeration speed of the device. ++ */ ++static void init_devspd(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t val; ++ dcfg_data_t dcfg; ++ ++ 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 = 0x3; ++ } else if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { ++ /* High speed PHY running at full speed */ ++ val = 0x1; ++ } else { ++ /* High speed PHY running at high speed */ ++ val = 0x0; ++ } ++ ++ DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); ++ ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++} ++ ++/** ++ * This function calculates the number of IN EPS ++ * using GHWCFG1 and GHWCFG2 registers values ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ */ ++static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t num_in_eps = 0; ++ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; ++ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 3; ++ uint32_t num_tx_fifos = core_if->hwcfg4.b.num_in_eps; ++ int i; ++ ++ for (i = 0; i < num_eps; ++i) { ++ if (!(hwcfg1 & 0x1)) ++ num_in_eps++; ++ ++ hwcfg1 >>= 2; ++ } ++ ++ if (core_if->hwcfg4.b.ded_fifo_en) { ++ num_in_eps = ++ (num_in_eps > num_tx_fifos) ? num_tx_fifos : num_in_eps; ++ } ++ ++ return num_in_eps; ++} ++ ++/** ++ * This function calculates the number of OUT EPS ++ * using GHWCFG1 and GHWCFG2 registers values ++ * ++ * @param core_if Programming view of the DWC_otg controller ++ */ ++static uint32_t calc_num_out_eps(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t num_out_eps = 0; ++ uint32_t num_eps = core_if->hwcfg2.b.num_dev_ep; ++ uint32_t hwcfg1 = core_if->hwcfg1.d32 >> 2; ++ int i; ++ ++ for (i = 0; i < num_eps; ++i) { ++ if (!(hwcfg1 & 0x1)) ++ num_out_eps++; ++ ++ hwcfg1 >>= 2; ++ } ++ return num_out_eps; ++} ++ ++/** ++ * 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) ++{ ++ int i = 0; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t usbcfg = {.d32 = 0 }; ++ gi2cctl_data_t i2cctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "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); ++ ++ core_if->adp_enable = core_if->core_params->adp_supp_enable; ++ core_if->power_down = core_if->core_params->power_down; ++ core_if->otg_sts = 0; ++ ++ /* Initialize parameters from Hardware configuration registers. */ ++ dev_if->num_in_eps = calc_num_in_eps(core_if); ++ dev_if->num_out_eps = calc_num_out_eps(core_if); ++ ++ DWC_DEBUGPL(DBG_CIL, "num_dev_perio_in_ep=%d\n", ++ core_if->hwcfg4.b.num_dev_perio_in_ep); ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ dev_if->perio_tx_fifo_size[i] = ++ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; ++ DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->perio_tx_fifo_size[i]); ++ } ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ dev_if->tx_fifo_size[i] = ++ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; ++ DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", ++ i, dev_if->tx_fifo_size[i]); ++ } ++ ++ 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; ++ ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "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; ++ DWC_DEBUGPL(DBG_CIL, "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); ++ } else { ++ init_devspd(core_if); ++ } ++ ++ if (core_if->core_params->i2c_enable) { ++ DWC_DEBUGPL(DBG_CIL, "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. */ ++ ++ if (core_if->core_params->phy_type == 2) { ++ /* ULPI interface */ ++ usbcfg.b.ulpi_utmi_sel = 1; ++ usbcfg.b.phyif = 0; ++ usbcfg.b.ddrsel = ++ core_if->core_params->phy_ulpi_ddr; ++ } else if (core_if->core_params->phy_type == 1) { ++ /* UTMI+ interface */ ++ usbcfg.b.ulpi_utmi_sel = 0; ++ if (core_if->core_params->phy_utmi_width == 16) { ++ usbcfg.b.phyif = 1; ++ ++ } else { ++ usbcfg.b.phyif = 0; ++ } ++ } else { ++ DWC_ERROR("FS PHY TYPE\n"); ++ } ++ 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)) { ++ DWC_DEBUGPL(DBG_CIL, "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: ++ DWC_DEBUGPL(DBG_CIL, "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: ++ DWC_DEBUGPL(DBG_CIL, "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: ++ DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n"); ++ /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for ++ Host mode ISOC in issue fix - vahrama */ ++ /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */ ++ ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4; ++ 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) { ++ DWC_PRINTF("Using Descriptor DMA mode\n"); ++ } else { ++ DWC_PRINTF("Using Buffer DMA mode\n"); ++ ++ } ++ } else { ++ DWC_PRINTF("Using Slave mode\n"); ++ core_if->dma_desc_enable = 0; ++ } ++ ++ if (core_if->core_params->ahb_single) { ++ ahbcfg.b.ahbsingle = 1; ++ } ++ ++ ahbcfg.b.dmaenable = core_if->dma_enable; ++ 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; ++ DWC_PRINTF("Periodic Transfer Interrupt Enhancement - %s\n", ++ ((core_if->pti_enh_enable) ? "enabled" : "disabled")); ++ DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n", ++ ((core_if->multiproc_int_enable) ? "enabled" : "disabled")); ++ ++ /* ++ * 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); ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->core_params->lpm_enable) { ++ glpmcfg_data_t lpmcfg = {.d32 = 0 }; ++ ++ /* To enable LPM support set lpm_cap_en bit */ ++ lpmcfg.b.lpm_cap_en = 1; ++ ++ /* Make AppL1Res ACK */ ++ lpmcfg.b.appl_resp = 1; ++ ++ /* Retry 3 times */ ++ lpmcfg.b.retry_count = 3; ++ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg, ++ 0, lpmcfg.d32); ++ ++ } ++#endif ++ 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); ++ } ++ { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.otgver = core_if->core_params->otg_ver; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, ++ gotgctl.d32); ++ /* Set OTG version supported */ ++ core_if->otg_ver = core_if->core_params->otg_ver; ++ DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n", ++ core_if->core_params->otg_ver, core_if->otg_ver); ++ } ++ ++ ++ /* Enable common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* Do device or host intialization based on mode during PCD ++ * and HCD initialization */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY, "Host Mode\n"); ++ core_if->op_state = A_HOST; ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "Device Mode\n"); ++ core_if->op_state = B_PERIPHERAL; ++#ifdef DWC_DEVICE_ONLY ++ dwc_otg_core_dev_init(core_if); ++#endif ++ } ++} ++ ++/** ++ * This function enables the Device mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* Enable interrupts */ ++ intr_mask.b.usbreset = 1; ++ intr_mask.b.enumdone = 1; ++ /* Disable Disconnect interrupt in Device mode */ ++ intr_mask.b.disconnect = 0; ++ ++ if (!core_if->multiproc_int_enable) { ++ intr_mask.b.inepintr = 1; ++ intr_mask.b.outepintr = 1; ++ } ++ ++ intr_mask.b.erlysuspend = 1; ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.epmismatch = 1; ++ } ++ ++ //intr_mask.b.incomplisoout = 1; ++ intr_mask.b.incomplisoin = 1; ++ ++/* Enable the ignore frame number for ISOC xfers - MAS */ ++/* Disable to support high bandwith ISOC transfers - manukz */ ++#if 0 ++#ifdef DWC_UTE_PER_IO ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dctl_data_t dctl1 = {.d32 = 0 }; ++ dctl1.b.ifrmnum = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl1.d32); ++ DWC_DEBUG("----Enabled Ignore frame number (0x%08x)", ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl)); ++ } ++ } ++#endif ++#endif ++#ifdef DWC_EN_ISOC ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (core_if->pti_enh_enable) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.ifrmnum = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); ++ } else { ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++ } ++ } ++ } else { ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ /** @todo NGS: Should this be a module parameter? */ ++#ifdef USE_PERIODIC_EP ++ intr_mask.b.isooutdrop = 1; ++ intr_mask.b.eopframe = 1; ++ intr_mask.b.incomplisoin = 1; ++ intr_mask.b.incomplisoout = 1; ++#endif ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, ++ DWC_READ_REG32(&global_regs->gintmsk)); ++} ++ ++/** ++ * This function initializes the DWC_otg controller registers for ++ * device mode. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ * ++ */ ++void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_core_params_t *params = core_if->core_params; ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint32_t rx_fifo_size; ++ fifosize_data_t nptxfifosize; ++ fifosize_data_t txfifosize; ++ dthrctl_data_t dthrctl; ++ fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ hwcfg3_data_t hwcfg3 = {.d32 = 0 }; ++ ++ /* Restart the Phy Clock */ ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ ++ /* Device configuration register */ ++ init_devspd(core_if); ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0; ++ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80; ++ /* Enable Device OUT NAK in case of DDMA mode*/ ++ if (core_if->core_params->dev_out_nak) { ++ dcfg.b.endevoutnak = 1; ++ } ++ ++ if (core_if->core_params->cont_on_bna) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.encontonbna = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Configure data FIFO sizes */ ++ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->dev_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->dev_nperio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz); ++ core_if->init_rxfsiz = params->dev_rx_fifo_size; ++#endif ++ rx_fifo_size = params->dev_rx_fifo_size; ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); ++ ++ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++ /** Set Periodic Tx FIFO Mask all bits 0 */ ++ core_if->p_tx_msk = 0; ++ ++ /** Set Tx FIFO Mask all bits 0 */ ++ core_if->tx_msk = 0; ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, ++ nptxfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ /**@todo NGS: Fix Periodic FIFO Sizing! */ ++ /* ++ * Periodic Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_perio_tx_fifo_size array and the FIFO size registers in ++ * the dptxfsiz array run from 0 to 14. ++ */ ++ /** @todo Finish debug of this */ ++ ptxfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { ++ ptxfifosize.b.depth = ++ params->dev_perio_tx_fifo_size[i]; ++ DWC_DEBUGPL(DBG_CIL, ++ "initial dtxfsiz[%d]=%08x\n", i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ ptxfifosize.d32); ++ DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ptxfifosize.b.startaddr += ptxfifosize.b.depth; ++ } ++ } else { ++ /* ++ * Tx FIFOs These FIFOs are numbered from 1 to 15. ++ * Indexes of the FIFO size module parameters in the ++ * dev_tx_fifo_size array and the FIFO size registers in ++ * the dtxfsiz array run from 0 to 14. ++ */ ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_gnptxfsiz = ++ (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ core_if->init_gnptxfsiz = ++ params->dev_nperio_tx_fifo_size; ++#endif ++ nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; ++ nptxfifosize.b.startaddr = params->dev_rx_fifo_size; ++ ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, ++ nptxfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ txfifosize.b.startaddr = ++ nptxfifosize.b.startaddr + nptxfifosize.b.depth; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { ++ ++ txfifosize.b.depth = ++ params->dev_tx_fifo_size[i]; ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "initial dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ++#ifdef DWC_UTE_CFI ++ core_if->pwron_txfsiz[i] = ++ (DWC_READ_REG32 ++ (&global_regs->dtxfsiz[i]) >> 16); ++ core_if->init_txfsiz[i] = ++ params->dev_tx_fifo_size[i]; ++#endif ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], ++ txfifosize.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "new dtxfsiz[%d]=%08x\n", ++ i, ++ DWC_READ_REG32(&global_regs->dtxfsiz ++ [i])); ++ ++ txfifosize.b.startaddr += txfifosize.b.depth; ++ } ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */ ++ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); ++ hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3); ++ gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16); ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz; ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } ++ } ++ ++ /* Flush the FIFOs */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); ++ ++ /* Flush the Learning Queue. */ ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]); ++ } ++ DWC_DEBUGPL(DBG_CILV,"\n"); ++ } ++ ++ /* Clear all pending Device Interrupts */ ++ /** @todo - if the condition needed to be checked ++ * or in any case all pending interrutps should be cleared? ++ */ ++ if (core_if->multiproc_int_enable) { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&dev_if-> ++ dev_global_regs->diepeachintmsk[i], 0); ++ } ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ DWC_WRITE_REG32(&dev_if-> ++ dev_global_regs->doepeachintmsk[i], 0); ++ } ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0); ++ } else { ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0); ++ } ++ ++ for (i = 0; i <= dev_if->num_in_eps; i++) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena) { ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } else { ++ depctl.d32 = 0; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF); ++ } ++ ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (depctl.b.epena) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintsts = {.d32 = 0 }; ++ doepint_data_t doepint = {.d32 = 0 }; ++ dctl.b.sgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ do { ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ do { ++ dwc_udelay(10); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[i]->doepint); ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ depctl.d32 = 0; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF); ++ } ++ ++ if (core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ dev_if->non_iso_tx_thr_en = params->thr_ctl & 0x1; ++ dev_if->iso_tx_thr_en = (params->thr_ctl >> 1) & 0x1; ++ dev_if->rx_thr_en = (params->thr_ctl >> 2) & 0x1; ++ ++ dev_if->rx_thr_length = params->rx_thr_length; ++ dev_if->tx_thr_length = params->tx_thr_length; ++ ++ dev_if->setup_desc_index = 0; ++ ++ dthrctl.d32 = 0; ++ dthrctl.b.non_iso_thr_en = dev_if->non_iso_tx_thr_en; ++ dthrctl.b.iso_thr_en = dev_if->iso_tx_thr_en; ++ dthrctl.b.tx_thr_len = dev_if->tx_thr_length; ++ dthrctl.b.rx_thr_en = dev_if->rx_thr_en; ++ dthrctl.b.rx_thr_len = dev_if->rx_thr_length; ++ dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio; ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl, ++ dthrctl.d32); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ "Non ISO Tx Thr - %d\nISO Tx Thr - %d\nRx Thr - %d\nTx Thr Len - %d\nRx Thr Len - %d\n", ++ dthrctl.b.non_iso_thr_en, dthrctl.b.iso_thr_en, ++ dthrctl.b.rx_thr_en, dthrctl.b.tx_thr_len, ++ dthrctl.b.rx_thr_len); ++ ++ } ++ ++ dwc_otg_enable_device_interrupts(core_if); ++ ++ { ++ diepmsk_data_t msk = {.d32 = 0 }; ++ msk.b.txfifoundrn = 1; ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[0], msk.d32, msk.d32); ++ } else { ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, ++ msk.d32, msk.d32); ++ } ++ } ++ ++ if (core_if->multiproc_int_enable) { ++ /* Set NAK on Babble */ ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.nakonbble = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ ++ if (core_if->snpsid >= OTG_CORE_REV_2_94a) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.sftdiscon = 0; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++} ++ ++/** ++ * This function enables the Host mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts. */ ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Enable the common interrupts */ ++ dwc_otg_enable_common_interrupts(core_if); ++ ++ /* ++ * Enable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ ++ intr_mask.b.disconnect = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++} ++ ++/** ++ * This function disables the Host Mode interrupts. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s()\n", __func__); ++ ++ /* ++ * Disable host mode interrupts without disturbing common ++ * interrupts. ++ */ ++ intr_mask.b.sofintr = 1; ++ intr_mask.b.portintr = 1; ++ intr_mask.b.hcintr = 1; ++ intr_mask.b.ptxfempty = 1; ++ intr_mask.b.nptxfempty = 1; ++ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0); ++} ++ ++/** ++ * 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; ++ uint16_t rxfsiz, nptxfsiz, hptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ int i; ++ hcchar_data_t hcchar; ++ hcfg_data_t hcfg; ++ hfir_data_t hfir; ++ dwc_otg_hc_regs_t *hc_regs; ++ int num_channels; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_CILV, "%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); ++ ++ } ++ ++ /* This bit allows dynamic reloading of the HFIR register ++ * during runtime. This bit needs to be programmed during ++ * initial configuration and its value must not be changed ++ * during runtime.*/ ++ if (core_if->core_params->reload_ctl == 1) { ++ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.hfirrldctrl = 1; ++ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.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)))) { ++ ++ DWC_ERROR("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) { ++ DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", ++ core_if->total_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "Rx FIFO Size=%d\n", ++ params->host_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "NP Tx FIFO Size=%d\n", ++ params->host_nperio_tx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "P Tx FIFO Size=%d\n", ++ params->host_perio_tx_fifo_size); ++ ++ /* Rx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ DWC_WRITE_REG32(&global_regs->grxfsiz, ++ params->host_rx_fifo_size); ++ DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ ++ /* Non-periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "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); ++ DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); ++ ++ /* Periodic Tx FIFO */ ++ DWC_DEBUGPL(DBG_CIL, "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); ++ DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", ++ DWC_READ_REG32(&global_regs->hptxfsiz)); ++ ++ if (core_if->en_multiple_tx_fifo ++ && core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */ ++ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); ++ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz; ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } ++ } ++ ++ /* TODO - check this */ ++ /* 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); ++ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ ++ 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); ++ DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs); ++ do { ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (++count > 1000) { ++ DWC_ERROR ++ ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n", ++ __func__, i, hcchar.d32, &hc_regs->hcchar); ++ break; ++ } ++ dwc_udelay(1); ++ } while (hcchar.b.chen); ++ } ++ } ++ ++ /* Turn on the vbus power. */ ++ DWC_PRINTF("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); ++ DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(host_if->hprt0, hprt0.d32); ++ } ++ } ++ ++ dwc_otg_enable_host_interrupts(core_if); ++} ++ ++/** ++ * 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, dwc_hc_t * hc) ++{ ++ uint32_t intr_enable; ++ hcintmsk_data_t hc_intr_mask; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ ++ uint8_t hc_num = hc->hc_num; ++ 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); ++ ++ /* Enable channel interrupts required for this transfer. */ ++ hc_intr_mask.d32 = 0; ++ hc_intr_mask.b.chhltd = 1; ++ if (core_if->dma_enable) { ++ /* For Descriptor DMA mode core halts the channel on AHB error. Interrupt is not required */ ++ if (!core_if->dma_desc_enable) ++ hc_intr_mask.b.ahberr = 1; ++ else { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ hc_intr_mask.b.xfercompl = 1; ++ } ++ ++ if (hc->error_state && !hc->do_split && ++ hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ hc_intr_mask.b.ack = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) { ++ hc_intr_mask.b.nak = 1; ++ } ++ } ++ } ++ } else { ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } else { ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.nyet = 1; ++ if (hc->do_ping) { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ hc_intr_mask.b.nak = 1; ++ if (hc->complete_split) { ++ hc_intr_mask.b.nyet = 1; ++ } else { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ ++ if (hc->error_state) { ++ hc_intr_mask.b.ack = 1; ++ } ++ break; ++ case DWC_OTG_EP_TYPE_INTR: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.nak = 1; ++ hc_intr_mask.b.stall = 1; ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.datatglerr = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.bblerr = 1; ++ } ++ if (hc->error_state) { ++ hc_intr_mask.b.ack = 1; ++ } ++ if (hc->do_split) { ++ if (hc->complete_split) { ++ hc_intr_mask.b.nyet = 1; ++ } else { ++ hc_intr_mask.b.ack = 1; ++ } ++ } ++ break; ++ case DWC_OTG_EP_TYPE_ISOC: ++ hc_intr_mask.b.xfercompl = 1; ++ hc_intr_mask.b.frmovrun = 1; ++ hc_intr_mask.b.ack = 1; ++ ++ if (hc->ep_is_in) { ++ hc_intr_mask.b.xacterr = 1; ++ hc_intr_mask.b.bblerr = 1; ++ } ++ break; ++ } ++ } ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32); ++ ++ /* Enable the top level host channel interrupt. */ ++ intr_enable = (1 << hc_num); ++ DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable); ++ ++ /* Make sure host channel interrupts are enabled. */ ++ gintmsk.b.hcintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); ++ ++ /* ++ * Program the HCCHARn register with the endpoint characteristics for ++ * the current transfer. ++ */ ++ hcchar.d32 = 0; ++ hcchar.b.devaddr = hc->dev_addr; ++ hcchar.b.epnum = hc->ep_num; ++ hcchar.b.epdir = hc->ep_is_in; ++ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); ++ hcchar.b.eptype = hc->ep_type; ++ hcchar.b.mps = hc->max_packet; ++ ++ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n", ++ __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum); ++ DWC_DEBUGPL(DBG_HCDV, " Is In %d, Is Low Speed %d, EP Type %d, " ++ "Max Pkt %d, Multi Cnt %d\n", ++ hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype, ++ hcchar.b.mps, hcchar.b.multicnt); ++ ++ /* ++ * Program the HCSPLIT register for SPLITs ++ */ ++ hcsplt.d32 = 0; ++ if (hc->do_split) { ++ DWC_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", ++ hc->hc_num, ++ hc->complete_split ? "CSPLIT" : "SSPLIT"); ++ hcsplt.b.compsplt = hc->complete_split; ++ hcsplt.b.xactpos = hc->xact_pos; ++ hcsplt.b.hubaddr = hc->hub_addr; ++ hcsplt.b.prtaddr = hc->port_addr; ++ DWC_DEBUGPL(DBG_HCDV, "\t comp split %d\n", hc->complete_split); ++ DWC_DEBUGPL(DBG_HCDV, "\t xact pos %d\n", hc->xact_pos); ++ DWC_DEBUGPL(DBG_HCDV, "\t hub addr %d\n", hc->hub_addr); ++ DWC_DEBUGPL(DBG_HCDV, "\t port addr %d\n", hc->port_addr); ++ DWC_DEBUGPL(DBG_HCDV, "\t is_in %d\n", hc->ep_is_in); ++ DWC_DEBUGPL(DBG_HCDV, "\t Max Pkt: %d\n", hcchar.b.mps); ++ DWC_DEBUGPL(DBG_HCDV, "\t xferlen: %d\n", hc->xfer_len); ++ } ++ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); ++ ++} ++ ++/** ++ * Attempts to halt a host channel. This function should only be called in ++ * Slave mode or to abort a transfer in either Slave mode or DMA mode. Under ++ * normal circumstances in DMA mode, the controller halts the channel when the ++ * transfer is complete or a condition occurs that requires application ++ * intervention. ++ * ++ * In slave mode, checks for a free request queue entry, then sets the Channel ++ * Enable and Channel Disable bits of the Host Channel Characteristics ++ * register of the specified channel to intiate the halt. If there is no free ++ * request queue entry, sets only the Channel Disable bit of the HCCHARn ++ * register to flush requests for this channel. In the latter case, sets a ++ * flag to indicate that the host channel needs to be halted when a request ++ * queue slot is open. ++ * ++ * In DMA mode, always sets the Channel Enable and Channel Disable bits of the ++ * HCCHARn register. The controller ensures there is space in the request ++ * queue before submitting the halt request. ++ * ++ * Some time may elapse before the core flushes any posted requests for this ++ * host channel and halts. The Channel Halted interrupt handler completes the ++ * deactivation of the host channel. ++ * ++ * @param core_if Controller register interface. ++ * @param hc Host channel to halt. ++ * @param halt_status Reason for halting the channel. ++ */ ++void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc, dwc_otg_halt_status_e halt_status) ++{ ++ gnptxsts_data_t nptxsts; ++ hptxsts_data_t hptxsts; ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs; ++ dwc_otg_core_global_regs_t *global_regs; ++ dwc_otg_host_global_regs_t *host_global_regs; ++ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ global_regs = core_if->core_global_regs; ++ host_global_regs = core_if->host_if->host_global_regs; ++ ++ DWC_ASSERT(!(halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS), ++ "halt_status = %d\n", halt_status); ++ ++ if (halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || ++ halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ /* ++ * Disable all channel interrupts except Ch Halted. The QTD ++ * and QH state associated with this transfer has been cleared ++ * (in the case of URB_DEQUEUE), so the channel needs to be ++ * shut down carefully to prevent crashes. ++ */ ++ hcintmsk_data_t hcintmsk; ++ hcintmsk.d32 = 0; ++ hcintmsk.b.chhltd = 1; ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32); ++ ++ /* ++ * Make sure no other interrupts besides halt are currently ++ * pending. Handling another interrupt could cause a crash due ++ * to the QTD and QH state. ++ */ ++ DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32); ++ ++ /* ++ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR ++ * even if the channel was already halted for some other ++ * reason. ++ */ ++ hc->halt_status = halt_status; ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen == 0) { ++ /* ++ * The channel is either already halted or it hasn't ++ * started yet. In DMA mode, the transfer may halt if ++ * it finishes normally or a condition occurs that ++ * requires driver intervention. Don't want to halt ++ * the channel again. In either Slave or DMA mode, ++ * it's possible that the transfer has been assigned ++ * to a channel, but not started yet when an URB is ++ * dequeued. Don't want to halt a channel that hasn't ++ * started yet. ++ */ ++ return; ++ } ++ } ++ if (hc->halt_pending) { ++ /* ++ * A halt has already been issued for this channel. This might ++ * happen when a transfer is aborted by a higher level in ++ * the stack. ++ */ ++#ifdef DEBUG ++ DWC_PRINTF ++ ("*** %s: Channel %d, _hc->halt_pending already set ***\n", ++ __func__, hc->hc_num); ++ ++#endif ++ return; ++ } ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* No need to set the bit in DDMA for disabling the channel */ ++ //TODO check it everywhere channel is disabled ++ if (!core_if->core_params->dma_desc_enable) ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 1; ++ ++ if (!core_if->dma_enable) { ++ /* Check for space in the request queue to issue the halt. */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { ++ nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ if (nptxsts.b.nptxqspcavail == 0) { ++ hcchar.b.chen = 0; ++ } ++ } else { ++ hptxsts.d32 = ++ DWC_READ_REG32(&host_global_regs->hptxsts); ++ if ((hptxsts.b.ptxqspcavail == 0) ++ || (core_if->queuing_high_bandwidth)) { ++ hcchar.b.chen = 0; ++ } ++ } ++ } ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ hc->halt_status = halt_status; ++ ++ if (hcchar.b.chen) { ++ hc->halt_pending = 1; ++ hc->halt_on_queue = 0; ++ } else { ++ hc->halt_on_queue = 1; ++ } ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n", hcchar.d32); ++ DWC_DEBUGPL(DBG_HCDV, " halt_pending: %d\n", hc->halt_pending); ++ DWC_DEBUGPL(DBG_HCDV, " halt_on_queue: %d\n", hc->halt_on_queue); ++ DWC_DEBUGPL(DBG_HCDV, " halt_status: %d\n", hc->halt_status); ++ ++ return; ++} ++ ++/** ++ * Clears the transfer state for a host channel. This function is normally ++ * called after a transfer is done and the host channel is being released. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Identifies the host channel to clean up. ++ */ ++void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ dwc_otg_hc_regs_t *hc_regs; ++ ++ hc->xfer_started = 0; ++ ++ /* ++ * Clear channel interrupt enables and any unhandled channel interrupt ++ * conditions. ++ */ ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0); ++ DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF); ++#ifdef DEBUG ++ DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]); ++#endif ++} ++ ++/** ++ * Sets the channel property that indicates in which frame a periodic transfer ++ * should occur. This is always set to the _next_ frame. This function has no ++ * effect on non-periodic transfers. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Identifies the host channel to set up and its properties. ++ * @param hcchar Current value of the HCCHAR register for the specified host ++ * channel. ++ */ ++static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc, hcchar_data_t * hcchar) ++{ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ hfnum_data_t hfnum; ++ hfnum.d32 = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum); ++ ++ /* 1 if _next_ frame is odd, 0 if it's even */ ++ hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; ++#ifdef DEBUG ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR && hc->do_split ++ && !hc->complete_split) { ++ switch (hfnum.b.frnum & 0x7) { ++ case 7: ++ core_if->hfnum_7_samples++; ++ core_if->hfnum_7_frrem_accum += hfnum.b.frrem; ++ break; ++ case 0: ++ core_if->hfnum_0_samples++; ++ core_if->hfnum_0_frrem_accum += hfnum.b.frrem; ++ break; ++ default: ++ core_if->hfnum_other_samples++; ++ core_if->hfnum_other_frrem_accum += ++ hfnum.b.frrem; ++ break; ++ } ++ } ++#endif ++ } ++} ++ ++#ifdef DEBUG ++void hc_xfer_timeout(void *ptr) ++{ ++ hc_xfer_info_t *xfer_info = NULL; ++ int hc_num = 0; ++ ++ if (ptr) ++ xfer_info = (hc_xfer_info_t *) ptr; ++ ++ if (!xfer_info->hc) { ++ DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc); ++ return; ++ } ++ ++ hc_num = xfer_info->hc->hc_num; ++ DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num); ++ DWC_WARN(" start_hcchar_val 0x%08x\n", ++ xfer_info->core_if->start_hcchar_val[hc_num]); ++} ++#endif ++ ++void ep_xfer_timeout(void *ptr) ++{ ++ ep_xfer_info_t *xfer_info = NULL; ++ int ep_num = 0; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (ptr) ++ xfer_info = (ep_xfer_info_t *) ptr; ++ ++ if (!xfer_info->ep) { ++ DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep); ++ return; ++ } ++ ++ ep_num = xfer_info->ep->num; ++ DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num); ++ /* Put the sate to 2 as it was time outed */ ++ xfer_info->state = 2; ++ ++ dctl.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts); ++ gintmsk.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk); ++ ++ if (!gintmsk.b.goutnakeff) { ++ /* Unmask it */ ++ gintmsk.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk, ++ gintmsk.d32); ++ ++ } ++ ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++} ++ ++void set_pid_isoc(dwc_hc_t * hc) ++{ ++ /* Set up the initial PID for the transfer. */ ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) { ++ if (hc->ep_is_in) { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } else if (hc->multi_count == 2) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA2; ++ } ++ } else { ++ if (hc->multi_count == 1) { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_MDATA; ++ } ++ } ++ } else { ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for a host channel and ++ * starts the transfer. May be called in either Slave mode or DMA mode. In ++ * Slave mode, the caller must ensure that there is sufficient space in the ++ * request queue and Tx Data FIFO. ++ * ++ * For an OUT transfer in Slave mode, it loads a data packet into the ++ * appropriate FIFO. If necessary, additional data packets will be loaded in ++ * the Host ISR. ++ * ++ * For an IN transfer in Slave mode, a data packet is requested. The data ++ * packets are unloaded from the Rx FIFO in the Host ISR. If necessary, ++ * additional data packets are requested in the Host ISR. ++ * ++ * For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ ++ * register along with a packet count of 1 and the channel is enabled. This ++ * causes a single PING transaction to occur. Other fields in HCTSIZ are ++ * simply set to 0 since no data transfer occurs in this case. ++ * ++ * For a PING transfer in DMA mode, the HCTSIZ register is initialized with ++ * all the information required to perform the subsequent data transfer. In ++ * addition, the Do Ping bit is set in the HCTSIZ register. In this case, the ++ * controller performs the entire PING protocol, then starts the data ++ * transfer. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Information needed to initialize the host channel. The xfer_len ++ * value may be reduced to accommodate the max widths of the XferSize and ++ * PktCnt fields in the HCTSIZn register. The multi_count value may be changed ++ * to reflect the final xfer_len value. ++ */ ++void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ uint16_t num_packets; ++ uint32_t max_hc_xfer_size = core_if->core_params->max_transfer_size; ++ uint16_t max_hc_pkt_count = core_if->core_params->max_packet_count; ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) { ++ if (!core_if->dma_enable) { ++ dwc_otg_hc_do_ping(core_if, hc); ++ hc->xfer_started = 1; ++ return; ++ } else { ++ hctsiz.b.dopng = 1; ++ } ++ } ++ ++ if (hc->do_split) { ++ num_packets = 1; ++ ++ if (hc->complete_split && !hc->ep_is_in) { ++ /* For CSPLIT OUT Transfer, set the size to 0 so the ++ * core doesn't expect any data written to the FIFO */ ++ hc->xfer_len = 0; ++ } else if (hc->ep_is_in || (hc->xfer_len > hc->max_packet)) { ++ hc->xfer_len = hc->max_packet; ++ } else if (!hc->ep_is_in && (hc->xfer_len > 188)) { ++ hc->xfer_len = 188; ++ } ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } else { ++ /* ++ * Ensure that the transfer length and packet count will fit ++ * in the widths allocated for them in the HCTSIZn register. ++ */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure the transfer size is no larger than one ++ * (micro)frame's worth of data. (A check was done ++ * when the periodic transfer was accepted to ensure ++ * that a (micro)frame's worth of data can be ++ * programmed into a channel.) ++ */ ++ uint32_t max_periodic_len = ++ hc->multi_count * hc->max_packet; ++ if (hc->xfer_len > max_periodic_len) { ++ hc->xfer_len = max_periodic_len; ++ } else { ++ } ++ } else if (hc->xfer_len > max_hc_xfer_size) { ++ /* Make sure that xfer_len is a multiple of max packet size. */ ++ hc->xfer_len = max_hc_xfer_size - hc->max_packet + 1; ++ } ++ ++ if (hc->xfer_len > 0) { ++ num_packets = ++ (hc->xfer_len + hc->max_packet - ++ 1) / hc->max_packet; ++ if (num_packets > max_hc_pkt_count) { ++ num_packets = max_hc_pkt_count; ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ ++ if (hc->ep_is_in) { ++ /* Always program an integral # of max packets for IN transfers. */ ++ hc->xfer_len = num_packets * hc->max_packet; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * Make sure that the multi_count field matches the ++ * actual transfer length. ++ */ ++ hc->multi_count = num_packets; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ set_pid_isoc(hc); ++ ++ hctsiz.b.xfersize = hc->xfer_len; ++ } ++ ++ hc->start_pkt_count = num_packets; ++ hctsiz.b.pktcnt = num_packets; ++ hctsiz.b.pid = hc->data_pid_start; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); ++ DWC_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n", hctsiz.b.pktcnt); ++ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ ++ if (core_if->dma_enable) { ++ dwc_dma_t dma_addr; ++ if (hc->align_buff) { ++ dma_addr = hc->align_buff; ++ } else { ++ dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff); ++ } ++ DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr); ++ } ++ ++ /* Start the split */ ++ if (hc->do_split) { ++ hcsplt_data_t hcsplt; ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hcsplt.b.spltena = 1; ++ DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32); ++ } ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* 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); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++ if (!core_if->dma_enable && !hc->ep_is_in && hc->xfer_len > 0) { ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ dwc_otg_hc_write_packet(core_if, hc); ++ } ++#ifdef DEBUG ++ if (hc->ep_type != DWC_OTG_EP_TYPE_INTR) { ++ DWC_DEBUGPL(DBG_HCDV, "transfer %d from core_if %p\n", ++ hc->hc_num, core_if);//GRAYG ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); ++ } ++#endif ++} ++ ++/** ++ * This function does the setup for a data transfer for a host channel ++ * and starts the transfer in Descriptor DMA mode. ++ * ++ * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. ++ * Sets PID and NTD values. For periodic transfers ++ * initializes SCHED_INFO field with micro-frame bitmap. ++ * ++ * Initializes HCDMA register with descriptor list address and CTD value ++ * then starts the transfer via enabling the channel. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param hc Information needed to initialize the host channel. ++ */ ++void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcdma_data_t hcdma; ++ ++ hctsiz.d32 = 0; ++ ++ if (hc->do_ping) ++ hctsiz.b_ddma.dopng = 1; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ set_pid_isoc(hc); ++ ++ /* Packet Count and Xfer Size are not used in Descriptor DMA mode */ ++ hctsiz.b_ddma.pid = hc->data_pid_start; ++ hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ ++ hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); ++ DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); ++ ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcdma.d32 = 0; ++ hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11; ++ ++ /* Always start from first descriptor. */ ++ hcdma.b.ctd = 0; ++ DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.multicnt = hc->multi_count; ++ ++#ifdef DEBUG ++ core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", ++ __func__, hc->hc_num, hcchar.d32); ++ } ++#endif ++ ++ /* 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); ++ ++ hc->xfer_started = 1; ++ hc->requests++; ++ ++#ifdef DEBUG ++ if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) ++ && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) { ++ DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n", ++ hc->hc_num, core_if);//GRAYG ++ core_if->hc_xfer_info[hc->hc_num].core_if = core_if; ++ core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); ++ } ++#endif ++ ++} ++ ++/** ++ * This function continues a data transfer that was started by previous call ++ * to dwc_otg_hc_start_transfer. The caller must ensure there is ++ * sufficient space in the request queue and Tx Data FIFO. This function ++ * should only be called in Slave mode. In DMA mode, the controller acts ++ * autonomously to complete transfers programmed to a host channel. ++ * ++ * For an OUT transfer, a new data packet is loaded into the appropriate FIFO ++ * if there is any data remaining to be queued. For an IN transfer, another ++ * data packet is always requested. For the SETUP phase of a control transfer, ++ * this function does nothing. ++ * ++ * @return 1 if a new request is queued, 0 if no more requests are required ++ * for this transfer. ++ */ ++int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ if (hc->do_split) { ++ /* SPLITs always queue just once per channel */ ++ return 0; ++ } else if (hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { ++ /* SETUPs are queued only once since they can't be NAKed. */ ++ return 0; ++ } else if (hc->ep_is_in) { ++ /* ++ * Always queue another request for other IN transfers. If ++ * back-to-back INs are issued and NAKs are received for both, ++ * the driver may still be processing the first NAK when the ++ * second NAK is received. When the interrupt handler clears ++ * the NAK interrupt for the first NAK, the second NAK will ++ * not be seen. So we can't depend on the NAK interrupt ++ * handler to requeue a NAKed request. Instead, IN requests ++ * are issued each time this function is called. When the ++ * transfer completes, the extra requests for the channel will ++ * be flushed. ++ */ ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs = ++ core_if->host_if->hc_regs[hc->hc_num]; ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", ++ hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ hc->requests++; ++ return 1; ++ } else { ++ /* OUT transfers. */ ++ if (hc->xfer_count < hc->xfer_len) { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ hcchar_data_t hcchar; ++ dwc_otg_hc_regs_t *hc_regs; ++ hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hc_set_even_odd_frame(core_if, hc, &hcchar); ++ } ++ ++ /* Load OUT packet into the appropriate Tx FIFO. */ ++ dwc_otg_hc_write_packet(core_if, hc); ++ hc->requests++; ++ return 1; ++ } else { ++ return 0; ++ } ++ } ++} ++ ++/** ++ * Starts a PING transfer. This function should only be called in Slave mode. ++ * The Do Ping bit is set in the HCTSIZ register, then the channel is enabled. ++ */ ++void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); ++ ++ hctsiz.d32 = 0; ++ hctsiz.b.dopng = 1; ++ hctsiz.b.pktcnt = 1; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.chen = 1; ++ hcchar.b.chdis = 0; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++} ++ ++/* ++ * This function writes a packet into the Tx FIFO associated with the Host ++ * Channel. For a channel associated with a non-periodic EP, the non-periodic ++ * Tx FIFO is written. For a channel associated with a periodic EP, the ++ * periodic Tx FIFO is written. This function should only be called in Slave ++ * mode. ++ * ++ * Upon return the xfer_buff and xfer_count fields in _hc are incremented by ++ * then number of bytes written to the Tx FIFO. ++ */ ++void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) ++{ ++ uint32_t i; ++ uint32_t remaining_count; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ ++ uint32_t *data_buff = (uint32_t *) (hc->xfer_buff); ++ uint32_t *data_fifo = core_if->data_fifo[hc->hc_num]; ++ ++ remaining_count = hc->xfer_len - hc->xfer_count; ++ if (remaining_count > hc->max_packet) { ++ byte_count = hc->max_packet; ++ } else { ++ byte_count = remaining_count; ++ } ++ ++ dword_count = (byte_count + 3) / 4; ++ ++ if ((((unsigned long)data_buff) & 0x3) == 0) { ++ /* xfer_buff is DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ DWC_WRITE_REG32(data_fifo, *data_buff); ++ } ++ } else { ++ /* xfer_buff is not DWORD aligned. */ ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ uint32_t data; ++ data = ++ (data_buff[0] | data_buff[1] << 8 | data_buff[2] << ++ 16 | data_buff[3] << 24); ++ DWC_WRITE_REG32(data_fifo, data); ++ } ++ } ++ ++ hc->xfer_count += byte_count; ++ hc->xfer_buff += byte_count; ++} ++ ++/** ++ * Gets the current USB frame number. This is the frame number from the last ++ * SOF packet. ++ */ ++uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /* read current frame/microframe number from DSTS register */ ++ return dsts.b.soffn; ++} ++ ++/** ++ * Calculates and gets the frame Interval value of HFIR register according PHY ++ * type and speed.The application can modify a value of HFIR register only after ++ * the Port Enable bit of the Host Port Control and Status register ++ * (HPRT.PrtEnaPort) has been set. ++*/ ++ ++uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ hwcfg2_data_t hwcfg2; ++ hprt0_data_t hprt0; ++ int clock = 60; // default value ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3) ++ clock = 48; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 30; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 48; ++ if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2) ++ clock = 48; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1) ++ clock = 48; ++ if (hprt0.b.prtspd == 0) ++ /* High speed case */ ++ return 125 * clock; ++ else ++ /* FS/LS case */ ++ return 1000 * clock; ++} ++ ++/** ++ * This function reads a setup packet from the Rx FIFO into the destination ++ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) ++ * Interrupt routine when a SETUP packet has been received in Slave mode. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dest Destination buffer for packet data. ++ */ ++void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest) ++{ ++ device_grxsts_data_t status; ++ /* Get the 8 bytes of a setup transaction data */ ++ ++ /* Pop 2 DWORDS off the receive data FIFO into memory */ ++ dest[0] = DWC_READ_REG32(core_if->data_fifo[0]); ++ dest[1] = DWC_READ_REG32(core_if->data_fifo[0]); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ status.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->grxstsp); ++ DWC_DEBUGPL(DBG_ANY, ++ "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, status.b.pktsts, ++ status.b.fn, status.b.fn); ++ } ++} ++ ++/** ++ * This function enables EP0 OUT to receive SETUP packets and configures EP0 ++ * IN for transmitting packets. It is normally called when the ++ * "Enumeration Done" interrupt occurs. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dsts_data_t dsts; ++ depctl_data_t diepctl; ++ depctl_data_t doepctl; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ ep->stp_rollover = 0; ++ /* Read the Device Status and Endpoint 0 Control registers */ ++ dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts); ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ ++ /* Set the MPS of the IN EP based on the enumeration speed */ ++ switch (dsts.b.enumspd) { ++ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ diepctl.b.mps = DWC_DEP0CTL_MPS_64; ++ break; ++ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ diepctl.b.mps = DWC_DEP0CTL_MPS_8; ++ break; ++ } ++ ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Enable OUT EP for receive */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ doepctl.b.epena = 1; ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++ dctl.b.cgnpinnak = 1; ++ ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n", ++ DWC_READ_REG32(&dev_if->dev_global_regs->dctl)); ++ ++} ++ ++/** ++ * This function activates an EP. The Device EP control register for ++ * the EP is configured as defined in the ep structure. Note: This ++ * function is not used for EP0. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to activate. ++ */ ++void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t depctl; ++ volatile uint32_t *addr; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++#ifdef DWC_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ /* If the EP is already active don't change the EP Control ++ * register. */ ++ depctl.d32 = DWC_READ_REG32(addr); ++ if (!depctl.b.usbactep) { ++ depctl.b.mps = ep->maxpacket; ++ depctl.b.eptype = ep->type; ++ depctl.b.txfnum = ep->tx_fifo_num; ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ depctl.b.setd0pid = 1; // ??? ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ depctl.b.usbactep = 1; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG*/ ++ if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) { // NP IN EP ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq) ++ break; ++ } ++ core_if->nextep_seq[i] = ep->num; ++ core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq; ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt++; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", ++ core_if->nextep_seq[i]); ++ } ++ ++ } ++ ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr)); ++ } ++ ++ /* Enable the Interrupt for this EP */ ++ if (core_if->multiproc_int_enable) { ++ if (ep->is_in == 1) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++ diepmsk.b.txfifoundrn = 1; //????? ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ diepmsk.b.nak = 1; ++ } ++ ++ ++ ++/* ++ if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++/* ++ if (core_if->dma_enable) { ++ doepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ diepeachintmsk[ep->num], diepmsk.d32); ++ ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ doepmsk.b.outtknepdis = 1; ++ ++/* ++ ++ if (core_if->dma_desc_enable) { ++ doepmsk.b.bna = 1; ++ } ++*/ ++/* ++ doepmsk.b.babble = 1; ++ doepmsk.b.nyet = 1; ++ doepmsk.b.nak = 1; ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> ++ doepeachintmsk[ep->num], doepmsk.d32); ++ } ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk, ++ 0, daintmsk.d32); ++ } else { ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (ep->is_in) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.nak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32); ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.outtknepdis = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32); ++ } ++ } ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk, ++ 0, daintmsk.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", ++ DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk)); ++ ++ ep->stall_clear_flag = 0; ++ ++ return; ++} ++ ++/** ++ * This function deactivates an EP. This is done by clearing the USB Active ++ * EP bit in the Device EP control register. Note: This function is not used ++ * for EP0. EP0 cannot be deactivated. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to deactivate. ++ */ ++void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i = 0; ++ ++#ifdef DWC_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif ++ ++ /* Read DEPCTLn register */ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ daintmsk.ep.in = 1 << ep->num; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ daintmsk.ep.out = 1 << ep->num; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ depctl.b.usbactep = 0; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG*/ ++ if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == ep->num) ++ break; ++ } ++ core_if->nextep_seq[i] = core_if->nextep_seq[ep->num]; ++ if (core_if->first_in_nextep_seq == ep->num) ++ core_if->first_in_nextep_seq = i; ++ core_if->nextep_seq[ep->num] = 0xff; ++ depctl.b.nextep = 0; ++ dcfg.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt--; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (ep->is_in == 1) ++ depctl.b.txfnum = 0; ++ ++ if (core_if->dma_desc_enable) ++ depctl.b.epdis = 1; ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++ if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC ++ && depctl.b.epena) { ++ depctl_data_t depctl = {.d32 = 0}; ++ if (ep->is_in) { ++ diepint_data_t diepint = {.d32 = 0}; ++ ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++ } while (!diepint.b.inepnakeff); ++ diepint.b.inepnakeff = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++ } while (!diepint.b.epdisabled); ++ diepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ } else { ++ dctl_data_t dctl = {.d32 = 0}; ++ gintmsk_data_t gintsts = {.d32 = 0}; ++ doepint_data_t doepint = {.d32 = 0}; ++ dctl.b.sgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ do { ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32); ++ do ++ { ++ dwc_udelay(10); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doepint); ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ } ++ ++ /* Disable the Interrupt for this EP */ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ daintmsk.d32, 0); ++ ++ if (ep->is_in == 1) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[ep->num], 0); ++ } else { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[ep->num], 0); ++ } ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32, 0); ++ } ++ ++} ++ ++/** ++ * This function initializes dma descriptor chain. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ uint32_t offset; ++ uint32_t xfer_est; ++ int i; ++ unsigned maxxfer_local, total_len; ++ ++ if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR && ++ (ep->maxpacket%4)) { ++ maxxfer_local = ep->maxpacket; ++ total_len = ep->xfer_len; ++ } else { ++ maxxfer_local = ep->maxxfer; ++ total_len = ep->total_len; ++ } ++ ++ ep->desc_cnt = (total_len / maxxfer_local) + ++ ((total_len % maxxfer_local) ? 1 : 0); ++ ++ if (!ep->desc_cnt) ++ ep->desc_cnt = 1; ++ ++ if (ep->desc_cnt > MAX_DMA_DESC_CNT) ++ ep->desc_cnt = MAX_DMA_DESC_CNT; ++ ++ dma_desc = ep->desc_addr; ++ if (maxxfer_local == ep->maxpacket) { ++ if ((total_len % maxxfer_local) && ++ (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) { ++ xfer_est = (ep->desc_cnt - 1) * maxxfer_local + ++ (total_len % maxxfer_local); ++ } else ++ xfer_est = ep->desc_cnt * maxxfer_local; ++ } else ++ xfer_est = total_len; ++ offset = 0; ++ for (i = 0; i < ep->desc_cnt; ++i) { ++ /** DMA Descriptor Setup */ ++ if (xfer_est > maxxfer_local) { ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 0; ++ dma_desc->status.b.ioc = 0; ++ dma_desc->status.b.sp = 0; ++ dma_desc->status.b.bytes = maxxfer_local; ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ xfer_est -= maxxfer_local; ++ offset += maxxfer_local; ++ } else { ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ if (ep->is_in) { ++ dma_desc->status.b.sp = ++ (xfer_est % ++ ep->maxpacket) ? 1 : ((ep-> ++ sent_zlp) ? 1 : 0); ++ dma_desc->status.b.bytes = xfer_est; ++ } else { ++ if (maxxfer_local == ep->maxpacket) ++ dma_desc->status.b.bytes = xfer_est; ++ else ++ dma_desc->status.b.bytes = ++ xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); ++ } ++ ++ dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ } ++ dma_desc++; ++ } ++} ++/** ++ * This function is called when to write ISOC data into appropriate dedicated ++ * periodic FIFO. ++ */ ++static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ int epnum = dwc_ep->num; ++ int dwords; ++ ++ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = dwc_ep->xfer_len - dwc_ep->xfer_count; ++ ++ if (len > dwc_ep->maxpacket) { ++ len = dwc_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail > dwords && ++ dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, dwc_ep, 0); ++ ++ len = dwc_ep->xfer_len - dwc_ep->xfer_count; ++ if (len > dwc_ep->maxpacket) { ++ len = dwc_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p, total_len = %d\n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff, ++ ep->total_len); ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ ++ gnptxsts_data_t gtxstatus; ++ ++ gtxstatus.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ if (core_if->en_multiple_tx_fifo == 0 ++ && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) { ++#ifdef DEBUG ++ DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); ++ ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? ++ MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ ++ ++ /* Zero Length Packet? */ ++ if ((ep->xfer_len - ep->xfer_count) == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - ep->xfer_count - 1 + ++ ep->maxpacket) / ep->maxpacket; ++ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { ++ deptsiz.b.pktcnt = MAX_PKT_CNT; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ } ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = deptsiz.b.pktcnt; ++ } ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (ep->type != DWC_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = 1; ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++#ifdef DWC_UTE_CFI ++ /* The descriptor chain should be already initialized by now */ ++ if (ep->buff_mode != BM_STANDARD) { ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ ep->descs_dma_addr); ++ } else { ++#endif ++ init_dma_desc_chain(core_if, ep); ++ /** DIEPDMAn Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ ep->dma_desc_addr); ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ if (ep->type != DWC_OTG_EP_TYPE_ISOC) { ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, ++ * the data will be written into the fifo by the ISR. ++ */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk = 1 << ep->num; ++ DWC_MODIFY_REG32 ++ (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ ++ } ++ } ++ } else { ++ write_isoc_tx_fifo(core_if, ep); ++ } ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0}; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ } ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); ++ ++ if (!core_if->dma_desc_enable) { ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len ++ - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ } ++ ++ /* Program the transfer size and packet count as follows: ++ * ++ * pktcnt = N ++ * xfersize = N * maxpacket ++ */ ++ if ((ep->xfer_len - ep->xfer_count) == 0) { ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - ep->xfer_count + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { ++ deptsiz.b.pktcnt = MAX_PKT_CNT; ++ } ++ if (!core_if->dma_desc_enable) { ++ ep->xfer_len = ++ deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; ++ } ++ deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "ep%d xfersize=%d pktcnt=%d\n", ++ ep->num, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++#ifdef DWC_UTE_CFI ++ /* The descriptor chain should be already initialized by now */ ++ if (ep->buff_mode != BM_STANDARD) { ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ ep->descs_dma_addr); ++ } else { ++#endif ++ /** This is used for interrupt out transfers*/ ++ if (!ep->xfer_len) ++ ep->xfer_len = ep->total_len; ++ init_dma_desc_chain(core_if, ep); ++ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == DWC_OTG_EP_TYPE_BULK) { ++ deptsiz.b.pktcnt = (ep->total_len + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = ep->total_len; ++ /* Remember initial value of doeptsiz */ ++ core_if->start_doeptsiz_val[ep->num] = deptsiz.d32; ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ } ++ } ++ /** DOEPDMAn Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ ep->dma_desc_addr); ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0}; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", ++ DWC_READ_REG32(&out_regs->doepctl), ++ DWC_READ_REG32(&out_regs->doeptsiz)); ++ DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> ++ daintmsk), ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gintmsk)); ++ ++ /* Timer is scheduling only for out bulk transfers for ++ * "Device DDMA OUT NAK Enhancement" feature to inform user ++ * about received data payload in case of timeout ++ */ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == DWC_OTG_EP_TYPE_BULK) { ++ core_if->ep_xfer_info[ep->num].core_if = core_if; ++ core_if->ep_xfer_info[ep->num].ep = ep; ++ core_if->ep_xfer_info[ep->num].state = 1; ++ ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000); ++ } ++ } ++ } ++} ++ ++/** ++ * This function setup a zero length transfer in Buffer DMA and ++ * Slave modes for usb requests with zero field set ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ ++ depctl_data_t depctl; ++ deptsiz_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s()\n", __func__); ++ DWC_PRINTF("zero length transfer is called\n"); ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); ++ ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.b.mc = 1; ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, ++ * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, ++ * the data will be written into the fifo by the ISR. ++ */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk = 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[ep->num]; ++ ++ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); ++ ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for EP0 and starts ++ * the transfer. For an IN transfer, the packets will be loaded into ++ * the appropriate Tx FIFO in the ISR. For OUT transfers, the packets are ++ * unloaded from the Rx FIFO in the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz0_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ ++ DWC_DEBUGPL(DBG_PCD, "ep%d-%s xfer_len=%d xfer_cnt=%d " ++ "xfer_buff=%p start_xfer_buff=%p \n", ++ ep->num, (ep->is_in ? "IN" : "OUT"), ep->xfer_len, ++ ep->xfer_count, ep->xfer_buff, ep->start_xfer_buff); ++ ++ ep->total_len = ep->xfer_len; ++ ++ /* IN endpoint */ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ ++ gnptxsts_data_t gtxstatus; ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ if (depctl.b.epena) ++ return; ++ } ++ ++ gtxstatus.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ /* If dedicated FIFO every time flush fifo before enable ep*/ ++ if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a) ++ dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num); ++ ++ if (core_if->en_multiple_tx_fifo == 0 ++ && gtxstatus.b.nptxqspcavail == 0 ++ && !core_if->dma_enable) { ++#ifdef DEBUG ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", ++ DWC_READ_REG32(&in_regs->diepctl)); ++ DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", ++ deptsiz.d32, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ DWC_PRINTF("TX Queue or FIFO Full (0x%0x)\n", ++ gtxstatus.d32); ++#endif ++ return; ++ } ++ ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ ++ /* Zero Length Packet? */ ++ if (ep->xfer_len == 0) { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 1; ++ } else { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ if (ep->xfer_len > ep->maxpacket) { ++ ep->xfer_len = ep->maxpacket; ++ deptsiz.b.xfersize = ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = ep->xfer_len; ++ } ++ deptsiz.b.pktcnt = 1; ++ ++ } ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ dma_desc = core_if->dev_if->in_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.sp = ++ (ep->xfer_len == ep->maxpacket) ? 0 : 1; ++ dma_desc->status.b.bytes = ep->xfer_len; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DIEPDMA0 Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ core_if-> ++ dev_if->dma_in_desc_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ } ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk |= 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ } else { ++ /* OUT endpoint */ ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[0]; ++ ++ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count as follows: ++ * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) ++ * pktcnt = N */ ++ /* Zero Length Packet */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ deptsiz.b.supcnt = 3; ++ ++ DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ } else { ++ dma_desc = core_if->dev_if->out_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.mtrf = 0; ++ dma_desc->status.b.sr = 0; ++ } ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = ep->maxpacket; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ core_if->dev_if-> ++ dma_out_desc_addr); ++ } ++ } else { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ /* EP enable */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32); ++ } ++} ++ ++/** ++ * This function continues control IN transfers started by ++ * dwc_otg_ep0_start_transfer, when the transfer does not fit in a ++ * single packet. NOTE: The DIEPCTL0/DOEPCTL0 registers only have one ++ * bit for the packet count. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP0 data. ++ */ ++void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ deptsiz0_data_t deptsiz; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ ++ if (ep->is_in == 1) { ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[0]; ++ gnptxsts_data_t tx_status = {.d32 = 0 }; ++ ++ tx_status.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ /** @todo Should there be check for room in the Tx ++ * Status Queue. If not remove the code above this comment. */ ++ ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.b.xfersize = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ deptsiz.b.pktcnt = 1; ++ if (core_if->dma_enable == 0) { ++ ep->xfer_len += deptsiz.b.xfersize; ++ } else { ++ ep->xfer_len = deptsiz.b.xfersize; ++ } ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ } else { ++ ep->xfer_len = ++ (ep->total_len - ep->xfer_count) > ++ ep->maxpacket ? ep->maxpacket : (ep->total_len - ++ ep->xfer_count); ++ ++ dma_desc = core_if->dev_if->in_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.sp = ++ (ep->xfer_len == ep->maxpacket) ? 0 : 1; ++ dma_desc->status.b.bytes = ep->xfer_len; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DIEPDMA0 Register write */ ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ core_if->dev_if->dma_in_desc_addr); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { ++ if (core_if->dma_desc_enable == 0) ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); ++ ++ /** ++ * Enable the Non-Periodic Tx FIFO empty interrupt, the ++ * data will be written into the fifo by the ISR. ++ */ ++ if (!core_if->dma_enable) { ++ if (core_if->en_multiple_tx_fifo == 0) { ++ /* First clear it from GINTSTS */ ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ ++ } else { ++ /* Enable the Tx FIFO Empty Interrupt for this EP */ ++ if (ep->xfer_len > 0) { ++ uint32_t fifoemptymsk = 0; ++ fifoemptymsk |= 1 << ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); ++ } ++ } ++ } ++ } else { ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[0]; ++ ++ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); ++ ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->maxpacket; ++ deptsiz.b.pktcnt = 1; ++ ++ if (core_if->dma_desc_enable == 0) { ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } else { ++ dma_desc = core_if->dev_if->out_desc_addr; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = ep->maxpacket; ++ dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ core_if->dev_if->dma_out_desc_addr); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN len=%d xfersize=%d pktcnt=%d [%08x]\n", ++ ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { ++ if (core_if->dma_desc_enable == 0) ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) ep->dma_addr); ++ ++ } ++ ++ /* EP enable, IN data in FIFO */ ++ depctl.b.cnak = 1; ++ depctl.b.epena = 1; ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); ++ ++ } ++} ++ ++#ifdef DEBUG ++void dump_msg(const u8 * buf, unsigned int length) ++{ ++ unsigned int start, num, i; ++ char line[52], *p; ++ ++ if (length >= 512) ++ return; ++ start = 0; ++ while (length > 0) { ++ num = length < 16u ? length : 16u; ++ p = line; ++ for (i = 0; i < num; ++i) { ++ if (i == 8) ++ *p++ = ' '; ++ DWC_SPRINTF(p, " %02x", buf[i]); ++ p += 3; ++ } ++ *p = 0; ++ DWC_PRINTF("%6x: %s\n", start, line); ++ buf += num; ++ start += num; ++ length -= num; ++ } ++} ++#else ++static inline void dump_msg(const u8 * buf, unsigned int length) ++{ ++} ++#endif ++ ++/** ++ * This function writes a packet into the Tx FIFO associated with the ++ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For ++ * periodic EPs the periodic Tx FIFO associated with the EP is written ++ * with all packets for the next micro-frame. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to write packet for. ++ * @param dma Indicates if DMA is being used. ++ */ ++void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep, ++ int dma) ++{ ++ /** ++ * The buffer is padded to DWORD on a per packet basis in ++ * slave/dma mode if the MPS is not DWORD aligned. The last ++ * packet, if short, is also padded to a multiple of DWORD. ++ * ++ * ep->xfer_buff always starts DWORD aligned in memory and is a ++ * multiple of DWORD in length ++ * ++ * ep->xfer_len can be any number of bytes ++ * ++ * ep->xfer_count is a multiple of ep->maxpacket until the last ++ * packet ++ * ++ * FIFO access is DWORD */ ++ ++ uint32_t i; ++ uint32_t byte_count; ++ uint32_t dword_count; ++ uint32_t *fifo; ++ uint32_t *data_buff = (uint32_t *) ep->xfer_buff; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p)\n", __func__, core_if, ++ ep); ++ if (ep->xfer_count >= ep->xfer_len) { ++ DWC_WARN("%s() No data for EP%d!!!\n", __func__, ep->num); ++ return; ++ } ++ ++ /* Find the byte length of the packet either short packet or MPS */ ++ if ((ep->xfer_len - ep->xfer_count) < ep->maxpacket) { ++ byte_count = ep->xfer_len - ep->xfer_count; ++ } else { ++ byte_count = ep->maxpacket; ++ } ++ ++ /* Find the DWORD length, padded by extra bytes as neccessary if MPS ++ * is not a multiple of DWORD */ ++ dword_count = (byte_count + 3) / 4; ++ ++#ifdef VERBOSE ++ dump_msg(ep->xfer_buff, byte_count); ++#endif ++ ++ /**@todo NGS Where are the Periodic Tx FIFO addresses ++ * intialized? What should this be? */ ++ ++ fifo = core_if->data_fifo[ep->num]; ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "fifo=%p buff=%p *p=%08x bc=%d\n", ++ fifo, data_buff, *data_buff, byte_count); ++ ++ if (!dma) { ++ for (i = 0; i < dword_count; i++, data_buff++) { ++ DWC_WRITE_REG32(fifo, *data_buff); ++ } ++ } ++ ++ ep->xfer_count += byte_count; ++ ep->xfer_buff += byte_count; ++ ep->dma_addr += byte_count; ++} ++ ++/** ++ * Set the EP STALL. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to set the stall on. ++ */ ++void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ volatile uint32_t *depctl_addr; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ } ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ } else { ++ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* set the stall bit */ ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); ++ ++ return; ++} ++ ++/** ++ * Clear the EP STALL. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to clear stall from. ++ */ ++void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl; ++ volatile uint32_t *depctl_addr; ++ ++ DWC_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, ep->num, ++ (ep->is_in ? "IN" : "OUT")); ++ ++ if (ep->is_in == 1) { ++ depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); ++ } else { ++ depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); ++ } ++ ++ depctl.d32 = DWC_READ_REG32(depctl_addr); ++ ++ /* clear the stall bits */ ++ depctl.b.stall = 0; ++ ++ /* ++ * USB Spec 9.4.5: For endpoints using data toggle, regardless ++ * of whether an endpoint has the Halt feature set, a ++ * ClearFeature(ENDPOINT_HALT) request always results in the ++ * data toggle being reinitialized to DATA0. ++ */ ++ if (ep->type == DWC_OTG_EP_TYPE_INTR || ++ ep->type == DWC_OTG_EP_TYPE_BULK) { ++ depctl.b.setd0pid = 1; /* DATA0 */ ++ } ++ ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); ++ return; ++} ++ ++/** ++ * This function reads a packet from the Rx FIFO into the destination ++ * buffer. To read SETUP data use dwc_otg_read_setup_packet. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dest Destination buffer for the packet. ++ * @param bytes Number of bytes to copy to the destination. ++ */ ++void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, ++ uint8_t * dest, uint16_t bytes) ++{ ++ int i; ++ int word_count = (bytes + 3) / 4; ++ ++ volatile uint32_t *fifo = core_if->data_fifo[0]; ++ uint32_t *data_buff = (uint32_t *) dest; ++ ++ /** ++ * @todo Account for the case where _dest is not dword aligned. This ++ * requires reading data from the FIFO into a uint32_t temp buffer, ++ * then moving it into the data buffer. ++ */ ++ ++ DWC_DEBUGPL((DBG_PCDV | DBG_CILV), "%s(%p,%p,%d)\n", __func__, ++ core_if, dest, bytes); ++ ++ for (i = 0; i < word_count; i++, data_buff++) { ++ *data_buff = DWC_READ_REG32(fifo); ++ } ++ ++ return; ++} ++ ++/** ++ * This functions reads the device registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ volatile uint32_t *addr; ++ ++ DWC_PRINTF("Device Global Registers\n"); ++ addr = &core_if->dev_if->dev_global_regs->dcfg; ++ DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dctl; ++ DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dsts; ++ DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->diepmsk; ++ DWC_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->doepmsk; ++ DWC_PRINTF("DOEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daint; ++ DWC_PRINTF("DAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->daintmsk; ++ DWC_PRINTF("DAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dtknqr1; ++ DWC_PRINTF("DTKNQR1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ if (core_if->hwcfg2.b.dev_token_q_depth > 6) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr2; ++ DWC_PRINTF("DTKNQR2 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbusdis; ++ DWC_PRINTF("DVBUSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dvbuspulse; ++ DWC_PRINTF("DVBUSPULSE @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; ++ DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ if (core_if->hwcfg2.b.dev_token_q_depth > 22) { ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; ++ DWC_PRINTF("DTKNQR4 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; ++ DWC_PRINTF("FIFOEMPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ if (core_if->hwcfg2.b.multi_proc_int) { ++ ++ addr = &core_if->dev_if->dev_global_regs->deachint; ++ DWC_PRINTF("DEACHINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->deachintmsk; ++ DWC_PRINTF("DEACHINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->diepeachintmsk[i]; ++ DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->doepeachintmsk[i]; ++ DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ } ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_PRINTF("Device IN EP %d Registers\n", i); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepctl; ++ DWC_PRINTF("DIEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepint; ++ DWC_PRINTF("DIEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; ++ DWC_PRINTF("DIETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdma; ++ DWC_PRINTF("DIEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts; ++ DWC_PRINTF("DTXFSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->in_ep_regs[i]->diepdmab; ++ DWC_PRINTF("DIEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ ); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ DWC_PRINTF("Device OUT EP %d Registers\n", i); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepctl; ++ DWC_PRINTF("DOEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepint; ++ DWC_PRINTF("DOEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; ++ DWC_PRINTF("DOETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdma; ++ DWC_PRINTF("DOEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */ ++ addr = &core_if->dev_if->out_ep_regs[i]->doepdmab; ++ DWC_PRINTF("DOEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ } ++} ++ ++/** ++ * This functions reads the SPRAM and prints its content ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if) ++{ ++ volatile uint8_t *addr, *start_addr, *end_addr; ++ ++ DWC_PRINTF("SPRAM Data:\n"); ++ start_addr = (void *)core_if->core_global_regs; ++ DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr); ++ start_addr += 0x00028000; ++ end_addr = (void *)core_if->core_global_regs; ++ end_addr += 0x000280e0; ++ ++ for (addr = start_addr; addr < end_addr; addr += 16) { ++ DWC_PRINTF ++ ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", ++ (unsigned long)addr, addr[0], addr[1], addr[2], addr[3], ++ addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], ++ addr[10], addr[11], addr[12], addr[13], addr[14], addr[15] ++ ); ++ } ++ ++ return; ++} ++ ++/** ++ * This function reads the host registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ volatile uint32_t *addr; ++ ++ DWC_PRINTF("Host Global Registers\n"); ++ addr = &core_if->host_if->host_global_regs->hcfg; ++ DWC_PRINTF("HCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfir; ++ DWC_PRINTF("HFIR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hfnum; ++ DWC_PRINTF("HFNUM @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->hptxsts; ++ DWC_PRINTF("HPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->haint; ++ DWC_PRINTF("HAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->host_global_regs->haintmsk; ++ DWC_PRINTF("HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ if (core_if->dma_desc_enable) { ++ addr = &core_if->host_if->host_global_regs->hflbaddr; ++ DWC_PRINTF("HFLBADDR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ addr = core_if->host_if->hprt0; ++ DWC_PRINTF("HPRT0 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ DWC_PRINTF("Host Channel %d Specific Registers\n", i); ++ addr = &core_if->host_if->hc_regs[i]->hcchar; ++ DWC_PRINTF("HCCHAR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcsplt; ++ DWC_PRINTF("HCSPLT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcint; ++ DWC_PRINTF("HCINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcintmsk; ++ DWC_PRINTF("HCINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hctsiz; ++ DWC_PRINTF("HCTSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->host_if->hc_regs[i]->hcdma; ++ DWC_PRINTF("HCDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ if (core_if->dma_desc_enable) { ++ addr = &core_if->host_if->hc_regs[i]->hcdmab; ++ DWC_PRINTF("HCDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ ++ } ++ return; ++} ++ ++/** ++ * This function reads the core global registers and prints them ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if) ++{ ++ int i, ep_num; ++ volatile uint32_t *addr; ++ char *txfsiz; ++ ++ DWC_PRINTF("Core Global Registers\n"); ++ addr = &core_if->core_global_regs->gotgctl; ++ DWC_PRINTF("GOTGCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gotgint; ++ DWC_PRINTF("GOTGINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gahbcfg; ++ DWC_PRINTF("GAHBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gusbcfg; ++ DWC_PRINTF("GUSBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grstctl; ++ DWC_PRINTF("GRSTCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gintsts; ++ DWC_PRINTF("GINTSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gintmsk; ++ DWC_PRINTF("GINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grxstsr; ++ DWC_PRINTF("GRXSTSR @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->grxfsiz; ++ DWC_PRINTF("GRXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gnptxfsiz; ++ DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gnptxsts; ++ DWC_PRINTF("GNPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gi2cctl; ++ DWC_PRINTF("GI2CCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpvndctl; ++ DWC_PRINTF("GPVNDCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ggpio; ++ DWC_PRINTF("GGPIO @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->guid; ++ DWC_PRINTF("GUID @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gsnpsid; ++ DWC_PRINTF("GSNPSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg1; ++ DWC_PRINTF("GHWCFG1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg2; ++ DWC_PRINTF("GHWCFG2 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg3; ++ DWC_PRINTF("GHWCFG3 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->ghwcfg4; ++ DWC_PRINTF("GHWCFG4 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->glpmcfg; ++ DWC_PRINTF("GLPMCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpwrdn; ++ DWC_PRINTF("GPWRDN @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gdfifocfg; ++ DWC_PRINTF("GDFIFOCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->adpctl; ++ DWC_PRINTF("ADPCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ dwc_otg_adp_read_reg(core_if)); ++ addr = &core_if->core_global_regs->hptxfsiz; ++ DWC_PRINTF("HPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep; ++ txfsiz = "DPTXFSIZ"; ++ } else { ++ ep_num = core_if->hwcfg4.b.num_in_eps; ++ txfsiz = "DIENPTXF"; ++ } ++ for (i = 0; i < ep_num; i++) { ++ addr = &core_if->core_global_regs->dtxfsiz[i]; ++ DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1, ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } ++ addr = core_if->pcgcctl; ++ DWC_PRINTF("PCGCCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++} ++ ++/** ++ * 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; ++ ++ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "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) { ++ DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", ++ __func__, greset.d32, ++ DWC_READ_REG32(&global_regs->gnptxsts)); ++ break; ++ } ++ dwc_udelay(1); ++ } while (greset.b.txfflsh == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_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; ++ ++ DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%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) { ++ DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, ++ greset.d32); ++ break; ++ } ++ dwc_udelay(1); ++ } while (greset.b.rxfflsh == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_udelay(1); ++} ++ ++/** ++ * 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; ++ ++ DWC_DEBUGPL(DBG_CILV, "%s\n", __func__); ++ /* Wait for AHB master IDLE state. */ ++ do { ++ dwc_udelay(10); ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); ++ if (++count > 100000) { ++ DWC_WARN("%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 > 10000) { ++ DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", ++ __func__, greset.d32); ++ break; ++ } ++ dwc_udelay(1); ++ } ++ while (greset.b.csftrst == 1); ++ ++ /* Wait for 3 PHY Clocks */ ++ dwc_mdelay(100); ++} ++ ++uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t * _core_if) ++{ ++ return (dwc_otg_mode(_core_if) != DWC_HOST_MODE); ++} ++ ++uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if) ++{ ++ return (dwc_otg_mode(_core_if) == DWC_HOST_MODE); ++} ++ ++/** ++ * Register HCD callbacks. The callbacks are used to start and stop ++ * the HCD for interrupt processing. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param cb the HCD callback structure. ++ * @param p pointer to be passed to callback function (usb_hcd*). ++ */ ++void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if, ++ dwc_otg_cil_callbacks_t * cb, void *p) ++{ ++ core_if->hcd_cb = cb; ++ cb->p = p; ++} ++ ++/** ++ * Register PCD callbacks. The callbacks are used to start and stop ++ * the PCD for interrupt processing. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param cb the PCD callback structure. ++ * @param p pointer to be passed to callback function (pcd*). ++ */ ++void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * core_if, ++ dwc_otg_cil_callbacks_t * cb, void *p) ++{ ++ core_if->pcd_cb = cb; ++ cb->p = p; ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function writes isoc data per 1 (micro)frame into tx fifo ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ uint32_t dwords; ++ ++ ep->xfer_len = ep->data_per_frame; ++ ep->xfer_count = 0; ++ ++ ep_regs = core_if->dev_if->in_ep_regs[ep->num]; ++ ++ len = ep->xfer_len - ep->xfer_count; ++ ++ if (len > ep->maxpacket) { ++ len = ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail > dwords && ++ ep->xfer_count < ep->xfer_len && ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, ep, 0); ++ ++ len = ep->xfer_len - ep->xfer_count; ++ if (len > ep->maxpacket) { ++ len = ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num, ++ txstatus.d32); ++ } ++} ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ ep->xfer_len = ep->data_per_frame; ++ ep->xfer_count = 0; ++ ep->xfer_buff = ep->cur_pkt_addr; ++ ep->dma_addr = ep->cur_pkt_dma_addr; ++ ++ if (ep->is_in) { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ deptsiz.b.mc = deptsiz.b.pktcnt; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, ++ deptsiz.d32); ++ ++ /* Write the DMA register */ ++ if (core_if->dma_enable) { ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->in_ep_regs[ep->num]-> ++ diepdma), (uint32_t) ep->dma_addr); ++ } ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz, deptsiz.d32); ++ ++ if (core_if->dma_enable) { ++ DWC_WRITE_REG32(& ++ (core_if->dev_if-> ++ out_ep_regs[ep->num]->doepdma), ++ (uint32_t) ep->dma_addr); ++ } ++ } ++ ++ /** Enable endpoint, clear nak */ ++ ++ depctl.d32 = 0; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ep->next_frame = dsts.b.soffn + ep->bInterval; ++ ++ if (ep->next_frame & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } else { ++ ep->next_frame += ep->bInterval; ++ ++ if (ep->next_frame & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, 0, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ if (ep->is_in && core_if->dma_enable == 0) { ++ write_isoc_frame_data(core_if, ep); ++ } ++ ++} ++#endif /* DWC_EN_ISOC */ ++ ++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; ++} ++ ++static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ core_if->core_params = DWC_ALLOC(sizeof(*core_if->core_params)); ++ if (!core_if->core_params) { ++ return -DWC_E_NO_MEMORY; ++ } ++ dwc_otg_set_uninitialized((int32_t *) core_if->core_params, ++ sizeof(*core_if->core_params) / ++ sizeof(int32_t)); ++ DWC_PRINTF("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); ++ dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default); ++ dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default); ++ dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default); ++ dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default); ++ dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default); ++ dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default); ++ dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default); ++ DWC_PRINTF("Finished setting default values for core params\n"); ++ ++ return 0; ++} ++ ++uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->dma_enable; ++} ++ ++/* 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)) { ++ DWC_WARN("Wrong value for otg_cap parameter\n"); ++ DWC_WARN("otg_cap parameter must be 0,1 or 2\n"); ++ retval = -DWC_E_INVALID; ++ 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)) { ++ DWC_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 = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for opt parameter\n"); ++ return -DWC_E_INVALID; ++ } ++ 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)) { ++ DWC_WARN("Wrong value for dma enable\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) { ++ DWC_ERROR ++ ("%d invalid for dma_enable paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for dma_enable\n"); ++ DWC_WARN("dma_desc_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_ERROR ++ ("%d invalid for dma_desc_enable paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ 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)) { ++ DWC_WARN("Wrong value for host_support_fs_low_power\n"); ++ DWC_WARN("host_support_fs_low_power must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ 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)) { ++ DWC_WARN("Wrong value for enable_dynamic_fifo\n"); ++ DWC_WARN("enable_dynamic_fifo must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->enable_dynamic_fifo)) { ++ DWC_ERROR ++ ("%d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ 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)) { ++ DWC_WARN("Wrong value for data_fifo_size\n"); ++ DWC_WARN("data_fifo_size must be 32-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > core_if->hwcfg3.b.dfifo_depth) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->data_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for data_fifo_size parameter. Check HW configuration.\n", ++ val); ++ } ++ val = core_if->hwcfg3.b.dfifo_depth; ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for dev_rx_fifo_size\n"); ++ DWC_WARN("dev_rx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) { ++ DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val); ++ } ++ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for dev_nperio_tx_fifo\n"); ++ DWC_WARN("dev_nperio_tx_fifo must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_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 = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for host_rx_fifo_size\n"); ++ DWC_WARN("host_rx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_rx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for host_rx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for host_nperio_tx_fifo_size\n"); ++ DWC_WARN("host_nperio_tx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_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 = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for host_perio_tx_fifo_size\n"); ++ DWC_WARN("host_perio_tx_fifo_size must be 16-32768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > ((core_if->hptxfsiz.d32) >> 16)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_perio_tx_fifo_size)) { ++ DWC_ERROR ++ ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n", ++ val); ++ } ++ val = (core_if->hptxfsiz.d32) >> 16; ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for max_transfer_size\n"); ++ DWC_WARN("max_transfer_size must be 2047-524288\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->max_transfer_size)) { ++ DWC_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 = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for max_packet_count\n"); ++ DWC_WARN("max_packet_count must be 15-511\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->max_packet_count)) { ++ DWC_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 = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for host_channels\n"); ++ DWC_WARN("host_channels must be 1-16\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (core_if->hwcfg2.b.num_host_chan + 1)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_channels)) { ++ DWC_ERROR ++ ("%d invalid for host_channels. Check HW configurations.\n", ++ val); ++ } ++ val = (core_if->hwcfg2.b.num_host_chan + 1); ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for dev_endpoints\n"); ++ DWC_WARN("dev_endpoints must be 1-15\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > (core_if->hwcfg2.b.num_dev_ep)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_endpoints)) { ++ DWC_ERROR ++ ("%d invalid for dev_endpoints. Check HW configurations.\n", ++ val); ++ } ++ val = core_if->hwcfg2.b.num_dev_ep; ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for phy_type\n"); ++ DWC_WARN("phy_type must be 0,1 or 2\n"); ++ return -DWC_E_INVALID; ++ } ++#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)) { ++ DWC_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 = -DWC_E_INVALID; ++ } ++#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)) { ++ DWC_WARN("Wrong value for speed parameter\n"); ++ DWC_WARN("max_speed parameter must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ 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)) { ++ DWC_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 = -DWC_E_INVALID; ++ } ++ 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)) { ++ DWC_WARN ++ ("Wrong value for host_ls_low_power_phy_clk parameter\n"); ++ DWC_WARN("host_ls_low_power_phy_clk must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_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 = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for phy_ulpi_ddr\n"); ++ DWC_WARN("phy_upli_ddr must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong valaue for phy_ulpi_ext_vbus\n"); ++ DWC_WARN("phy_ulpi_ext_vbus must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong valaue for phy_utmi_width\n"); ++ DWC_WARN("phy_utmi_width must be 8 or 16\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong valaue for ulpi_fs_ls\n"); ++ DWC_WARN("ulpi_fs_ls must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong valaue for ts_dline\n"); ++ DWC_WARN("ts_dline must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong valaue for i2c_enable\n"); ++ DWC_WARN("i2c_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++#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)) { ++ DWC_ERROR ++ ("%d invalid for i2c_enable. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++#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)) { ++ DWC_WARN("Wrong value for dev_perio_tx_fifo_size\n"); ++ DWC_WARN("dev_perio_tx_fifo_size must be 4-768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > ++ (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) { ++ DWC_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->dtxfsiz[fifo_num])); ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong valaue for en_multiple_tx_fifo,\n"); ++ DWC_WARN("en_multiple_tx_fifo must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->en_multiple_tx_fifo)) { ++ DWC_ERROR ++ ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for dev_tx_fifo_size\n"); ++ DWC_WARN("dev_tx_fifo_size must be 4-768\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val > ++ (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_tx_fifo_size[fifo_num])) { ++ DWC_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->dtxfsiz[fifo_num])); ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for thr_ctl\n"); ++ DWC_WARN("thr_ctl must be 0-7\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_ERROR ++ ("%d invalid for parameter thr_ctl. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong value for lpm_enable\n"); ++ DWC_WARN("lpm_enable must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val && !core_if->hwcfg3.b.otg_lpm_en) { ++ if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter lpm_enable. Check HW configuration.\n", ++ val); ++ } ++ val = 0; ++ retval = -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong valaue for tx_thr_length\n"); ++ DWC_WARN("tx_thr_length must be 8 - 128\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("Wrong valaue for rx_thr_length\n"); ++ DWC_WARN("rx_thr_length must be 8 - 128\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_WARN("`%d' invalid for parameter `dma_burst_size'\n", val); ++ return -DWC_E_INVALID; ++ } ++ 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)) { ++ DWC_WARN("`%d' invalid for parameter `pti_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) { ++ if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter pti_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ 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)) { ++ DWC_WARN("`%d' invalid for parameter `mpi_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter mpi_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ 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_adp_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->hwcfg3.b.adp_supp == 0)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->adp_supp_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter adp_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->adp_supp_enable = val; ++ /*Set OTG version 2.0 in case of enabling ADP*/ ++ if (val) ++ dwc_otg_set_param_otg_ver(core_if, 1); ++ ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->adp_supp_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)) { ++ DWC_WARN("`%d' invalid for parameter `ic_usb_cap'\n", val); ++ DWC_WARN("ic_usb_cap must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) { ++ if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) { ++ DWC_ERROR ++ ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ 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)) { ++ DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val); ++ DWC_WARN("ahb_thr_ratio must be 0 - 3\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ 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)) { ++ DWC_ERROR ++ ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ 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; ++} ++ ++int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ hwcfg4_data_t hwcfg4 = {.d32 = 0 }; ++ hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { ++ DWC_WARN("`%d' invalid for parameter `power_down'\n", val); ++ DWC_WARN("power_down must be 0 - 2\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) { ++ valid = 0; ++ } ++ if ((val == 3) ++ && ((core_if->snpsid < OTG_CORE_REV_3_00a) ++ || (hwcfg4.b.xhiber == 0))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->power_down)) { ++ DWC_ERROR ++ ("%d invalid for parameter power_down. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->power_down = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->power_down; ++} ++ ++int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val); ++ DWC_WARN("reload_ctl must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) { ++ DWC_ERROR("%d invalid for parameter reload_ctl." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->reload_ctl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->reload_ctl; ++} ++ ++int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val); ++ DWC_WARN("dev_out_nak must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) { ++ DWC_ERROR("%d invalid for parameter dev_out_nak." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->dev_out_nak = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_out_nak; ++} ++ ++int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val); ++ DWC_WARN("cont_on_bna must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) { ++ DWC_ERROR("%d invalid for parameter cont_on_bna." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->cont_on_bna = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->cont_on_bna; ++} ++ ++int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val); ++ DWC_WARN("ahb_single must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) { ++ DWC_ERROR("%d invalid for parameter ahb_single." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->ahb_single = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ahb_single; ++} ++ ++int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val); ++ DWC_WARN ++ ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->otg_ver = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->otg_ver; ++} ++ ++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) ++{ ++ if(core_if->otg_ver == 0) { ++ 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); ++ } else { ++ core_if->otg_sts = val; ++ } ++} ++ ++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) ++{ ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ return gintsts.b.curmode; ++} ++ ++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_devspeed(dwc_otg_core_if_t * core_if) ++{ ++ dcfg_data_t dcfg; ++ /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */ ++ ++ dcfg.d32 = -1; //GRAYG ++ DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if); ++ if (NULL == core_if) ++ DWC_ERROR("reg request with NULL core_if\n"); ++ DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)\n", __func__, ++ core_if, core_if->dev_if); ++ if (NULL == core_if->dev_if) ++ DWC_ERROR("reg request with NULL dev_if\n"); ++ DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)->dev_if(%p)->" ++ "dev_global_regs(%p)\n", __func__, ++ core_if, core_if->dev_if, ++ core_if->dev_if->dev_global_regs); ++ if (NULL == core_if->dev_if->dev_global_regs) ++ DWC_ERROR("reg request with NULL dev_global_regs\n"); ++ else { ++ DWC_DEBUGPL(DBG_CILV, "%s - &core_if(%p)->dev_if(%p)->" ++ "dev_global_regs(%p)->dcfg = %p\n", __func__, ++ core_if, core_if->dev_if, ++ core_if->dev_if->dev_global_regs, ++ &core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ } ++ return dcfg.b.devspd; ++} ++ ++void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ dcfg_data_t dcfg; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.devspd = val; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.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_enumspeed(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ return dsts.b.enumspd; ++} ++ ++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; ++ ++} ++ ++uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->hibernation_suspend; ++} ++ ++void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ 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_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = val; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if) ++{ ++ hfir_data_t hfir; ++ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ return hfir.b.frint; ++ ++} ++ ++void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hfir_data_t hfir; ++ uint32_t fram_int; ++ fram_int = calc_frame_interval(core_if); ++ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ if (!core_if->core_params->reload_ctl) { ++ DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is" ++ "not set to 1.\nShould load driver with reload_ctl=1" ++ " module parameter\n"); ++ return; ++ } ++ switch (fram_int) { ++ case 3750: ++ if ((val < 3350) || (val > 4150)) { ++ DWC_WARN("HFIR interval for HS core and 30 MHz" ++ "clock freq should be from 3350 to 4150\n"); ++ return; ++ } ++ break; ++ case 30000: ++ if ((val < 26820) || (val > 33180)) { ++ DWC_WARN("HFIR interval for FS/LS core and 30 MHz" ++ "clock freq should be from 26820 to 33180\n"); ++ return; ++ } ++ break; ++ case 6000: ++ if ((val < 5360) || (val > 6640)) { ++ DWC_WARN("HFIR interval for HS core and 48 MHz" ++ "clock freq should be from 5360 to 6640\n"); ++ return; ++ } ++ break; ++ case 48000: ++ if ((val < 42912) || (val > 53088)) { ++ DWC_WARN("HFIR interval for FS/LS core and 48 MHz" ++ "clock freq should be from 42912 to 53088\n"); ++ return; ++ } ++ break; ++ case 7500: ++ if ((val < 6700) || (val > 8300)) { ++ DWC_WARN("HFIR interval for HS core and 60 MHz" ++ "clock freq should be from 6700 to 8300\n"); ++ return; ++ } ++ break; ++ case 60000: ++ if ((val < 53640) || (val > 65536)) { ++ DWC_WARN("HFIR interval for FS/LS core and 60 MHz" ++ "clock freq should be from 53640 to 65536\n"); ++ return; ++ } ++ break; ++ default: ++ DWC_WARN("Unknown frame interval\n"); ++ return; ++ break; ++ ++ } ++ hfir.b.frint = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32); ++} ++ ++uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ return hcfg.b.modechtimen; ++ ++} ++ ++void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.modechtimen = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hprt0_data_t hprt0; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = val; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if) ++{ ++ dctl_data_t dctl; ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ return dctl.b.rmtwkupsig; ++} ++ ++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); ++ ++ DWC_ASSERT(! ++ ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts), ++ "lx_state = %d, lmpcfg.prt_sleep_sts = %d\n", ++ core_if->lx_state, lpmcfg.b.prt_sleep_sts); ++ ++ 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); ++} ++ ++uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if) ++{ ++ return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103); ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if) ++{ ++ core_if->srp_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ ); ++} ++ ++void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl); ++ gotgctl_data_t mem; ++ gotgctl_data_t val; ++ ++ val.d32 = DWC_READ_REG32(addr); ++ if (val.b.sesreq) { ++ DWC_ERROR("Session Request Already active!\n"); ++ return; ++ } ++ ++ DWC_INFO("Session Request Initated\n"); //NOTICE ++ mem.d32 = DWC_READ_REG32(addr); ++ mem.b.sesreq = 1; ++ DWC_WRITE_REG32(addr, mem.d32); ++ ++ /* Start the SRP timer */ ++ dwc_otg_pcd_start_srp_timer(core_if); ++ return; ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h +new file mode 100644 +index 0000000..d367cd1 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h +@@ -0,0 +1,1464 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $ ++ * $Revision: #123 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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. ++ * ========================================================================== */ ++ ++#if !defined(__DWC_CIL_H__) ++#define __DWC_CIL_H__ ++ ++#include "dwc_list.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_regs.h" ++ ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_adp.h" ++ ++/** ++ * @file ++ * This file contains the interface to the Core Interface Layer. ++ */ ++ ++#ifdef DWC_UTE_CFI ++ ++#define MAX_DMA_DESCS_PER_EP 256 ++ ++/** ++ * Enumeration for the data buffer mode ++ */ ++typedef enum _data_buffer_mode { ++ BM_STANDARD = 0, /* data buffer is in normal mode */ ++ BM_SG = 1, /* data buffer uses the scatter/gather mode */ ++ BM_CONCAT = 2, /* data buffer uses the concatenation mode */ ++ BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */ ++ BM_ALIGN = 4 /* data buffer is in buffer alignment mode */ ++} data_buffer_mode_e; ++#endif //DWC_UTE_CFI ++ ++/** Macros defined for DWC OTG HW Release version */ ++ ++#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 OTG_CORE_REV_2_91a 0x4F54291A ++#define OTG_CORE_REV_2_92a 0x4F54292A ++#define OTG_CORE_REV_2_93a 0x4F54293A ++#define OTG_CORE_REV_2_94a 0x4F54294A ++#define OTG_CORE_REV_3_00a 0x4F54300A ++ ++/** ++ * Information for each ISOC packet. ++ */ ++typedef struct iso_pkt_info { ++ uint32_t offset; ++ uint32_t length; ++ int32_t status; ++} iso_pkt_info_t; ++ ++/** ++ * The dwc_ep structure represents the state of a single ++ * endpoint when acting in device mode. It contains the data items ++ * needed for an endpoint to be activated and transfer packets. ++ */ ++typedef struct dwc_ep { ++ /** EP number used for register address lookup */ ++ uint8_t num; ++ /** EP direction 0 = OUT */ ++ unsigned is_in:1; ++ /** EP active. */ ++ unsigned active:1; ++ ++ /** ++ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic ++ * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/ ++ unsigned tx_fifo_num:4; ++ /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ ++ unsigned type:2; ++#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 ++ ++ /** DATA start PID for INTR and BULK EP */ ++ unsigned data_pid_start:1; ++ /** Frame (even/odd) for ISOC EP */ ++ unsigned even_odd_frame:1; ++ /** Max Packet bytes */ ++ unsigned maxpacket:11; ++ ++ /** Max Transfer size */ ++ uint32_t maxxfer; ++ ++ /** @name Transfer state */ ++ /** @{ */ ++ ++ /** ++ * Pointer to the beginning of the transfer buffer -- do not modify ++ * during transfer. ++ */ ++ ++ dwc_dma_t dma_addr; ++ ++ dwc_dma_t dma_desc_addr; ++ dwc_otg_dev_dma_desc_t *desc_addr; ++ ++ uint8_t *start_xfer_buff; ++ /** pointer to the transfer buffer */ ++ uint8_t *xfer_buff; ++ /** Number of bytes to transfer */ ++ unsigned xfer_len:19; ++ /** Number of bytes transferred. */ ++ unsigned xfer_count:19; ++ /** Sent ZLP */ ++ unsigned sent_zlp:1; ++ /** Total len for control transfer */ ++ unsigned total_len:19; ++ ++ /** stall clear flag */ ++ unsigned stall_clear_flag:1; ++ ++ /** SETUP pkt cnt rollover flag for EP0 out*/ ++ unsigned stp_rollover; ++ ++#ifdef DWC_UTE_CFI ++ /* The buffer mode */ ++ data_buffer_mode_e buff_mode; ++ ++ /* The chain of DMA descriptors. ++ * MAX_DMA_DESCS_PER_EP will be allocated for each active EP. ++ */ ++ dwc_otg_dma_desc_t *descs; ++ ++ /* The DMA address of the descriptors chain start */ ++ dma_addr_t descs_dma_addr; ++ /** This variable stores the length of the last enqueued request */ ++ uint32_t cfi_req_len; ++#endif //DWC_UTE_CFI ++ ++/** Max DMA Descriptor count for any EP */ ++#define MAX_DMA_DESC_CNT 256 ++ /** Allocated DMA Desc count */ ++ uint32_t desc_cnt; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** Next frame num to setup next ISOC transfer */ ++ uint32_t frame_num; ++ /** Indicates SOF number overrun in DSTS */ ++ uint8_t frm_overrun; ++ ++#ifdef DWC_UTE_PER_IO ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t xiso_frame_num; ++ /** bInterval */ ++ uint32_t xiso_bInterval; ++ /** Count of currently active transfers - shall be either 0 or 1 */ ++ int xiso_active_xfers; ++ int xiso_queued_xfers; ++#endif ++#ifdef DWC_EN_ISOC ++ /** ++ * Variables specific for ISOC EPs ++ * ++ */ ++ /** DMA addresses of ISOC buffers */ ++ dwc_dma_t dma_addr0; ++ dwc_dma_t dma_addr1; ++ ++ dwc_dma_t iso_dma_desc_addr; ++ dwc_otg_dev_dma_desc_t *iso_desc_addr; ++ ++ /** pointer to the transfer buffers */ ++ uint8_t *xfer_buff0; ++ uint8_t *xfer_buff1; ++ ++ /** number of ISOC Buffer is processing */ ++ uint32_t proc_buf_num; ++ /** Interval of ISOC Buffer processing */ ++ uint32_t buf_proc_intrvl; ++ /** Data size for regular frame */ ++ uint32_t data_per_frame; ++ ++ /* todo - pattern data support is to be implemented in the future */ ++ /** Data size for pattern frame */ ++ uint32_t data_pattern_frame; ++ /** Frame number of pattern data */ ++ uint32_t sync_frame; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** ISO Packet number per frame */ ++ uint32_t pkt_per_frm; ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t next_frame; ++ /** Number of packets per buffer processing */ ++ uint32_t pkt_cnt; ++ /** Info for all isoc packets */ ++ iso_pkt_info_t *pkt_info; ++ /** current pkt number */ ++ uint32_t cur_pkt; ++ /** current pkt number */ ++ uint8_t *cur_pkt_addr; ++ /** current pkt number */ ++ uint32_t cur_pkt_dma_addr; ++#endif /* DWC_EN_ISOC */ ++ ++/** @} */ ++} dwc_ep_t; ++ ++/* ++ * Reasons for halting a host channel. ++ */ ++typedef enum dwc_otg_halt_status { ++ DWC_OTG_HC_XFER_NO_HALT_STATUS, ++ DWC_OTG_HC_XFER_COMPLETE, ++ DWC_OTG_HC_XFER_URB_COMPLETE, ++ DWC_OTG_HC_XFER_ACK, ++ DWC_OTG_HC_XFER_NAK, ++ DWC_OTG_HC_XFER_NYET, ++ DWC_OTG_HC_XFER_STALL, ++ DWC_OTG_HC_XFER_XACT_ERR, ++ DWC_OTG_HC_XFER_FRAME_OVERRUN, ++ DWC_OTG_HC_XFER_BABBLE_ERR, ++ DWC_OTG_HC_XFER_DATA_TOGGLE_ERR, ++ DWC_OTG_HC_XFER_AHB_ERR, ++ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE, ++ DWC_OTG_HC_XFER_URB_DEQUEUE ++} dwc_otg_halt_status_e; ++ ++/** ++ * Host channel descriptor. This structure represents the state of a single ++ * host channel when acting in host mode. It contains the data items needed to ++ * transfer packets to an endpoint via a host channel. ++ */ ++typedef struct dwc_hc { ++ /** Host channel number used for register address lookup */ ++ uint8_t hc_num; ++ ++ /** Device to access */ ++ unsigned dev_addr:7; ++ ++ /** EP to access */ ++ unsigned ep_num:4; ++ ++ /** EP direction. 0: OUT, 1: IN */ ++ unsigned ep_is_in:1; ++ ++ /** ++ * EP speed. ++ * One of the following values: ++ * - DWC_OTG_EP_SPEED_LOW ++ * - DWC_OTG_EP_SPEED_FULL ++ * - DWC_OTG_EP_SPEED_HIGH ++ */ ++ unsigned speed:2; ++#define DWC_OTG_EP_SPEED_LOW 0 ++#define DWC_OTG_EP_SPEED_FULL 1 ++#define DWC_OTG_EP_SPEED_HIGH 2 ++ ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - DWC_OTG_EP_TYPE_CONTROL: 0 ++ * - DWC_OTG_EP_TYPE_ISOC: 1 ++ * - DWC_OTG_EP_TYPE_BULK: 2 ++ * - DWC_OTG_EP_TYPE_INTR: 3 ++ */ ++ unsigned ep_type:2; ++ ++ /** Max packet size in bytes */ ++ unsigned max_packet:11; ++ ++ /** ++ * PID for initial transaction. ++ * 0: DATA0,
++ * 1: DATA2,
++ * 2: DATA1,
++ * 3: MDATA (non-Control EP), ++ * SETUP (Control EP) ++ */ ++ unsigned data_pid_start:2; ++#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 ++ ++ /** Number of periodic transactions per (micro)frame */ ++ unsigned multi_count:2; ++ ++ /** @name Transfer State */ ++ /** @{ */ ++ ++ /** Pointer to the current transfer buffer position. */ ++ uint8_t *xfer_buff; ++ /** ++ * In Buffer DMA mode this buffer will be used ++ * if xfer_buff is not DWORD aligned. ++ */ ++ dwc_dma_t align_buff; ++ /** Total number of bytes to transfer. */ ++ uint32_t xfer_len; ++ /** Number of bytes transferred so far. */ ++ uint32_t xfer_count; ++ /** Packet count at start of transfer.*/ ++ uint16_t start_pkt_count; ++ ++ /** ++ * Flag to indicate whether the transfer has been started. Set to 1 if ++ * it has been started, 0 otherwise. ++ */ ++ uint8_t xfer_started; ++ ++ /** ++ * Set to 1 to indicate that a PING request should be issued on this ++ * channel. If 0, process normally. ++ */ ++ uint8_t do_ping; ++ ++ /** ++ * Set to 1 to indicate that the error count for this transaction is ++ * non-zero. Set to 0 if the error count is 0. ++ */ ++ uint8_t error_state; ++ ++ /** ++ * Set to 1 to indicate that this channel should be halted the next ++ * time a request is queued for the channel. This is necessary in ++ * slave mode if no request queue space is available when an attempt ++ * is made to halt the channel. ++ */ ++ uint8_t halt_on_queue; ++ ++ /** ++ * Set to 1 if the host channel has been halted, but the core is not ++ * finished flushing queued requests. Otherwise 0. ++ */ ++ uint8_t halt_pending; ++ ++ /** ++ * Reason for halting the host channel. ++ */ ++ dwc_otg_halt_status_e halt_status; ++ ++ /* ++ * Split settings for the host channel ++ */ ++ uint8_t do_split; /**< Enable split for the channel */ ++ uint8_t complete_split; /**< Enable complete split */ ++ uint8_t hub_addr; /**< Address of high speed hub */ ++ ++ uint8_t port_addr; /**< Port of the low/full speed device */ ++ /** Split transaction position ++ * One of the following values: ++ * - DWC_HCSPLIT_XACTPOS_MID ++ * - DWC_HCSPLIT_XACTPOS_BEGIN ++ * - DWC_HCSPLIT_XACTPOS_END ++ * - DWC_HCSPLIT_XACTPOS_ALL */ ++ uint8_t xact_pos; ++ ++ /** Set when the host channel does a short read. */ ++ uint8_t short_read; ++ ++ /** ++ * Number of requests issued for this channel since it was assigned to ++ * the current transfer (not counting PINGs). ++ */ ++ uint8_t requests; ++ ++ /** ++ * Queue Head for the transfer being processed by this channel. ++ */ ++ struct dwc_otg_qh *qh; ++ ++ /** @} */ ++ ++ /** Entry in list of host channels. */ ++ DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry; ++ ++ /** @name Descriptor DMA support */ ++ /** @{ */ ++ ++ /** Number of Transfer Descriptors */ ++ uint16_t ntd; ++ ++ /** Descriptor List DMA address */ ++ dwc_dma_t desc_list_addr; ++ ++ /** Scheduling micro-frame bitmap. */ ++ uint8_t schinfo; ++ ++ /** @} */ ++} dwc_hc_t; ++ ++/** ++ * 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 ++ * Descriptor mode for accessing the data FIFOs in device mode. The driver ++ * will automatically detect the value for this 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 65,535 (default 65,535) ++ */ ++ 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; ++ ++ /** ADP Support ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t adp_supp_enable; ++ ++ /** HFIR Reload Control ++ * 0 - The HFIR cannot be reloaded dynamically. ++ * 1 - Allow dynamic reloading of the HFIR register during runtime. ++ */ ++ int32_t reload_ctl; ++ ++ /** DCFG: Enable device Out NAK ++ * 0 - The core does not set NAK after Bulk Out transfer complete. ++ * 1 - The core sets NAK after Bulk OUT transfer complete. ++ */ ++ int32_t dev_out_nak; ++ ++ /** DCFG: Enable Continue on BNA ++ * After receiving BNA interrupt the core disables the endpoint,when the ++ * endpoint is re-enabled by the application the core starts processing ++ * 0 - from the DOEPDMA descriptor ++ * 1 - from the descriptor which received the BNA. ++ */ ++ int32_t cont_on_bna; ++ ++ /** GAHBCFG: AHB Single Support ++ * This bit when programmed supports SINGLE transfers for remainder ++ * data in a transfer for DMA mode of operation. ++ * 0 - in this case the remainder data will be sent using INCR burst size. ++ * 1 - in this case the remainder data will be sent using SINGLE burst size. ++ */ ++ int32_t ahb_single; ++ ++ /** Core Power down mode ++ * 0 - No Power Down is enabled ++ * 1 - Reserved ++ * 2 - Complete Power Down (Hibernation) ++ */ ++ int32_t power_down; ++ ++ /** OTG revision supported ++ * 0 - OTG 1.3 revision ++ * 1 - OTG 2.0 revision ++ */ ++ int32_t otg_ver; ++ ++} dwc_otg_core_params_t; ++ ++#ifdef DEBUG ++struct dwc_otg_core_if; ++typedef struct hc_xfer_info { ++ struct dwc_otg_core_if *core_if; ++ dwc_hc_t *hc; ++} hc_xfer_info_t; ++#endif ++ ++typedef struct ep_xfer_info { ++ struct dwc_otg_core_if *core_if; ++ dwc_ep_t *ep; ++ uint8_t state; ++} ep_xfer_info_t; ++/* ++ * Device States ++ */ ++typedef enum dwc_otg_lx_state { ++ /** On state */ ++ DWC_OTG_L0, ++ /** LPM sleep state*/ ++ DWC_OTG_L1, ++ /** USB suspend state*/ ++ DWC_OTG_L2, ++ /** Off state*/ ++ DWC_OTG_L3 ++} dwc_otg_lx_state_e; ++ ++struct dwc_otg_global_regs_backup { ++ uint32_t gotgctl_local; ++ uint32_t gintmsk_local; ++ uint32_t gahbcfg_local; ++ uint32_t gusbcfg_local; ++ uint32_t grxfsiz_local; ++ uint32_t gnptxfsiz_local; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ uint32_t glpmcfg_local; ++#endif ++ uint32_t gi2cctl_local; ++ uint32_t hptxfsiz_local; ++ uint32_t pcgcctl_local; ++ uint32_t gdfifocfg_local; ++ uint32_t dtxfsiz_local[MAX_EPS_CHANNELS]; ++ uint32_t gpwrdn_local; ++ uint32_t xhib_pcgcctl; ++ uint32_t xhib_gpwrdn; ++}; ++ ++struct dwc_otg_host_regs_backup { ++ uint32_t hcfg_local; ++ uint32_t haintmsk_local; ++ uint32_t hcintmsk_local[MAX_EPS_CHANNELS]; ++ uint32_t hprt0_local; ++ uint32_t hfir_local; ++}; ++ ++struct dwc_otg_dev_regs_backup { ++ uint32_t dcfg; ++ uint32_t dctl; ++ uint32_t daintmsk; ++ uint32_t diepmsk; ++ uint32_t doepmsk; ++ uint32_t diepctl[MAX_EPS_CHANNELS]; ++ uint32_t dieptsiz[MAX_EPS_CHANNELS]; ++ uint32_t diepdma[MAX_EPS_CHANNELS]; ++}; ++/** ++ * The dwc_otg_core_if 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; ++ ++ /** Device-specific information */ ++ dwc_otg_dev_if_t *dev_if; ++ /** 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; ++ ++ /* ++ * SRP Success flag, set by srp success interrupt in FS I2C mode ++ */ ++ uint8_t srp_success; ++ uint8_t srp_timer_started; ++ /** Timer for SRP. If it expires before SRP is successful ++ * clear the SRP. */ ++ dwc_timer_t *srp_timer; ++ ++#ifdef DWC_DEV_SRPCAP ++ /* This timer is needed to power on the hibernated host core if SRP is not ++ * initiated on connected SRP capable device for limited period of time ++ */ ++ uint8_t pwron_timer_started; ++ dwc_timer_t *pwron_timer; ++#endif ++ /* 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; ++ fifosize_data_t hptxfsiz; ++ ++ /** Host and Device Configuration -- stored here for convenience.*/ ++ hcfg_data_t hcfg; ++ dcfg_data_t dcfg; ++ ++ /** 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) ++ ++ /** HCD callbacks */ ++ struct dwc_otg_cil_callbacks *hcd_cb; ++ /** PCD callbacks */ ++ struct dwc_otg_cil_callbacks *pcd_cb; ++ ++ /** Device mode Periodic Tx FIFO Mask */ ++ uint32_t p_tx_msk; ++ /** Device mode Periodic Tx FIFO Mask */ ++ uint32_t tx_msk; ++ ++ /** Workqueue object used for handling several interrupts */ ++ dwc_workq_t *wq_otg; ++ ++ /** Timer object used for handling "Wakeup Detected" Interrupt */ ++ dwc_timer_t *wkp_timer; ++ /** This arrays used for debug purposes for DEV OUT NAK enhancement */ ++ uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS]; ++ ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS]; ++ dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS]; ++#ifdef DEBUG ++ uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; ++ ++ hc_xfer_info_t hc_xfer_info[MAX_EPS_CHANNELS]; ++ dwc_timer_t *hc_xfer_timer[MAX_EPS_CHANNELS]; ++ ++ uint32_t hfnum_7_samples; ++ uint64_t hfnum_7_frrem_accum; ++ uint32_t hfnum_0_samples; ++ uint64_t hfnum_0_frrem_accum; ++ uint32_t hfnum_other_samples; ++ uint64_t hfnum_other_frrem_accum; ++#endif ++ ++#ifdef DWC_UTE_CFI ++ uint16_t pwron_rxfsiz; ++ uint16_t pwron_gnptxfsiz; ++ uint16_t pwron_txfsiz[15]; ++ ++ uint16_t init_rxfsiz; ++ uint16_t init_gnptxfsiz; ++ uint16_t init_txfsiz[15]; ++#endif ++ ++ /** Lx state of device */ ++ dwc_otg_lx_state_e lx_state; ++ ++ /** Saved Core Global registers */ ++ struct dwc_otg_global_regs_backup *gr_backup; ++ /** Saved Host registers */ ++ struct dwc_otg_host_regs_backup *hr_backup; ++ /** Saved Device registers */ ++ struct dwc_otg_dev_regs_backup *dr_backup; ++ ++ /** Power Down Enable */ ++ uint32_t power_down; ++ ++ /** ADP support Enable */ ++ uint32_t adp_enable; ++ ++ /** ADP structure object */ ++ dwc_otg_adp_t adp; ++ ++ /** hibernation/suspend flag */ ++ int hibernation_suspend; ++ ++ /** Device mode extended hibernation flag */ ++ int xhib; ++ ++ /** OTG revision supported */ ++ uint32_t otg_ver; ++ ++ /** OTG status flag used for HNP polling */ ++ uint8_t otg_sts; ++ ++ /** Pointer to either hcd->lock or pcd->lock */ ++ dwc_spinlock_t *lock; ++ ++ /** Start predict NextEP based on Learning Queue if equal 1, ++ * also used as counter of disabled NP IN EP's */ ++ uint8_t start_predict; ++ ++ /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and ++ * active, 0xff otherwise */ ++ uint8_t nextep_seq[MAX_EPS_CHANNELS]; ++ ++ /** Index of fisrt EP in nextep_seq array which should be re-enabled **/ ++ uint8_t first_in_nextep_seq; ++ ++ /** Frame number while entering to ISR - needed for ISOCs **/ ++ uint32_t frame_num; ++ ++}; ++ ++#ifdef DEBUG ++/* ++ * This function is called when transfer is timed out. ++ */ ++extern void hc_xfer_timeout(void *ptr); ++#endif ++ ++/* ++ * This function is called when transfer is timed out on endpoint. ++ */ ++extern void ep_xfer_timeout(void *ptr); ++ ++/* ++ * The following functions are functions for works ++ * using during handling some interrupts ++ */ ++extern void w_conn_id_status_change(void *p); ++ ++extern void w_wakeup_detected(void *p); ++ ++/** Saves global register values into system memory. */ ++extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if); ++/** Saves device register values into system memory. */ ++extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if); ++/** Saves host register values into system memory. */ ++extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if); ++/** Restore global register values. */ ++extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if); ++/** Restore host register values. */ ++extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset); ++/** Restore device register values. */ ++extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, ++ int rem_wakeup); ++extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if); ++extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, ++ int is_host); ++ ++extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int restore_mode, int reset); ++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/* ++ * The following functions support initialization of the CIL driver component ++ * and the DWC_otg controller. ++ */ ++extern void dwc_otg_core_host_init(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_core_dev_init(dwc_otg_core_if_t * _core_if); ++ ++/** @name Device CIL Functions ++ * The following functions support managing the DWC_otg controller in device ++ * mode. ++ */ ++/**@{*/ ++extern void dwc_otg_wakeup(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_read_setup_packet(dwc_otg_core_if_t * _core_if, ++ uint32_t * _dest); ++extern uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_ep0_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_activate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_deactivate(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_ep_write_packet(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep, int _dma); ++extern void dwc_otg_ep_set_stall(dwc_otg_core_if_t * _core_if, dwc_ep_t * _ep); ++extern void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * _core_if, ++ dwc_ep_t * _ep); ++extern void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * _core_if); ++ ++#ifdef DWC_EN_ISOC ++extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep); ++extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep); ++#endif /* DWC_EN_ISOC */ ++/**@}*/ ++ ++/** @name Host CIL Functions ++ * The following functions support managing the DWC_otg controller in host ++ * mode. ++ */ ++/**@{*/ ++extern void dwc_otg_hc_init(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_halt(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc, dwc_otg_halt_status_e _halt_status); ++extern void dwc_otg_hc_cleanup(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern void dwc_otg_hc_do_ping(dwc_otg_core_if_t * _core_if, dwc_hc_t * _hc); ++extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if, ++ dwc_hc_t * _hc); ++extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if); ++ ++extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc); ++ ++extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if); ++ ++/* Macro used to clear one channel interrupt */ ++#define clear_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ hcint_data_t hcint_clear = {.d32 = 0}; \ ++ hcint_clear.b._intr_ = 1; \ ++ DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \ ++} while (0) ++ ++/* ++ * Macro used to disable one channel interrupt. Channel interrupts are ++ * disabled when the channel is halted or released by the interrupt handler. ++ * There is no need to handle further interrupts of that type until the ++ * channel is re-assigned. In fact, subsequent handling may cause crashes ++ * because the channel structures are cleaned up when the channel is released. ++ */ ++#define disable_hc_int(_hc_regs_, _intr_) \ ++do { \ ++ hcintmsk_data_t hcintmsk = {.d32 = 0}; \ ++ hcintmsk.b._intr_ = 1; \ ++ DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \ ++} while (0) ++ ++/** ++ * 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 ++ */ ++static inline 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; ++} ++ ++/**@}*/ ++ ++/** @name Common CIL Functions ++ * The following functions support managing the DWC_otg controller in either ++ * device or host mode. ++ */ ++/**@{*/ ++ ++extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, ++ uint8_t * dest, uint16_t bytes); ++ ++extern void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * _core_if, const int _num); ++extern void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * _core_if); ++extern void dwc_otg_core_reset(dwc_otg_core_if_t * _core_if); ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if) ++{ ++ return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) & ++ DWC_READ_REG32(&core_if->core_global_regs->gintmsk)); ++} ++ ++/** ++ * This function returns the OTG Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if) ++{ ++ return (DWC_READ_REG32(&core_if->core_global_regs->gotgint)); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the IN endpoint interrupt bits. ++ */ ++static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t * ++ core_if) ++{ ++ ++ uint32_t v; ++ ++ if (core_if->multiproc_int_enable) { ++ v = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ DWC_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); ++ } else { ++ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ } ++ return (v & 0xffff); ++} ++ ++/** ++ * This function reads the Device All Endpoints Interrupt register and ++ * returns the OUT endpoint interrupt bits. ++ */ ++static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t * ++ core_if) ++{ ++ uint32_t v; ++ ++ if (core_if->multiproc_int_enable) { ++ v = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ DWC_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); ++ } else { ++ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ } ++ ++ return ((v & 0xffff0000) >> 16); ++} ++ ++/** ++ * This function returns the Device IN EP Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ uint32_t v, msk, emp; ++ ++ if (core_if->multiproc_int_enable) { ++ msk = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->diepeachintmsk[ep->num]); ++ emp = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ msk |= ((emp >> ep->num) & 0x1) << 7; ++ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ } else { ++ msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk); ++ emp = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ msk |= ((emp >> ep->num) & 0x1) << 7; ++ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ } ++ ++ return v; ++} ++ ++/** ++ * This function returns the Device OUT EP Interrupt register ++ */ ++static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t * ++ _core_if, dwc_ep_t * _ep) ++{ ++ dwc_otg_dev_if_t *dev_if = _core_if->dev_if; ++ uint32_t v; ++ doepmsk_data_t msk = {.d32 = 0 }; ++ ++ if (_core_if->multiproc_int_enable) { ++ msk.d32 = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->doepeachintmsk[_ep->num]); ++ if (_core_if->pti_enh_enable) { ++ msk.b.pktdrpsts = 1; ++ } ++ v = DWC_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; ++ } else { ++ msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk); ++ if (_core_if->pti_enh_enable) { ++ msk.b.pktdrpsts = 1; ++ } ++ v = DWC_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; ++ } ++ return v; ++} ++ ++/** ++ * 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, dwc_hc_t * _hc) ++{ ++ return (DWC_READ_REG32 ++ (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint)); ++} ++ ++/** ++ * 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); ++} ++ ++/**@}*/ ++ ++/** ++ * DWC_otg CIL callback structure. This structure allows the HCD and ++ * PCD to register functions used for starting and stopping the PCD ++ * and HCD for role change on for a DRD. ++ */ ++typedef struct dwc_otg_cil_callbacks { ++ /** Start function for role change */ ++ int (*start) (void *_p); ++ /** Stop Function for role change */ ++ int (*stop) (void *_p); ++ /** Disconnect Function for role change */ ++ int (*disconnect) (void *_p); ++ /** Resume/Remote wakeup Function */ ++ int (*resume_wakeup) (void *_p); ++ /** Suspend function */ ++ int (*suspend) (void *_p); ++ /** Session Start (SRP) */ ++ int (*session_start) (void *_p); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ /** Sleep (switch to L0 state) */ ++ int (*sleep) (void *_p); ++#endif ++ /** Pointer passed to start() and stop() */ ++ void *p; ++} dwc_otg_cil_callbacks_t; ++ ++extern void dwc_otg_cil_register_pcd_callbacks(dwc_otg_core_if_t * _core_if, ++ dwc_otg_cil_callbacks_t * _cb, ++ void *_p); ++extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if, ++ dwc_otg_cil_callbacks_t * _cb, ++ void *_p); ++ ++void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if); ++ ++////////////////////////////////////////////////////////////////////// ++/** Start the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->start) { ++ core_if->hcd_cb->start(core_if->hcd_cb->p); ++ } ++} ++ ++/** Stop the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->stop) { ++ core_if->hcd_cb->stop(core_if->hcd_cb->p); ++ } ++} ++ ++/** Disconnect the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->disconnect) { ++ core_if->hcd_cb->disconnect(core_if->hcd_cb->p); ++ } ++} ++ ++/** Inform the HCD the a New Session has begun. Helper function for ++ * using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->session_start) { ++ core_if->hcd_cb->session_start(core_if->hcd_cb->p); ++ } ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * Inform the HCD about LPM sleep. ++ * Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->sleep) { ++ core_if->hcd_cb->sleep(core_if->hcd_cb->p); ++ } ++} ++#endif ++ ++/** Resume the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { ++ core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); ++ } ++} ++ ++/** Start the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_start(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->start) { ++ core_if->pcd_cb->start(core_if->pcd_cb->p); ++ } ++} ++ ++/** Stop the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->stop) { ++ core_if->pcd_cb->stop(core_if->pcd_cb->p); ++ } ++} ++ ++/** Suspend the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->suspend) { ++ core_if->pcd_cb->suspend(core_if->pcd_cb->p); ++ } ++} ++ ++/** Resume the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++} ++ ++////////////////////////////////////////////////////////////////////// ++ ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +new file mode 100644 +index 0000000..21804c4 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +@@ -0,0 +1,1563 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ ++ * $Revision: #32 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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. ++ * ========================================================================== */ ++ ++/** @file ++ * ++ * The Core Interface Layer provides basic services for accessing and ++ * managing the DWC_otg hardware. These services are used by both the ++ * Host Controller Driver and the Peripheral Controller Driver. ++ * ++ * This file contains the Common Interrupt handlers. ++ */ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_hcd.h" ++ ++#ifdef DEBUG ++inline const char *op_state_str(dwc_otg_core_if_t * core_if) ++{ ++ return (core_if->op_state == A_HOST ? "a_host" : ++ (core_if->op_state == A_SUSPEND ? "a_suspend" : ++ (core_if->op_state == A_PERIPHERAL ? "a_peripheral" : ++ (core_if->op_state == B_PERIPHERAL ? "b_peripheral" : ++ (core_if->op_state == B_HOST ? "b_host" : "unknown"))))); ++} ++#endif ++ ++/** This function will log a debug message ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ DWC_WARN("Mode Mismatch Interrupt: currently in %s mode\n", ++ dwc_otg_mode(core_if) ? "Host" : "Device"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.modemismatch = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This function handles the OTG Interrupts. It reads the OTG ++ * Interrupt Register (GOTGINT) to determine what interrupt has ++ * occurred. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gotgint_data_t gotgint; ++ gotgctl_data_t gotgctl; ++ gintmsk_data_t gintmsk; ++ gpwrdn_data_t gpwrdn; ++ ++ gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, ++ op_state_str(core_if)); ++ ++ if (gotgint.b.sesenddet) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session End Detected++ (%s)\n", ++ op_state_str(core_if)); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ ++ if (core_if->op_state == B_HOST) { ++ cil_pcd_start(core_if); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ /* If not B_HOST and Device HNP still set. HNP ++ * Did not succeed!*/ ++ if (gotgctl.b.devhnpen) { ++ DWC_DEBUGPL(DBG_ANY, "Session End Detected\n"); ++ __DWC_ERROR("Device Not Connected/Responding!\n"); ++ } ++ ++ /* If Session End Detected the B-Cable has ++ * been disconnected. */ ++ /* Reset PCD and Gadget driver to a ++ * clean state. */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ ++ if (core_if->adp_enable) { ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_otg_adp_sense_start(core_if); ++ } ++ } ++ ++ gotgctl.d32 = 0; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ } ++ if (gotgint.b.sesreqsucstschng) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Session Reqeust Success Status Change++\n"); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ if (gotgctl.b.sesreqscs) { ++ ++ if ((core_if->core_params->phy_type == ++ DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) { ++ core_if->srp_success = 1; ++ } else { ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_resume(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ /* Clear Session Request */ ++ gotgctl.d32 = 0; ++ gotgctl.b.sesreq = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, ++ gotgctl.d32, 0); ++ } ++ } ++ } ++ if (gotgint.b.hstnegsucstschng) { ++ /* Print statements during the HNP interrupt handling ++ * can cause it to fail.*/ ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ /* WA for 3.00a- HW is not setting cur_mode, even sometimes ++ * this does not help*/ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ dwc_udelay(100); ++ if (gotgctl.b.hstnegscs) { ++ if (dwc_otg_is_host_mode(core_if)) { ++ core_if->op_state = B_HOST; ++ /* ++ * Need to disable SOF interrupt immediately. ++ * When switching from device to host, the PCD ++ * interrupt handler won't handle the ++ * interrupt if host mode is already set. The ++ * HCD interrupt handler won't get called if ++ * the HCD state is HALT. This means that the ++ * interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, ++ gintmsk.d32, 0); ++ /* Call callback function with spin lock released */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = B_HOST; ++ } ++ } else { ++ gotgctl.d32 = 0; ++ gotgctl.b.hnpreq = 1; ++ gotgctl.b.devhnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); ++ __DWC_ERROR("Device Not Connected/Responding\n"); ++ } ++ } ++ if (gotgint.b.hstnegdet) { ++ /* The disconnect interrupt is set at the same time as ++ * Host Negotiation Detected. During the mode ++ * switch all interrupts are cleared so the disconnect ++ * interrupt handler will not get executed. ++ */ ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "Host Negotiation Detected++ (%s)\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Device")); ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", ++ core_if->op_state); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_PERIPHERAL; ++ } else { ++ /* ++ * Need to disable SOF interrupt immediately. When ++ * switching from device to host, the PCD interrupt ++ * handler won't handle the interrupt if host mode is ++ * already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that ++ * the interrupt does not get handled and Linux ++ * complains loudly. ++ */ ++ gintmsk.d32 = 0; ++ gintmsk.b.sofintr = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ } ++ if (gotgint.b.adevtoutchng) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " ++ "A-Device Timeout Change++\n"); ++ } ++ if (gotgint.b.debdone) { ++ DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " "Debounce Done++\n"); ++ } ++ ++ /* Clear GOTGINT */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32); ++ ++ return 1; ++} ++ ++void w_conn_id_status_change(void *p) ++{ ++ dwc_otg_core_if_t *core_if = p; ++ uint32_t count = 0; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); ++ DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); ++ ++ /* B-Device connector (Device Mode) */ ++ if (gotgctl.b.conidsts) { ++ /* Wait for switch to device mode. */ ++ while (!dwc_otg_is_device_mode(core_if)) { ++ DWC_PRINTF("Waiting for Peripheral Mode, Mode=%s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral")); ++ dwc_mdelay(100); ++ if (++count > 10000) ++ break; ++ } ++ DWC_ASSERT(++count < 10000, ++ "Connection id status change timed out"); ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ /* A-Device connector (Host Mode) */ ++ while (!dwc_otg_is_host_mode(core_if)) { ++ DWC_PRINTF("Waiting for Host Mode, Mode=%s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : ++ "Peripheral")); ++ dwc_mdelay(100); ++ if (++count > 10000) ++ break; ++ } ++ DWC_ASSERT(++count < 10000, ++ "Connection id status change timed out"); ++ core_if->op_state = A_HOST; ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++} ++ ++/** ++ * This function handles the Connector ID Status Change Interrupt. It ++ * reads the OTG Interrupt Register (GOTCTL) to determine whether this ++ * is a Device to Host Mode transition or a Host Mode to Device ++ * Transition. ++ * ++ * This only occurs when the cable is connected/removed from the PHY ++ * connector. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if) ++{ ++ ++ /* ++ * Need to disable SOF interrupt immediately. If switching from device ++ * to host, the PCD interrupt handler won't handle the interrupt if ++ * host mode is already set. The HCD interrupt handler won't get ++ * called if the HCD state is HALT. This means that the interrupt does ++ * not get handled and Linux complains loudly. ++ */ ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ ++ gintmsk.b.sofintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ DWC_DEBUGPL(DBG_CIL, ++ " ++Connector ID Status Change Interrupt++ (%s)\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device")); ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ /* ++ * Need to schedule a work, as there are possible DELAY function calls ++ * Release lock before scheduling workq as it holds spinlock during scheduling ++ */ ++ ++ DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change, ++ core_if, "connection id status change"); ++ DWC_SPINLOCK(core_if->lock); ++ ++ /* Set flag and clear interrupt */ ++ gintsts.b.conidstschng = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device is initiating the Session ++ * Request Protocol to request the host to turn on bus power so a new ++ * session can begin. The handler responds by turning on bus power. If ++ * the DWC_otg controller is in low power mode, the handler brings the ++ * controller out of low power mode before turning on bus power. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++#ifndef DWC_HOST_ONLY ++ DWC_DEBUGPL(DBG_ANY, "++Session Request Interrupt++\n"); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_PRINTF("SRP: Device mode\n"); ++ } else { ++ hprt0_data_t hprt0; ++ DWC_PRINTF("SRP: Host mode\n"); ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Start the Connection timer. So a message can be displayed ++ * if connect does not occur within 10 seconds. */ ++ cil_hcd_session_start(core_if); ++ } ++#endif ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sessreqintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++void w_wakeup_detected(void *p) ++{ ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) p; ++ /* ++ * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms ++ * so that OPT tests pass with all PHYs). ++ */ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++#if 0 ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ dwc_udelay(10); ++#endif //0 ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); ++// dwc_mdelay(70); ++ hprt0.b.prtres = 0; /* Resume */ ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n", ++ DWC_READ_REG32(core_if->host_if->hprt0)); ++ ++ cil_hcd_resume(core_if); ++ ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++} ++ ++/** ++ * This interrupt indicates that the DWC_otg controller has detected a ++ * resume or remote wakeup sequence. If the DWC_otg controller is in ++ * low power mode, the handler must brings the controller out of low ++ * power mode. The controller automatically begins resume ++ * signaling. The handler schedules a time to stop resume signaling. ++ */ ++int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "++Resume and Remote Wakeup Detected Interrupt++\n"); ++ ++ DWC_PRINTF("%s lxstate = %d\n", __func__, core_if->lx_state); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> ++ dsts)); ++ if (core_if->lx_state == DWC_OTG_L2) { ++#ifdef PARTIAL_POWER_DOWN ++ if (core_if->hwcfg4.b.power_optimiz) { ++ pcgcctl_data_t power = {.d32 = 0 }; ++ ++ power.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", ++ power.d32); ++ ++ power.b.stoppclk = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.pwrclmp = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ } ++#endif ++ /* Clear the Remote Wakeup Signaling */ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, dctl.d32, 0); ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ } else { ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ } ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++ } else { ++ if (core_if->lx_state != DWC_OTG_L1) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ ++ /* Restart the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71); ++ } else { ++ /** Change to L0 state*/ ++ core_if->lx_state = DWC_OTG_L0; ++ } ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.wkupintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * Device disconnect. ++ */ ++static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if) ++{ ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = { .d32 = 0 }; ++ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps*/ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * remote wakeup sequence. ++ */ ++static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_ANY, ++ "++Powerdown Remote Wakeup Detected Interrupt++\n"); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (gpwrdn.b.idsts) { // Device Mode ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ dwc_otg_device_hibernation_restore(core_if, 0, 0); ++ } ++ } else { ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ dwc_otg_host_hibernation_restore(core_if, 1, 0); ++ } ++ } ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n"); ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->gpwrdn_local; ++ if (gpwrdn.b.dis_vbus == 1) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ } ++ ++ if (core_if->adp_enable) { ++ uint8_t is_host = 0; ++ DWC_SPINUNLOCK(core_if->lock); ++ /* Change the core_if's lock to hcd/pcd lock depend on mode? */ ++#ifndef DWC_HOST_ONLY ++ if (gpwrdn_temp.b.idsts) ++ core_if->lock = otg_dev->pcd->lock; ++#endif ++#ifndef DWC_DEVICE_ONLY ++ if (!gpwrdn_temp.b.idsts) { ++ core_if->lock = otg_dev->hcd->lock; ++ is_host = 1; ++ } ++#endif ++ DWC_PRINTF("RESTART ADP\n"); ++ if (core_if->adp.probe_enabled) ++ dwc_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ dwc_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ ++ /* Disable PMU and restart ADP */ ++ gpwrdn_temp.d32 = 0; ++ gpwrdn_temp.b.pmuactv = 1; ++ gpwrdn_temp.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ DWC_PRINTF("Check point 1\n"); ++ dwc_mdelay(110); ++ dwc_otg_adp_start(core_if, is_host); ++ DWC_SPINLOCK(core_if->lock); ++ } ++ ++ ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) && ++ gpwrdn.b.bsessvld == 0) { ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */ ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ dwc_otg_initiate_srp(core_if); ++ } ++ } ++ ++ return 1; ++} ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * status change either on IDDIG or BSessVld. ++ */ ++static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev) ++{ ++ int retval; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (core_if->power_down == 2) { ++ if (core_if->hibernation_suspend <= 0) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } else ++ gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local; ++ ++ } else { ++ gpwrdn_temp.d32 = core_if->adp.gpwrdn; ++ } ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) { ++ retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev); ++ } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) { ++ retval = dwc_otg_handle_pwrdn_session_change(core_if); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * SRP. ++ */ ++static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++#ifdef DWC_DEV_SRPCAP ++ if (core_if->pwron_timer_started) { ++ core_if->pwron_timer_started = 0; ++ DWC_TIMER_CANCEL(core_if->pwron_timer); ++ } ++#endif ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Programm Disable VBUS to 0 */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Initialize the core as Host */ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ ++ return 1; ++} ++ ++/** This interrupt indicates that restore command after Hibernation ++ * was completed by the core. */ ++int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if) ++{ ++ pcgcctl_data_t pcgcctl; ++ DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n"); ++ ++ //TODO De-assert restore signal. 8.a ++ pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ if (pcgcctl.b.restoremode == 1) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ /* ++ * If restore mode is Remote Wakeup, ++ * unmask Remote Wakeup interrupt. ++ */ ++ gintmsk.b.wkupintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that a device has been disconnected from ++ * the root port. ++ */ ++int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_ANY, "++Disconnect Detected Interrupt++ (%s) %s\n", ++ (dwc_otg_is_host_mode(core_if) ? "Host" : "Device"), ++ op_state_str(core_if)); ++ ++/** @todo Consolidate this if statement. */ ++#ifndef DWC_HOST_ONLY ++ if (core_if->op_state == B_HOST) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = B_PERIPHERAL; ++ } else if (dwc_otg_is_device_mode(core_if)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (gotgctl.b.hstsethnpen == 1) { ++ /* Do nothing, if HNP in process the OTG ++ * interrupt "Host Negotiation Detected" ++ * interrupt will do the mode switch. ++ */ ++ } else if (gotgctl.b.devhnpen == 0) { ++ /* If in device mode Disconnect and stop the HCD, then ++ * start the PCD. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = B_PERIPHERAL; ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); ++ } ++ } else { ++ if (core_if->op_state == A_HOST) { ++ /* A-Cable still connected but device disconnected. */ ++ cil_hcd_disconnect(core_if); ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ cil_hcd_stop(core_if); ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_otg_adp_probe_start(core_if); ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ } ++ } ++ } ++#endif ++ /* Change to L3(OFF) state */ ++ core_if->lx_state = DWC_OTG_L3; ++ ++ gintsts.d32 = 0; ++ gintsts.b.disconnect = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that SUSPEND state has been detected on ++ * the USB. ++ * ++ * For HNP the USB Suspend interrupt signals the change from ++ * "a_peripheral" to "a_host". ++ * ++ * When power management is enabled the core will be put in low power ++ * mode. ++ */ ++int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ gintsts_data_t gintsts; ++ dcfg_data_t dcfg; ++ ++ DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ /* Check the Device status register to determine if the Suspend ++ * state is active. */ ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); ++ DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " ++ "HWCFG4.power Optimize=%d\n", ++ dsts.b.suspsts, core_if->hwcfg4.b.power_optimiz); ++ ++#ifdef PARTIAL_POWER_DOWN ++/** @todo Add a module parameter for power management. */ ++ ++ if (dsts.b.suspsts && core_if->hwcfg4.b.power_optimiz) { ++ pcgcctl_data_t power = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_CIL, "suspend\n"); ++ ++ power.b.pwrclmp = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); ++ ++ power.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); ++ ++ power.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); ++ ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "disconnect?\n"); ++ } ++#endif ++ /* PCD callback for suspend. Release the lock inside of callback function */ ++ cil_pcd_suspend(core_if); ++ if (core_if->power_down == 2) ++ { ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state); ++ DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ DWC_PRINTF("Start of hibernation completed\n"); ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_dev_regs(core_if); ++ ++ gusbcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ } ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ /* Enable interrupts from wake up logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Unmask device mode interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Enable Power Down Clamp */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ DWC_PRINTF("Hibernation completed\n"); ++ ++ return 1; ++ } ++ } else if (core_if->power_down == 3) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state); ++ DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { ++ DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n"); ++ core_if->xhib = 1; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_dev_regs(core_if); ++ ++ /* Wait for 10 PHY clocks */ ++ dwc_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1); ++ ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_switch = 1; ++ core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n"); ++ ++ return 1; ++ } ++ } ++ } else { ++ if (core_if->op_state == A_PERIPHERAL) { ++ DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); ++ /* Clear the a_peripheral flag, back to a_host. */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ core_if->op_state = A_HOST; ++ } ++ } ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ ++ dwc_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0); ++ ++ pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn; ++ gpwrdn.b.restore = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ restore_lpm_i2c_regs(core_if); ++ ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 0; ++ pcgcctl.b.extnd_hiber_switch = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ gahbcfg.d32 = core_if->gr_backup->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.d32 |= 0x608; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 1; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ pcgcctl.b.rstpdwnmodule = 1; ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ return 1; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * This function hadles LPM transaction received interrupt. ++ */ ++static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) ++{ ++ glpmcfg_data_t lpmcfg; ++ gintsts_data_t gintsts; ++ ++ if (!core_if->core_params->lpm_enable) { ++ DWC_PRINTF("Unexpected LPM interrupt\n"); ++ } ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32); ++ ++ if (dwc_otg_is_host_mode(core_if)) { ++ cil_hcd_sleep(core_if); ++ } else { ++ lpmcfg.b.hird_thres |= (1 << 4); ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ } ++ ++ /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ ++ dwc_udelay(10); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ /* Save the current state */ ++ core_if->lx_state = DWC_OTG_L1; ++ } ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.lpmtranrcvd = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ return 1; ++} ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ ++/** ++ * This function returns the Core Interrupt register. ++ */ ++static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) ++{ ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; ++ gintmsk_data_t gintmsk_common = {.d32 = 0 }; ++ gintmsk_common.b.wkupintr = 1; ++ gintmsk_common.b.sessreqintr = 1; ++ gintmsk_common.b.conidstschng = 1; ++ gintmsk_common.b.otgintr = 1; ++ gintmsk_common.b.modemismatch = 1; ++ gintmsk_common.b.disconnect = 1; ++ gintmsk_common.b.usbsuspend = 1; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ gintmsk_common.b.lpmtranrcvd = 1; ++#endif ++ gintmsk_common.b.restoredone = 1; ++ /** @todo: The port interrupt occurs while in device ++ * mode. Added code to CIL to clear the interrupt for now! ++ */ ++ gintmsk_common.b.portintr = 1; ++ ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ ++#ifdef DEBUG ++ /* if any common interrupts set */ ++ if (gintsts.d32 & gintmsk_common.d32) { ++ DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", ++ gintsts.d32, gintmsk.d32); ++ } ++#endif ++ if (gahbcfg.b.glblintrmsk) ++ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); ++ else ++ return 0; ++ ++} ++ ++/* MACRO for clearing interupt bits in GPWRDN register */ ++#define CLEAR_GPWRDN_INTR(__core_if,__intr) \ ++do { \ ++ gpwrdn_data_t gpwrdn = {.d32=0}; \ ++ gpwrdn.b.__intr = 1; \ ++ DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \ ++ 0, gpwrdn.d32); \ ++} while (0) ++ ++/** ++ * Common interrupt handler. ++ * ++ * The common interrupts are those that occur in both Host and Device mode. ++ * This handler handles the following interrupts: ++ * - Mode Mismatch Interrupt ++ * - Disconnect Interrupt ++ * - OTG Interrupt ++ * - Connector ID Status Change Interrupt ++ * - Session Request Interrupt. ++ * - Resume / Remote Wakeup Detected Interrupt. ++ * - LPM Transaction Received Interrupt ++ * - ADP Transaction Received Interrupt ++ * ++ */ ++int32_t dwc_otg_handle_common_intr(void *dev) ++{ ++ int retval = 0; ++ gintsts_data_t gintsts; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ dwc_otg_device_t *otg_dev = dev; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (dwc_otg_is_device_mode(core_if)) ++ core_if->frame_num = dwc_otg_get_frame_number(core_if); ++ ++ if (core_if->lock) ++ DWC_SPINLOCK(core_if->lock); ++ ++ if (core_if->power_down == 3 && core_if->xhib == 1) { ++ DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n"); ++ retval |= dwc_otg_handle_xhib_exit_intr(core_if); ++ core_if->xhib = 2; ++ if (core_if->lock) ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ return retval; ++ } ++ ++ if (core_if->hibernation_suspend <= 0) { ++ gintsts.d32 = dwc_otg_read_common_intr(core_if); ++ ++ if (gintsts.b.modemismatch) { ++ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); ++ } ++ if (gintsts.b.otgintr) { ++ retval |= dwc_otg_handle_otg_intr(core_if); ++ } ++ if (gintsts.b.conidstschng) { ++ retval |= ++ dwc_otg_handle_conn_id_status_change_intr(core_if); ++ } ++ if (gintsts.b.disconnect) { ++ retval |= dwc_otg_handle_disconnect_intr(core_if); ++ } ++ if (gintsts.b.sessreqintr) { ++ retval |= dwc_otg_handle_session_req_intr(core_if); ++ } ++ if (gintsts.b.wkupintr) { ++ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); ++ } ++ if (gintsts.b.usbsuspend) { ++ retval |= dwc_otg_handle_usb_suspend_intr(core_if); ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (gintsts.b.lpmtranrcvd) { ++ retval |= dwc_otg_handle_lpm_intr(core_if); ++ } ++#endif ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ if (core_if->power_down == 2) ++ core_if->hibernation_suspend = -1; ++ else if (core_if->power_down == 3 && core_if->xhib == 2) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, 0xFFFFFFFF); ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "RESTORE DONE generated\n"); ++ ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ pcgcctl.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl); ++ dwc_udelay(50); ++ ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ dwc_udelay(10); ++ ++ dwc_otg_restore_global_regs(core_if); ++ dwc_otg_restore_dev_regs(core_if, 0); ++ ++ dctl.d32 = 0; ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ dwc_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ core_if->xhib = 0; ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ ++ } ++ ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ DWC_PRINTF(" --Restore done interrupt received-- \n"); ++ retval |= 1; ++ } ++ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { ++ /* The port interrupt occurs while in device mode with HPRT0 ++ * Port Enable/Disable. ++ */ ++ gintsts.d32 = 0; ++ gintsts.b.portintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ retval |= 1; ++ ++ } ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); ++ ++ if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, disconn_det); ++ if (gpwrdn.b.linestate == 0) { ++ dwc_otg_handle_pwrdn_disconnect_intr(core_if); ++ } else { ++ DWC_PRINTF("Disconnect detected while linestate is not 0\n"); ++ } ++ ++ retval |= 1; ++ } ++ if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) { ++ CLEAR_GPWRDN_INTR(core_if, lnstschng); ++ /* remote wakeup from hibernation */ ++ if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) { ++ dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if); ++ } else { ++ DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate); ++ } ++ retval |= 1; ++ } ++ if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, rst_det); ++ if (gpwrdn.b.linestate == 0) { ++ DWC_PRINTF("Reset detected\n"); ++ retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1); ++ } ++ } ++ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, srp_det); ++ dwc_otg_handle_pwrdn_srp_intr(core_if); ++ retval |= 1; ++ } ++ } ++ /* Handle ADP interrupt here */ ++ if (gpwrdn.b.adp_int) { ++ DWC_PRINTF("ADP interrupt\n"); ++ CLEAR_GPWRDN_INTR(core_if, adp_int); ++ dwc_otg_adp_handle_intr(core_if); ++ retval |= 1; ++ } ++ if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) { ++ DWC_PRINTF("STS CHNG interrupt asserted\n"); ++ CLEAR_GPWRDN_INTR(core_if, sts_chngint); ++ dwc_otg_handle_pwrdn_stschng_intr(otg_dev); ++ ++ retval |= 1; ++ } ++ if (core_if->lock) ++ DWC_SPINUNLOCK(core_if->lock); ++ ++ return retval; ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h +new file mode 100644 +index 0000000..10b68c4 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h +@@ -0,0 +1,705 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $ ++ * $Revision: #13 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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. ++ * ========================================================================== */ ++#if !defined(__DWC_CORE_IF_H__) ++#define __DWC_CORE_IF_H__ ++ ++#include "dwc_os.h" ++ ++/** @file ++ * This file defines DWC_OTG Core API ++ */ ++ ++struct dwc_otg_core_if; ++typedef struct dwc_otg_core_if dwc_otg_core_if_t; ++ ++/** 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 ++ ++extern dwc_otg_core_if_t *dwc_otg_cil_init(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(void *otg_dev); ++ ++/** @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 1 ++#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 8192 ++#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 1024 ++#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 1024 ++#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 1024 ++#define dwc_param_host_perio_tx_fifo_size_default 0x200 // Broadcom BCM2708 ++ ++/** The maximum transfer size supported in bytes. ++ * 2047 to 65,535 (default 65,535) ++ */ ++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 ++#define dwc_param_host_channels_default 8 // Broadcom BCM2708 ++ ++/** 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 16 ++#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 768 ++ ++/** 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 1 ++ ++/** ++ * 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 ADP capability is enabled ++ */ ++extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_adp_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 ++ ++extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if); ++#define dwc_param_power_down_default 0 ++ ++extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if); ++#define dwc_param_reload_ctl_default 0 ++ ++extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if); ++#define dwc_param_dev_out_nak_default 0 ++ ++extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if); ++#define dwc_param_cont_on_bna_default 0 ++ ++extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if); ++#define dwc_param_ahb_single_default 0 ++ ++extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if); ++#define dwc_param_otg_ver_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); ++ ++/** ++ * Get value of flag indicating core state - hibernated or not ++ */ ++extern uint32_t dwc_otg_get_core_state(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); ++ ++/** ++ * Get value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of Fram Interval field from the HFIR regsiter ++ */ ++extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of Frame Interval field from the HFIR regsiter ++ */ ++extern void dwc_otg_set_fr_interval(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); ++ ++/** ++ * GHPTXFSIZE ++ */ ++extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if); ++ ++/** @} */ ++ ++#endif /* __DWC_CORE_IF_H__ */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h +new file mode 100644 +index 0000000..8681aa9 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h +@@ -0,0 +1,116 @@ ++/* ========================================================================== ++ * ++ * 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_DBG_H__ ++#define __DWC_OTG_DBG_H__ ++ ++/** @file ++ * This file defines debug levels. ++ * Debugging support vanishes in non-debug builds. ++ */ ++ ++/** ++ * The Debug Level bit-mask variable. ++ */ ++extern uint32_t g_dbg_lvl; ++/** ++ * Set the Debug Level variable. ++ */ ++static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new) ++{ ++ uint32_t old = g_dbg_lvl; ++ g_dbg_lvl = new; ++ return old; ++} ++ ++/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */ ++#define DBG_CIL (0x2) ++/** When debug level has the DBG_CILV bit set, display CIL Verbose debug ++ * messages */ ++#define DBG_CILV (0x20) ++/** When debug level has the DBG_PCD bit set, display PCD (Device) debug ++ * messages */ ++#define DBG_PCD (0x4) ++/** When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug ++ * messages */ ++#define DBG_PCDV (0x40) ++/** When debug level has the DBG_HCD bit set, display Host debug messages */ ++#define DBG_HCD (0x8) ++/** When debug level has the DBG_HCDV bit set, display Verbose Host debug ++ * messages */ ++#define DBG_HCDV (0x80) ++/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host ++ * mode. */ ++#define DBG_HCD_URB (0x800) ++/** When debug level has the DBG_HCDI bit set, display host interrupt ++ * messages. */ ++#define DBG_HCDI (0x1000) ++ ++/** When debug level has any bit set, display debug messages */ ++#define DBG_ANY (0xFF) ++ ++/** All debug messages off */ ++#define DBG_OFF 0 ++ ++/** Prefix string for DWC_DEBUG print macros. */ ++#define USB_DWC "DWC_otg: " ++ ++/** ++ * Print a debug message when the Global debug level variable contains ++ * the bit defined in lvl. ++ * ++ * @param[in] lvl - Debug level, use one of the DBG_ constants above. ++ * @param[in] x - like printf ++ * ++ * Example:

++ * ++ * DWC_DEBUGPL( DBG_ANY, "%s(%p)\n", __func__, _reg_base_addr); ++ * ++ *
++ * results in:
++ * ++ * usb-DWC_otg: dwc_otg_cil_init(ca867000) ++ * ++ */ ++#ifdef DEBUG ++ ++# define DWC_DEBUGPL(lvl, x...) do{ if ((lvl)&g_dbg_lvl)__DWC_DEBUG(USB_DWC x ); }while(0) ++# define DWC_DEBUGP(x...) DWC_DEBUGPL(DBG_ANY, x ) ++ ++# define CHK_DEBUG_LEVEL(level) ((level) & g_dbg_lvl) ++ ++#else ++ ++# define DWC_DEBUGPL(lvl, x...) do{}while(0) ++# define DWC_DEBUGP(x...) ++ ++# define CHK_DEBUG_LEVEL(level) (0) ++ ++#endif /*DEBUG*/ ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c +new file mode 100644 +index 0000000..e7f99e1 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c +@@ -0,0 +1,1700 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ ++ * $Revision: #92 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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. ++ * ========================================================================== */ ++ ++/** @file ++ * The dwc_otg_driver module provides the initialization and cleanup entry ++ * points for the DWC_otg driver. This module will be dynamically installed ++ * after Linux is booted using the insmod command. When the module is ++ * installed, the dwc_otg_driver_init function is called. When the module is ++ * removed (using rmmod), the dwc_otg_driver_cleanup function is called. ++ * ++ * This module also defines a data structure for the dwc_otg_driver, which is ++ * used in conjunction with the standard ARM lm_device structure. These ++ * structures allow the OTG driver to comply with the standard Linux driver ++ * model in which devices and drivers are registered with a bus driver. This ++ * has the benefit that Linux can expose attributes of the driver and device ++ * in its special sysfs file system. Users can then read or write files in ++ * this file system to perform diagnostics on the driver components or the ++ * device. ++ */ ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_os.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_attr.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_hcd_if.h" ++ ++#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012" ++#define DWC_DRIVER_DESC "HS OTG USB Controller driver" ++ ++bool microframe_schedule=true; ++ ++static const char dwc_driver_name[] = "dwc_otg"; ++ ++extern int pcd_init( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *dev ++#endif ++ ); ++extern int hcd_init( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *dev ++#endif ++ ); ++ ++extern int pcd_remove( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *_dev ++#endif ++ ); ++ ++extern void hcd_remove( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *_dev ++#endif ++ ); ++ ++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); ++ ++/*-------------------------------------------------------------------------*/ ++/* Encapsulate the module parameter settings */ ++ ++struct dwc_otg_driver_module_params { ++ int32_t opt; ++ int32_t otg_cap; ++ int32_t dma_enable; ++ int32_t dma_desc_enable; ++ int32_t dma_burst_size; ++ int32_t speed; ++ int32_t host_support_fs_ls_low_power; ++ int32_t host_ls_low_power_phy_clk; ++ int32_t enable_dynamic_fifo; ++ int32_t data_fifo_size; ++ int32_t dev_rx_fifo_size; ++ int32_t dev_nperio_tx_fifo_size; ++ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ int32_t host_rx_fifo_size; ++ int32_t host_nperio_tx_fifo_size; ++ int32_t host_perio_tx_fifo_size; ++ int32_t max_transfer_size; ++ int32_t max_packet_count; ++ int32_t host_channels; ++ int32_t dev_endpoints; ++ int32_t phy_type; ++ int32_t phy_utmi_width; ++ int32_t phy_ulpi_ddr; ++ int32_t phy_ulpi_ext_vbus; ++ int32_t i2c_enable; ++ int32_t ulpi_fs_ls; ++ int32_t ts_dline; ++ int32_t en_multiple_tx_fifo; ++ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; ++ uint32_t thr_ctl; ++ uint32_t tx_thr_length; ++ uint32_t rx_thr_length; ++ int32_t pti_enable; ++ int32_t mpi_enable; ++ int32_t lpm_enable; ++ int32_t ic_usb_cap; ++ int32_t ahb_thr_ratio; ++ int32_t power_down; ++ int32_t reload_ctl; ++ int32_t dev_out_nak; ++ int32_t cont_on_bna; ++ int32_t ahb_single; ++ int32_t otg_ver; ++ int32_t adp_enable; ++}; ++ ++static struct dwc_otg_driver_module_params dwc_otg_module_params = { ++ .opt = -1, ++ .otg_cap = -1, ++ .dma_enable = -1, ++ .dma_desc_enable = -1, ++ .dma_burst_size = -1, ++ .speed = -1, ++ .host_support_fs_ls_low_power = -1, ++ .host_ls_low_power_phy_clk = -1, ++ .enable_dynamic_fifo = -1, ++ .data_fifo_size = -1, ++ .dev_rx_fifo_size = -1, ++ .dev_nperio_tx_fifo_size = -1, ++ .dev_perio_tx_fifo_size = { ++ /* dev_perio_tx_fifo_size_1 */ ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1 ++ /* 15 */ ++ }, ++ .host_rx_fifo_size = -1, ++ .host_nperio_tx_fifo_size = -1, ++ .host_perio_tx_fifo_size = -1, ++ .max_transfer_size = -1, ++ .max_packet_count = -1, ++ .host_channels = -1, ++ .dev_endpoints = -1, ++ .phy_type = -1, ++ .phy_utmi_width = -1, ++ .phy_ulpi_ddr = -1, ++ .phy_ulpi_ext_vbus = -1, ++ .i2c_enable = -1, ++ .ulpi_fs_ls = -1, ++ .ts_dline = -1, ++ .en_multiple_tx_fifo = -1, ++ .dev_tx_fifo_size = { ++ /* dev_tx_fifo_size */ ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1, ++ -1 ++ /* 15 */ ++ }, ++ .thr_ctl = -1, ++ .tx_thr_length = -1, ++ .rx_thr_length = -1, ++ .pti_enable = -1, ++ .mpi_enable = -1, ++ .lpm_enable = -1, ++ .ic_usb_cap = -1, ++ .ahb_thr_ratio = -1, ++ .power_down = -1, ++ .reload_ctl = -1, ++ .dev_out_nak = -1, ++ .cont_on_bna = -1, ++ .ahb_single = -1, ++ .otg_ver = -1, ++ .adp_enable = -1, ++}; ++ ++/** ++ * This function shows the Driver Version. ++ */ ++static ssize_t version_show(struct device_driver *dev, char *buf) ++{ ++ return snprintf(buf, sizeof(DWC_DRIVER_VERSION) + 2, "%s\n", ++ DWC_DRIVER_VERSION); ++} ++ ++static DRIVER_ATTR(version, S_IRUGO, version_show, NULL); ++ ++/** ++ * Global Debug Level Mask. ++ */ ++uint32_t g_dbg_lvl = 0; /* OFF */ ++ ++/** ++ * This function shows the driver Debug Level. ++ */ ++static ssize_t dbg_level_show(struct device_driver *drv, char *buf) ++{ ++ return sprintf(buf, "0x%0x\n", g_dbg_lvl); ++} ++ ++/** ++ * This function stores the driver Debug Level. ++ */ ++static ssize_t dbg_level_store(struct device_driver *drv, const char *buf, ++ size_t count) ++{ ++ g_dbg_lvl = simple_strtoul(buf, NULL, 16); ++ return count; ++} ++ ++static DRIVER_ATTR(debuglevel, S_IRUGO | S_IWUSR, dbg_level_show, ++ dbg_level_store); ++ ++/** ++ * This function is called during module intialization ++ * to pass module parameters to the DWC_OTG CORE. ++ */ ++static int set_parameters(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ int i; ++ ++ if (dwc_otg_module_params.otg_cap != -1) { ++ retval += ++ dwc_otg_set_param_otg_cap(core_if, ++ dwc_otg_module_params.otg_cap); ++ } ++ if (dwc_otg_module_params.dma_enable != -1) { ++ retval += ++ dwc_otg_set_param_dma_enable(core_if, ++ dwc_otg_module_params. ++ dma_enable); ++ } ++ if (dwc_otg_module_params.dma_desc_enable != -1) { ++ retval += ++ dwc_otg_set_param_dma_desc_enable(core_if, ++ dwc_otg_module_params. ++ dma_desc_enable); ++ } ++ if (dwc_otg_module_params.opt != -1) { ++ retval += ++ dwc_otg_set_param_opt(core_if, dwc_otg_module_params.opt); ++ } ++ if (dwc_otg_module_params.dma_burst_size != -1) { ++ retval += ++ dwc_otg_set_param_dma_burst_size(core_if, ++ dwc_otg_module_params. ++ dma_burst_size); ++ } ++ if (dwc_otg_module_params.host_support_fs_ls_low_power != -1) { ++ retval += ++ dwc_otg_set_param_host_support_fs_ls_low_power(core_if, ++ dwc_otg_module_params. ++ host_support_fs_ls_low_power); ++ } ++ if (dwc_otg_module_params.enable_dynamic_fifo != -1) { ++ retval += ++ dwc_otg_set_param_enable_dynamic_fifo(core_if, ++ dwc_otg_module_params. ++ enable_dynamic_fifo); ++ } ++ if (dwc_otg_module_params.data_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_data_fifo_size(core_if, ++ dwc_otg_module_params. ++ data_fifo_size); ++ } ++ if (dwc_otg_module_params.dev_rx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_dev_rx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_rx_fifo_size); ++ } ++ if (dwc_otg_module_params.dev_nperio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_nperio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_rx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_rx_fifo_size(core_if, ++ dwc_otg_module_params.host_rx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_nperio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_nperio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ host_nperio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.host_perio_tx_fifo_size != -1) { ++ retval += ++ dwc_otg_set_param_host_perio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ host_perio_tx_fifo_size); ++ } ++ if (dwc_otg_module_params.max_transfer_size != -1) { ++ retval += ++ dwc_otg_set_param_max_transfer_size(core_if, ++ dwc_otg_module_params. ++ max_transfer_size); ++ } ++ if (dwc_otg_module_params.max_packet_count != -1) { ++ retval += ++ dwc_otg_set_param_max_packet_count(core_if, ++ dwc_otg_module_params. ++ max_packet_count); ++ } ++ if (dwc_otg_module_params.host_channels != -1) { ++ retval += ++ dwc_otg_set_param_host_channels(core_if, ++ dwc_otg_module_params. ++ host_channels); ++ } ++ if (dwc_otg_module_params.dev_endpoints != -1) { ++ retval += ++ dwc_otg_set_param_dev_endpoints(core_if, ++ dwc_otg_module_params. ++ dev_endpoints); ++ } ++ if (dwc_otg_module_params.phy_type != -1) { ++ retval += ++ dwc_otg_set_param_phy_type(core_if, ++ dwc_otg_module_params.phy_type); ++ } ++ if (dwc_otg_module_params.speed != -1) { ++ retval += ++ dwc_otg_set_param_speed(core_if, ++ dwc_otg_module_params.speed); ++ } ++ if (dwc_otg_module_params.host_ls_low_power_phy_clk != -1) { ++ retval += ++ dwc_otg_set_param_host_ls_low_power_phy_clk(core_if, ++ dwc_otg_module_params. ++ host_ls_low_power_phy_clk); ++ } ++ if (dwc_otg_module_params.phy_ulpi_ddr != -1) { ++ retval += ++ dwc_otg_set_param_phy_ulpi_ddr(core_if, ++ dwc_otg_module_params. ++ phy_ulpi_ddr); ++ } ++ if (dwc_otg_module_params.phy_ulpi_ext_vbus != -1) { ++ retval += ++ dwc_otg_set_param_phy_ulpi_ext_vbus(core_if, ++ dwc_otg_module_params. ++ phy_ulpi_ext_vbus); ++ } ++ if (dwc_otg_module_params.phy_utmi_width != -1) { ++ retval += ++ dwc_otg_set_param_phy_utmi_width(core_if, ++ dwc_otg_module_params. ++ phy_utmi_width); ++ } ++ if (dwc_otg_module_params.ulpi_fs_ls != -1) { ++ retval += ++ dwc_otg_set_param_ulpi_fs_ls(core_if, ++ dwc_otg_module_params.ulpi_fs_ls); ++ } ++ if (dwc_otg_module_params.ts_dline != -1) { ++ retval += ++ dwc_otg_set_param_ts_dline(core_if, ++ dwc_otg_module_params.ts_dline); ++ } ++ if (dwc_otg_module_params.i2c_enable != -1) { ++ retval += ++ dwc_otg_set_param_i2c_enable(core_if, ++ dwc_otg_module_params. ++ i2c_enable); ++ } ++ if (dwc_otg_module_params.en_multiple_tx_fifo != -1) { ++ retval += ++ dwc_otg_set_param_en_multiple_tx_fifo(core_if, ++ dwc_otg_module_params. ++ en_multiple_tx_fifo); ++ } ++ for (i = 0; i < 15; i++) { ++ if (dwc_otg_module_params.dev_perio_tx_fifo_size[i] != -1) { ++ retval += ++ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_perio_tx_fifo_size ++ [i], i); ++ } ++ } ++ ++ for (i = 0; i < 15; i++) { ++ if (dwc_otg_module_params.dev_tx_fifo_size[i] != -1) { ++ retval += dwc_otg_set_param_dev_tx_fifo_size(core_if, ++ dwc_otg_module_params. ++ dev_tx_fifo_size ++ [i], i); ++ } ++ } ++ if (dwc_otg_module_params.thr_ctl != -1) { ++ retval += ++ dwc_otg_set_param_thr_ctl(core_if, ++ dwc_otg_module_params.thr_ctl); ++ } ++ if (dwc_otg_module_params.mpi_enable != -1) { ++ retval += ++ dwc_otg_set_param_mpi_enable(core_if, ++ dwc_otg_module_params. ++ mpi_enable); ++ } ++ if (dwc_otg_module_params.pti_enable != -1) { ++ retval += ++ dwc_otg_set_param_pti_enable(core_if, ++ dwc_otg_module_params. ++ pti_enable); ++ } ++ if (dwc_otg_module_params.lpm_enable != -1) { ++ retval += ++ dwc_otg_set_param_lpm_enable(core_if, ++ dwc_otg_module_params. ++ lpm_enable); ++ } ++ if (dwc_otg_module_params.ic_usb_cap != -1) { ++ retval += ++ dwc_otg_set_param_ic_usb_cap(core_if, ++ dwc_otg_module_params. ++ ic_usb_cap); ++ } ++ if (dwc_otg_module_params.tx_thr_length != -1) { ++ retval += ++ dwc_otg_set_param_tx_thr_length(core_if, ++ dwc_otg_module_params.tx_thr_length); ++ } ++ if (dwc_otg_module_params.rx_thr_length != -1) { ++ retval += ++ dwc_otg_set_param_rx_thr_length(core_if, ++ dwc_otg_module_params. ++ rx_thr_length); ++ } ++ if (dwc_otg_module_params.ahb_thr_ratio != -1) { ++ retval += ++ dwc_otg_set_param_ahb_thr_ratio(core_if, ++ dwc_otg_module_params.ahb_thr_ratio); ++ } ++ if (dwc_otg_module_params.power_down != -1) { ++ retval += ++ dwc_otg_set_param_power_down(core_if, ++ dwc_otg_module_params.power_down); ++ } ++ if (dwc_otg_module_params.reload_ctl != -1) { ++ retval += ++ dwc_otg_set_param_reload_ctl(core_if, ++ dwc_otg_module_params.reload_ctl); ++ } ++ ++ if (dwc_otg_module_params.dev_out_nak != -1) { ++ retval += ++ dwc_otg_set_param_dev_out_nak(core_if, ++ dwc_otg_module_params.dev_out_nak); ++ } ++ ++ if (dwc_otg_module_params.cont_on_bna != -1) { ++ retval += ++ dwc_otg_set_param_cont_on_bna(core_if, ++ dwc_otg_module_params.cont_on_bna); ++ } ++ ++ if (dwc_otg_module_params.ahb_single != -1) { ++ retval += ++ dwc_otg_set_param_ahb_single(core_if, ++ dwc_otg_module_params.ahb_single); ++ } ++ ++ if (dwc_otg_module_params.otg_ver != -1) { ++ retval += ++ dwc_otg_set_param_otg_ver(core_if, ++ dwc_otg_module_params.otg_ver); ++ } ++ if (dwc_otg_module_params.adp_enable != -1) { ++ retval += ++ dwc_otg_set_param_adp_enable(core_if, ++ dwc_otg_module_params. ++ adp_enable); ++ } ++ return retval; ++} ++ ++/** ++ * This function is the top level interrupt handler for the Common ++ * (Device and host modes) interrupts. ++ */ ++static irqreturn_t dwc_otg_common_irq(int irq, void *dev) ++{ ++ int32_t retval = IRQ_NONE; ++ ++ retval = dwc_otg_handle_common_intr(dev); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** ++ * This function is called when a lm_device is unregistered with the ++ * dwc_otg_driver. This happens, for example, when the rmmod command is ++ * executed. The device may or may not be electrically present. If it is ++ * present, the driver stops device processing. Any resources used on behalf ++ * of this device are freed. ++ * ++ * @param _dev ++ */ ++#ifdef LM_INTERFACE ++#define REM_RETVAL(n) ++static void dwc_otg_driver_remove( struct lm_device *_dev ) ++{ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); ++#elif defined(PCI_INTERFACE) ++#define REM_RETVAL(n) ++static void dwc_otg_driver_remove( struct pci_dev *_dev ) ++{ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); ++#elif defined(PLATFORM_INTERFACE) ++#define REM_RETVAL(n) n ++static int dwc_otg_driver_remove( struct platform_device *_dev ) ++{ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); ++#endif ++ ++ DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev); ++ ++ if (!otg_dev) { ++ /* Memory allocation for the dwc_otg_device failed. */ ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); ++ return REM_RETVAL(-ENOMEM); ++ } ++#ifndef DWC_DEVICE_ONLY ++ if (otg_dev->hcd) { ++ hcd_remove(_dev); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); ++ return REM_RETVAL(-EINVAL); ++ } ++#endif ++ ++#ifndef DWC_HOST_ONLY ++ if (otg_dev->pcd) { ++ pcd_remove(_dev); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__); ++ return REM_RETVAL(-EINVAL); ++ } ++#endif ++ /* ++ * Free the IRQ ++ */ ++ if (otg_dev->common_irq_installed) { ++#ifdef PLATFORM_INTERFACE ++ free_irq(platform_get_irq(_dev, 0), otg_dev); ++#else ++ free_irq(_dev->irq, otg_dev); ++#endif ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__); ++ return REM_RETVAL(-ENXIO); ++ } ++ ++ if (otg_dev->core_if) { ++ dwc_otg_cil_remove(otg_dev->core_if); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__); ++ return REM_RETVAL(-ENXIO); ++ } ++ ++ /* ++ * Remove the device attributes ++ */ ++ dwc_otg_attr_remove(_dev); ++ ++ /* ++ * Return the memory. ++ */ ++ if (otg_dev->os_dep.base) { ++ iounmap(otg_dev->os_dep.base); ++ } ++ DWC_FREE(otg_dev); ++ ++ /* ++ * Clear the drvdata pointer. ++ */ ++#ifdef LM_INTERFACE ++ lm_set_drvdata(_dev, 0); ++#elif defined(PCI_INTERFACE) ++ release_mem_region(otg_dev->os_dep.rsrc_start, ++ otg_dev->os_dep.rsrc_len); ++ pci_set_drvdata(_dev, 0); ++#elif defined(PLATFORM_INTERFACE) ++ platform_set_drvdata(_dev, 0); ++#endif ++ return REM_RETVAL(0); ++} ++ ++/** ++ * This function is called when an lm_device is bound to a ++ * dwc_otg_driver. It creates the driver components required to ++ * control the device (CIL, HCD, and PCD) and it initializes the ++ * device. The driver components are stored in a dwc_otg_device ++ * structure. A reference to the dwc_otg_device is saved in the ++ * lm_device. This allows the driver to access the dwc_otg_device ++ * structure on subsequent calls to driver methods for this device. ++ * ++ * @param _dev Bus device ++ */ ++static int dwc_otg_driver_probe( ++#ifdef LM_INTERFACE ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev, ++ const struct pci_device_id *id ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *_dev ++#endif ++ ) ++{ ++ int retval = 0; ++ dwc_otg_device_t *dwc_otg_device; ++ int devirq; ++ ++ dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev); ++#ifdef LM_INTERFACE ++ dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start); ++#elif defined(PCI_INTERFACE) ++ if (!id) { ++ DWC_ERROR("Invalid pci_device_id %p", id); ++ return -EINVAL; ++ } ++ ++ if (!_dev || (pci_enable_device(_dev) < 0)) { ++ DWC_ERROR("Invalid pci_device %p", _dev); ++ return -ENODEV; ++ } ++ dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)pci_resource_start(_dev,0)); ++ /* other stuff needed as well? */ ++ ++#elif defined(PLATFORM_INTERFACE) ++ dev_dbg(&_dev->dev, "start=0x%08x (len 0x%x)\n", ++ (unsigned)_dev->resource->start, ++ (unsigned)(_dev->resource->end - _dev->resource->start)); ++#endif ++ ++ dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t)); ++ ++ if (!dwc_otg_device) { ++ dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n"); ++ return -ENOMEM; ++ } ++ ++ memset(dwc_otg_device, 0, sizeof(*dwc_otg_device)); ++ dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF; ++ ++ /* ++ * Map the DWC_otg Core memory into virtual address space. ++ */ ++#ifdef LM_INTERFACE ++ dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K); ++ ++ if (!dwc_otg_device->os_dep.base) { ++ dev_err(&_dev->dev, "ioremap() failed\n"); ++ DWC_FREE(dwc_otg_device); ++ return -ENOMEM; ++ } ++ dev_dbg(&_dev->dev, "base=0x%08x\n", ++ (unsigned)dwc_otg_device->os_dep.base); ++#elif defined(PCI_INTERFACE) ++ _dev->current_state = PCI_D0; ++ _dev->dev.power.power_state = PMSG_ON; ++ ++ if (!_dev->irq) { ++ DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!", ++ pci_name(_dev)); ++ iounmap(dwc_otg_device->os_dep.base); ++ DWC_FREE(dwc_otg_device); ++ return -ENODEV; ++ } ++ ++ dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0); ++ dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0); ++ DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n", ++ (unsigned)dwc_otg_device->os_dep.rsrc_start, ++ (unsigned)dwc_otg_device->os_dep.rsrc_len); ++ if (!request_mem_region ++ (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len, ++ "dwc_otg")) { ++ dev_dbg(&_dev->dev, "error requesting memory\n"); ++ iounmap(dwc_otg_device->os_dep.base); ++ DWC_FREE(dwc_otg_device); ++ return -EFAULT; ++ } ++ ++ dwc_otg_device->os_dep.base = ++ ioremap_nocache(dwc_otg_device->os_dep.rsrc_start, ++ dwc_otg_device->os_dep.rsrc_len); ++ if (dwc_otg_device->os_dep.base == NULL) { ++ dev_dbg(&_dev->dev, "error mapping memory\n"); ++ release_mem_region(dwc_otg_device->os_dep.rsrc_start, ++ dwc_otg_device->os_dep.rsrc_len); ++ iounmap(dwc_otg_device->os_dep.base); ++ DWC_FREE(dwc_otg_device); ++ return -EFAULT; ++ } ++ dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n", ++ dwc_otg_device->os_dep.base); ++ dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base; ++ dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n", ++ dwc_otg_device->os_dep.base); ++ dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__, ++ (unsigned)dwc_otg_device->os_dep.rsrc_start, ++ dwc_otg_device->os_dep.base); ++ ++ pci_set_master(_dev); ++ pci_set_drvdata(_dev, dwc_otg_device); ++#elif defined(PLATFORM_INTERFACE) ++ DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n", ++ _dev->resource->start, ++ _dev->resource->end - _dev->resource->start + 1); ++#if 1 ++ if (!request_mem_region(_dev->resource->start, ++ _dev->resource->end - _dev->resource->start + 1, ++ "dwc_otg")) { ++ dev_dbg(&_dev->dev, "error reserving mapped memory\n"); ++ retval = -EFAULT; ++ goto fail; ++ } ++ ++ dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start, ++ _dev->resource->end - ++ _dev->resource->start+1); ++#else ++ { ++ struct map_desc desc = { ++ .virtual = IO_ADDRESS((unsigned)_dev->resource->start), ++ .pfn = __phys_to_pfn((unsigned)_dev->resource->start), ++ .length = SZ_128K, ++ .type = MT_DEVICE ++ }; ++ iotable_init(&desc, 1); ++ dwc_otg_device->os_dep.base = (void *)desc.virtual; ++ } ++#endif ++ if (!dwc_otg_device->os_dep.base) { ++ dev_err(&_dev->dev, "ioremap() failed\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ dev_dbg(&_dev->dev, "base=0x%08x\n", ++ (unsigned)dwc_otg_device->os_dep.base); ++#endif ++ ++ /* ++ * Initialize driver data to point to the global DWC_otg ++ * Device structure. ++ */ ++#ifdef LM_INTERFACE ++ lm_set_drvdata(_dev, dwc_otg_device); ++#elif defined(PLATFORM_INTERFACE) ++ platform_set_drvdata(_dev, dwc_otg_device); ++#endif ++ dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device); ++ ++ dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base); ++ DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n", ++ dwc_otg_device, dwc_otg_device->core_if);//GRAYG ++ ++ if (!dwc_otg_device->core_if) { ++ dev_err(&_dev->dev, "CIL initialization failed!\n"); ++ retval = -ENOMEM; ++ goto fail; ++ } ++ ++ dev_dbg(&_dev->dev, "Calling get_gsnpsid\n"); ++ /* ++ * Attempt to ensure this device is really a DWC_otg Controller. ++ * Read and verify the SNPSID register contents. The value should be ++ * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3", ++ * as in "OTG version 2.XX" or "OTG version 3.XX". ++ */ ++ ++ if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) && ++ ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) { ++ dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n", ++ dwc_otg_get_gsnpsid(dwc_otg_device->core_if)); ++ retval = -EINVAL; ++ goto fail; ++ } ++ ++ /* ++ * Validate parameter values. ++ */ ++ dev_dbg(&_dev->dev, "Calling set_parameters\n"); ++ if (set_parameters(dwc_otg_device->core_if)) { ++ retval = -EINVAL; ++ goto fail; ++ } ++ ++ /* ++ * Create Device Attributes in sysfs ++ */ ++ dev_dbg(&_dev->dev, "Calling attr_create\n"); ++ dwc_otg_attr_create(_dev); ++ ++ /* ++ * Disable the global interrupt until all the interrupt ++ * handlers are installed. ++ */ ++ dev_dbg(&_dev->dev, "Calling disable_global_interrupts\n"); ++ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); ++ ++ /* ++ * Install the interrupt handler for the common interrupts before ++ * enabling common interrupts in core_init below. ++ */ ++ ++#if defined(PLATFORM_INTERFACE) ++ devirq = platform_get_irq(_dev, 0); ++#else ++ devirq = _dev->irq; ++#endif ++ DWC_DEBUGPL(DBG_CIL, "registering (common) handler for irq%d\n", ++ devirq); ++ dev_dbg(&_dev->dev, "Calling request_irq(%d)\n", devirq); ++ retval = request_irq(devirq, dwc_otg_common_irq, ++ IRQF_SHARED, ++ "dwc_otg", dwc_otg_device); ++ if (retval) { ++ DWC_ERROR("request of irq%d failed\n", devirq); ++ retval = -EBUSY; ++ goto fail; ++ } else { ++ dwc_otg_device->common_irq_installed = 1; ++ } ++ ++#ifndef IRQF_TRIGGER_LOW ++#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE) ++ dev_dbg(&_dev->dev, "Calling set_irq_type\n"); ++ set_irq_type(devirq, ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) ++ IRQT_LOW ++#else ++ IRQ_TYPE_LEVEL_LOW ++#endif ++ ); ++#endif ++#endif /*IRQF_TRIGGER_LOW*/ ++ ++ /* ++ * Initialize the DWC_otg core. ++ */ ++ dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n"); ++ dwc_otg_core_init(dwc_otg_device->core_if); ++ ++#ifndef DWC_HOST_ONLY ++ /* ++ * Initialize the PCD ++ */ ++ dev_dbg(&_dev->dev, "Calling pcd_init\n"); ++ retval = pcd_init(_dev); ++ if (retval != 0) { ++ DWC_ERROR("pcd_init failed\n"); ++ dwc_otg_device->pcd = NULL; ++ goto fail; ++ } ++#endif ++#ifndef DWC_DEVICE_ONLY ++ /* ++ * Initialize the HCD ++ */ ++ dev_dbg(&_dev->dev, "Calling hcd_init\n"); ++ retval = hcd_init(_dev); ++ if (retval != 0) { ++ DWC_ERROR("hcd_init failed\n"); ++ dwc_otg_device->hcd = NULL; ++ goto fail; ++ } ++#endif ++ /* Recover from drvdata having been overwritten by hcd_init() */ ++#ifdef LM_INTERFACE ++ lm_set_drvdata(_dev, dwc_otg_device); ++#elif defined(PLATFORM_INTERFACE) ++ platform_set_drvdata(_dev, dwc_otg_device); ++#elif defined(PCI_INTERFACE) ++ pci_set_drvdata(_dev, dwc_otg_device); ++ dwc_otg_device->os_dep.pcidev = _dev; ++#endif ++ ++ /* ++ * Enable the global interrupt after all the interrupt ++ * handlers are installed if there is no ADP support else ++ * perform initial actions required for Internal ADP logic. ++ */ ++ if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) { ++ dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n"); ++ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); ++ dev_dbg(&_dev->dev, "Done\n"); ++ } else ++ dwc_otg_adp_start(dwc_otg_device->core_if, ++ dwc_otg_is_host_mode(dwc_otg_device->core_if)); ++ ++ return 0; ++ ++fail: ++ dwc_otg_driver_remove(_dev); ++ return retval; ++} ++ ++/** ++ * This structure defines the methods to be called by a bus driver ++ * during the lifecycle of a device on that bus. Both drivers and ++ * devices are registered with a bus driver. The bus driver matches ++ * devices to drivers based on information in the device and driver ++ * structures. ++ * ++ * The probe function is called when the bus driver matches a device ++ * to this driver. The remove function is called when a device is ++ * unregistered with the bus driver. ++ */ ++#ifdef LM_INTERFACE ++static struct lm_driver dwc_otg_driver = { ++ .drv = {.name = (char *)dwc_driver_name,}, ++ .probe = dwc_otg_driver_probe, ++ .remove = dwc_otg_driver_remove, ++ // 'suspend' and 'resume' absent ++}; ++#elif defined(PCI_INTERFACE) ++static const struct pci_device_id pci_ids[] = { { ++ PCI_DEVICE(0x16c3, 0xabcd), ++ .driver_data = ++ (unsigned long)0xdeadbeef, ++ }, { /* end: all zeroes */ } ++}; ++ ++MODULE_DEVICE_TABLE(pci, pci_ids); ++ ++/* pci driver glue; this is a "new style" PCI driver module */ ++static struct pci_driver dwc_otg_driver = { ++ .name = "dwc_otg", ++ .id_table = pci_ids, ++ ++ .probe = dwc_otg_driver_probe, ++ .remove = dwc_otg_driver_remove, ++ ++ .driver = { ++ .name = (char *)dwc_driver_name, ++ }, ++}; ++#elif defined(PLATFORM_INTERFACE) ++static struct platform_device_id platform_ids[] = { ++ { ++ .name = "bcm2708_usb", ++ .driver_data = (kernel_ulong_t) 0xdeadbeef, ++ }, ++ { /* end: all zeroes */ } ++}; ++MODULE_DEVICE_TABLE(platform, platform_ids); ++ ++static struct platform_driver dwc_otg_driver = { ++ .driver = { ++ .name = (char *)dwc_driver_name, ++ }, ++ .id_table = platform_ids, ++ ++ .probe = dwc_otg_driver_probe, ++ .remove = dwc_otg_driver_remove, ++ // no 'shutdown', 'suspend', 'resume', 'suspend_late' or 'resume_early' ++}; ++#endif ++ ++/** ++ * This function is called when the dwc_otg_driver is installed with the ++ * insmod command. It registers the dwc_otg_driver structure with the ++ * appropriate bus driver. This will cause the dwc_otg_driver_probe function ++ * to be called. In addition, the bus driver will automatically expose ++ * attributes defined for the device and driver in the special sysfs file ++ * system. ++ * ++ * @return ++ */ ++static int __init dwc_otg_driver_init(void) ++{ ++ int retval = 0; ++ int error; ++ struct device_driver *drv; ++ printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name, ++ DWC_DRIVER_VERSION, ++#ifdef LM_INTERFACE ++ "logicmodule"); ++ retval = lm_driver_register(&dwc_otg_driver); ++ drv = &dwc_otg_driver.drv; ++#elif defined(PCI_INTERFACE) ++ "pci"); ++ retval = pci_register_driver(&dwc_otg_driver); ++ drv = &dwc_otg_driver.driver; ++#elif defined(PLATFORM_INTERFACE) ++ "platform"); ++ retval = platform_driver_register(&dwc_otg_driver); ++ drv = &dwc_otg_driver.driver; ++#endif ++ if (retval < 0) { ++ printk(KERN_ERR "%s retval=%d\n", __func__, retval); ++ return retval; ++ } ++ ++ error = driver_create_file(drv, &driver_attr_version); ++#ifdef DEBUG ++ error = driver_create_file(drv, &driver_attr_debuglevel); ++#endif ++ return retval; ++} ++ ++module_init(dwc_otg_driver_init); ++ ++/** ++ * This function is called when the driver is removed from the kernel ++ * with the rmmod command. The driver unregisters itself with its bus ++ * driver. ++ * ++ */ ++static void __exit dwc_otg_driver_cleanup(void) ++{ ++ printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n"); ++ ++#ifdef LM_INTERFACE ++ driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel); ++ driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version); ++ lm_driver_unregister(&dwc_otg_driver); ++#elif defined(PCI_INTERFACE) ++ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel); ++ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version); ++ pci_unregister_driver(&dwc_otg_driver); ++#elif defined(PLATFORM_INTERFACE) ++ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel); ++ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version); ++ platform_driver_unregister(&dwc_otg_driver); ++#endif ++ ++ printk(KERN_INFO "%s module removed\n", dwc_driver_name); ++} ++ ++module_exit(dwc_otg_driver_cleanup); ++ ++MODULE_DESCRIPTION(DWC_DRIVER_DESC); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE("GPL"); ++ ++module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444); ++MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None"); ++module_param_named(opt, dwc_otg_module_params.opt, int, 0444); ++MODULE_PARM_DESC(opt, "OPT Mode"); ++module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444); ++MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled"); ++ ++module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int, ++ 0444); ++MODULE_PARM_DESC(dma_desc_enable, ++ "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled"); ++ ++module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int, ++ 0444); ++MODULE_PARM_DESC(dma_burst_size, ++ "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256"); ++module_param_named(speed, dwc_otg_module_params.speed, int, 0444); ++MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed"); ++module_param_named(host_support_fs_ls_low_power, ++ dwc_otg_module_params.host_support_fs_ls_low_power, int, ++ 0444); ++MODULE_PARM_DESC(host_support_fs_ls_low_power, ++ "Support Low Power w/FS or LS 0=Support 1=Don't Support"); ++module_param_named(host_ls_low_power_phy_clk, ++ dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444); ++MODULE_PARM_DESC(host_ls_low_power_phy_clk, ++ "Low Speed Low Power Clock 0=48Mhz 1=6Mhz"); ++module_param_named(enable_dynamic_fifo, ++ dwc_otg_module_params.enable_dynamic_fifo, int, 0444); ++MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing"); ++module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int, ++ 0444); ++MODULE_PARM_DESC(data_fifo_size, ++ "Total number of words in the data FIFO memory 32-32768"); ++module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size, ++ int, 0444); ++MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); ++module_param_named(dev_nperio_tx_fifo_size, ++ dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(dev_nperio_tx_fifo_size, ++ "Number of words in the non-periodic Tx FIFO 16-32768"); ++module_param_named(dev_perio_tx_fifo_size_1, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_1, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_2, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_2, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_3, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_3, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_4, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_4, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_5, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_5, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_6, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_6, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_7, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_7, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_8, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_8, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_9, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_9, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_10, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_10, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_11, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_11, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_12, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[11], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_12, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_13, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[12], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_13, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_14, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[13], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_14, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(dev_perio_tx_fifo_size_15, ++ dwc_otg_module_params.dev_perio_tx_fifo_size[14], int, 0444); ++MODULE_PARM_DESC(dev_perio_tx_fifo_size_15, ++ "Number of words in the periodic Tx FIFO 4-768"); ++module_param_named(host_rx_fifo_size, dwc_otg_module_params.host_rx_fifo_size, ++ int, 0444); ++MODULE_PARM_DESC(host_rx_fifo_size, "Number of words in the Rx FIFO 16-32768"); ++module_param_named(host_nperio_tx_fifo_size, ++ dwc_otg_module_params.host_nperio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(host_nperio_tx_fifo_size, ++ "Number of words in the non-periodic Tx FIFO 16-32768"); ++module_param_named(host_perio_tx_fifo_size, ++ dwc_otg_module_params.host_perio_tx_fifo_size, int, 0444); ++MODULE_PARM_DESC(host_perio_tx_fifo_size, ++ "Number of words in the host periodic Tx FIFO 16-32768"); ++module_param_named(max_transfer_size, dwc_otg_module_params.max_transfer_size, ++ int, 0444); ++/** @todo Set the max to 512K, modify checks */ ++MODULE_PARM_DESC(max_transfer_size, ++ "The maximum transfer size supported in bytes 2047-65535"); ++module_param_named(max_packet_count, dwc_otg_module_params.max_packet_count, ++ int, 0444); ++MODULE_PARM_DESC(max_packet_count, ++ "The maximum number of packets in a transfer 15-511"); ++module_param_named(host_channels, dwc_otg_module_params.host_channels, int, ++ 0444); ++MODULE_PARM_DESC(host_channels, ++ "The number of host channel registers to use 1-16"); ++module_param_named(dev_endpoints, dwc_otg_module_params.dev_endpoints, int, ++ 0444); ++MODULE_PARM_DESC(dev_endpoints, ++ "The number of endpoints in addition to EP0 available for device mode 1-15"); ++module_param_named(phy_type, dwc_otg_module_params.phy_type, int, 0444); ++MODULE_PARM_DESC(phy_type, "0=Reserved 1=UTMI+ 2=ULPI"); ++module_param_named(phy_utmi_width, dwc_otg_module_params.phy_utmi_width, int, ++ 0444); ++MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits"); ++module_param_named(phy_ulpi_ddr, dwc_otg_module_params.phy_ulpi_ddr, int, 0444); ++MODULE_PARM_DESC(phy_ulpi_ddr, ++ "ULPI at double or single data rate 0=Single 1=Double"); ++module_param_named(phy_ulpi_ext_vbus, dwc_otg_module_params.phy_ulpi_ext_vbus, ++ int, 0444); ++MODULE_PARM_DESC(phy_ulpi_ext_vbus, ++ "ULPI PHY using internal or external vbus 0=Internal"); ++module_param_named(i2c_enable, dwc_otg_module_params.i2c_enable, int, 0444); ++MODULE_PARM_DESC(i2c_enable, "FS PHY Interface"); ++module_param_named(ulpi_fs_ls, dwc_otg_module_params.ulpi_fs_ls, int, 0444); ++MODULE_PARM_DESC(ulpi_fs_ls, "ULPI PHY FS/LS mode only"); ++module_param_named(ts_dline, dwc_otg_module_params.ts_dline, int, 0444); ++MODULE_PARM_DESC(ts_dline, "Term select Dline pulsing for all PHYs"); ++module_param_named(debug, g_dbg_lvl, int, 0444); ++MODULE_PARM_DESC(debug, ""); ++ ++module_param_named(en_multiple_tx_fifo, ++ dwc_otg_module_params.en_multiple_tx_fifo, int, 0444); ++MODULE_PARM_DESC(en_multiple_tx_fifo, ++ "Dedicated Non Periodic Tx FIFOs 0=disabled 1=enabled"); ++module_param_named(dev_tx_fifo_size_1, ++ dwc_otg_module_params.dev_tx_fifo_size[0], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_1, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_2, ++ dwc_otg_module_params.dev_tx_fifo_size[1], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_2, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_3, ++ dwc_otg_module_params.dev_tx_fifo_size[2], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_3, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_4, ++ dwc_otg_module_params.dev_tx_fifo_size[3], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_4, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_5, ++ dwc_otg_module_params.dev_tx_fifo_size[4], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_5, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_6, ++ dwc_otg_module_params.dev_tx_fifo_size[5], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_6, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_7, ++ dwc_otg_module_params.dev_tx_fifo_size[6], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_7, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_8, ++ dwc_otg_module_params.dev_tx_fifo_size[7], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_8, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_9, ++ dwc_otg_module_params.dev_tx_fifo_size[8], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_9, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_10, ++ dwc_otg_module_params.dev_tx_fifo_size[9], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_10, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_11, ++ dwc_otg_module_params.dev_tx_fifo_size[10], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_11, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_12, ++ dwc_otg_module_params.dev_tx_fifo_size[11], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_12, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_13, ++ dwc_otg_module_params.dev_tx_fifo_size[12], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_13, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_14, ++ dwc_otg_module_params.dev_tx_fifo_size[13], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_14, "Number of words in the Tx FIFO 4-768"); ++module_param_named(dev_tx_fifo_size_15, ++ dwc_otg_module_params.dev_tx_fifo_size[14], int, 0444); ++MODULE_PARM_DESC(dev_tx_fifo_size_15, "Number of words in the Tx FIFO 4-768"); ++ ++module_param_named(thr_ctl, dwc_otg_module_params.thr_ctl, int, 0444); ++MODULE_PARM_DESC(thr_ctl, ++ "Thresholding enable flag bit 0 - non ISO Tx thr., 1 - ISO Tx thr., 2 - Rx thr.- bit 0=disabled 1=enabled"); ++module_param_named(tx_thr_length, dwc_otg_module_params.tx_thr_length, int, ++ 0444); ++MODULE_PARM_DESC(tx_thr_length, "Tx Threshold length in 32 bit DWORDs"); ++module_param_named(rx_thr_length, dwc_otg_module_params.rx_thr_length, int, ++ 0444); ++MODULE_PARM_DESC(rx_thr_length, "Rx Threshold length in 32 bit DWORDs"); ++ ++module_param_named(pti_enable, dwc_otg_module_params.pti_enable, int, 0444); ++module_param_named(mpi_enable, dwc_otg_module_params.mpi_enable, int, 0444); ++module_param_named(lpm_enable, dwc_otg_module_params.lpm_enable, int, 0444); ++MODULE_PARM_DESC(lpm_enable, "LPM Enable 0=LPM Disabled 1=LPM Enabled"); ++module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444); ++MODULE_PARM_DESC(ic_usb_cap, ++ "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled"); ++module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int, ++ 0444); ++MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio"); ++module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444); ++MODULE_PARM_DESC(power_down, "Power Down Mode"); ++module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444); ++MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control"); ++module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444); ++MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK"); ++module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444); ++MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA"); ++module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444); ++MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support"); ++module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444); ++MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled"); ++module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444); ++MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0"); ++module_param(microframe_schedule, bool, 0444); ++MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler"); ++ ++/** @page "Module Parameters" ++ * ++ * The following parameters may be specified when starting the module. ++ * These parameters define how the DWC_otg controller should be ++ * configured. Parameter values are passed to the CIL initialization ++ * function dwc_otg_cil_init ++ * ++ * Example: modprobe dwc_otg speed=1 otg_cap=1 ++ * ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++*/ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.h b/drivers/usb/host/dwc_otg/dwc_otg_driver.h +new file mode 100644 +index 0000000..8a0e41b +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h +@@ -0,0 +1,86 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $ ++ * $Revision: #19 $ ++ * $Date: 2010/11/15 $ ++ * $Change: 1627671 $ ++ * ++ * 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_DRIVER_H__ ++#define __DWC_OTG_DRIVER_H__ ++ ++/** @file ++ * This file contains the interface to the Linux driver. ++ */ ++#include "dwc_otg_os_dep.h" ++#include "dwc_otg_core_if.h" ++ ++/* Type declarations */ ++struct dwc_otg_pcd; ++struct dwc_otg_hcd; ++ ++/** ++ * This structure is a wrapper that encapsulates the driver components used to ++ * manage a single DWC_otg controller. ++ */ ++typedef struct dwc_otg_device { ++ /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE ++ * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD ++ * require this. */ ++ struct os_dependent os_dep; ++ ++ /** Pointer to the core interface structure. */ ++ dwc_otg_core_if_t *core_if; ++ ++ /** Pointer to the PCD structure. */ ++ struct dwc_otg_pcd *pcd; ++ ++ /** Pointer to the HCD structure. */ ++ struct dwc_otg_hcd *hcd; ++ ++ /** Flag to indicate whether the common IRQ handler is installed. */ ++ uint8_t common_irq_installed; ++ ++} dwc_otg_device_t; ++ ++/*We must clear S3C24XX_EINTPEND external interrupt register ++ * because after clearing in this register trigerred IRQ from ++ * H/W core in kernel interrupt can be occured again before OTG ++ * handlers clear all IRQ sources of Core registers because of ++ * timing latencies and Low Level IRQ Type. ++ */ ++#ifdef CONFIG_MACH_IPMATE ++#define S3C2410X_CLEAR_EINTPEND() \ ++do { \ ++ __raw_writel(1UL << 11,S3C24XX_EINTPEND); \ ++} while (0) ++#else ++#define S3C2410X_CLEAR_EINTPEND() do { } while (0) ++#endif ++ ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +new file mode 100644 +index 0000000..434d0c4 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -0,0 +1,3473 @@ ++ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ ++ * $Revision: #104 $ ++ * $Date: 2011/10/24 $ ++ * $Change: 1871159 $ ++ * ++ * 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_DEVICE_ONLY ++ ++/** @file ++ * This file implements HCD Core. All code in this file is portable and doesn't ++ * use any OS specific functions. ++ * Interface provided by HCD Core is defined in ++ * header file. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++extern bool microframe_schedule; ++ ++//#define DEBUG_HOST_CHANNELS ++#ifdef DEBUG_HOST_CHANNELS ++static int last_sel_trans_num_per_scheduled = 0; ++static int last_sel_trans_num_nonper_scheduled = 0; ++static int last_sel_trans_num_avail_hc_at_start = 0; ++static int last_sel_trans_num_avail_hc_at_end = 0; ++#endif /* DEBUG_HOST_CHANNELS */ ++ ++dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) ++{ ++ return DWC_ALLOC(sizeof(dwc_otg_hcd_t)); ++} ++ ++/** ++ * Connection timeout function. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. ++ */ ++void dwc_otg_hcd_connect_timeout(void *ptr) ++{ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, ptr); ++ DWC_PRINTF("Connect Timeout\n"); ++ __DWC_ERROR("Device Not Connected/Responding\n"); ++} ++ ++#if defined(DEBUG) ++static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ if (qh->channel != NULL) { ++ dwc_hc_t *hc = qh->channel; ++ dwc_list_link_t *item; ++ dwc_otg_qh_t *qh_item; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ int i; ++ ++ dwc_otg_hc_regs_t *hc_regs; ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ uint32_t hcdma; ++ ++ hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcdma = DWC_READ_REG32(&hc_regs->hcdma); ++ ++ DWC_PRINTF(" Assigned to channel %p:\n", hc); ++ DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, ++ hcsplt.d32); ++ DWC_PRINTF(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, ++ hcdma); ++ DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ DWC_PRINTF(" ep_type: %d\n", hc->ep_type); ++ DWC_PRINTF(" max_packet: %d\n", hc->max_packet); ++ DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); ++ DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started); ++ DWC_PRINTF(" halt_status: %d\n", hc->halt_status); ++ DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); ++ DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len); ++ DWC_PRINTF(" qh: %p\n", hc->qh); ++ DWC_PRINTF(" NP inactive sched:\n"); ++ DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_inactive) { ++ qh_item = ++ DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ DWC_PRINTF(" %p\n", qh_item); ++ } ++ DWC_PRINTF(" NP active sched:\n"); ++ DWC_LIST_FOREACH(item, &hcd->non_periodic_sched_active) { ++ qh_item = ++ DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ DWC_PRINTF(" %p\n", qh_item); ++ } ++ DWC_PRINTF(" Channels: \n"); ++ for (i = 0; i < num_channels; i++) { ++ dwc_hc_t *hc = hcd->hc_ptr_array[i]; ++ DWC_PRINTF(" %2d: %p\n", i, hc); ++ } ++ } ++} ++#else ++#define dump_channel_info(hcd, qh) ++#endif /* DEBUG */ ++ ++/** ++ * Work queue function for starting the HCD when A-Cable is connected. ++ * The hcd_start() must be called in a process context. ++ */ ++static void hcd_start_func(void *_vp) ++{ ++ dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) _vp; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s() %p\n", __func__, hcd); ++ if (hcd) { ++ hcd->fops->start(hcd); ++ } ++} ++ ++static void del_xfer_timers(dwc_otg_hcd_t * hcd) ++{ ++#ifdef DEBUG ++ int i; ++ int num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ DWC_TIMER_CANCEL(hcd->core_if->hc_xfer_timer[i]); ++ } ++#endif ++} ++ ++static void del_timers(dwc_otg_hcd_t * hcd) ++{ ++ del_xfer_timers(hcd); ++ DWC_TIMER_CANCEL(hcd->conn_timer); ++} ++ ++/** ++ * Processes all the URBs in a single list of QHs. Completes them with ++ * -ETIMEDOUT and frees the QTD. ++ */ ++static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) ++{ ++ dwc_list_link_t *qh_item; ++ dwc_otg_qh_t *qh; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ ++ DWC_LIST_FOREACH(qh_item, qh_list) { ++ qh = DWC_LIST_ENTRY(qh_item, dwc_otg_qh_t, qh_list_entry); ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, ++ &qh->qtd_list, qtd_list_entry) { ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ if (qtd->urb != NULL) { ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_TIMEOUT); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ ++ } ++ } ++} ++ ++/** ++ * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic ++ * and periodic schedules. The QTD associated with each URB is removed from ++ * the schedule and freed. This function may be called when a disconnect is ++ * detected or when the HCD is being stopped. ++ */ ++static void kill_all_urbs(dwc_otg_hcd_t * hcd) ++{ ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->non_periodic_sched_active); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_inactive); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_ready); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_assigned); ++ kill_urbs_in_qh_list(hcd, &hcd->periodic_sched_queued); ++} ++ ++/** ++ * Start the connection timer. An OTG host is required to display a ++ * message if the device does not connect within 10 seconds. The ++ * timer is deleted if a port connect interrupt occurs before the ++ * timer expires. ++ */ ++static void dwc_otg_hcd_start_connect_timer(dwc_otg_hcd_t * hcd) ++{ ++ DWC_TIMER_SCHEDULE(hcd->conn_timer, 10000 /* 10 secs */ ); ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_session_start_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); ++ dwc_otg_hcd = p; ++ dwc_otg_hcd_start_connect_timer(dwc_otg_hcd); ++ return 1; ++} ++ ++/** ++ * HCD Callback function for starting the HCD when A-Cable is ++ * connected. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_start_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ dwc_otg_core_if_t *core_if; ++ hprt0_data_t hprt0; ++ ++ core_if = dwc_otg_hcd->core_if; ++ ++ if (core_if->op_state == B_HOST) { ++ /* ++ * Reset the port. During a HNP mode switch the reset ++ * needs to occur within 1ms and have a duration of at ++ * least 50ms. ++ */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, ++ hcd_start_func, dwc_otg_hcd, 50, ++ "start hcd"); ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for disconnect of the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_disconnect_cb(void *p) ++{ ++ gintsts_data_t intr; ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ ++ /* ++ * Set status flags for the hub driver. ++ */ ++ dwc_otg_hcd->flags.b.port_connect_status_change = 1; ++ dwc_otg_hcd->flags.b.port_connect_status = 0; ++ ++ /* ++ * Shutdown any transfers in process by clearing the Tx FIFO Empty ++ * interrupt mask and status bits and disabling subsequent host ++ * channel interrupts. ++ */ ++ intr.d32 = 0; ++ intr.b.nptxfempty = 1; ++ intr.b.ptxfempty = 1; ++ intr.b.hcintr = 1; ++ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, ++ intr.d32, 0); ++ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, ++ intr.d32, 0); ++ ++ del_timers(dwc_otg_hcd); ++ ++ /* ++ * Turn off the vbus power only if the core has transitioned to device ++ * mode. If still in host mode, need to keep power on to detect a ++ * reconnection. ++ */ ++ if (dwc_otg_is_device_mode(dwc_otg_hcd->core_if)) { ++ if (dwc_otg_hcd->core_if->op_state != A_SUSPEND) { ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ DWC_PRINTF("Disconnect: PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ ++ dwc_otg_disable_host_interrupts(dwc_otg_hcd->core_if); ++ } ++ ++ /* Respond with an error status to all URBs in the schedule. */ ++ kill_all_urbs(dwc_otg_hcd); ++ ++ if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) { ++ /* Clean up any host channels that were in use. */ ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ dwc_otg_hc_regs_t *hc_regs; ++ hcchar_data_t hcchar; ++ ++ num_channels = dwc_otg_hcd->core_if->core_params->host_channels; ++ ++ if (!dwc_otg_hcd->core_if->dma_enable) { ++ /* Flush out any channel requests in slave mode. */ ++ for (i = 0; i < num_channels; i++) { ++ channel = dwc_otg_hcd->hc_ptr_array[i]; ++ if (DWC_CIRCLEQ_EMPTY_ENTRY ++ (channel, hc_list_entry)) { ++ hc_regs = ++ dwc_otg_hcd->core_if-> ++ host_if->hc_regs[i]; ++ hcchar.d32 = ++ DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chen = 0; ++ hcchar.b.chdis = 1; ++ hcchar.b.epdir = 0; ++ DWC_WRITE_REG32 ++ (&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ } ++ } ++ } ++ ++ for (i = 0; i < num_channels; i++) { ++ channel = dwc_otg_hcd->hc_ptr_array[i]; ++ if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) { ++ hc_regs = ++ dwc_otg_hcd->core_if->host_if->hc_regs[i]; ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ /* Halt the channel. */ ++ hcchar.b.chdis = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, ++ hcchar.d32); ++ } ++ ++ dwc_otg_hc_cleanup(dwc_otg_hcd->core_if, ++ channel); ++ DWC_CIRCLEQ_INSERT_TAIL ++ (&dwc_otg_hcd->free_hc_list, channel, ++ hc_list_entry); ++ /* ++ * Added for Descriptor DMA to prevent channel double cleanup ++ * in release_channel_ddma(). Which called from ep_disable ++ * when device disconnect. ++ */ ++ channel->qh = NULL; ++ } ++ } ++ } ++ ++ if (dwc_otg_hcd->fops->disconnect) { ++ dwc_otg_hcd->fops->disconnect(dwc_otg_hcd); ++ } ++ ++ return 1; ++} ++ ++/** ++ * HCD Callback function for stopping the HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int32_t dwc_otg_hcd_stop_cb(void *p) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = p; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, p); ++ dwc_otg_hcd_stop(dwc_otg_hcd); ++ return 1; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * HCD Callback function for sleep of HCD. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int dwc_otg_hcd_sleep_cb(void *p) ++{ ++ dwc_otg_hcd_t *hcd = p; ++ ++ dwc_otg_hcd_free_hc_from_lpm(hcd); ++ ++ return 0; ++} ++#endif ++ ++/** ++ * HCD Callback function for Remote Wakeup. ++ * ++ * @param p void pointer to the struct usb_hcd ++ */ ++static int dwc_otg_hcd_rem_wakeup_cb(void *p) ++{ ++ dwc_otg_hcd_t *hcd = p; ++ ++ if (hcd->core_if->lx_state == DWC_OTG_L2) { ++ hcd->flags.b.port_suspend_change = 1; ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ else { ++ hcd->flags.b.port_l1_change = 1; ++ } ++#endif ++ return 0; ++} ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD STOP\n"); ++ ++ /* ++ * The root hub should be disconnected before this function is called. ++ * The disconnect will clear the QTD lists (via ..._hcd_urb_dequeue) ++ * and the QH lists (via ..._hcd_endpoint_disable). ++ */ ++ ++ /* Turn off all host-specific interrupts. */ ++ dwc_otg_disable_host_interrupts(hcd->core_if); ++ ++ /* Turn off the vbus power */ ++ DWC_PRINTF("PortPower off\n"); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(1); ++} ++ ++int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle, ++ int atomic_alloc) ++{ ++ dwc_irqflags_t flags; ++ int retval = 0; ++ dwc_otg_qtd_t *qtd; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++#ifdef DEBUG /* integrity checks (Broadcom) */ ++ if (NULL == hcd->core_if) { ++ DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n"); ++ /* No longer connected. */ ++ return -DWC_E_INVALID; ++ } ++#endif ++ if (!hcd->flags.b.port_connect_status) { ++ /* No longer connected. */ ++ DWC_ERROR("Not connected\n"); ++ return -DWC_E_NO_DEVICE; ++ } ++ ++ qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc); ++ if (qtd == NULL) { ++ DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++#ifdef DEBUG /* integrity checks (Broadcom) */ ++ if (qtd->urb == NULL) { ++ DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++ if (qtd->urb->priv == NULL) { ++ DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n"); ++ return -DWC_E_NO_MEMORY; ++ } ++#endif ++ retval = ++ dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc); ++ // creates a new queue in ep_handle if it doesn't exist already ++ if (retval < 0) { ++ DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " ++ "Error status %d\n", retval); ++ dwc_otg_hcd_qtd_free(qtd); ++ } else { ++ qtd->qh = *ep_handle; ++ } ++ intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); ++ if (!intr_mask.b.sofintr && retval == 0) { ++ dwc_otg_transaction_type_e tr_type; ++ if ((qtd->qh->ep_type == UE_BULK) ++ && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { ++ /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ ++ return 0; ++ } ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ } ++ ++ return retval; ++} ++ ++int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ dwc_otg_qh_t *qh; ++ dwc_otg_qtd_t *urb_qtd; ++ ++#ifdef DEBUG /* integrity checks (Broadcom) */ ++ ++ if (hcd == NULL) { ++ DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n"); ++ return -DWC_E_INVALID; ++ } ++ if (dwc_otg_urb == NULL) { ++ DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n"); ++ return -DWC_E_INVALID; ++ } ++ if (dwc_otg_urb->qtd == NULL) { ++ DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n"); ++ return -DWC_E_INVALID; ++ } ++ urb_qtd = dwc_otg_urb->qtd; ++ if (urb_qtd->qh == NULL) { ++ DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n"); ++ return -DWC_E_INVALID; ++ } ++#else ++ urb_qtd = dwc_otg_urb->qtd; ++#endif ++ qh = urb_qtd->qh; ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ if (urb_qtd->in_process) { ++ dump_channel_info(hcd, qh); ++ } ++ } ++#ifdef DEBUG /* integrity checks (Broadcom) */ ++ if (hcd->core_if == NULL) { ++ DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n"); ++ return -DWC_E_INVALID; ++ } ++#endif ++ if (urb_qtd->in_process && qh->channel) { ++ /* The QTD is in process (it has been assigned to a channel). */ ++ if (hcd->flags.b.port_connect_status) { ++ /* ++ * If still connected (i.e. in host mode), halt the ++ * channel so it can be used for other transfers. If ++ * no longer connected, the host registers can't be ++ * written to halt the channel since the core is in ++ * device mode. ++ */ ++ dwc_otg_hc_halt(hcd->core_if, qh->channel, ++ DWC_OTG_HC_XFER_URB_DEQUEUE); ++ } ++ } ++ ++ /* ++ * Free the QTD and clean up the associated QH. Leave the QH in the ++ * schedule if it has any remaining QTDs. ++ */ ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - " ++ "delete %sQueue handler\n", ++ hcd->core_if->dma_desc_enable?"DMA ":""); ++ if (!hcd->core_if->dma_desc_enable) { ++ uint8_t b = urb_qtd->in_process; ++ dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); ++ if (b) { ++ dwc_otg_hcd_qh_deactivate(hcd, qh, 0); ++ qh->channel = NULL; ++ } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } ++ } else { ++ dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); ++ } ++ return 0; ++} ++ ++int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, ++ int retry) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ int retval = 0; ++ dwc_irqflags_t flags; ++ ++ if (retry < 0) { ++ retval = -DWC_E_INVALID; ++ goto done; ++ } ++ ++ if (!qh) { ++ retval = -DWC_E_INVALID; ++ goto done; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ ++ while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) { ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ retry--; ++ dwc_msleep(5); ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ } ++ ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ /* ++ * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove ++ * and qh_free to prevent stack dump on DWC_DMA_FREE() with ++ * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() ++ * and dwc_otg_hcd_frame_list_alloc(). ++ */ ++ dwc_otg_hcd_qh_free(hcd, qh); ++ ++done: ++ return retval; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int retval = 0; ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ if (!qh) ++ return -DWC_E_INVALID; ++ ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ return retval; ++} ++#endif ++ ++/** ++ * HCD Callback structure for handling mode switching. ++ */ ++static dwc_otg_cil_callbacks_t hcd_cil_callbacks = { ++ .start = dwc_otg_hcd_start_cb, ++ .stop = dwc_otg_hcd_stop_cb, ++ .disconnect = dwc_otg_hcd_disconnect_cb, ++ .session_start = dwc_otg_hcd_session_start_cb, ++ .resume_wakeup = dwc_otg_hcd_rem_wakeup_cb, ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ .sleep = dwc_otg_hcd_sleep_cb, ++#endif ++ .p = 0, ++}; ++ ++/** ++ * Reset tasklet function ++ */ ++static void reset_tasklet_func(void *data) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = (dwc_otg_hcd_t *) data; ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ hprt0_data_t hprt0; ++ ++ DWC_DEBUGPL(DBG_HCDV, "USB RESET tasklet called\n"); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtrst = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(60); ++ ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_otg_hcd->flags.b.port_reset_change = 1; ++} ++ ++static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) ++{ ++ dwc_list_link_t *item; ++ dwc_otg_qh_t *qh; ++ dwc_irqflags_t flags; ++ ++ if (!qh_list->next) { ++ /* The list hasn't been initialized yet. */ ++ return; ++ } ++ /* ++ * Hold spinlock here. Not needed in that case if bellow ++ * function is being called from ISR ++ */ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ /* Ensure there are no QTDs or URBs left. */ ++ kill_urbs_in_qh_list(hcd, qh_list); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ ++ DWC_LIST_FOREACH(item, qh_list) { ++ qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); ++ dwc_otg_hcd_qh_remove_and_free(hcd, qh); ++ } ++} ++ ++/** ++ * Exit from Hibernation if Host did not detect SRP from connected SRP capable ++ * Device during SRP time by host power up. ++ */ ++void dwc_otg_hcd_power_up(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Enable VBUS */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++} ++ ++/** ++ * Frees secondary storage associated with the dwc_otg_hcd structure contained ++ * in the struct usb_hcd field. ++ */ ++static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int i; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD FREE\n"); ++ ++ del_timers(dwc_otg_hcd); ++ ++ /* Free memory for QH/QTD lists */ ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_inactive); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->non_periodic_sched_active); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_inactive); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_ready); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_assigned); ++ qh_list_free(dwc_otg_hcd, &dwc_otg_hcd->periodic_sched_queued); ++ ++ /* Free memory for the host channels. */ ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ dwc_hc_t *hc = dwc_otg_hcd->hc_ptr_array[i]; ++ ++#ifdef DEBUG ++ if (dwc_otg_hcd->core_if->hc_xfer_timer[i]) { ++ DWC_TIMER_FREE(dwc_otg_hcd->core_if->hc_xfer_timer[i]); ++ } ++#endif ++ if (hc != NULL) { ++ DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", ++ i, hc); ++ DWC_FREE(hc); ++ } ++ } ++ ++ if (dwc_otg_hcd->core_if->dma_enable) { ++ if (dwc_otg_hcd->status_buf_dma) { ++ DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ dwc_otg_hcd->status_buf, ++ dwc_otg_hcd->status_buf_dma); ++ } ++ } else if (dwc_otg_hcd->status_buf != NULL) { ++ DWC_FREE(dwc_otg_hcd->status_buf); ++ } ++ DWC_SPINLOCK_FREE(dwc_otg_hcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ dwc_otg_hcd->core_if->lock = NULL; ++ ++ DWC_TIMER_FREE(dwc_otg_hcd->conn_timer); ++ DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet); ++ ++#ifdef DWC_DEV_SRPCAP ++ if (dwc_otg_hcd->core_if->power_down == 2 && ++ dwc_otg_hcd->core_if->pwron_timer) { ++ DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer); ++ } ++#endif ++ DWC_FREE(dwc_otg_hcd); ++} ++ ++int init_hcd_usecs(dwc_otg_hcd_t *_hcd); ++ ++int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ ++ hcd->lock = DWC_SPINLOCK_ALLOC(); ++ DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n", ++ hcd, core_if); ++ if (!hcd->lock) { ++ DWC_ERROR("Could not allocate lock for pcd"); ++ DWC_FREE(hcd); ++ retval = -DWC_E_NO_MEMORY; ++ goto out; ++ } ++ hcd->core_if = core_if; ++ ++ /* Register the HCD CIL Callbacks */ ++ dwc_otg_cil_register_hcd_callbacks(hcd->core_if, ++ &hcd_cil_callbacks, hcd); ++ ++ /* Initialize the non-periodic schedule. */ ++ DWC_LIST_INIT(&hcd->non_periodic_sched_inactive); ++ DWC_LIST_INIT(&hcd->non_periodic_sched_active); ++ ++ /* Initialize the periodic schedule. */ ++ DWC_LIST_INIT(&hcd->periodic_sched_inactive); ++ DWC_LIST_INIT(&hcd->periodic_sched_ready); ++ DWC_LIST_INIT(&hcd->periodic_sched_assigned); ++ DWC_LIST_INIT(&hcd->periodic_sched_queued); ++ ++ /* ++ * Create a host channel descriptor for each host channel implemented ++ * in the controller. Initialize the channel descriptor array. ++ */ ++ DWC_CIRCLEQ_INIT(&hcd->free_hc_list); ++ num_channels = hcd->core_if->core_params->host_channels; ++ DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array)); ++ for (i = 0; i < num_channels; i++) { ++ channel = DWC_ALLOC(sizeof(dwc_hc_t)); ++ if (channel == NULL) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: host channel allocation failed\n", ++ __func__); ++ dwc_otg_hcd_free(hcd); ++ goto out; ++ } ++ channel->hc_num = i; ++ hcd->hc_ptr_array[i] = channel; ++#ifdef DEBUG ++ hcd->core_if->hc_xfer_timer[i] = ++ DWC_TIMER_ALLOC("hc timer", hc_xfer_timeout, ++ &hcd->core_if->hc_xfer_info[i]); ++#endif ++ DWC_DEBUGPL(DBG_HCDV, "HCD Added channel #%d, hc=%p\n", i, ++ channel); ++ } ++ ++ /* Initialize the Connection timeout timer. */ ++ hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer", ++ dwc_otg_hcd_connect_timeout, 0); ++ ++ printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled"); ++ if (microframe_schedule) ++ init_hcd_usecs(hcd); ++ ++ /* Initialize reset tasklet. */ ++ hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd); ++#ifdef DWC_DEV_SRPCAP ++ if (hcd->core_if->power_down == 2) { ++ /* Initialize Power on timer for Host power up in case hibernation */ ++ hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER", ++ dwc_otg_hcd_power_up, core_if); ++ } ++#endif ++ ++ /* ++ * Allocate space for storing data on status transactions. Normally no ++ * data is sent, but this space acts as a bit bucket. This must be ++ * done after usb_add_hcd since that function allocates the DMA buffer ++ * pool. ++ */ ++ if (hcd->core_if->dma_enable) { ++ hcd->status_buf = ++ DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ &hcd->status_buf_dma); ++ } else { ++ hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); ++ } ++ if (!hcd->status_buf) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: status_buf allocation failed\n", __func__); ++ dwc_otg_hcd_free(hcd); ++ goto out; ++ } ++ ++ hcd->otg_port = 1; ++ hcd->frame_list = NULL; ++ hcd->frame_list_dma = 0; ++ hcd->periodic_qh_count = 0; ++out: ++ return retval; ++} ++ ++void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd) ++{ ++ /* Turn off all host-specific interrupts. */ ++ dwc_otg_disable_host_interrupts(hcd->core_if); ++ ++ dwc_otg_hcd_free(hcd); ++} ++ ++/** ++ * Initializes dynamic portions of the DWC_otg HCD state. ++ */ ++static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd) ++{ ++ int num_channels; ++ int i; ++ dwc_hc_t *channel; ++ dwc_hc_t *channel_tmp; ++ ++ hcd->flags.d32 = 0; ++ ++ hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; ++ if (!microframe_schedule) { ++ hcd->non_periodic_channels = 0; ++ hcd->periodic_channels = 0; ++ } else { ++ hcd->available_host_channels = hcd->core_if->core_params->host_channels; ++ } ++ /* ++ * Put all channels in the free channel list and clean up channel ++ * states. ++ */ ++ DWC_CIRCLEQ_FOREACH_SAFE(channel, channel_tmp, ++ &hcd->free_hc_list, hc_list_entry) { ++ DWC_CIRCLEQ_REMOVE(&hcd->free_hc_list, channel, hc_list_entry); ++ } ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ for (i = 0; i < num_channels; i++) { ++ channel = hcd->hc_ptr_array[i]; ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, channel, ++ hc_list_entry); ++ dwc_otg_hc_cleanup(hcd->core_if, channel); ++ } ++ ++ /* Initialize the DWC core for host mode operation. */ ++ dwc_otg_core_host_init(hcd->core_if); ++ ++ /* Set core_if's lock pointer to the hcd->lock */ ++ hcd->core_if->lock = hcd->lock; ++} ++ ++/** ++ * Assigns transactions from a QTD to a free host channel and initializes the ++ * host channel to perform the transactions. The host channel is removed from ++ * the free list. ++ * ++ * @param hcd The HCD state structure. ++ * @param qh Transactions from the first QTD for this QH are selected and ++ * assigned to a free host channel. ++ */ ++static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_hc_t *hc; ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_hcd_urb_t *urb; ++ void* ptr = NULL; ++ ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ ++ urb = qtd->urb; ++ ++ DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length); ++ ++ if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) ++ urb->actual_length = urb->length; ++ ++ ++ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); ++ ++ /* Remove the host channel from the free list. */ ++ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ qh->channel = hc; ++ ++ qtd->in_process = 1; ++ ++ /* ++ * Use usb_pipedevice to determine device address. This address is ++ * 0 before the SET_ADDRESS command and the correct address afterward. ++ */ ++ hc->dev_addr = dwc_otg_hcd_get_dev_addr(&urb->pipe_info); ++ hc->ep_num = dwc_otg_hcd_get_ep_num(&urb->pipe_info); ++ hc->speed = qh->dev_speed; ++ hc->max_packet = dwc_max_packet(qh->maxp); ++ ++ hc->xfer_started = 0; ++ hc->halt_status = DWC_OTG_HC_XFER_NO_HALT_STATUS; ++ hc->error_state = (qtd->error_count > 0); ++ hc->halt_on_queue = 0; ++ hc->halt_pending = 0; ++ hc->requests = 0; ++ ++ /* ++ * The following values may be modified in the transfer type section ++ * below. The xfer_len value may be reduced when the transfer is ++ * started to accommodate the max widths of the XferSize and PktCnt ++ * fields in the HCTSIZn register. ++ */ ++ ++ hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } else { ++ hc->do_ping = qh->ping_state; ++ } ++ ++ hc->data_pid_start = qh->data_toggle; ++ hc->multi_count = 1; ++ ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length; ++ ++ /* For non-dword aligned case */ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && !hcd->core_if->dma_desc_enable) { ++ ptr = (uint8_t *) urb->buf + urb->actual_length; ++ } ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->buf + urb->actual_length; ++ } ++ hc->xfer_len = urb->length - urb->actual_length; ++ hc->xfer_count = 0; ++ ++ /* ++ * Set the split attributes ++ */ ++ hc->do_split = 0; ++ if (qh->do_split) { ++ uint32_t hub_addr, port_addr; ++ hc->do_split = 1; ++ hc->xact_pos = qtd->isoc_split_pos; ++ hc->complete_split = qtd->complete_split; ++ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr); ++ hc->hub_addr = (uint8_t) hub_addr; ++ hc->port_addr = (uint8_t) port_addr; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { ++ case UE_CONTROL: ++ hc->ep_type = DWC_OTG_EP_TYPE_CONTROL; ++ switch (qtd->control_phase) { ++ case DWC_OTG_CONTROL_SETUP: ++ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction\n"); ++ hc->do_ping = 0; ++ hc->ep_is_in = 0; ++ hc->data_pid_start = DWC_OTG_HC_PID_SETUP; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->setup_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->setup_packet; ++ } ++ hc->xfer_len = 8; ++ ptr = NULL; ++ break; ++ case DWC_OTG_CONTROL_DATA: ++ DWC_DEBUGPL(DBG_HCDV, " Control data transaction\n"); ++ hc->data_pid_start = qtd->data_toggle; ++ break; ++ case DWC_OTG_CONTROL_STATUS: ++ /* ++ * Direction is opposite of data direction or IN if no ++ * data. ++ */ ++ DWC_DEBUGPL(DBG_HCDV, " Control status transaction\n"); ++ if (urb->length == 0) { ++ hc->ep_is_in = 1; ++ } else { ++ hc->ep_is_in = ++ dwc_otg_hcd_is_pipe_out(&urb->pipe_info); ++ } ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } ++ ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; ++ ++ hc->xfer_len = 0; ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf_dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) hcd->status_buf; ++ } ++ ptr = NULL; ++ break; ++ } ++ break; ++ case UE_BULK: ++ hc->ep_type = DWC_OTG_EP_TYPE_BULK; ++ break; ++ case UE_INTERRUPT: ++ hc->ep_type = DWC_OTG_EP_TYPE_INTR; ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ ++ hc->ep_type = DWC_OTG_EP_TYPE_ISOC; ++ ++ if (hcd->core_if->dma_desc_enable) ++ break; ++ ++ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; ++ ++ frame_desc->status = 0; ++ ++ if (hcd->core_if->dma_enable) { ++ hc->xfer_buff = (uint8_t *) urb->dma; ++ } else { ++ hc->xfer_buff = (uint8_t *) urb->buf; ++ } ++ hc->xfer_buff += ++ frame_desc->offset + qtd->isoc_split_offset; ++ hc->xfer_len = ++ frame_desc->length - qtd->isoc_split_offset; ++ ++ /* For non-dword aligned buffers */ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && hcd->core_if->dma_enable) { ++ ptr = ++ (uint8_t *) urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset; ++ } else ++ ptr = NULL; ++ ++ if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) { ++ if (hc->xfer_len <= 188) { ++ hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ } else { ++ hc->xact_pos = ++ DWC_HCSPLIT_XACTPOS_BEGIN; ++ } ++ } ++ } ++ break; ++ } ++ /* non DWORD-aligned buffer case */ ++ if (ptr) { ++ uint32_t buf_size; ++ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ buf_size = hcd->core_if->core_params->max_transfer_size; ++ } else { ++ buf_size = 4096; ++ } ++ if (!qh->dw_align_buf) { ++ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, ++ &qh->dw_align_buf_dma); ++ if (!qh->dw_align_buf) { ++ DWC_ERROR ++ ("%s: Failed to allocate memory to handle " ++ "non-dword aligned buffer case\n", ++ __func__); ++ return; ++ } ++ } ++ if (!hc->ep_is_in) { ++ dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len); ++ } ++ hc->align_buff = qh->dw_align_buf_dma; ++ } else { ++ hc->align_buff = 0; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This value may be modified when the transfer is started to ++ * reflect the actual transfer length. ++ */ ++ hc->multi_count = dwc_hb_mult(qh->maxp); ++ } ++ ++ if (hcd->core_if->dma_desc_enable) ++ hc->desc_list_addr = qh->desc_list_dma; ++ ++ dwc_otg_hc_init(hcd->core_if, hc); ++ hc->qh = qh; ++} ++ ++/** ++ * This function selects transactions from the HCD transfer schedule and ++ * assigns them to available host channels. It is called from HCD interrupt ++ * handler functions. ++ * ++ * @param hcd The HCD state structure. ++ * ++ * @return The types of new transactions that were assigned to host channels. ++ */ ++dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) ++{ ++ dwc_list_link_t *qh_ptr; ++ dwc_otg_qh_t *qh; ++ int num_channels; ++ dwc_irqflags_t flags; ++ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); ++ dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE; ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); ++#endif ++ ++#ifdef DEBUG_HOST_CHANNELS ++ last_sel_trans_num_per_scheduled = 0; ++ last_sel_trans_num_nonper_scheduled = 0; ++ last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels; ++#endif /* DEBUG_HOST_CHANNELS */ ++ ++ /* Process entries in the periodic ready list. */ ++ qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); ++ ++ while (qh_ptr != &hcd->periodic_sched_ready && ++ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ if (microframe_schedule) { ++ // Make sure we leave one channel for non periodic transactions. ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ if (hcd->available_host_channels <= 1) { ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ break; ++ } ++ hcd->available_host_channels--; ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++#ifdef DEBUG_HOST_CHANNELS ++ last_sel_trans_num_per_scheduled++; ++#endif /* DEBUG_HOST_CHANNELS */ ++ } ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ assign_and_init_hc(hcd, qh); ++ ++ /* ++ * Move the QH from the periodic ready schedule to the ++ * periodic assigned schedule. ++ */ ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ ++ ret_val = DWC_OTG_TRANSACTION_PERIODIC; ++ } ++ ++ /* ++ * Process entries in the inactive portion of the non-periodic ++ * schedule. Some free host channels may not be used if they are ++ * reserved for periodic transfers. ++ */ ++ qh_ptr = hcd->non_periodic_sched_inactive.next; ++ num_channels = hcd->core_if->core_params->host_channels; ++ while (qh_ptr != &hcd->non_periodic_sched_inactive && ++ (microframe_schedule || hcd->non_periodic_channels < ++ num_channels - hcd->periodic_channels) && ++ !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ ++ if (microframe_schedule) { ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ if (hcd->available_host_channels < 1) { ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ break; ++ } ++ hcd->available_host_channels--; ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++#ifdef DEBUG_HOST_CHANNELS ++ last_sel_trans_num_nonper_scheduled++; ++#endif /* DEBUG_HOST_CHANNELS */ ++ } ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ ++ assign_and_init_hc(hcd, qh); ++ ++ /* ++ * Move the QH from the non-periodic inactive schedule to the ++ * non-periodic active schedule. ++ */ ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active, ++ &qh->qh_list_entry); ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ ++ if (ret_val == DWC_OTG_TRANSACTION_NONE) { ++ ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; ++ } else { ++ ret_val = DWC_OTG_TRANSACTION_ALL; ++ } ++ ++ if (!microframe_schedule) ++ hcd->non_periodic_channels++; ++ } ++ ++#ifdef DEBUG_HOST_CHANNELS ++ last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels; ++#endif /* DEBUG_HOST_CHANNELS */ ++ ++ DWC_SPINLOCK_FREE(channel_lock); ++ return ret_val; ++} ++ ++/** ++ * Attempts to queue a single transaction request for a host channel ++ * associated with either a periodic or non-periodic transfer. This function ++ * assumes that there is space available in the appropriate request queue. For ++ * an OUT transfer or SETUP transaction in Slave mode, it checks whether space ++ * is available in the appropriate Tx FIFO. ++ * ++ * @param hcd The HCD state structure. ++ * @param hc Host channel descriptor associated with either a periodic or ++ * non-periodic transfer. ++ * @param fifo_dwords_avail Number of DWORDs available in the periodic Tx ++ * FIFO for periodic transfers or the non-periodic Tx FIFO for non-periodic ++ * transfers. ++ * ++ * @return 1 if a request is queued and more requests may be needed to ++ * complete the transfer, 0 if no more requests are required for this ++ * transfer, -1 if there is insufficient space in the Tx FIFO. ++ */ ++static int queue_transaction(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, uint16_t fifo_dwords_avail) ++{ ++ int retval; ++ ++ if (hcd->core_if->dma_enable) { ++ if (hcd->core_if->dma_desc_enable) { ++ if (!hc->xfer_started ++ || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { ++ dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh); ++ hc->qh->ping_state = 0; ++ } ++ } else if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ hc->qh->ping_state = 0; ++ } ++ retval = 0; ++ } else if (hc->halt_pending) { ++ /* Don't queue a request if the channel has been halted. */ ++ retval = 0; ++ } else if (hc->halt_on_queue) { ++ dwc_otg_hc_halt(hcd->core_if, hc, hc->halt_status); ++ retval = 0; ++ } else if (hc->do_ping) { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ } ++ retval = 0; ++ } else if (!hc->ep_is_in || hc->data_pid_start == DWC_OTG_HC_PID_SETUP) { ++ if ((fifo_dwords_avail * 4) >= hc->max_packet) { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ retval = 1; ++ } else { ++ retval = ++ dwc_otg_hc_continue_transfer(hcd->core_if, ++ hc); ++ } ++ } else { ++ retval = -1; ++ } ++ } else { ++ if (!hc->xfer_started) { ++ dwc_otg_hc_start_transfer(hcd->core_if, hc); ++ retval = 1; ++ } else { ++ retval = dwc_otg_hc_continue_transfer(hcd->core_if, hc); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Processes periodic channels for the next frame and queues transactions for ++ * these channels to the DWC_otg controller. After queueing transactions, the ++ * Periodic Tx FIFO Empty interrupt is enabled if there are more transactions ++ * to queue as Periodic Tx FIFO or request queue space becomes available. ++ * Otherwise, the Periodic Tx FIFO Empty interrupt is disabled. ++ */ ++static void process_periodic_channels(dwc_otg_hcd_t * hcd) ++{ ++ hptxsts_data_t tx_status; ++ dwc_list_link_t *qh_ptr; ++ dwc_otg_qh_t *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ ++ dwc_otg_host_global_regs_t *host_regs; ++ host_regs = hcd->core_if->host_if->host_global_regs; ++ ++ DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, " P Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ ++ qh_ptr = hcd->periodic_sched_assigned.next; ++ while (qh_ptr != &hcd->periodic_sched_assigned) { ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ if (tx_status.b.ptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ ++ /* ++ * Set a flag if we're queuing high-bandwidth in slave mode. ++ * The flag prevents any halts to get into the request queue in ++ * the middle of multiple high-bandwidth packets getting queued. ++ */ ++ if (!hcd->core_if->dma_enable && qh->channel->multi_count > 1) { ++ hcd->core_if->queuing_high_bandwidth = 1; ++ } ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.ptxfspcavail); ++ if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* ++ * In Slave mode, stay on the current transfer until there is ++ * nothing more to do or the high-bandwidth request count is ++ * reached. In DMA mode, only need to queue one request. The ++ * controller automatically handles multiple packets for ++ * high-bandwidth transfers. ++ */ ++ if (hcd->core_if->dma_enable || status == 0 || ++ qh->channel->requests == qh->channel->multi_count) { ++ qh_ptr = qh_ptr->next; ++ /* ++ * Move the QH from the periodic assigned schedule to ++ * the periodic queued schedule. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_queued, ++ &qh->qh_list_entry); ++ ++ /* done queuing high bandwidth */ ++ hcd->core_if->queuing_high_bandwidth = 0; ++ } ++ } ++ ++ if (!hcd->core_if->dma_enable) { ++ dwc_otg_core_global_regs_t *global_regs; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ global_regs = hcd->core_if->core_global_regs; ++ intr_mask.b.ptxfempty = 1; ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.ptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, ++ " P Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.ptxfspcavail); ++#endif ++ if (!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned) || ++ no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the periodic Tx ++ * FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * Processes active non-periodic channels and queues transactions for these ++ * channels to the DWC_otg controller. After queueing transactions, the NP Tx ++ * FIFO Empty interrupt is enabled if there are more transactions to queue as ++ * NP Tx FIFO or request queue space becomes available. Otherwise, the NP Tx ++ * FIFO Empty interrupt is disabled. ++ */ ++static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) ++{ ++ gnptxsts_data_t tx_status; ++ dwc_list_link_t *orig_qh_ptr; ++ dwc_otg_qh_t *qh; ++ int status; ++ int no_queue_space = 0; ++ int no_fifo_space = 0; ++ int more_to_do = 0; ++ ++ dwc_otg_core_global_regs_t *global_regs = ++ hcd->core_if->core_global_regs; ++ ++ DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (before queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, " NP Tx FIFO Space Avail (before queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ /* ++ * Keep track of the starting point. Skip over the start-of-list ++ * entry. ++ */ ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ } ++ orig_qh_ptr = hcd->non_periodic_qh_ptr; ++ ++ /* ++ * Process once through the active list or until no more space is ++ * available in the request queue or the Tx FIFO. ++ */ ++ do { ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { ++ no_queue_space = 1; ++ break; ++ } ++ ++ qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t, ++ qh_list_entry); ++ status = ++ queue_transaction(hcd, qh->channel, ++ tx_status.b.nptxfspcavail); ++ ++ if (status > 0) { ++ more_to_do = 1; ++ } else if (status < 0) { ++ no_fifo_space = 1; ++ break; ++ } ++ ++ /* Advance to next QH, skipping start-of-list entry. */ ++ hcd->non_periodic_qh_ptr = hcd->non_periodic_qh_ptr->next; ++ if (hcd->non_periodic_qh_ptr == &hcd->non_periodic_sched_active) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ ++ } while (hcd->non_periodic_qh_ptr != orig_qh_ptr); ++ ++ if (!hcd->core_if->dma_enable) { ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ intr_mask.b.nptxfempty = 1; ++ ++#ifdef DEBUG ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx Req Queue Space Avail (after queue): %d\n", ++ tx_status.b.nptxqspcavail); ++ DWC_DEBUGPL(DBG_HCDV, ++ " NP Tx FIFO Space Avail (after queue): %d\n", ++ tx_status.b.nptxfspcavail); ++#endif ++ if (more_to_do || no_queue_space || no_fifo_space) { ++ /* ++ * May need to queue more transactions as the request ++ * queue or Tx FIFO empties. Enable the non-periodic ++ * Tx FIFO empty interrupt. (Always use the half-empty ++ * level to ensure that new requests are loaded as ++ * soon as possible.) ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, ++ intr_mask.d32); ++ } else { ++ /* ++ * Disable the Tx FIFO empty interrupt since there are ++ * no more transactions that need to be queued right ++ * now. This function is called from interrupt ++ * handlers to queue more transactions as transfer ++ * states change. ++ */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, ++ 0); ++ } ++ } ++} ++ ++/** ++ * This function processes the currently active host channels and queues ++ * transactions for these channels to the DWC_otg controller. It is called ++ * from HCD interrupt handler functions. ++ * ++ * @param hcd The HCD state structure. ++ * @param tr_type The type(s) of transactions to queue (non-periodic, ++ * periodic, or both). ++ */ ++void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, ++ dwc_otg_transaction_type_e tr_type) ++{ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); ++#endif ++ /* Process host channels associated with periodic transfers. */ ++ if ((tr_type == DWC_OTG_TRANSACTION_PERIODIC || ++ tr_type == DWC_OTG_TRANSACTION_ALL) && ++ !DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) { ++ ++ process_periodic_channels(hcd); ++ } ++ ++ /* Process host channels associated with non-periodic transfers. */ ++ if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC || ++ tr_type == DWC_OTG_TRANSACTION_ALL) { ++ if (!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) { ++ process_non_periodic_channels(hcd); ++ } else { ++ /* ++ * Ensure NP Tx FIFO empty interrupt is disabled when ++ * there are no non-periodic transfers to process. ++ */ ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ gintmsk.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&hcd->core_if-> ++ core_global_regs->gintmsk, gintmsk.d32, ++ 0); ++ } ++ } ++} ++ ++#ifdef DWC_HS_ELECT_TST ++/* ++ * Quick and dirty hack to implement the HS Electrical Test ++ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature. ++ * ++ * This code was copied from our userspace app "hset". It sends a ++ * Get Device Descriptor control sequence in two parts, first the ++ * Setup packet by itself, followed some time later by the In and ++ * Ack packets. Rather than trying to figure out how to add this ++ * functionality to the normal driver code, we just hijack the ++ * hardware, using these two function to drive the hardware ++ * directly. ++ */ ++ ++static dwc_otg_core_global_regs_t *global_regs; ++static dwc_otg_host_global_regs_t *hc_global_regs; ++static dwc_otg_hc_regs_t *hc_regs; ++static uint32_t *data_fifo; ++ ++static void do_setup(void) ++{ ++ gintsts_data_t gintsts; ++ hctsiz_data_t hctsiz; ++ hcchar_data_t hcchar; ++ haint_data_t haint; ++ hcint_data_t hcint; ++ ++ /* Enable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* ++ * Send Setup packet (Get Device Descriptor) ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++// hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ 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); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ /* Fill FIFO with Setup data for Get Device Descriptor */ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ DWC_WRITE_REG32(data_fifo++, 0x01000680); ++ DWC_WRITE_REG32(data_fifo++, 0x00080000); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Disable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++} ++ ++static void do_in_ack(void) ++{ ++ gintsts_data_t gintsts; ++ hctsiz_data_t hctsiz; ++ hcchar_data_t hcchar; ++ haint_data_t haint; ++ hcint_data_t hcint; ++ host_grxsts_data_t grxsts; ++ ++ /* Enable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); ++ ++ /* Enable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* ++ * Receive Control In packet ++ */ ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ hctsiz.d32 = 0; ++ hctsiz.b.xfersize = 8; ++ hctsiz.b.pktcnt = 1; ++ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 1; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer */ ++ if (grxsts.b.bcnt > 0) { ++ int i; ++ int word_count = (grxsts.b.bcnt + 3) / 4; ++ ++ data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); ++ ++ for (i = 0; i < word_count; i++) { ++ (void)DWC_READ_REG32(data_fifo++); ++ } ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for receive status queue interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.rxstsqlvl == 0); ++ ++ /* Read RXSTS */ ++ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ /* Clear RXSTSQLVL in GINTSTS */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: ++ break; ++ ++ default: ++ break; ++ } ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++// usleep(100000); ++// mdelay(100); ++ dwc_mdelay(1); ++ ++ /* ++ * Send handshake packet ++ */ ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Make sure channel is disabled */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chen) { ++ hcchar.b.chdis = 1; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ //sleep(1); ++ dwc_mdelay(1000); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ } ++ ++ /* Set HCTSIZ */ ++ 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); ++ ++ /* Set HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.epdir = 0; ++ hcchar.b.epnum = 0; ++ hcchar.b.mps = 8; ++ hcchar.b.chen = 1; ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); ++ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ ++ /* Wait for host channel interrupt */ ++ do { ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++ } while (gintsts.b.hcintr == 0); ++ ++ /* Disable HCINTs */ ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); ++ ++ /* Disable HAINTs */ ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); ++ ++ /* Read HAINT */ ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); ++ ++ /* Read HCINT */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ ++ /* Read HCCHAR */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ ++ /* Clear HCINT */ ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); ++ ++ /* Clear HAINT */ ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); ++ ++ /* Clear GINTSTS */ ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ /* Read GINTSTS */ ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); ++} ++#endif ++ ++/** Handles hub class-specific requests. */ ++int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint16_t typeReq, ++ uint16_t wValue, ++ uint16_t wIndex, uint8_t * buf, uint16_t wLength) ++{ ++ int retval = 0; ++ ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ usb_hub_descriptor_t *hub_desc; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ uint32_t port_status; ++ ++ switch (typeReq) { ++ case UCR_CLEAR_HUB_FEATURE: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearHubFeature 0x%x\n", wValue); ++ switch (wValue) { ++ case UHF_C_HUB_LOCAL_POWER: ++ case UHF_C_HUB_OVER_CURRENT: ++ /* Nothing required here */ ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "ClearHubFeature request %xh unknown\n", ++ wValue); ++ } ++ break; ++ case UCR_CLEAR_PORT_FEATURE: ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (wValue != UHF_PORT_L1) ++#endif ++ if (!wIndex || wIndex > 1) ++ goto error; ++ ++ switch (wValue) { ++ case UHF_PORT_ENABLE: ++ DWC_DEBUGPL(DBG_ANY, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtena = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_SUSPEND: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); ++ ++ if (core_if->power_down == 2) { ++ dwc_otg_host_hibernation_restore(core_if, 0, 0); ++ } else { ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ dwc_mdelay(5); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ hprt0.b.prtsusp = 0; ++ /* Clear Resume bit */ ++ dwc_mdelay(100); ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UHF_PORT_L1: ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ glpmcfg_data_t lpmcfg = {.d32 = 0 }; ++ ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if-> ++ core_global_regs->glpmcfg); ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ lpmcfg.b.prt_sleep_sts = 1; ++ DWC_WRITE_REG32(&core_if-> ++ core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ ++ /* Clear Enbl_L1Gating bit. */ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, ++ 0); ++ ++ dwc_mdelay(5); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ /* This bit will be cleared in wakeup interrupt handle */ ++ break; ++ } ++#endif ++ case UHF_PORT_POWER: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_INDICATOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_INDICATOR\n"); ++ /* Port inidicator not supported */ ++ break; ++ case UHF_C_PORT_CONNECTION: ++ /* Clears drivers internal connect status change ++ * flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n"); ++ dwc_otg_hcd->flags.b.port_connect_status_change = 0; ++ break; ++ case UHF_C_PORT_RESET: ++ /* Clears the driver's internal Port Reset Change ++ * flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_RESET\n"); ++ dwc_otg_hcd->flags.b.port_reset_change = 0; ++ break; ++ case UHF_C_PORT_ENABLE: ++ /* Clears the driver's internal Port ++ * Enable/Disable Change flag */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n"); ++ dwc_otg_hcd->flags.b.port_enable_change = 0; ++ break; ++ case UHF_C_PORT_SUSPEND: ++ /* Clears the driver's internal Port Suspend ++ * Change flag, which is set when resume signaling on ++ * the host port is complete */ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n"); ++ dwc_otg_hcd->flags.b.port_suspend_change = 0; ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UHF_C_PORT_L1: ++ dwc_otg_hcd->flags.b.port_l1_change = 0; ++ break; ++#endif ++ case UHF_C_PORT_OVER_CURRENT: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n"); ++ dwc_otg_hcd->flags.b.port_over_current_change = 0; ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "ClearPortFeature request %xh " ++ "unknown or unsupported\n", wValue); ++ } ++ break; ++ case UCR_GET_HUB_DESCRIPTOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetHubDescriptor\n"); ++ hub_desc = (usb_hub_descriptor_t *) buf; ++ hub_desc->bDescLength = 9; ++ hub_desc->bDescriptorType = 0x29; ++ hub_desc->bNbrPorts = 1; ++ USETW(hub_desc->wHubCharacteristics, 0x08); ++ hub_desc->bPwrOn2PwrGood = 1; ++ hub_desc->bHubContrCurrent = 0; ++ hub_desc->DeviceRemovable[0] = 0; ++ hub_desc->DeviceRemovable[1] = 0xff; ++ break; ++ case UCR_GET_HUB_STATUS: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetHubStatus\n"); ++ DWC_MEMSET(buf, 0, 4); ++ break; ++ case UCR_GET_PORT_STATUS: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n", ++ wIndex, dwc_otg_hcd->flags.d32); ++ if (!wIndex || wIndex > 1) ++ goto error; ++ ++ port_status = 0; ++ ++ if (dwc_otg_hcd->flags.b.port_connect_status_change) ++ port_status |= (1 << UHF_C_PORT_CONNECTION); ++ ++ if (dwc_otg_hcd->flags.b.port_enable_change) ++ port_status |= (1 << UHF_C_PORT_ENABLE); ++ ++ if (dwc_otg_hcd->flags.b.port_suspend_change) ++ port_status |= (1 << UHF_C_PORT_SUSPEND); ++ ++ if (dwc_otg_hcd->flags.b.port_l1_change) ++ port_status |= (1 << UHF_C_PORT_L1); ++ ++ if (dwc_otg_hcd->flags.b.port_reset_change) { ++ port_status |= (1 << UHF_C_PORT_RESET); ++ } ++ ++ if (dwc_otg_hcd->flags.b.port_over_current_change) { ++ DWC_WARN("Overcurrent change detected\n"); ++ port_status |= (1 << UHF_C_PORT_OVER_CURRENT); ++ } ++ ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return 0's for the remainder of the port status ++ * since the port register can't be read if the core ++ * is in device mode. ++ */ ++ *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); ++ break; ++ } ++ ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); ++ ++ if (hprt0.b.prtconnsts) ++ port_status |= (1 << UHF_PORT_CONNECTION); ++ ++ if (hprt0.b.prtena) ++ port_status |= (1 << UHF_PORT_ENABLE); ++ ++ if (hprt0.b.prtsusp) ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ ++ if (hprt0.b.prtovrcurract) ++ port_status |= (1 << UHF_PORT_OVER_CURRENT); ++ ++ if (hprt0.b.prtrst) ++ port_status |= (1 << UHF_PORT_RESET); ++ ++ if (hprt0.b.prtpwr) ++ port_status |= (1 << UHF_PORT_POWER); ++ ++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) ++ port_status |= (1 << UHF_PORT_HIGH_SPEED); ++ else if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED) ++ port_status |= (1 << UHF_PORT_LOW_SPEED); ++ ++ if (hprt0.b.prttstctl) ++ port_status |= (1 << UHF_PORT_TEST); ++ if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) { ++ port_status |= (1 << UHF_PORT_L1); ++ } ++ /* ++ For Synopsys HW emulation of Power down wkup_control asserts the ++ hreset_n and prst_n on suspned. This causes the HPRT0 to be zero. ++ We intentionally tell the software that port is in L2Suspend state. ++ Only for STE. ++ */ ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ } ++ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ ++ ++ *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); ++ ++ break; ++ case UCR_SET_HUB_FEATURE: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetHubFeature\n"); ++ /* No HUB features supported */ ++ break; ++ case UCR_SET_PORT_FEATURE: ++ if (wValue != UHF_PORT_TEST && (!wIndex || wIndex > 1)) ++ goto error; ++ ++ if (!dwc_otg_hcd->flags.b.port_connect_status) { ++ /* ++ * The port is disconnected, which means the core is ++ * either in device mode or it soon will be. Just ++ * return without doing anything since the port ++ * register can't be written if the core is in device ++ * mode. ++ */ ++ break; ++ } ++ ++ switch (wValue) { ++ case UHF_PORT_SUSPEND: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); ++ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) { ++ goto error; ++ } ++ if (core_if->power_down == 2) { ++ int timeout = 300; ++ dwc_irqflags_t flags; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++#ifdef DWC_DEV_SRPCAP ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++#endif ++ DWC_PRINTF("Preparing for complete power-off\n"); ++ ++ /* Save registers before hibernation */ ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_host_regs(core_if); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtena = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Spin hprt0.b.prtsusp to became 1 */ ++ do { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ if (hprt0.b.prtsusp) { ++ break; ++ } ++ dwc_mdelay(1); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_WARN("Suspend wasn't genereted\n"); ++ } ++ dwc_udelay(10); ++ ++ /* ++ * We need to disable interrupts to prevent servicing of any IRQ ++ * during going to hibernation ++ */ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ core_if->lx_state = DWC_OTG_L2; ++#ifdef DWC_DEV_SRPCAP ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ hprt0.b.prtena = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++#endif ++ gusbcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ dwc_udelay(10); ++ } ++#ifdef DWC_DEV_SRPCAP ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++#endif ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = 0; ++#ifdef DWC_DEV_SRPCAP ++ gpwrdn.b.srp_det_msk = 1; ++#endif ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Enable Power Down Clamp and all interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++#ifdef DWC_DEV_SRPCAP ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) ++ { ++ core_if->pwron_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ ); ++ } ++#endif ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags); ++ ++ DWC_PRINTF("Host hibernation completed\n"); ++ // Exit from case statement ++ break; ++ ++ } ++ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex && ++ dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gotgctl, 0, gotgctl.d32); ++ core_if->op_state = A_SUSPEND; ++ } ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ { ++ dwc_irqflags_t flags; ++ /* Update lx_state */ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ core_if->lx_state = DWC_OTG_L2; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++ } ++ /* Suspend the Phy Clock */ ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ } ++ ++ /* For HNP the bus must be suspended for at least 200ms. */ ++ if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ dwc_mdelay(200); ++ } ++ ++ /** @todo - check how sw can wait for 1 sec to check asesvld??? */ ++#if 0 //vahrama !!!!!!!!!!!!!!!!!! ++ if (core_if->adp_enable) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn; ++ ++ while (gotgctl.b.asesvld == 1) { ++ gotgctl.d32 = ++ DWC_READ_REG32(&core_if-> ++ core_global_regs-> ++ gotgctl); ++ dwc_mdelay(100); ++ } ++ ++ /* Enable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_otg_adp_probe_start(core_if); ++ } ++#endif ++ break; ++ case UHF_PORT_POWER: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_POWER\n"); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ break; ++ case UHF_PORT_RESET: ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ /* If we are going to exit from Hibernated ++ * state via USB RESET. ++ */ ++ dwc_otg_host_hibernation_restore(core_if, 0, 1); ++ } else { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_RESET\n"); ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.enbl_sleep_gating = 1; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ { ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ DWC_WRITE_REG32 ++ (&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ dwc_mdelay(1); ++ } ++ } ++#endif ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ /* Clear suspend bit if resetting from suspended state. */ ++ hprt0.b.prtsusp = 0; ++ /* When B-Host the Port reset bit is set in ++ * the Start HCD Callback function, so that ++ * the reset is started within 1ms of the HNP ++ * success interrupt. */ ++ if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) { ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtrst = 1; ++ DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ ++ dwc_mdelay(60); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */ ++ } ++ break; ++#ifdef DWC_HS_ELECT_TST ++ case UHF_PORT_TEST: ++ { ++ uint32_t t; ++ gintmsk_data_t gintmsk; ++ ++ t = (wIndex >> 8); /* MSB wIndex USB */ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_TEST %d\n", ++ t); ++ DWC_WARN("USB_PORT_FEAT_TEST %d\n", t); ++ if (t < 6) { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prttstctl = t; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } else { ++ /* Setup global vars with reg addresses (quick and ++ * dirty hack, should be cleaned up) ++ */ ++ global_regs = core_if->core_global_regs; ++ hc_global_regs = ++ core_if->host_if->host_global_regs; ++ hc_regs = ++ (dwc_otg_hc_regs_t *) ((char *) ++ global_regs + ++ 0x500); ++ data_fifo = ++ (uint32_t *) ((char *)global_regs + ++ 0x1000); ++ ++ if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Drive suspend on the root port */ ++ hprt0.d32 = ++ dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Drive resume on the root port */ ++ hprt0.d32 = ++ dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 0; ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ dwc_mdelay(100); ++ ++ /* Clear the resume bit */ ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* 15 second delay per the test spec */ ++ dwc_mdelay(15000); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ ++ /* Save current interrupt mask */ ++ gintmsk.d32 = ++ DWC_READ_REG32 ++ (&global_regs->gintmsk); ++ ++ /* Disable all interrupts while we muck with ++ * the hardware directly ++ */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); ++ ++ /* Send the Setup packet */ ++ do_setup(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Send the In and Ack packets */ ++ do_in_ack(); ++ ++ /* 15 second delay so nothing else happens for awhile */ ++ dwc_mdelay(15000); ++ ++ /* Restore interrupts */ ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); ++ } ++ } ++ break; ++ } ++#endif /* DWC_HS_ELECT_TST */ ++ ++ case UHF_PORT_INDICATOR: ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_INDICATOR\n"); ++ /* Not supported */ ++ break; ++ default: ++ retval = -DWC_E_INVALID; ++ DWC_ERROR("DWC OTG HCD - " ++ "SetPortFeature request %xh " ++ "unknown or unsupported\n", wValue); ++ break; ++ } ++ break; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ case UCR_SET_AND_TEST_PORT_FEATURE: ++ if (wValue != UHF_PORT_L1) { ++ goto error; ++ } ++ { ++ int portnum, hird, devaddr, remwake; ++ glpmcfg_data_t lpmcfg; ++ uint32_t time_usecs; ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; ++ ++ if (!dwc_otg_get_param_lpm_enable(core_if)) { ++ goto error; ++ } ++ if (wValue != UHF_PORT_L1 || wLength != 1) { ++ goto error; ++ } ++ /* Check if the port currently is in SLEEP state */ ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ DWC_INFO("Port is already in sleep mode\n"); ++ buf[0] = 0; /* Return success */ ++ break; ++ } ++ ++ portnum = wIndex & 0xf; ++ hird = (wIndex >> 4) & 0xf; ++ devaddr = (wIndex >> 8) & 0x7f; ++ remwake = (wIndex >> 15); ++ ++ if (portnum != 1) { ++ retval = -DWC_E_INVALID; ++ DWC_WARN ++ ("Wrong port number(%d) in SetandTestPortFeature request\n", ++ portnum); ++ break; ++ } ++ ++ DWC_PRINTF ++ ("SetandTestPortFeature request: portnum = %d, hird = %d, devaddr = %d, rewake = %d\n", ++ portnum, hird, devaddr, remwake); ++ /* Disable LPM interrupt */ ++ gintmsk.d32 = 0; ++ gintmsk.b.lpmtranrcvd = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ gintmsk.d32, 0); ++ ++ if (dwc_otg_hcd_send_lpm ++ (dwc_otg_hcd, devaddr, hird, remwake)) { ++ retval = -DWC_E_INVALID; ++ break; ++ } ++ ++ time_usecs = 10 * (lpmcfg.b.retry_count + 1); ++ /* We will consider timeout if time_usecs microseconds pass, ++ * and we don't receive LPM transaction status. ++ * After receiving non-error responce(ACK/NYET/STALL) from device, ++ * core will set lpmtranrcvd bit. ++ */ ++ do { ++ gintsts.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.lpmtranrcvd) { ++ break; ++ } ++ dwc_udelay(1); ++ } while (--time_usecs); ++ /* lpm_int bit will be cleared in LPM interrupt handler */ ++ ++ /* Now fill status ++ * 0x00 - Success ++ * 0x10 - NYET ++ * 0x11 - Timeout ++ */ ++ if (!gintsts.b.lpmtranrcvd) { ++ buf[0] = 0x3; /* Completion code is Timeout */ ++ dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd); ++ } else { ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.lpm_resp == 0x3) { ++ /* ACK responce from the device */ ++ buf[0] = 0x00; /* Success */ ++ } else if (lpmcfg.b.lpm_resp == 0x2) { ++ /* NYET responce from the device */ ++ buf[0] = 0x2; ++ } else { ++ /* Otherwise responce with Timeout */ ++ buf[0] = 0x3; ++ } ++ } ++ DWC_PRINTF("Device responce to LPM trans is %x\n", ++ lpmcfg.b.lpm_resp); ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, ++ gintmsk.d32); ++ ++ break; ++ } ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ default: ++error: ++ retval = -DWC_E_INVALID; ++ DWC_WARN("DWC OTG HCD - " ++ "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", ++ typeReq, wIndex, wValue); ++ break; ++ } ++ ++ return retval; ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** Returns index of host channel to perform LPM transaction. */ ++int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr) ++{ ++ dwc_otg_core_if_t *core_if = hcd->core_if; ++ dwc_hc_t *hc; ++ hcchar_data_t hcchar; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ DWC_PRINTF("No free channel to select for LPM transaction\n"); ++ return -1; ++ } ++ ++ hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); ++ ++ /* Mask host channel interrupts. */ ++ gintmsk.b.hcintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); ++ ++ /* Fill fields that core needs for LPM transaction */ ++ hcchar.b.devaddr = devaddr; ++ hcchar.b.epnum = 0; ++ hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; ++ hcchar.b.mps = 64; ++ hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); ++ hcchar.b.epdir = 0; /* OUT */ ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, ++ hcchar.d32); ++ ++ /* Remove the host channel from the free list. */ ++ DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ DWC_PRINTF("hcnum = %d devaddr = %d\n", hc->hc_num, devaddr); ++ ++ return hc->hc_num; ++} ++ ++/** Release hc after performing LPM transaction */ ++void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd) ++{ ++ dwc_hc_t *hc; ++ glpmcfg_data_t lpmcfg; ++ uint8_t hc_num; ++ ++ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); ++ hc_num = lpmcfg.b.lpm_chan_index; ++ ++ hc = hcd->hc_ptr_array[hc_num]; ++ ++ DWC_PRINTF("Freeing channel %d after LPM\n", hc_num); ++ /* Return host channel to free list */ ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++} ++ ++int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird, ++ uint8_t bRemoteWake) ++{ ++ glpmcfg_data_t lpmcfg; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ int channel; ++ ++ channel = dwc_otg_hcd_get_hc_for_lpm_tran(hcd, devaddr); ++ if (channel < 0) { ++ return channel; ++ } ++ ++ pcgcctl.b.enbl_sleep_gating = 1; ++ DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ /* Read LPM config register */ ++ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); ++ ++ /* Program LPM transaction fields */ ++ lpmcfg.b.rem_wkup_en = bRemoteWake; ++ lpmcfg.b.hird = hird; ++ lpmcfg.b.hird_thres = 0x1c; ++ lpmcfg.b.lpm_chan_index = channel; ++ lpmcfg.b.en_utmi_sleep = 1; ++ /* Program LPM config register */ ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ /* Send LPM transaction */ ++ lpmcfg.b.send_lpm = 1; ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_USB_DWC_OTG_LPM */ ++ ++int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port) ++{ ++ int retval; ++ ++ if (port != 1) { ++ return -DWC_E_INVALID; ++ } ++ ++ retval = (hcd->flags.b.port_connect_status_change || ++ hcd->flags.b.port_reset_change || ++ hcd->flags.b.port_enable_change || ++ hcd->flags.b.port_suspend_change || ++ hcd->flags.b.port_over_current_change); ++#ifdef DEBUG ++ if (retval) { ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB STATUS DATA:" ++ " Root port status changed\n"); ++ DWC_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n", ++ hcd->flags.b.port_connect_status_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n", ++ hcd->flags.b.port_reset_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n", ++ hcd->flags.b.port_enable_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n", ++ hcd->flags.b.port_suspend_change); ++ DWC_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n", ++ hcd->flags.b.port_over_current_change); ++ } ++#endif ++ return retval; ++} ++ ++int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ hfnum_data_t hfnum; ++ hfnum.d32 = ++ DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs-> ++ hfnum); ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", ++ hfnum.b.frnum); ++#endif ++ return hfnum.b.frnum; ++} ++ ++int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, ++ struct dwc_otg_hcd_function_ops *fops) ++{ ++ int retval = 0; ++ ++ hcd->fops = fops; ++ if (!dwc_otg_is_device_mode(hcd->core_if) && ++ (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) { ++ dwc_otg_hcd_reinit(hcd); ++ } else { ++ retval = -DWC_E_NO_DEVICE; ++ } ++ ++ return retval; ++} ++ ++void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd) ++{ ++ return hcd->priv; ++} ++ ++void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data) ++{ ++ hcd->priv = priv_data; ++} ++ ++uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd) ++{ ++ return hcd->otg_port; ++} ++ ++uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd) ++{ ++ uint32_t is_b_host; ++ if (hcd->core_if->op_state == B_HOST) { ++ is_b_host = 1; ++ } else { ++ is_b_host = 0; ++ } ++ ++ return is_b_host; ++} ++ ++dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, ++ int iso_desc_count, int atomic_alloc) ++{ ++ dwc_otg_hcd_urb_t *dwc_otg_urb; ++ uint32_t size; ++ ++ size = ++ sizeof(*dwc_otg_urb) + ++ iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc); ++ if (atomic_alloc) ++ dwc_otg_urb = DWC_ALLOC_ATOMIC(size); ++ else ++ dwc_otg_urb = DWC_ALLOC(size); ++ ++ if (NULL != dwc_otg_urb) ++ dwc_otg_urb->packet_count = iso_desc_count; ++ else { ++ dwc_otg_urb->packet_count = 0; ++ if (size != 0) { ++ DWC_ERROR("**** DWC OTG HCD URB alloc - " ++ "%salloc of %db failed\n", ++ atomic_alloc?"atomic ":"", size); ++ } ++ } ++ ++ return dwc_otg_urb; ++} ++ ++void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ uint8_t dev_addr, uint8_t ep_num, ++ uint8_t ep_type, uint8_t ep_dir, uint16_t mps) ++{ ++ dwc_otg_hcd_fill_pipe(&dwc_otg_urb->pipe_info, dev_addr, ep_num, ++ ep_type, ep_dir, mps); ++#if 0 ++ DWC_PRINTF ++ ("addr = %d, ep_num = %d, ep_dir = 0x%x, ep_type = 0x%x, mps = %d\n", ++ dev_addr, ep_num, ep_dir, ep_type, mps); ++#endif ++} ++ ++void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ void *urb_handle, void *buf, dwc_dma_t dma, ++ uint32_t buflen, void *setup_packet, ++ dwc_dma_t setup_dma, uint32_t flags, ++ uint16_t interval) ++{ ++ dwc_otg_urb->priv = urb_handle; ++ dwc_otg_urb->buf = buf; ++ dwc_otg_urb->dma = dma; ++ dwc_otg_urb->length = buflen; ++ dwc_otg_urb->setup_packet = setup_packet; ++ dwc_otg_urb->setup_dma = setup_dma; ++ dwc_otg_urb->flags = flags; ++ dwc_otg_urb->interval = interval; ++ dwc_otg_urb->status = -DWC_E_IN_PROGRESS; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->status; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->actual_length; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * dwc_otg_urb) ++{ ++ return dwc_otg_urb->error_count; ++} ++ ++void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num, uint32_t offset, ++ uint32_t length) ++{ ++ dwc_otg_urb->iso_descs[desc_num].offset = offset; ++ dwc_otg_urb->iso_descs[desc_num].length = length; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num) ++{ ++ return dwc_otg_urb->iso_descs[desc_num].status; ++} ++ ++uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, int desc_num) ++{ ++ return dwc_otg_urb->iso_descs[desc_num].actual_length; ++} ++ ++int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int allocated = 0; ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ ++ if (qh) { ++ if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ allocated = 1; ++ } ++ } ++ return allocated; ++} ++ ++int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ int freed = 0; ++ DWC_ASSERT(qh, "qh is not allocated\n"); ++ ++ if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ freed = 1; ++ } ++ ++ return freed; ++} ++ ++uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ DWC_ASSERT(qh, "qh is not allocated\n"); ++ return qh->usecs; ++} ++ ++void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd) ++{ ++#ifdef DEBUG ++ int num_channels; ++ int i; ++ gnptxsts_data_t np_tx_status; ++ hptxsts_data_t p_tx_status; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ DWC_PRINTF("\n"); ++ DWC_PRINTF ++ ("************************************************************\n"); ++ DWC_PRINTF("HCD State:\n"); ++ DWC_PRINTF(" Num channels: %d\n", num_channels); ++ for (i = 0; i < num_channels; i++) { ++ dwc_hc_t *hc = hcd->hc_ptr_array[i]; ++ DWC_PRINTF(" Channel %d:\n", i); ++ DWC_PRINTF(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n", ++ hc->dev_addr, hc->ep_num, hc->ep_is_in); ++ DWC_PRINTF(" speed: %d\n", hc->speed); ++ DWC_PRINTF(" ep_type: %d\n", hc->ep_type); ++ DWC_PRINTF(" max_packet: %d\n", hc->max_packet); ++ DWC_PRINTF(" data_pid_start: %d\n", hc->data_pid_start); ++ DWC_PRINTF(" multi_count: %d\n", hc->multi_count); ++ DWC_PRINTF(" xfer_started: %d\n", hc->xfer_started); ++ DWC_PRINTF(" xfer_buff: %p\n", hc->xfer_buff); ++ DWC_PRINTF(" xfer_len: %d\n", hc->xfer_len); ++ DWC_PRINTF(" xfer_count: %d\n", hc->xfer_count); ++ DWC_PRINTF(" halt_on_queue: %d\n", hc->halt_on_queue); ++ DWC_PRINTF(" halt_pending: %d\n", hc->halt_pending); ++ DWC_PRINTF(" halt_status: %d\n", hc->halt_status); ++ DWC_PRINTF(" do_split: %d\n", hc->do_split); ++ DWC_PRINTF(" complete_split: %d\n", hc->complete_split); ++ DWC_PRINTF(" hub_addr: %d\n", hc->hub_addr); ++ DWC_PRINTF(" port_addr: %d\n", hc->port_addr); ++ DWC_PRINTF(" xact_pos: %d\n", hc->xact_pos); ++ DWC_PRINTF(" requests: %d\n", hc->requests); ++ DWC_PRINTF(" qh: %p\n", hc->qh); ++ if (hc->xfer_started) { ++ hfnum_data_t hfnum; ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hfnum.d32 = ++ DWC_READ_REG32(&hcd->core_if-> ++ host_if->host_global_regs->hfnum); ++ hcchar.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcchar); ++ hctsiz.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hctsiz); ++ hcint.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcint); ++ hcintmsk.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcintmsk); ++ DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32); ++ DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32); ++ DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32); ++ DWC_PRINTF(" hcint: 0x%08x\n", hcint.d32); ++ DWC_PRINTF(" hcintmsk: 0x%08x\n", hcintmsk.d32); ++ } ++ if (hc->xfer_started && hc->qh) { ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_hcd_urb_t *urb; ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) { ++ if (!qtd->in_process) ++ break; ++ ++ urb = qtd->urb; ++ DWC_PRINTF(" URB Info:\n"); ++ DWC_PRINTF(" qtd: %p, urb: %p\n", qtd, urb); ++ if (urb) { ++ DWC_PRINTF(" Dev: %d, EP: %d %s\n", ++ dwc_otg_hcd_get_dev_addr(&urb-> ++ pipe_info), ++ dwc_otg_hcd_get_ep_num(&urb-> ++ pipe_info), ++ dwc_otg_hcd_is_pipe_in(&urb-> ++ pipe_info) ? ++ "IN" : "OUT"); ++ DWC_PRINTF(" Max packet size: %d\n", ++ dwc_otg_hcd_get_mps(&urb-> ++ pipe_info)); ++ DWC_PRINTF(" transfer_buffer: %p\n", ++ urb->buf); ++ DWC_PRINTF(" transfer_dma: %p\n", ++ (void *)urb->dma); ++ DWC_PRINTF(" transfer_buffer_length: %d\n", ++ urb->length); ++ DWC_PRINTF(" actual_length: %d\n", ++ urb->actual_length); ++ } ++ } ++ } ++ } ++ DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels); ++ DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels); ++ DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs); ++ np_tx_status.d32 = ++ DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts); ++ DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n", ++ np_tx_status.b.nptxqspcavail); ++ DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n", ++ np_tx_status.b.nptxfspcavail); ++ p_tx_status.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts); ++ DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n", ++ p_tx_status.b.ptxqspcavail); ++ DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); ++ dwc_otg_hcd_dump_frrem(hcd); ++ dwc_otg_dump_global_registers(hcd->core_if); ++ dwc_otg_dump_host_registers(hcd->core_if); ++ DWC_PRINTF ++ ("************************************************************\n"); ++ DWC_PRINTF("\n"); ++#endif ++} ++ ++#ifdef DEBUG ++void dwc_print_setup_data(uint8_t * setup) ++{ ++ int i; ++ if (CHK_DEBUG_LEVEL(DBG_HCD)) { ++ DWC_PRINTF("Setup Data = MSB "); ++ for (i = 7; i >= 0; i--) ++ DWC_PRINTF("%02x ", setup[i]); ++ DWC_PRINTF("\n"); ++ DWC_PRINTF(" bmRequestType Tranfer = %s\n", ++ (setup[0] & 0x80) ? "Device-to-Host" : ++ "Host-to-Device"); ++ DWC_PRINTF(" bmRequestType Type = "); ++ switch ((setup[0] & 0x60) >> 5) { ++ case 0: ++ DWC_PRINTF("Standard\n"); ++ break; ++ case 1: ++ DWC_PRINTF("Class\n"); ++ break; ++ case 2: ++ DWC_PRINTF("Vendor\n"); ++ break; ++ case 3: ++ DWC_PRINTF("Reserved\n"); ++ break; ++ } ++ DWC_PRINTF(" bmRequestType Recipient = "); ++ switch (setup[0] & 0x1f) { ++ case 0: ++ DWC_PRINTF("Device\n"); ++ break; ++ case 1: ++ DWC_PRINTF("Interface\n"); ++ break; ++ case 2: ++ DWC_PRINTF("Endpoint\n"); ++ break; ++ case 3: ++ DWC_PRINTF("Other\n"); ++ break; ++ default: ++ DWC_PRINTF("Reserved\n"); ++ break; ++ } ++ DWC_PRINTF(" bRequest = 0x%0x\n", setup[1]); ++ DWC_PRINTF(" wValue = 0x%0x\n", *((uint16_t *) & setup[2])); ++ DWC_PRINTF(" wIndex = 0x%0x\n", *((uint16_t *) & setup[4])); ++ DWC_PRINTF(" wLength = 0x%0x\n\n", *((uint16_t *) & setup[6])); ++ } ++} ++#endif ++ ++void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd) ++{ ++#if 0 ++ DWC_PRINTF("Frame remaining at SOF:\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->frrem_samples, hcd->frrem_accum, ++ (hcd->frrem_samples > 0) ? ++ hcd->frrem_accum / hcd->frrem_samples : 0); ++ ++ DWC_PRINTF("\n"); ++ DWC_PRINTF("Frame remaining at start_transfer (uframe 7):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_7_samples, ++ hcd->core_if->hfnum_7_frrem_accum, ++ (hcd->core_if->hfnum_7_samples > ++ 0) ? hcd->core_if->hfnum_7_frrem_accum / ++ hcd->core_if->hfnum_7_samples : 0); ++ DWC_PRINTF("Frame remaining at start_transfer (uframe 0):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_0_samples, ++ hcd->core_if->hfnum_0_frrem_accum, ++ (hcd->core_if->hfnum_0_samples > ++ 0) ? hcd->core_if->hfnum_0_frrem_accum / ++ hcd->core_if->hfnum_0_samples : 0); ++ DWC_PRINTF("Frame remaining at start_transfer (uframe 1-6):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->core_if->hfnum_other_samples, ++ hcd->core_if->hfnum_other_frrem_accum, ++ (hcd->core_if->hfnum_other_samples > ++ 0) ? hcd->core_if->hfnum_other_frrem_accum / ++ hcd->core_if->hfnum_other_samples : 0); ++ ++ DWC_PRINTF("\n"); ++ DWC_PRINTF("Frame remaining at sample point A (uframe 7):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_7_samples_a, hcd->hfnum_7_frrem_accum_a, ++ (hcd->hfnum_7_samples_a > 0) ? ++ hcd->hfnum_7_frrem_accum_a / hcd->hfnum_7_samples_a : 0); ++ DWC_PRINTF("Frame remaining at sample point A (uframe 0):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_0_samples_a, hcd->hfnum_0_frrem_accum_a, ++ (hcd->hfnum_0_samples_a > 0) ? ++ hcd->hfnum_0_frrem_accum_a / hcd->hfnum_0_samples_a : 0); ++ DWC_PRINTF("Frame remaining at sample point A (uframe 1-6):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_other_samples_a, hcd->hfnum_other_frrem_accum_a, ++ (hcd->hfnum_other_samples_a > 0) ? ++ hcd->hfnum_other_frrem_accum_a / ++ hcd->hfnum_other_samples_a : 0); ++ ++ DWC_PRINTF("\n"); ++ DWC_PRINTF("Frame remaining at sample point B (uframe 7):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_7_samples_b, hcd->hfnum_7_frrem_accum_b, ++ (hcd->hfnum_7_samples_b > 0) ? ++ hcd->hfnum_7_frrem_accum_b / hcd->hfnum_7_samples_b : 0); ++ DWC_PRINTF("Frame remaining at sample point B (uframe 0):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_0_samples_b, hcd->hfnum_0_frrem_accum_b, ++ (hcd->hfnum_0_samples_b > 0) ? ++ hcd->hfnum_0_frrem_accum_b / hcd->hfnum_0_samples_b : 0); ++ DWC_PRINTF("Frame remaining at sample point B (uframe 1-6):\n"); ++ DWC_PRINTF(" samples %u, accum %llu, avg %llu\n", ++ hcd->hfnum_other_samples_b, hcd->hfnum_other_frrem_accum_b, ++ (hcd->hfnum_other_samples_b > 0) ? ++ hcd->hfnum_other_frrem_accum_b / ++ hcd->hfnum_other_samples_b : 0); ++#endif ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +new file mode 100644 +index 0000000..8075595 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +@@ -0,0 +1,824 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ ++ * $Revision: #58 $ ++ * $Date: 2011/09/15 $ ++ * $Change: 1846647 $ ++ * ++ * 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_DEVICE_ONLY ++#ifndef __DWC_HCD_H__ ++#define __DWC_HCD_H__ ++ ++#include "dwc_otg_os_dep.h" ++#include "usb.h" ++#include "dwc_otg_hcd_if.h" ++#include "dwc_otg_core_if.h" ++#include "dwc_list.h" ++#include "dwc_otg_cil.h" ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Host Contoller Driver (HCD). ++ * ++ * The Host Controller Driver (HCD) is responsible for translating requests ++ * from the USB Driver into the appropriate actions on the DWC_otg controller. ++ * It isolates the USBD from the specifics of the controller by providing an ++ * API to the USBD. ++ */ ++ ++struct dwc_otg_hcd_pipe_info { ++ uint8_t dev_addr; ++ uint8_t ep_num; ++ uint8_t pipe_type; ++ uint8_t pipe_dir; ++ uint16_t mps; ++}; ++ ++struct dwc_otg_hcd_iso_packet_desc { ++ uint32_t offset; ++ uint32_t length; ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct dwc_otg_qtd; ++ ++struct dwc_otg_hcd_urb { ++ void *priv; ++ struct dwc_otg_qtd *qtd; ++ void *buf; ++ dwc_dma_t dma; ++ void *setup_packet; ++ dwc_dma_t setup_dma; ++ uint32_t length; ++ uint32_t actual_length; ++ uint32_t status; ++ uint32_t error_count; ++ uint32_t packet_count; ++ uint32_t flags; ++ uint16_t interval; ++ struct dwc_otg_hcd_pipe_info pipe_info; ++ struct dwc_otg_hcd_iso_packet_desc iso_descs[0]; ++}; ++ ++static inline uint8_t dwc_otg_hcd_get_ep_num(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return pipe->ep_num; ++} ++ ++static inline uint8_t dwc_otg_hcd_get_pipe_type(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return pipe->pipe_type; ++} ++ ++static inline uint16_t dwc_otg_hcd_get_mps(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return pipe->mps; ++} ++ ++static inline uint8_t dwc_otg_hcd_get_dev_addr(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return pipe->dev_addr; ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_isoc(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_ISOCHRONOUS); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_int(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_INTERRUPT); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_bulk(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_BULK); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_control(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (pipe->pipe_type == UE_CONTROL); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_in(struct dwc_otg_hcd_pipe_info *pipe) ++{ ++ return (pipe->pipe_dir == UE_DIR_IN); ++} ++ ++static inline uint8_t dwc_otg_hcd_is_pipe_out(struct dwc_otg_hcd_pipe_info ++ *pipe) ++{ ++ return (!dwc_otg_hcd_is_pipe_in(pipe)); ++} ++ ++static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, ++ uint8_t devaddr, uint8_t ep_num, ++ uint8_t pipe_type, uint8_t pipe_dir, ++ uint16_t mps) ++{ ++ pipe->dev_addr = devaddr; ++ pipe->ep_num = ep_num; ++ pipe->pipe_type = pipe_type; ++ pipe->pipe_dir = pipe_dir; ++ pipe->mps = mps; ++} ++ ++/** ++ * Phases for control transfers. ++ */ ++typedef enum dwc_otg_control_phase { ++ DWC_OTG_CONTROL_SETUP, ++ DWC_OTG_CONTROL_DATA, ++ DWC_OTG_CONTROL_STATUS ++} dwc_otg_control_phase_e; ++ ++/** Transaction types. */ ++typedef enum dwc_otg_transaction_type { ++ DWC_OTG_TRANSACTION_NONE, ++ DWC_OTG_TRANSACTION_PERIODIC, ++ DWC_OTG_TRANSACTION_NON_PERIODIC, ++ DWC_OTG_TRANSACTION_ALL ++} dwc_otg_transaction_type_e; ++ ++struct dwc_otg_qh; ++ ++/** ++ * A Queue Transfer Descriptor (QTD) holds the state of a bulk, control, ++ * interrupt, or isochronous transfer. A single QTD is created for each URB ++ * (of one of these types) submitted to the HCD. The transfer associated with ++ * a QTD may require one or multiple transactions. ++ * ++ * A QTD is linked to a Queue Head, which is entered in either the ++ * non-periodic or periodic schedule for execution. When a QTD is chosen for ++ * execution, some or all of its transactions may be executed. After ++ * execution, the state of the QTD is updated. The QTD may be retired if all ++ * its transactions are complete or if an error occurred. Otherwise, it ++ * remains in the schedule so more transactions can be executed later. ++ */ ++typedef struct dwc_otg_qtd { ++ /** ++ * Determines the PID of the next data packet for the data phase of ++ * control transfers. Ignored for other transfer types.
++ * One of the following values: ++ * - DWC_OTG_HC_PID_DATA0 ++ * - DWC_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Current phase for control transfers (Setup, Data, or Status). */ ++ dwc_otg_control_phase_e control_phase; ++ ++ /** Keep track of the current split type ++ * for FS/LS endpoints on a HS Hub */ ++ uint8_t complete_split; ++ ++ /** How many bytes transferred during SSPLIT OUT */ ++ uint32_t ssplit_out_xfer_count; ++ ++ /** ++ * Holds the number of bus errors that have occurred for a transaction ++ * within this transfer. ++ */ ++ uint8_t error_count; ++ ++ /** ++ * Index of the next frame descriptor for an isochronous transfer. A ++ * frame descriptor describes the buffer position and length of the ++ * data to be transferred in the next scheduled (micro)frame of an ++ * isochronous transfer. It also holds status for that transaction. ++ * The frame index starts at 0. ++ */ ++ uint16_t isoc_frame_index; ++ ++ /** Position of the ISOC split on full/low speed */ ++ uint8_t isoc_split_pos; ++ ++ /** Position of the ISOC split in the buffer for the current frame */ ++ uint16_t isoc_split_offset; ++ ++ /** URB for this transfer */ ++ struct dwc_otg_hcd_urb *urb; ++ ++ struct dwc_otg_qh *qh; ++ ++ /** This list of QTDs */ ++ DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry; ++ ++ /** Indicates if this QTD is currently processed by HW. */ ++ uint8_t in_process; ++ ++ /** Number of DMA descriptors for this QTD */ ++ uint8_t n_desc; ++ ++ /** ++ * Last activated frame(packet) index. ++ * Used in Descriptor DMA mode only. ++ */ ++ uint16_t isoc_frame_index_last; ++ ++} dwc_otg_qtd_t; ++ ++DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd); ++ ++/** ++ * A Queue Head (QH) holds the static characteristics of an endpoint and ++ * maintains a list of transfers (QTDs) for that endpoint. A QH structure may ++ * be entered in either the non-periodic or periodic schedule. ++ */ ++typedef struct dwc_otg_qh { ++ /** ++ * Endpoint type. ++ * One of the following values: ++ * - UE_CONTROL ++ * - UE_BULK ++ * - UE_INTERRUPT ++ * - UE_ISOCHRONOUS ++ */ ++ uint8_t ep_type; ++ uint8_t ep_is_in; ++ ++ /** wMaxPacketSize Field of Endpoint Descriptor. */ ++ uint16_t maxp; ++ ++ /** ++ * Device speed. ++ * One of the following values: ++ * - DWC_OTG_EP_SPEED_LOW ++ * - DWC_OTG_EP_SPEED_FULL ++ * - DWC_OTG_EP_SPEED_HIGH ++ */ ++ uint8_t dev_speed; ++ ++ /** ++ * Determines the PID of the next data packet for non-control ++ * transfers. Ignored for control transfers.
++ * One of the following values: ++ * - DWC_OTG_HC_PID_DATA0 ++ * - DWC_OTG_HC_PID_DATA1 ++ */ ++ uint8_t data_toggle; ++ ++ /** Ping state if 1. */ ++ uint8_t ping_state; ++ ++ /** ++ * List of QTDs for this QH. ++ */ ++ struct dwc_otg_qtd_list qtd_list; ++ ++ /** Host channel currently processing transfers for this QH. */ ++ struct dwc_hc *channel; ++ ++ /** Full/low speed endpoint on high-speed hub requires split. */ ++ uint8_t do_split; ++ ++ /** @name Periodic schedule information */ ++ /** @{ */ ++ ++ /** Bandwidth in microseconds per (micro)frame. */ ++ uint16_t usecs; ++ ++ /** Interval between transfers in (micro)frames. */ ++ uint16_t interval; ++ ++ /** ++ * (micro)frame to initialize a periodic transfer. The transfer ++ * executes in the following (micro)frame. ++ */ ++ uint16_t sched_frame; ++ ++ /** (micro)frame at which last start split was initialized. */ ++ uint16_t start_split_frame; ++ ++ /** @} */ ++ ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ */ ++ uint8_t *dw_align_buf; ++ dwc_dma_t dw_align_buf_dma; ++ ++ /** Entry for QH in either the periodic or non-periodic schedule. */ ++ dwc_list_link_t qh_list_entry; ++ ++ /** @name Descriptor DMA support */ ++ /** @{ */ ++ ++ /** Descriptor List. */ ++ dwc_otg_host_dma_desc_t *desc_list; ++ ++ /** Descriptor List physical address. */ ++ dwc_dma_t desc_list_dma; ++ ++ /** ++ * Xfer Bytes array. ++ * Each element corresponds to a descriptor and indicates ++ * original XferSize size value for the descriptor. ++ */ ++ uint32_t *n_bytes; ++ ++ /** Actual number of transfer descriptors in a list. */ ++ uint16_t ntd; ++ ++ /** First activated isochronous transfer descriptor index. */ ++ uint8_t td_first; ++ /** Last activated isochronous transfer descriptor index. */ ++ uint8_t td_last; ++ ++ /** @} */ ++ ++ ++ uint16_t speed; ++ uint16_t frame_usecs[8]; ++} dwc_otg_qh_t; ++ ++DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); ++ ++/** ++ * This structure holds the state of the HCD, including the non-periodic and ++ * periodic schedules. ++ */ ++struct dwc_otg_hcd { ++ /** The DWC otg device pointer */ ++ struct dwc_otg_device *otg_dev; ++ /** DWC OTG Core Interface Layer */ ++ dwc_otg_core_if_t *core_if; ++ ++ /** Function HCD driver callbacks */ ++ struct dwc_otg_hcd_function_ops *fops; ++ ++ /** Internal DWC HCD Flags */ ++ volatile union dwc_otg_hcd_internal_flags { ++ uint32_t d32; ++ struct { ++ unsigned port_connect_status_change:1; ++ unsigned port_connect_status:1; ++ unsigned port_reset_change:1; ++ unsigned port_enable_change:1; ++ unsigned port_suspend_change:1; ++ unsigned port_over_current_change:1; ++ unsigned port_l1_change:1; ++ unsigned reserved:26; ++ } b; ++ } flags; ++ ++ /** ++ * Inactive items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are not ++ * currently assigned to a host channel. ++ */ ++ dwc_list_link_t non_periodic_sched_inactive; ++ ++ /** ++ * Active items in the non-periodic schedule. This is a list of ++ * Queue Heads. Transfers associated with these Queue Heads are ++ * currently assigned to a host channel. ++ */ ++ dwc_list_link_t non_periodic_sched_active; ++ ++ /** ++ * Pointer to the next Queue Head to process in the active ++ * non-periodic schedule. ++ */ ++ dwc_list_link_t *non_periodic_qh_ptr; ++ ++ /** ++ * Inactive items in the periodic schedule. This is a list of QHs for ++ * periodic transfers that are _not_ scheduled for the next frame. ++ * Each QH in the list has an interval counter that determines when it ++ * needs to be scheduled for execution. This scheduling mechanism ++ * allows only a simple calculation for periodic bandwidth used (i.e. ++ * must assume that all periodic transfers may need to execute in the ++ * same frame). However, it greatly simplifies scheduling and should ++ * be sufficient for the vast majority of OTG hosts, which need to ++ * connect to a small number of peripherals at one time. ++ * ++ * Items move from this list to periodic_sched_ready when the QH ++ * interval counter is 0 at SOF. ++ */ ++ dwc_list_link_t periodic_sched_inactive; ++ ++ /** ++ * List of periodic QHs that are ready for execution in the next ++ * frame, but have not yet been assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_assigned as host ++ * channels become available during the current frame. ++ */ ++ dwc_list_link_t periodic_sched_ready; ++ ++ /** ++ * List of periodic QHs to be executed in the next frame that are ++ * assigned to host channels. ++ * ++ * Items move from this list to periodic_sched_queued as the ++ * transactions for the QH are queued to the DWC_otg controller. ++ */ ++ dwc_list_link_t periodic_sched_assigned; ++ ++ /** ++ * List of periodic QHs that have been queued for execution. ++ * ++ * Items move from this list to either periodic_sched_inactive or ++ * periodic_sched_ready when the channel associated with the transfer ++ * is released. If the interval for the QH is 1, the item moves to ++ * periodic_sched_ready because it must be rescheduled for the next ++ * frame. Otherwise, the item moves to periodic_sched_inactive. ++ */ ++ dwc_list_link_t periodic_sched_queued; ++ ++ /** ++ * Total bandwidth claimed so far for periodic transfers. This value ++ * is in microseconds per (micro)frame. The assumption is that all ++ * periodic transfers may occur in the same (micro)frame. ++ */ ++ uint16_t periodic_usecs; ++ ++ /** ++ * Total bandwidth claimed so far for all periodic transfers ++ * in a frame. ++ * This will include a mixture of HS and FS transfers. ++ * Units are microseconds per (micro)frame. ++ * We have a budget per frame and have to schedule ++ * transactions accordingly. ++ * Watch out for the fact that things are actually scheduled for the ++ * "next frame". ++ */ ++ uint16_t frame_usecs[8]; ++ ++ ++ /** ++ * Frame number read from the core at SOF. The value ranges from 0 to ++ * DWC_HFNUM_MAX_FRNUM. ++ */ ++ uint16_t frame_number; ++ ++ /** ++ * Count of periodic QHs, if using several eps. For SOF enable/disable. ++ */ ++ uint16_t periodic_qh_count; ++ ++ /** ++ * Free host channels in the controller. This is a list of ++ * dwc_hc_t items. ++ */ ++ struct hc_list free_hc_list; ++ /** ++ * Number of host channels assigned to periodic transfers. Currently ++ * assuming that there is a dedicated host channel for each periodic ++ * transaction and at least one host channel available for ++ * non-periodic transactions. ++ */ ++ int periodic_channels; /* microframe_schedule==0 */ ++ ++ /** ++ * Number of host channels assigned to non-periodic transfers. ++ */ ++ int non_periodic_channels; /* microframe_schedule==0 */ ++ ++ /** ++ * Number of host channels assigned to non-periodic transfers. ++ */ ++ int available_host_channels; ++ ++ /** ++ * Array of pointers to the host channel descriptors. Allows accessing ++ * a host channel descriptor given the host channel number. This is ++ * useful in interrupt handlers. ++ */ ++ struct dwc_hc *hc_ptr_array[MAX_EPS_CHANNELS]; ++ ++ /** ++ * Buffer to use for any data received during the status phase of a ++ * control transfer. Normally no data is transferred during the status ++ * phase. This buffer is used as a bit bucket. ++ */ ++ uint8_t *status_buf; ++ ++ /** ++ * DMA address for status_buf. ++ */ ++ dma_addr_t status_buf_dma; ++#define DWC_OTG_HCD_STATUS_BUF_SIZE 64 ++ ++ /** ++ * Connection timer. An OTG host must display a message if the device ++ * does not connect. Started when the VBus power is turned on via ++ * sysfs attribute "buspower". ++ */ ++ dwc_timer_t *conn_timer; ++ ++ /* Tasket to do a reset */ ++ dwc_tasklet_t *reset_tasklet; ++ ++ /* */ ++ dwc_spinlock_t *lock; ++ ++ /** ++ * Private data that could be used by OS wrapper. ++ */ ++ void *priv; ++ ++ uint8_t otg_port; ++ ++ /** Frame List */ ++ uint32_t *frame_list; ++ ++ /** Frame List DMA address */ ++ dma_addr_t frame_list_dma; ++ ++#ifdef DEBUG ++ uint32_t frrem_samples; ++ uint64_t frrem_accum; ++ ++ uint32_t hfnum_7_samples_a; ++ uint64_t hfnum_7_frrem_accum_a; ++ uint32_t hfnum_0_samples_a; ++ uint64_t hfnum_0_frrem_accum_a; ++ uint32_t hfnum_other_samples_a; ++ uint64_t hfnum_other_frrem_accum_a; ++ ++ uint32_t hfnum_7_samples_b; ++ uint64_t hfnum_7_frrem_accum_b; ++ uint32_t hfnum_0_samples_b; ++ uint64_t hfnum_0_frrem_accum_b; ++ uint32_t hfnum_other_samples_b; ++ uint64_t hfnum_other_frrem_accum_b; ++#endif ++}; ++ ++/** @name Transaction Execution Functions */ ++/** @{ */ ++extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t ++ * hcd); ++extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, ++ dwc_otg_transaction_type_e tr_type); ++ ++/** @} */ ++ ++/** @name Interrupt Handler Functions */ ++/** @{ */ ++extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_incomplete_periodic_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_conn_id_status_change_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_disconnect_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint32_t num); ++extern int32_t dwc_otg_hcd_handle_session_req_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t * ++ dwc_otg_hcd); ++/** @} */ ++ ++/** @name Schedule Queue Functions */ ++/** @{ */ ++ ++/* Implemented in dwc_otg_hcd_queue.c */ ++extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * urb, int atomic_alloc); ++extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ int sched_csplit); ++ ++/** Remove and free a QH */ ++static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd, ++ dwc_otg_qh_t * qh) ++{ ++ dwc_irqflags_t flags; ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ dwc_otg_hcd_qh_free(hcd, qh); ++} ++ ++/** Allocates memory for a QH structure. ++ * @return Returns the memory allocate or NULL on error. */ ++static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc) ++{ ++ if (atomic_alloc) ++ return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t)); ++ else ++ return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t)); ++} ++ ++extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, ++ int atomic_alloc); ++extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb); ++extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_qh_t ** qh, int atomic_alloc); ++ ++/** Allocates memory for a QTD structure. ++ * @return Returns the memory allocate or NULL on error. */ ++static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc) ++{ ++ if (atomic_alloc) ++ return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t)); ++ else ++ return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t)); ++} ++ ++/** Frees the memory for a QTD structure. QTD should already be removed from ++ * list. ++ * @param qtd QTD to free.*/ ++static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd) ++{ ++ DWC_FREE(qtd); ++} ++ ++/** Removes a QTD from list. ++ * @param hcd HCD instance. ++ * @param qtd QTD to remove from list. ++ * @param qh QTD belongs to. ++ */ ++static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_qh_t * qh) ++{ ++ DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); ++} ++ ++/** Remove and free a QTD ++ * Need to disable IRQ and hold hcd lock while calling this function out of ++ * interrupt servicing chain */ ++static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_qh_t * qh) ++{ ++ dwc_otg_hcd_qtd_remove(hcd, qtd, qh); ++ dwc_otg_hcd_qtd_free(qtd); ++} ++ ++/** @} */ ++ ++/** @name Descriptor DMA Supporting Functions */ ++/** @{ */ ++ ++extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status); ++ ++extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); ++ ++/** @} */ ++ ++/** @name Internal Functions */ ++/** @{ */ ++dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb); ++/** @} */ ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++extern int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, ++ uint8_t devaddr); ++extern void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd); ++#endif ++ ++/** Gets the QH that contains the list_head */ ++#define dwc_list_to_qh(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qh_t, qh_list_entry) ++ ++/** Gets the QTD that contains the list_head */ ++#define dwc_list_to_qtd(_list_head_ptr_) container_of(_list_head_ptr_, dwc_otg_qtd_t, qtd_list_entry) ++ ++/** Check if QH is non-periodic */ ++#define dwc_qh_is_non_per(_qh_ptr_) ((_qh_ptr_->ep_type == UE_BULK) || \ ++ (_qh_ptr_->ep_type == UE_CONTROL)) ++ ++/** High bandwidth multiplier as encoded in highspeed endpoint descriptors */ ++#define dwc_hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) ++ ++/** Packet size for any kind of endpoint descriptor */ ++#define dwc_max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) ++ ++/** ++ * Returns true if _frame1 is less than or equal to _frame2. The comparison is ++ * done modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the ++ * frame number when the max frame number is reached. ++ */ ++static inline int dwc_frame_num_le(uint16_t frame1, uint16_t frame2) ++{ ++ return ((frame2 - frame1) & DWC_HFNUM_MAX_FRNUM) <= ++ (DWC_HFNUM_MAX_FRNUM >> 1); ++} ++ ++/** ++ * Returns true if _frame1 is greater than _frame2. The comparison is done ++ * modulo DWC_HFNUM_MAX_FRNUM. This accounts for the rollover of the frame ++ * number when the max frame number is reached. ++ */ ++static inline int dwc_frame_num_gt(uint16_t frame1, uint16_t frame2) ++{ ++ return (frame1 != frame2) && ++ (((frame1 - frame2) & DWC_HFNUM_MAX_FRNUM) < ++ (DWC_HFNUM_MAX_FRNUM >> 1)); ++} ++ ++/** ++ * Increments _frame by the amount specified by _inc. The addition is done ++ * modulo DWC_HFNUM_MAX_FRNUM. Returns the incremented value. ++ */ ++static inline uint16_t dwc_frame_num_inc(uint16_t frame, uint16_t inc) ++{ ++ return (frame + inc) & DWC_HFNUM_MAX_FRNUM; ++} ++ ++static inline uint16_t dwc_full_frame_num(uint16_t frame) ++{ ++ return (frame & DWC_HFNUM_MAX_FRNUM) >> 3; ++} ++ ++static inline uint16_t dwc_micro_frame_num(uint16_t frame) ++{ ++ return frame & 0x7; ++} ++ ++void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd); ++ ++#ifdef DEBUG ++/** ++ * Macro to sample the remaining PHY clocks left in the current frame. This ++ * may be used during debugging to determine the average time it takes to ++ * execute sections of code. There are two possible sample points, "a" and ++ * "b", so the _letter argument must be one of these values. ++ * ++ * To dump the average sample times, read the "hcd_frrem" sysfs attribute. For ++ * example, "cat /sys/devices/lm0/hcd_frrem". ++ */ ++#define dwc_sample_frrem(_hcd, _qh, _letter) \ ++{ \ ++ hfnum_data_t hfnum; \ ++ dwc_otg_qtd_t *qtd; \ ++ qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \ ++ if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \ ++ hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ ++ switch (hfnum.b.frnum & 0x7) { \ ++ case 7: \ ++ _hcd->hfnum_7_samples_##_letter++; \ ++ _hcd->hfnum_7_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ case 0: \ ++ _hcd->hfnum_0_samples_##_letter++; \ ++ _hcd->hfnum_0_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ default: \ ++ _hcd->hfnum_other_samples_##_letter++; \ ++ _hcd->hfnum_other_frrem_accum_##_letter += hfnum.b.frrem; \ ++ break; \ ++ } \ ++ } \ ++} ++#else ++#define dwc_sample_frrem(_hcd, _qh, _letter) ++#endif ++#endif ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c +new file mode 100644 +index 0000000..d0d5fa1 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c +@@ -0,0 +1,1133 @@ ++/*========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ ++ * $Revision: #10 $ ++ * $Date: 2011/10/20 $ ++ * $Change: 1869464 $ ++ * ++ * 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_DEVICE_ONLY ++ ++/** @file ++ * This file contains Descriptor DMA support implementation for host mode. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++extern bool microframe_schedule; ++ ++static inline uint8_t frame_list_idx(uint16_t frame) ++{ ++ return (frame & (MAX_FRLIST_EN_NUM - 1)); ++} ++ ++static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx + inc) & ++ (((speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx - inc) & ++ (((speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t max_desc_num(dwc_otg_qh_t * qh) ++{ ++ return (((qh->ep_type == UE_ISOCHRONOUS) ++ && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) ++ ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC); ++} ++static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) ++{ ++ return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) ++ ? ((qh->interval + 8 - 1) / 8) ++ : qh->interval); ++} ++ ++static int desc_list_alloc(dwc_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ qh->desc_list = (dwc_otg_host_dma_desc_t *) ++ DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), ++ &qh->desc_list_dma); ++ ++ if (!qh->desc_list) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__); ++ ++ } ++ ++ dwc_memset(qh->desc_list, 0x00, ++ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); ++ ++ qh->n_bytes = ++ (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh)); ++ ++ if (!qh->n_bytes) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR ++ ("%s: Failed to allocate array for descriptors' size actual values\n", ++ __func__); ++ ++ } ++ return retval; ++ ++} ++ ++static void desc_list_free(dwc_otg_qh_t * qh) ++{ ++ if (qh->desc_list) { ++ DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, ++ qh->desc_list_dma); ++ qh->desc_list = NULL; ++ } ++ ++ if (qh->n_bytes) { ++ DWC_FREE(qh->n_bytes); ++ qh->n_bytes = NULL; ++ } ++} ++ ++static int frame_list_alloc(dwc_otg_hcd_t * hcd) ++{ ++ int retval = 0; ++ if (hcd->frame_list) ++ return 0; ++ ++ hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, ++ &hcd->frame_list_dma); ++ if (!hcd->frame_list) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: Frame List allocation failed\n", __func__); ++ } ++ ++ dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM); ++ ++ return retval; ++} ++ ++static void frame_list_free(dwc_otg_hcd_t * hcd) ++{ ++ if (!hcd->frame_list) ++ return; ++ ++ DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); ++ hcd->frame_list = NULL; ++} ++ ++static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en) ++{ ++ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (hcfg.b.perschedena) { ++ /* already enabled */ ++ return; ++ } ++ ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr, ++ hcd->frame_list_dma); ++ ++ switch (fr_list_en) { ++ case 64: ++ hcfg.b.frlisten = 3; ++ break; ++ case 32: ++ hcfg.b.frlisten = 2; ++ break; ++ case 16: ++ hcfg.b.frlisten = 1; ++ break; ++ case 8: ++ hcfg.b.frlisten = 0; ++ break; ++ default: ++ break; ++ } ++ ++ hcfg.b.perschedena = 1; ++ ++ DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n"); ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++ ++} ++ ++static void per_sched_disable(dwc_otg_hcd_t * hcd) ++{ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (!hcfg.b.perschedena) { ++ /* already disabled */ ++ return; ++ } ++ hcfg.b.perschedena = 0; ++ ++ DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n"); ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/* ++ * Activates/Deactivates FrameList entries for the channel ++ * based on endpoint servicing period. ++ */ ++void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable) ++{ ++ uint16_t i, j, inc; ++ dwc_hc_t *hc = NULL; ++ ++ if (!qh->channel) { ++ DWC_ERROR("qh->channel = %p", qh->channel); ++ return; ++ } ++ ++ if (!hcd) { ++ DWC_ERROR("------hcd = %p", hcd); ++ return; ++ } ++ ++ if (!hcd->frame_list) { ++ DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list); ++ return; ++ } ++ ++ hc = qh->channel; ++ inc = frame_incr_val(qh); ++ if (qh->ep_type == UE_ISOCHRONOUS) ++ i = frame_list_idx(qh->sched_frame); ++ else ++ i = 0; ++ ++ j = i; ++ do { ++ if (enable) ++ hcd->frame_list[j] |= (1 << hc->hc_num); ++ else ++ hcd->frame_list[j] &= ~(1 << hc->hc_num); ++ j = (j + inc) & (MAX_FRLIST_EN_NUM - 1); ++ } ++ while (j != i); ++ if (!enable) ++ return; ++ hc->schinfo = 0; ++ if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) { ++ j = 1; ++ /* TODO - check this */ ++ inc = (8 + qh->interval - 1) / qh->interval; ++ for (i = 0; i < inc; i++) { ++ hc->schinfo |= j; ++ j = j << qh->interval; ++ } ++ } else { ++ hc->schinfo = 0xff; ++ } ++} ++ ++#if 1 ++void dump_frame_list(dwc_otg_hcd_t * hcd) ++{ ++ int i = 0; ++ DWC_PRINTF("--FRAME LIST (hex) --\n"); ++ for (i = 0; i < MAX_FRLIST_EN_NUM; i++) { ++ DWC_PRINTF("%x\t", hcd->frame_list[i]); ++ if (!(i % 8) && i) ++ DWC_PRINTF("\n"); ++ } ++ DWC_PRINTF("\n----\n"); ++ ++} ++#endif ++ ++static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_irqflags_t flags; ++ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); ++ ++ dwc_hc_t *hc = qh->channel; ++ if (dwc_qh_is_non_per(qh)) { ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ if (!microframe_schedule) ++ hcd->non_periodic_channels--; ++ else ++ hcd->available_host_channels++; ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ } else ++ update_frame_list(hcd, qh, 0); ++ ++ /* ++ * The condition is added to prevent double cleanup try in case of device ++ * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb(). ++ */ ++ if (hc->qh) { ++ dwc_otg_hc_cleanup(hcd->core_if, hc); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ hc->qh = NULL; ++ } ++ ++ qh->channel = NULL; ++ qh->ntd = 0; ++ ++ if (qh->desc_list) { ++ dwc_memset(qh->desc_list, 0x00, ++ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); ++ } ++ DWC_SPINLOCK_FREE(channel_lock); ++} ++ ++/** ++ * Initializes a QH structure's Descriptor DMA related members. ++ * Allocates memory for descriptor list. ++ * On first periodic QH, allocates memory for FrameList ++ * and enables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ if (qh->do_split) { ++ DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n"); ++ return -1; ++ } ++ ++ retval = desc_list_alloc(qh); ++ ++ if ((retval == 0) ++ && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { ++ if (!hcd->frame_list) { ++ retval = frame_list_alloc(hcd); ++ /* Enable periodic schedule on first periodic QH */ ++ if (retval == 0) ++ per_sched_enable(hcd, MAX_FRLIST_EN_NUM); ++ } ++ } ++ ++ qh->ntd = 0; ++ ++ return retval; ++} ++ ++/** ++ * Frees descriptor list memory associated with the QH. ++ * If QH is periodic and the last, frees FrameList memory ++ * and disables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ */ ++void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ desc_list_free(qh); ++ ++ /* ++ * Channel still assigned due to some reasons. ++ * Seen on Isoc URB dequeue. Channel halted but no subsequent ++ * ChHalted interrupt to release the channel. Afterwards ++ * when it comes here from endpoint disable routine ++ * channel remains assigned. ++ */ ++ if (qh->channel) ++ release_channel_ddma(hcd, qh); ++ ++ if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) ++ && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) { ++ ++ per_sched_disable(hcd); ++ frame_list_free(hcd); ++ } ++} ++ ++static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx) ++{ ++ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { ++ /* ++ * Descriptor set(8 descriptors) index ++ * which is 8-aligned. ++ */ ++ return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; ++ } else { ++ return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1)); ++ } ++} ++ ++/* ++ * Determine starting frame for Isochronous transfer. ++ * Few frames skipped to prevent race condition with HC. ++ */ ++static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ uint8_t * skip_frames) ++{ ++ uint16_t frame = 0; ++ hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd); ++ ++ /* sched_frame is always frame number(not uFrame) both in FS and HS !! */ ++ ++ /* ++ * skip_frames is used to limit activated descriptors number ++ * to avoid the situation when HC services the last activated ++ * descriptor firstly. ++ * Example for FS: ++ * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor ++ * corresponding to curr_frame+1, the descriptor corresponding to frame 2 ++ * will be fetched. If the number of descriptors is max=64 (or greather) the ++ * list will be fully programmed with Active descriptors and it is possible ++ * case(rare) that the latest descriptor(considering rollback) corresponding ++ * to frame 2 will be serviced first. HS case is more probable because, in fact, ++ * up to 11 uframes(16 in the code) may be skipped. ++ */ ++ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { ++ /* ++ * Consider uframe counter also, to start xfer asap. ++ * If half of the frame elapsed skip 2 frames otherwise ++ * just 1 frame. ++ * Starting descriptor index must be 8-aligned, so ++ * if the current frame is near to complete the next one ++ * is skipped as well. ++ */ ++ ++ if (dwc_micro_frame_num(hcd->frame_number) >= 5) { ++ *skip_frames = 2 * 8; ++ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); ++ } else { ++ *skip_frames = 1 * 8; ++ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); ++ } ++ ++ frame = dwc_full_frame_num(frame); ++ } else { ++ /* ++ * Two frames are skipped for FS - the current and the next. ++ * But for descriptor programming, 1 frame(descriptor) is enough, ++ * see example above. ++ */ ++ *skip_frames = 1; ++ frame = dwc_frame_num_inc(hcd->frame_number, 2); ++ } ++ ++ return frame; ++} ++ ++/* ++ * Calculate initial descriptor index for isochronous transfer ++ * based on scheduled frame. ++ */ ++static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ uint16_t frame = 0, fr_idx, fr_idx_tmp; ++ uint8_t skip_frames = 0; ++ /* ++ * With current ISOC processing algorithm the channel is being ++ * released when no more QTDs in the list(qh->ntd == 0). ++ * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. ++ * ++ * So qh->channel != NULL branch is not used and just not removed from the ++ * source file. It is required for another possible approach which is, ++ * do not disable and release the channel when ISOC session completed, ++ * just move QH to inactive schedule until new QTD arrives. ++ * On new QTD, the QH moved back to 'ready' schedule, ++ * starting frame and therefore starting desc_index are recalculated. ++ * In this case channel is released only on ep_disable. ++ */ ++ ++ /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */ ++ if (qh->channel) { ++ frame = calc_starting_frame(hcd, qh, &skip_frames); ++ /* ++ * Calculate initial descriptor index based on FrameList current bitmap ++ * and servicing period. ++ */ ++ fr_idx_tmp = frame_list_idx(frame); ++ fr_idx = ++ (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - ++ fr_idx_tmp) ++ % frame_incr_val(qh); ++ fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM; ++ } else { ++ qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); ++ fr_idx = frame_list_idx(qh->sched_frame); ++ } ++ ++ qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); ++ ++ return skip_frames; ++} ++ ++#define ISOC_URB_GIVEBACK_ASAP ++ ++#define MAX_ISOC_XFER_SIZE_FS 1023 ++#define MAX_ISOC_XFER_SIZE_HS 3072 ++#define DESCNUM_THRESHOLD 4 ++ ++static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ uint8_t skip_frames) ++{ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, inc, n_desc, ntd_max, max_xfer_size; ++ ++ idx = qh->td_last; ++ inc = qh->interval; ++ n_desc = 0; ++ ++ ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval; ++ if (skip_frames && !qh->channel) ++ ntd_max = ntd_max - skip_frames / qh->interval; ++ ++ max_xfer_size = ++ (qh->dev_speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS : ++ MAX_ISOC_XFER_SIZE_FS; ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ while ((qh->ntd < ntd_max) ++ && (qtd->isoc_frame_index_last < ++ qtd->urb->packet_count)) { ++ ++ dma_desc = &qh->desc_list[idx]; ++ dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t)); ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; ++ ++ if (frame_desc->length > max_xfer_size) ++ qh->n_bytes[idx] = max_xfer_size; ++ else ++ qh->n_bytes[idx] = frame_desc->length; ++ dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx]; ++ dma_desc->status.b_isoc.a = 1; ++ dma_desc->status.b_isoc.sts = 0; ++ ++ dma_desc->buf = qtd->urb->dma + frame_desc->offset; ++ ++ qh->ntd++; ++ ++ qtd->isoc_frame_index_last++; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* ++ * Set IOC for each descriptor corresponding to the ++ * last frame of the URB. ++ */ ++ if (qtd->isoc_frame_index_last == ++ qtd->urb->packet_count) ++ dma_desc->status.b_isoc.ioc = 1; ++ ++#endif ++ idx = desclist_idx_inc(idx, inc, qh->dev_speed); ++ n_desc++; ++ ++ } ++ qtd->in_process = 1; ++ } ++ ++ qh->td_last = idx; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* Set IOC for the last descriptor if descriptor list is full */ ++ if (qh->ntd == ntd_max) { ++ idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++ } ++#else ++ /* ++ * Set IOC bit only for one descriptor. ++ * Always try to be ahead of HW processing, ++ * i.e. on IOC generation driver activates next descriptors but ++ * core continues to process descriptors followed the one with IOC set. ++ */ ++ ++ if (n_desc > DESCNUM_THRESHOLD) { ++ /* ++ * Move IOC "up". Required even if there is only one QTD ++ * in the list, cause QTDs migth continue to be queued, ++ * but during the activation it was only one queued. ++ * Actually more than one QTD might be in the list if this function called ++ * from XferCompletion - QTDs was queued during HW processing of the previous ++ * descriptor chunk. ++ */ ++ idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed); ++ } else { ++ /* ++ * Set the IOC for the latest descriptor ++ * if either number of descriptor is not greather than threshold ++ * or no more new descriptors activated. ++ */ ++ idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ } ++ ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++#endif ++} ++ ++static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ ++ dwc_hc_t *hc; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ dwc_otg_qtd_t *qtd; ++ int num_packets, len, n_desc = 0; ++ ++ hc = qh->channel; ++ ++ /* ++ * Start with hc->xfer_buff initialized in ++ * assign_and_init_hc(), then if SG transfer consists of multiple URBs, ++ * this pointer re-assigned to the buffer of the currently processed QTD. ++ * For non-SG request there is always one QTD active. ++ */ ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ ++ if (n_desc) { ++ /* SG request - more than 1 QTDs */ ++ hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length; ++ hc->xfer_len = qtd->urb->length - qtd->urb->actual_length; ++ } ++ ++ qtd->n_desc = 0; ++ ++ do { ++ dma_desc = &qh->desc_list[n_desc]; ++ len = hc->xfer_len; ++ ++ if (len > MAX_DMA_DESC_SIZE) ++ len = MAX_DMA_DESC_SIZE - hc->max_packet + 1; ++ ++ if (hc->ep_is_in) { ++ if (len > 0) { ++ num_packets = (len + hc->max_packet - 1) / hc->max_packet; ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ /* Always program an integral # of max packets for IN transfers. */ ++ len = num_packets * hc->max_packet; ++ } ++ ++ dma_desc->status.b.n_bytes = len; ++ ++ qh->n_bytes[n_desc] = len; ++ ++ if ((qh->ep_type == UE_CONTROL) ++ && (qtd->control_phase == DWC_OTG_CONTROL_SETUP)) ++ dma_desc->status.b.sup = 1; /* Setup Packet */ ++ ++ dma_desc->status.b.a = 1; /* Active descriptor */ ++ dma_desc->status.b.sts = 0; ++ ++ dma_desc->buf = ++ ((unsigned long)hc->xfer_buff & 0xffffffff); ++ ++ /* ++ * Last descriptor(or single) of IN transfer ++ * with actual size less than MaxPacket. ++ */ ++ if (len > hc->xfer_len) { ++ hc->xfer_len = 0; ++ } else { ++ hc->xfer_buff += len; ++ hc->xfer_len -= len; ++ } ++ ++ qtd->n_desc++; ++ n_desc++; ++ } ++ while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC)); ++ ++ ++ qtd->in_process = 1; ++ ++ if (qh->ep_type == UE_CONTROL) ++ break; ++ ++ if (n_desc == MAX_DMA_DESC_NUM_GENERIC) ++ break; ++ } ++ ++ if (n_desc) { ++ /* Request Transfer Complete interrupt for the last descriptor */ ++ qh->desc_list[n_desc - 1].status.b.ioc = 1; ++ /* End of List indicator */ ++ qh->desc_list[n_desc - 1].status.b.eol = 1; ++ ++ hc->ntd = n_desc; ++ } ++} ++ ++/** ++ * For Control and Bulk endpoints initializes descriptor list ++ * and starts the transfer. ++ * ++ * For Interrupt and Isochronous endpoints initializes descriptor list ++ * then updates FrameList, marking appropriate entries as active. ++ * In case of Isochronous, the starting descriptor index is calculated based ++ * on the scheduled frame, but only on the first transfer descriptor within a session. ++ * Then starts the transfer via enabling the channel. ++ * For Isochronous endpoint the channel is not halted on XferComplete ++ * interrupt so remains assigned to the endpoint(QH) until session is done. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ /* Channel is already assigned */ ++ dwc_hc_t *hc = qh->channel; ++ uint8_t skip_frames = 0; ++ ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case DWC_OTG_EP_TYPE_INTR: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ update_frame_list(hcd, qh, 1); ++ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case DWC_OTG_EP_TYPE_ISOC: ++ ++ if (!qh->ntd) ++ skip_frames = recalc_initial_desc_idx(hcd, qh); ++ ++ init_isoc_dma_desc(hcd, qh, skip_frames); ++ ++ if (!hc->xfer_started) { ++ ++ update_frame_list(hcd, qh, 1); ++ ++ /* ++ * Always set to max, instead of actual size. ++ * Otherwise ntd will be changed with ++ * channel being enabled. Not recommended. ++ * ++ */ ++ hc->ntd = max_desc_num(qh); ++ /* Enable channel only once for ISOC */ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ } ++ ++ break; ++ default: ++ ++ break; ++ } ++} ++ ++static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_otg_qh_t *qh; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, remain; ++ uint8_t urb_compl; ++ ++ qh = hc->qh; ++ idx = qh->td_first; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) ++ qtd->in_process = 0; ++ return; ++ } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || ++ (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) { ++ /* ++ * Channel is halted in these error cases. ++ * Considered as serious issues. ++ * Complete all URBs marking all frames as failed, ++ * irrespective whether some of the descriptors(frames) succeeded or no. ++ * Pass error code to completion routine as well, to ++ * update urb->status, some of class drivers might use it to stop ++ * queing transfer requests. ++ */ ++ int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) ++ ? (-DWC_E_IO) ++ : (-DWC_E_OVERFLOW); ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ for (idx = 0; idx < qtd->urb->packet_count; idx++) { ++ frame_desc = &qtd->urb->iso_descs[idx]; ++ frame_desc->status = err; ++ } ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ ++ if (!qtd->in_process) ++ break; ++ ++ urb_compl = 0; ++ ++ do { ++ ++ dma_desc = &qh->desc_list[idx]; ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0; ++ ++ if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) { ++ /* ++ * XactError or, unable to complete all the transactions ++ * in the scheduled micro-frame/frame, ++ * both indicated by DMA_DESC_STS_PKTERR. ++ */ ++ qtd->urb->error_count++; ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ } else { ++ /* Success */ ++ ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = 0; ++ } ++ ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers here. ++ * The individual frame_desc status are used instead. ++ */ ++ ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ /* ++ * This check is necessary because urb_dequeue can be called ++ * from urb complete callback(sound driver example). ++ * All pending URBs are dequeued there, so no need for ++ * further processing. ++ */ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ return; ++ } ++ ++ urb_compl = 1; ++ ++ } ++ ++ qh->ntd--; ++ ++ /* Stop if IOC requested descriptor reached */ ++ if (dma_desc->status.b_isoc.ioc) { ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ goto stop_scan; ++ } ++ ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ ++ if (urb_compl) ++ break; ++ } ++ while (idx != qh->td_first); ++ } ++stop_scan: ++ qh->td_first = idx; ++} ++ ++uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_host_dma_desc_t * dma_desc, ++ dwc_otg_halt_status_e halt_status, ++ uint32_t n_bytes, uint8_t * xfer_done) ++{ ++ ++ uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0; ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ urb->status = -DWC_E_IO; ++ return 1; ++ } ++ if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) { ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_STALL: ++ urb->status = -DWC_E_PIPE; ++ break; ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ urb->status = -DWC_E_OVERFLOW; ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ urb->status = -DWC_E_PROTOCOL; ++ break; ++ default: ++ DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__, ++ halt_status); ++ break; ++ } ++ return 1; ++ } ++ ++ if (dma_desc->status.b.a == 1) { ++ DWC_DEBUGPL(DBG_HCDV, ++ "Active descriptor encountered on channel %d\n", ++ hc->hc_num); ++ return 0; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) { ++ if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length == urb->length) { ++ /* ++ * For Control Data stage do not set urb->status=0 to prevent ++ * URB callback. Set it when Status phase done. See below. ++ */ ++ *xfer_done = 1; ++ } ++ ++ } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ /* No handling for SETUP stage */ ++ } else { ++ /* BULK and INTR */ ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length == urb->length) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_hcd_urb_t *urb = NULL; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_otg_qh_t *qh; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint32_t n_bytes, n_desc, i; ++ uint8_t failed = 0, xfer_done; ++ ++ n_desc = 0; ++ ++ qh = hc->qh; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ qtd->in_process = 0; ++ } ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ ++ urb = qtd->urb; ++ ++ n_bytes = 0; ++ xfer_done = 0; ++ ++ for (i = 0; i < qtd->n_desc; i++) { ++ dma_desc = &qh->desc_list[n_desc]; ++ ++ n_bytes = qh->n_bytes[n_desc]; ++ ++ failed = ++ update_non_isoc_urb_state_ddma(hcd, hc, qtd, ++ dma_desc, ++ halt_status, n_bytes, ++ &xfer_done); ++ ++ if (failed ++ || (xfer_done ++ && (urb->status != -DWC_E_IN_PROGRESS))) { ++ ++ hcd->fops->complete(hcd, urb->priv, urb, ++ urb->status); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ if (failed) ++ goto stop_scan; ++ } else if (qh->ep_type == UE_CONTROL) { ++ if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) { ++ if (urb->length > 0) { ++ qtd->control_phase = DWC_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ } ++ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); ++ } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { ++ if (xfer_done) { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); ++ } else if (i + 1 == qtd->n_desc) { ++ /* ++ * Last descriptor for Control data stage which is ++ * not completed yet. ++ */ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ } ++ } ++ ++ n_desc++; ++ } ++ ++ } ++ ++stop_scan: ++ ++ if (qh->ep_type != UE_CONTROL) { ++ /* ++ * Resetting the data toggle for bulk ++ * and interrupt endpoints in case of stall. See handle_hc_stall_intr() ++ */ ++ if (halt_status == DWC_OTG_HC_XFER_STALL) ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ else ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ hcint_data_t hcint; ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. It ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ } ++ ++} ++ ++/** ++ * This function is called from interrupt handlers. ++ * Scans the descriptor list, updates URB's status and ++ * calls completion routine for the URB if it's done. ++ * Releases the channel to be used by other transfers. ++ * In case of Isochronous endpoint the channel is not halted until ++ * the end of the session, i.e. QTD list is empty. ++ * If periodic channel released the FrameList is updated accordingly. ++ * ++ * Calls transaction selection routines to activate pending transfers. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param hc Host channel, the transfer is completed on. ++ * @param hc_regs Host channel registers. ++ * @param halt_status Reason the channel is being halted, ++ * or just XferComplete for isochronous transfer ++ */ ++void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ uint8_t continue_isoc_xfer = 0; ++ dwc_otg_transaction_type_e tr_type; ++ dwc_otg_qh_t *qh = hc->qh; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ ++ complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ /* Release the channel if halted or session completed */ ++ if (halt_status != DWC_OTG_HC_XFER_COMPLETE || ++ DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ ++ /* Halt the channel if session completed */ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); ++ } ++ ++ release_channel_ddma(hcd, qh); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* Keep in assigned schedule to continue transfer */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ continue_isoc_xfer = 1; ++ ++ } ++ /** @todo Consider the case when period exceeds FrameList size. ++ * Frame Rollover interrupt should be used. ++ */ ++ } else { ++ /* Scan descriptor list to complete the URB(s), then release the channel */ ++ complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ release_channel_ddma(hcd, qh); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ ++ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule on normal completion */ ++ dwc_otg_hcd_qh_add(hcd, qh); ++ } ++ ++ } ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) { ++ if (continue_isoc_xfer) { ++ if (tr_type == DWC_OTG_TRANSACTION_NONE) { ++ tr_type = DWC_OTG_TRANSACTION_PERIODIC; ++ } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) { ++ tr_type = DWC_OTG_TRANSACTION_ALL; ++ } ++ } ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h +new file mode 100644 +index 0000000..b3dc806 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h +@@ -0,0 +1,412 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $ ++ * $Revision: #12 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ ++ * ++ * 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_DEVICE_ONLY ++#ifndef __DWC_HCD_IF_H__ ++#define __DWC_HCD_IF_H__ ++ ++#include "dwc_otg_core_if.h" ++ ++/** @file ++ * This file defines DWC_OTG HCD Core API. ++ */ ++ ++struct dwc_otg_hcd; ++typedef struct dwc_otg_hcd dwc_otg_hcd_t; ++ ++struct dwc_otg_hcd_urb; ++typedef struct dwc_otg_hcd_urb dwc_otg_hcd_urb_t; ++ ++/** @name HCD Function Driver Callbacks */ ++/** @{ */ ++ ++/** This function is called whenever core switches to host mode. */ ++typedef int (*dwc_otg_hcd_start_cb_t) (dwc_otg_hcd_t * hcd); ++ ++/** This function is called when device has been disconnected */ ++typedef int (*dwc_otg_hcd_disconnect_cb_t) (dwc_otg_hcd_t * hcd); ++ ++/** Wrapper provides this function to HCD to core, so it can get hub information to which device is connected */ ++typedef int (*dwc_otg_hcd_hub_info_from_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle, ++ uint32_t * hub_addr, ++ uint32_t * port_addr); ++/** Via this function HCD core gets device speed */ ++typedef int (*dwc_otg_hcd_speed_from_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle); ++ ++/** This function is called when urb is completed */ ++typedef int (*dwc_otg_hcd_complete_urb_cb_t) (dwc_otg_hcd_t * hcd, ++ void *urb_handle, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int32_t status); ++ ++/** Via this function HCD core gets b_hnp_enable parameter */ ++typedef int (*dwc_otg_hcd_get_b_hnp_enable) (dwc_otg_hcd_t * hcd); ++ ++struct dwc_otg_hcd_function_ops { ++ dwc_otg_hcd_start_cb_t start; ++ dwc_otg_hcd_disconnect_cb_t disconnect; ++ dwc_otg_hcd_hub_info_from_urb_cb_t hub_info; ++ dwc_otg_hcd_speed_from_urb_cb_t speed; ++ dwc_otg_hcd_complete_urb_cb_t complete; ++ dwc_otg_hcd_get_b_hnp_enable get_b_hnp_enable; ++}; ++/** @} */ ++ ++/** @name HCD Core API */ ++/** @{ */ ++/** This function allocates dwc_otg_hcd structure and returns pointer on it. */ ++extern dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void); ++ ++/** This function should be called to initiate HCD Core. ++ * ++ * @param hcd The HCD ++ * @param core_if The DWC_OTG Core ++ * ++ * Returns -DWC_E_NO_MEMORY if no enough memory. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if); ++ ++/** Frees HCD ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_remove(dwc_otg_hcd_t * hcd); ++ ++/** This function should be called on every hardware interrupt. ++ * ++ * @param dwc_otg_hcd The HCD ++ * ++ * Returns non zero if interrupt is handled ++ * Return 0 if interrupt is not handled ++ */ ++extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++ ++/** ++ * Returns private data set by ++ * dwc_otg_hcd_set_priv_data function. ++ * ++ * @param hcd The HCD ++ */ ++extern void *dwc_otg_hcd_get_priv_data(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Set private data. ++ * ++ * @param hcd The HCD ++ * @param priv_data pointer to be stored in private data ++ */ ++extern void dwc_otg_hcd_set_priv_data(dwc_otg_hcd_t * hcd, void *priv_data); ++ ++/** ++ * This function initializes the HCD Core. ++ * ++ * @param hcd The HCD ++ * @param fops The Function Driver Operations data structure containing pointers to all callbacks. ++ * ++ * Returns -DWC_E_NO_DEVICE if Core is currently is in device mode. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, ++ struct dwc_otg_hcd_function_ops *fops); ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Handles hub class-specific requests. ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param typeReq Request Type ++ * @param wValue wValue from control request ++ * @param wIndex wIndex from control request ++ * @param buf data buffer ++ * @param wLength data buffer length ++ * ++ * Returns -DWC_E_INVALID if invalid argument is passed ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, ++ uint16_t typeReq, uint16_t wValue, ++ uint16_t wIndex, uint8_t * buf, ++ uint16_t wLength); ++ ++/** ++ * Returns otg port number. ++ * ++ * @param hcd The HCD ++ */ ++extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Returns OTG version - either 1.3 or 2.0. ++ * ++ * @param core_if The core_if structure pointer ++ */ ++extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Returns 1 if currently core is acting as B host, and 0 otherwise. ++ * ++ * @param hcd The HCD ++ */ ++extern uint32_t dwc_otg_hcd_is_b_host(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Returns current frame number. ++ * ++ * @param hcd The HCD ++ */ ++extern int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Dumps hcd state. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Dump the average frame remaining at SOF. This can be used to ++ * determine average interrupt latency. Frame remaining is also shown for ++ * start transfer and two additional sample points. ++ * Currently this function is not implemented. ++ * ++ * @param hcd The HCD ++ */ ++extern void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd); ++ ++/** ++ * Sends LPM transaction to the local device. ++ * ++ * @param hcd The HCD ++ * @param devaddr Device Address ++ * @param hird Host initiated resume duration ++ * @param bRemoteWake Value of bRemoteWake field in LPM transaction ++ * ++ * Returns negative value if sending LPM transaction was not succeeded. ++ * Returns 0 on success. ++ */ ++extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, ++ uint8_t hird, uint8_t bRemoteWake); ++ ++/* URB interface */ ++ ++/** ++ * Allocates memory for dwc_otg_hcd_urb structure. ++ * Allocated memory should be freed by call of DWC_FREE. ++ * ++ * @param hcd The HCD ++ * @param iso_desc_count Count of ISOC descriptors ++ * @param atomic_alloc Specefies whether to perform atomic allocation. ++ */ ++extern dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, ++ int iso_desc_count, ++ int atomic_alloc); ++ ++/** ++ * Set pipe information in URB. ++ * ++ * @param hcd_urb DWC_OTG URB ++ * @param devaddr Device Address ++ * @param ep_num Endpoint Number ++ * @param ep_type Endpoint Type ++ * @param ep_dir Endpoint Direction ++ * @param mps Max Packet Size ++ */ ++extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb, ++ uint8_t devaddr, uint8_t ep_num, ++ uint8_t ep_type, uint8_t ep_dir, ++ uint16_t mps); ++ ++/* Transfer flags */ ++#define URB_GIVEBACK_ASAP 0x1 ++#define URB_SEND_ZERO_PACKET 0x2 ++ ++/** ++ * Sets dwc_otg_hcd_urb parameters. ++ * ++ * @param urb DWC_OTG URB allocated by dwc_otg_hcd_urb_alloc function. ++ * @param urb_handle Unique handle for request, this will be passed back ++ * to function driver in completion callback. ++ * @param buf The buffer for the data ++ * @param dma The DMA buffer for the data ++ * @param buflen Transfer length ++ * @param sp Buffer for setup data ++ * @param sp_dma DMA address of setup data buffer ++ * @param flags Transfer flags ++ * @param interval Polling interval for interrupt or isochronous transfers. ++ */ ++extern void dwc_otg_hcd_urb_set_params(dwc_otg_hcd_urb_t * urb, ++ void *urb_handle, void *buf, ++ dwc_dma_t dma, uint32_t buflen, void *sp, ++ dwc_dma_t sp_dma, uint32_t flags, ++ uint16_t interval); ++ ++/** Gets status from dwc_otg_hcd_urb ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_status(dwc_otg_hcd_urb_t * dwc_otg_urb); ++ ++/** Gets actual length from dwc_otg_hcd_urb ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb); ++ ++/** Gets error count from dwc_otg_hcd_urb. Only for ISOC URBs ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_error_count(dwc_otg_hcd_urb_t * ++ dwc_otg_urb); ++ ++/** Set ISOC descriptor offset and length ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ * @param offset Offset from beginig of buffer. ++ * @param length Transaction length ++ */ ++extern void dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_hcd_urb_t * dwc_otg_urb, ++ int desc_num, uint32_t offset, ++ uint32_t length); ++ ++/** Get status of ISOC descriptor, specified by desc_num ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, int desc_num); ++ ++/** Get actual length of ISOC descriptor, specified by desc_num ++ * ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param desc_num ISOC descriptor number ++ */ ++extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * ++ dwc_otg_urb, ++ int desc_num); ++ ++/** Queue URB. After transfer is completes, the complete callback will be called with the URB status ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param dwc_otg_urb DWC_OTG URB ++ * @param ep_handle Out parameter for returning endpoint handle ++ * @param atomic_alloc Flag to do atomic allocation if needed ++ * ++ * Returns -DWC_E_NO_DEVICE if no device is connected. ++ * Returns -DWC_E_NO_MEMORY if there is no enough memory. ++ * Returns 0 on success. ++ */ ++extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, ++ void **ep_handle, int atomic_alloc); ++ ++/** De-queue the specified URB ++ * ++ * @param dwc_otg_hcd The HCD ++ * @param dwc_otg_urb DWC_OTG URB ++ */ ++extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd, ++ dwc_otg_hcd_urb_t * dwc_otg_urb); ++ ++/** Frees resources in the DWC_otg controller related to a given endpoint. ++ * Any URBs for the endpoint must already be dequeued. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function ++ * @param retry Number of retries if there are queued transfers. ++ * ++ * Returns -DWC_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, ++ int retry); ++ ++/* Resets the data toggle in qh structure. This function can be called from ++ * usb_clear_halt routine. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function ++ * ++ * Returns -DWC_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle); ++ ++/** Returns 1 if status of specified port is changed and 0 otherwise. ++ * ++ * @param hcd The HCD ++ * @param port Port number ++ */ ++extern int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port); ++ ++/** Call this function to check if bandwidth was allocated for specified endpoint. ++ * Only for ISOC and INTERRUPT endpoints. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern int dwc_otg_hcd_is_bandwidth_allocated(dwc_otg_hcd_t * hcd, ++ void *ep_handle); ++ ++/** Call this function to check if bandwidth was freed for specified endpoint. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern int dwc_otg_hcd_is_bandwidth_freed(dwc_otg_hcd_t * hcd, void *ep_handle); ++ ++/** Returns bandwidth allocated for specified endpoint in microseconds. ++ * Only for ISOC and INTERRUPT endpoints. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle ++ */ ++extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, ++ void *ep_handle); ++ ++/** @} */ ++ ++#endif /* __DWC_HCD_IF_H__ */ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +new file mode 100644 +index 0000000..63c1b55 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -0,0 +1,2106 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ ++ * $Revision: #89 $ ++ * $Date: 2011/10/20 $ ++ * $Change: 1869487 $ ++ * ++ * 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_DEVICE_ONLY ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++extern bool microframe_schedule; ++ ++/** @file ++ * This file contains the implementation of the HCD Interrupt handlers. ++ */ ++ ++/** This function handles interrupts for the HCD. */ ++int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int retval = 0; ++ ++ dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; ++ gintsts_data_t gintsts; ++#ifdef DEBUG ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ ++ //GRAYG: debugging ++ if (NULL == global_regs) { ++ DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p " ++ "core_if=%p\n", ++ dwc_otg_hcd, global_regs); ++ return retval; ++ } ++#endif ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } ++ DWC_SPINLOCK(dwc_otg_hcd->lock); ++ /* Check if HOST Mode */ ++ if (dwc_otg_is_host_mode(core_if)) { ++ gintsts.d32 = dwc_otg_read_core_intr(core_if); ++ if (!gintsts.d32) { ++ DWC_SPINUNLOCK(dwc_otg_hcd->lock); ++ return 0; ++ } ++#ifdef DEBUG ++ /* Don't print debug message in the interrupt handler on SOF */ ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCDI, "\n"); ++#endif ++ ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCDI, ++ "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n", ++ gintsts.d32, core_if); ++#endif ++ ++ if (gintsts.b.sofintr) { ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.rxstsqlvl) { ++ retval |= ++ dwc_otg_hcd_handle_rx_status_q_level_intr ++ (dwc_otg_hcd); ++ } ++ if (gintsts.b.nptxfempty) { ++ retval |= ++ dwc_otg_hcd_handle_np_tx_fifo_empty_intr ++ (dwc_otg_hcd); ++ } ++ if (gintsts.b.i2cintr) { ++ /** @todo Implement i2cintr handler. */ ++ } ++ if (gintsts.b.portintr) { ++ retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.hcintr) { ++ retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); ++ } ++ if (gintsts.b.ptxfempty) { ++ retval |= ++ dwc_otg_hcd_handle_perio_tx_fifo_empty_intr ++ (dwc_otg_hcd); ++ } ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ { ++ DWC_DEBUGPL(DBG_HCDI, ++ "DWC OTG HCD Finished Servicing Interrupts\n"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gintsts)); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gintmsk)); ++ } ++#endif ++ ++#ifdef DEBUG ++#ifndef DEBUG_SOF ++ if (gintsts.d32 != DWC_SOF_INTR_MASK) ++#endif ++ DWC_DEBUGPL(DBG_HCDI, "\n"); ++#endif ++ ++ } ++ DWC_SPINUNLOCK(dwc_otg_hcd->lock); ++ return retval; ++} ++ ++#ifdef DWC_TRACK_MISSED_SOFS ++#warning Compiling code to track missed SOFs ++#define FRAME_NUM_ARRAY_SIZE 1000 ++/** ++ * This function is for debug only. ++ */ ++static inline void track_missed_sofs(uint16_t curr_frame_number) ++{ ++ static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE]; ++ static int frame_num_idx = 0; ++ static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM; ++ static int dumped_frame_num_array = 0; ++ ++ if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) { ++ if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) != ++ curr_frame_number) { ++ frame_num_array[frame_num_idx] = curr_frame_number; ++ last_frame_num_array[frame_num_idx++] = last_frame_num; ++ } ++ } else if (!dumped_frame_num_array) { ++ int i; ++ DWC_PRINTF("Frame Last Frame\n"); ++ DWC_PRINTF("----- ----------\n"); ++ for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) { ++ DWC_PRINTF("0x%04x 0x%04x\n", ++ frame_num_array[i], last_frame_num_array[i]); ++ } ++ dumped_frame_num_array = 1; ++ } ++ last_frame_num = curr_frame_number; ++} ++#endif ++ ++/** ++ * Handles the start-of-frame interrupt in host mode. Non-periodic ++ * transactions may be queued to the DWC_otg controller for the current ++ * (micro)frame. Periodic transactions may be queued to the controller for the ++ * next (micro)frame. ++ */ ++int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) ++{ ++ hfnum_data_t hfnum; ++ dwc_list_link_t *qh_entry; ++ dwc_otg_qh_t *qh; ++ dwc_otg_transaction_type_e tr_type; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ ++ hfnum.d32 = ++ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); ++ ++#ifdef DEBUG_SOF ++ DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); ++#endif ++ hcd->frame_number = hfnum.b.frnum; ++ ++#ifdef DEBUG ++ hcd->frrem_accum += hfnum.b.frrem; ++ hcd->frrem_samples++; ++#endif ++ ++#ifdef DWC_TRACK_MISSED_SOFS ++ track_missed_sofs(hcd->frame_number); ++#endif ++ /* Determine whether any periodic QHs should be executed. */ ++ qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive); ++ while (qh_entry != &hcd->periodic_sched_inactive) { ++ qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry); ++ qh_entry = qh_entry->next; ++ if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { ++ /* ++ * Move QH to the ready list to be executed next ++ * (micro)frame. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, ++ &qh->qh_list_entry); ++ } ++ } ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ ++ /* Clear interrupt */ ++ gintsts.b.sofintr = 1; ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** Handles the Rx Status Queue Level Interrupt, which indicates that there is at ++ * least one packet in the Rx FIFO. The packets are moved from the FIFO to ++ * memory if the DWC_otg controller is operating in Slave mode. */ ++int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ host_grxsts_data_t grxsts; ++ dwc_hc_t *hc = NULL; ++ ++ DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); ++ ++ grxsts.d32 = ++ DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); ++ ++ hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; ++ if (!hc) { ++ DWC_ERROR("Unable to get corresponding channel\n"); ++ return 0; ++ } ++ ++ /* Packet Status */ ++ DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); ++ DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt); ++ DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid, ++ hc->data_pid_start); ++ DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts); ++ ++ switch (grxsts.b.pktsts) { ++ case DWC_GRXSTS_PKTSTS_IN: ++ /* Read the data into the host buffer. */ ++ if (grxsts.b.bcnt > 0) { ++ dwc_otg_read_packet(dwc_otg_hcd->core_if, ++ hc->xfer_buff, grxsts.b.bcnt); ++ ++ /* Update the HC fields for the next packet received. */ ++ hc->xfer_count += grxsts.b.bcnt; ++ hc->xfer_buff += grxsts.b.bcnt; ++ } ++ ++ case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: ++ case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR: ++ case DWC_GRXSTS_PKTSTS_CH_HALTED: ++ /* Handled in interrupt, just ignore data */ ++ break; ++ default: ++ DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n", ++ grxsts.b.pktsts); ++ break; ++ } ++ ++ return 1; ++} ++ ++/** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More ++ * data packets may be written to the FIFO for OUT transfers. More requests ++ * may be written to the non-periodic request queue for IN transfers. This ++ * interrupt is enabled only in Slave mode. */ ++int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n"); ++ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, ++ DWC_OTG_TRANSACTION_NON_PERIODIC); ++ return 1; ++} ++ ++/** This interrupt occurs when the periodic Tx FIFO is half-empty. More data ++ * packets may be written to the FIFO for OUT transfers. More requests may be ++ * written to the periodic request queue for IN transfers. This interrupt is ++ * enabled only in Slave mode. */ ++int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n"); ++ dwc_otg_hcd_queue_transactions(dwc_otg_hcd, ++ DWC_OTG_TRANSACTION_PERIODIC); ++ return 1; ++} ++ ++/** There are multiple conditions that can cause a port interrupt. This function ++ * determines which interrupt conditions have occurred and handles them ++ * appropriately. */ ++int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int retval = 0; ++ hprt0_data_t hprt0; ++ hprt0_data_t hprt0_modify; ++ ++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ ++ /* Clear appropriate bits in HPRT0 to clear the interrupt bit in ++ * GINTSTS */ ++ ++ hprt0_modify.b.prtena = 0; ++ hprt0_modify.b.prtconndet = 0; ++ hprt0_modify.b.prtenchng = 0; ++ hprt0_modify.b.prtovrcurrchng = 0; ++ ++ /* Port Connect Detected ++ * Set flag and clear if detected */ ++ if (dwc_otg_hcd->core_if->hibernation_suspend == 1) { ++ // Dont modify port status if we are in hibernation state ++ hprt0_modify.b.prtconndet = 1; ++ hprt0_modify.b.prtenchng = 1; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ return retval; ++ } ++ ++ if (hprt0.b.prtconndet) { ++ /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */ ++ if (dwc_otg_hcd->core_if->adp_enable && ++ dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) { ++ DWC_PRINTF("PORT CONNECT DETECTED ----------------\n"); ++ DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer); ++ dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ /* TODO - check if this is required, as ++ * host initialization was already performed ++ * after initial ADP probing ++ */ ++ /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ dwc_otg_core_init(dwc_otg_hcd->core_if); ++ dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if); ++ cil_hcd_start(dwc_otg_hcd->core_if);*/ ++ } else { ++ ++ DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " ++ "Port Connect Detected--\n", hprt0.d32); ++ dwc_otg_hcd->flags.b.port_connect_status_change = 1; ++ dwc_otg_hcd->flags.b.port_connect_status = 1; ++ hprt0_modify.b.prtconndet = 1; ++ ++ /* B-Device has connected, Delete the connection timer. */ ++ DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer); ++ } ++ /* The Hub driver asserts a reset when it sees port connect ++ * status change flag */ ++ retval |= 1; ++ } ++ ++ /* Port Enable Changed ++ * Clear if detected - Set internal flag if disabled */ ++ if (hprt0.b.prtenchng) { ++ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Enable Changed--\n", hprt0.d32); ++ hprt0_modify.b.prtenchng = 1; ++ if (hprt0.b.prtena == 1) { ++ hfir_data_t hfir; ++ int do_reset = 0; ++ dwc_otg_core_params_t *params = ++ dwc_otg_hcd->core_if->core_params; ++ dwc_otg_core_global_regs_t *global_regs = ++ dwc_otg_hcd->core_if->core_global_regs; ++ dwc_otg_host_if_t *host_if = ++ dwc_otg_hcd->core_if->host_if; ++ ++ /* Every time when port enables calculate ++ * HFIR.FrInterval ++ */ ++ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if); ++ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); ++ ++ /* Check if we need to adjust the PHY clock speed for ++ * low power and adjust it */ ++ if (params->host_support_fs_ls_low_power) { ++ gusbcfg_data_t usbcfg; ++ ++ usbcfg.d32 = ++ DWC_READ_REG32(&global_regs->gusbcfg); ++ ++ if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED ++ || hprt0.b.prtspd == ++ DWC_HPRT0_PRTSPD_FULL_SPEED) { ++ /* ++ * Low power ++ */ ++ hcfg_data_t hcfg; ++ if (usbcfg.b.phylpwrclksel == 0) { ++ /* Set PHY low power clock select for FS/LS devices */ ++ usbcfg.b.phylpwrclksel = 1; ++ DWC_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ ++ hcfg.d32 = ++ DWC_READ_REG32 ++ (&host_if->host_global_regs->hcfg); ++ ++ if (hprt0.b.prtspd == ++ DWC_HPRT0_PRTSPD_LOW_SPEED ++ && params->host_ls_low_power_phy_clk ++ == ++ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) ++ { ++ /* 6 MHZ */ ++ DWC_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 6 MHz (Low Power)\n"); ++ if (hcfg.b.fslspclksel != ++ DWC_HCFG_6_MHZ) { ++ hcfg.b.fslspclksel = ++ DWC_HCFG_6_MHZ; ++ DWC_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } else { ++ /* 48 MHZ */ ++ DWC_DEBUGPL(DBG_CIL, ++ "FS_PHY programming HCFG to 48 MHz ()\n"); ++ if (hcfg.b.fslspclksel != ++ DWC_HCFG_48_MHZ) { ++ hcfg.b.fslspclksel = ++ DWC_HCFG_48_MHZ; ++ DWC_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ do_reset = 1; ++ } ++ } ++ } else { ++ /* ++ * Not low power ++ */ ++ if (usbcfg.b.phylpwrclksel == 1) { ++ usbcfg.b.phylpwrclksel = 0; ++ DWC_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); ++ do_reset = 1; ++ } ++ } ++ ++ if (do_reset) { ++ DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet); ++ } ++ } ++ ++ if (!do_reset) { ++ /* Port has been enabled set the reset change flag */ ++ dwc_otg_hcd->flags.b.port_reset_change = 1; ++ } ++ } else { ++ dwc_otg_hcd->flags.b.port_enable_change = 1; ++ } ++ retval |= 1; ++ } ++ ++ /** Overcurrent Change Interrupt */ ++ if (hprt0.b.prtovrcurrchng) { ++ DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x " ++ "Port Overcurrent Changed--\n", hprt0.d32); ++ dwc_otg_hcd->flags.b.port_over_current_change = 1; ++ hprt0_modify.b.prtovrcurrchng = 1; ++ retval |= 1; ++ } ++ ++ /* Clear Port Interrupts */ ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ ++ return retval; ++} ++ ++/** This interrupt indicates that one or more host channels has a pending ++ * interrupt. There are multiple conditions that can cause each host channel ++ * interrupt. This function determines which conditions have occurred for each ++ * host channel interrupt and handles them appropriately. */ ++int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ int i; ++ int retval = 0; ++ haint_data_t haint; ++ ++ /* Clear appropriate bits in HCINTn to clear the interrupt bit in ++ * GINTSTS */ ++ ++ haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); ++ ++ for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { ++ if (haint.b2.chint & (1 << i)) { ++ retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); ++ } ++ } ++ ++ return retval; ++} ++ ++/** ++ * Gets the actual length of a transfer after the transfer halts. _halt_status ++ * holds the reason for the halt. ++ * ++ * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE, ++ * *short_read is set to 1 upon return if less than the requested ++ * number of bytes were transferred. Otherwise, *short_read is set to 0 upon ++ * return. short_read may also be NULL on entry, in which case it remains ++ * unchanged. ++ */ ++static uint32_t get_actual_xfer_length(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status, ++ int *short_read) ++{ ++ hctsiz_data_t hctsiz; ++ uint32_t length; ++ ++ if (short_read != NULL) { ++ *short_read = 0; ++ } ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ if (hc->ep_is_in) { ++ length = hc->xfer_len - hctsiz.b.xfersize; ++ if (short_read != NULL) { ++ *short_read = (hctsiz.b.xfersize != 0); ++ } ++ } else if (hc->qh->do_split) { ++ length = qtd->ssplit_out_xfer_count; ++ } else { ++ length = hc->xfer_len; ++ } ++ } else { ++ /* ++ * Must use the hctsiz.pktcnt field to determine how much data ++ * has been transferred. This field reflects the number of ++ * packets that have been transferred via the USB. This is ++ * always an integral number of packets if the transfer was ++ * halted before its normal completion. (Can't use the ++ * hctsiz.xfersize field because that reflects the number of ++ * bytes transferred via the AHB, not the USB). ++ */ ++ length = ++ (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet; ++ } ++ ++ return length; ++} ++ ++/** ++ * Updates the state of the URB after a Transfer Complete interrupt on the ++ * host channel. Updates the actual_length field of the URB based on the ++ * number of bytes transferred via the host channel. Sets the URB status ++ * if the data transfer is finished. ++ * ++ * @return 1 if the data transfer specified by the URB is completely finished, ++ * 0 otherwise. ++ */ ++static int update_urb_state_xfer_comp(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_hcd_urb_t * urb, ++ dwc_otg_qtd_t * qtd) ++{ ++ int xfer_done = 0; ++ int short_read = 0; ++ ++ int xfer_length; ++ ++ xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE, ++ &short_read); ++ ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && xfer_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ xfer_length); ++ } ++ ++ urb->actual_length += xfer_length; ++ ++ if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) && ++ (urb->flags & URB_SEND_ZERO_PACKET) ++ && (urb->actual_length == urb->length) ++ && !(urb->length % hc->max_packet)) { ++ xfer_done = 0; ++ } else if (short_read || urb->actual_length >= urb->length) { ++ xfer_done = 1; ++ urb->status = 0; ++ } ++ ++#ifdef DEBUG ++ { ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len); ++ DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", ++ hctsiz.b.xfersize); ++ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->length); ++ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n", ++ short_read, xfer_done); ++ } ++#endif ++ ++ return xfer_done; ++} ++ ++/* ++ * Save the starting data toggle for the next transfer. The data toggle is ++ * saved in the QH for non-control transfers and it's saved in the QTD for ++ * control transfers. ++ */ ++void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd) ++{ ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ ++ if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { ++ dwc_otg_qh_t *qh = hc->qh; ++ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ } else { ++ qh->data_toggle = DWC_OTG_HC_PID_DATA1; ++ } ++ } else { ++ if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) { ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA0; ++ } else { ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; ++ } ++ } ++} ++ ++/** ++ * Updates the state of an Isochronous URB when the transfer is stopped for ++ * any reason. The fields of the current entry in the frame descriptor array ++ * are set based on the transfer state and the input _halt_status. Completes ++ * the Isochronous URB if all the URB frames have been completed. ++ * ++ * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be ++ * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE. ++ */ ++static dwc_otg_halt_status_e ++update_isoc_urb_state(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ dwc_otg_halt_status_e ret_val = halt_status; ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ ++ frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_COMPLETE: ++ frame_desc->status = 0; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ hc->qh->dw_align_buf, frame_desc->actual_length); ++ } ++ ++ break; ++ case DWC_OTG_HC_XFER_FRAME_OVERRUN: ++ urb->error_count++; ++ if (hc->ep_is_in) { ++ frame_desc->status = -DWC_E_NO_STREAM_RES; ++ } else { ++ frame_desc->status = -DWC_E_COMMUNICATION; ++ } ++ frame_desc->actual_length = 0; ++ break; ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ urb->error_count++; ++ frame_desc->status = -DWC_E_OVERFLOW; ++ /* Don't need to update actual_length in this case. */ ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ urb->error_count++; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ frame_desc->actual_length = ++ get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); ++ ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ hc->qh->dw_align_buf, frame_desc->actual_length); ++ } ++ /* Skip whole frame */ ++ if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && ++ hc->ep_is_in && hcd->core_if->dma_enable) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ } ++ ++ break; ++ default: ++ DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status); ++ break; ++ } ++ if (++qtd->isoc_frame_index == urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers. ++ * The individual frame_desc statuses are used instead. ++ */ ++ hcd->fops->complete(hcd, urb->priv, urb, 0); ++ ret_val = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ ret_val = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ return ret_val; ++} ++ ++/** ++ * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic ++ * QHs, removes the QH from the active non-periodic schedule. If any QTDs are ++ * still linked to the QH, the QH is added to the end of the inactive ++ * non-periodic schedule. For periodic QHs, removes the QH from the periodic ++ * schedule if no more QTDs are linked to the QH. ++ */ ++static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd) ++{ ++ int continue_split = 0; ++ dwc_otg_qtd_t *qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd); ++ ++ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); ++ ++ if (qtd->complete_split) { ++ continue_split = 1; ++ } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID || ++ qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) { ++ continue_split = 1; ++ } ++ ++ if (free_qtd) { ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ continue_split = 0; ++ } ++ ++ qh->channel = NULL; ++ dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split); ++} ++ ++/** ++ * Releases a host channel for use by other transfers. Attempts to select and ++ * queue more transactions since at least one host channel is available. ++ * ++ * @param hcd The HCD state structure. ++ * @param hc The host channel to release. ++ * @param qtd The QTD associated with the host channel. This QTD may be freed ++ * if the transfer is complete or an error has occurred. ++ * @param halt_status Reason the channel is being released. This status ++ * determines the actions taken by this function. ++ */ ++static void release_channel(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_transaction_type_e tr_type; ++ int free_qtd; ++ dwc_irqflags_t flags; ++ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); ++ ++ DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", ++ __func__, hc->hc_num, halt_status, hc->xfer_len); ++ ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_URB_COMPLETE: ++ free_qtd = 1; ++ break; ++ case DWC_OTG_HC_XFER_AHB_ERR: ++ case DWC_OTG_HC_XFER_STALL: ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ free_qtd = 1; ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ if (qtd->error_count >= 3) { ++ DWC_DEBUGPL(DBG_HCDV, ++ " Complete URB with transaction error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -DWC_E_PROTOCOL; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_PROTOCOL); ++ } else { ++ free_qtd = 0; ++ } ++ break; ++ case DWC_OTG_HC_XFER_URB_DEQUEUE: ++ /* ++ * The QTD has already been removed and the QH has been ++ * deactivated. Don't want to do anything except release the ++ * host channel and try to queue more transfers. ++ */ ++ goto cleanup; ++ case DWC_OTG_HC_XFER_NO_HALT_STATUS: ++ free_qtd = 0; ++ break; ++ case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE: ++ DWC_DEBUGPL(DBG_HCDV, ++ " Complete URB with I/O error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -DWC_E_IO; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_IO); ++ break; ++ default: ++ free_qtd = 0; ++ break; ++ } ++ ++ deactivate_qh(hcd, hc->qh, free_qtd); ++ ++cleanup: ++ /* ++ * Release the host channel for use by other transfers. The cleanup ++ * function clears the channel interrupt enables and conditions, so ++ * there's no need to clear the Channel Halted interrupt separately. ++ */ ++ dwc_otg_hc_cleanup(hcd->core_if, hc); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ ++ if (!microframe_schedule) { ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hcd->non_periodic_channels--; ++ break; ++ ++ default: ++ /* ++ * Don't release reservations for periodic channels here. ++ * That's done when a periodic transfer is descheduled (i.e. ++ * when the QH is removed from the periodic schedule). ++ */ ++ break; ++ } ++ } else { ++ ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ hcd->available_host_channels++; ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ } ++ ++ /* Try to queue more transfers now that there's a free channel. */ ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++ DWC_SPINLOCK_FREE(channel_lock); ++} ++ ++/** ++ * Halts a host channel. If the channel cannot be halted immediately because ++ * the request queue is full, this function ensures that the FIFO empty ++ * interrupt for the appropriate queue is enabled so that the halt request can ++ * be queued when there is space in the request queue. ++ * ++ * This function may also be called in DMA mode. In that case, the channel is ++ * simply released since the core always halts the channel automatically in ++ * DMA mode. ++ */ ++static void halt_channel(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status) ++{ ++ if (hcd->core_if->dma_enable) { ++ release_channel(hcd, hc, qtd, halt_status); ++ return; ++ } ++ ++ /* Slave mode processing... */ ++ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); ++ ++ if (hc->halt_on_queue) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ dwc_otg_core_global_regs_t *global_regs; ++ global_regs = hcd->core_if->core_global_regs; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK) { ++ /* ++ * Make sure the Non-periodic Tx FIFO empty interrupt ++ * is enabled so that the non-periodic schedule will ++ * be processed. ++ */ ++ gintmsk.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } else { ++ /* ++ * Move the QH from the periodic queued schedule to ++ * the periodic assigned schedule. This allows the ++ * halt to be queued when the periodic schedule is ++ * processed. ++ */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &hc->qh->qh_list_entry); ++ ++ /* ++ * Make sure the Periodic Tx FIFO Empty interrupt is ++ * enabled so that the periodic schedule will be ++ * processed. ++ */ ++ gintmsk.b.ptxfempty = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); ++ } ++ } ++} ++ ++/** ++ * Performs common cleanup for non-periodic transfers after a Transfer ++ * Complete interrupt. This function should be called after any endpoint type ++ * specific handling is finished to release the host channel. ++ */ ++static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ hcint_data_t hcint; ++ ++ qtd->error_count = 0; ++ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. This ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ hc->qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ /* ++ * Always halt and release the host channel to make it available for ++ * more transfers. There may still be more phases for a control ++ * transfer or more data packets for a bulk transfer at this point, ++ * but the host channel is still halted. A channel will be reassigned ++ * to the transfer when the non-periodic schedule is processed after ++ * the channel is released. This allows transactions to be queued ++ * properly via dwc_otg_hcd_queue_transactions, which also enables the ++ * Tx FIFO Empty interrupt if necessary. ++ */ ++ if (hc->ep_is_in) { ++ /* ++ * IN transfers in Slave mode require an explicit disable to ++ * halt the channel. (In DMA mode, this call simply releases ++ * the channel.) ++ */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* ++ * The channel is automatically disabled by the core for OUT ++ * transfers in Slave mode. ++ */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++/** ++ * Performs common cleanup for periodic transfers after a Transfer Complete ++ * interrupt. This function should be called after any endpoint type specific ++ * handling is finished to release the host channel. ++ */ ++static void complete_periodic_xfer(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ hctsiz_data_t hctsiz; ++ qtd->error_count = 0; ++ ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { ++ /* Core halts channel in these cases. */ ++ release_channel(hcd, hc, qtd, halt_status); ++ } else { ++ /* Flush any outstanding requests from the Tx queue. */ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++} ++ ++static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ uint32_t len; ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ ++ len = get_actual_xfer_length(hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE, NULL); ++ ++ if (!len) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ return 0; ++ } ++ frame_desc->actual_length += len; ++ ++ if (hc->align_buff && len) ++ dwc_memcpy(qtd->urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset, hc->qh->dw_align_buf, len); ++ qtd->isoc_split_offset += len; ++ ++ if (frame_desc->length == frame_desc->actual_length) { ++ frame_desc->status = 0; ++ qtd->isoc_frame_index++; ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ } ++ ++ if (qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } else { ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ } ++ ++ return 1; /* Indicates that channel released */ ++} ++ ++/** ++ * Handles a host channel Transfer Complete interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ int urb_xfer_done; ++ dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "Transfer Complete--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ if (pipe_type == UE_ISOCHRONOUS) { ++ /* Do not disable the interrupt, just clear it */ ++ clear_hc_int(hc_regs, xfercomp); ++ return 1; ++ } ++ goto handle_xfercomp_done; ++ } ++ ++ /* ++ * Handle xfer complete on CSPLIT. ++ */ ++ ++ if (hc->qh->do_split) { ++ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in ++ && hcd->core_if->dma_enable) { ++ if (qtd->complete_split ++ && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, ++ qtd)) ++ goto handle_xfercomp_done; ++ } else { ++ qtd->complete_split = 0; ++ } ++ } ++ ++ /* Update the QTD and URB states. */ ++ switch (pipe_type) { ++ case UE_CONTROL: ++ switch (qtd->control_phase) { ++ case DWC_OTG_CONTROL_SETUP: ++ if (urb->length > 0) { ++ qtd->control_phase = DWC_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ } ++ DWC_DEBUGPL(DBG_HCDV, ++ " Control setup transaction done\n"); ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ break; ++ case DWC_OTG_CONTROL_DATA:{ ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, ++ qtd); ++ if (urb_xfer_done) { ++ qtd->control_phase = ++ DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, ++ " Control data transfer done\n"); ++ } else { ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ break; ++ } ++ case DWC_OTG_CONTROL_STATUS: ++ DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n"); ++ if (urb->status == -DWC_E_IN_PROGRESS) { ++ urb->status = 0; ++ } ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ break; ++ } ++ ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_BULK: ++ DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_INTERRUPT: ++ DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ ++ /* ++ * Interrupt URB is done on the first transfer complete ++ * interrupt. ++ */ ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ case UE_ISOCHRONOUS: ++ DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); ++ if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) { ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE); ++ } ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); ++ break; ++ } ++ ++handle_xfercomp_done: ++ disable_hc_int(hc_regs, xfercompl); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel STALL interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ ++ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ "STALL Received--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL); ++ goto handle_stall_done; ++ } ++ ++ if (pipe_type == UE_CONTROL) { ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE); ++ } ++ ++ if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) { ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE); ++ /* ++ * USB protocol requires resetting the data toggle for bulk ++ * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT) ++ * setup command is issued to the endpoint. Anticipate the ++ * CLEAR_FEATURE command since a STALL has occurred and reset ++ * the data toggle now. ++ */ ++ hc->qh->data_toggle = 0; ++ } ++ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL); ++ ++handle_stall_done: ++ disable_hc_int(hc_regs, stall); ++ ++ return 1; ++} ++ ++/* ++ * Updates the state of the URB when a transfer has been stopped due to an ++ * abnormal condition before the transfer completes. Modifies the ++ * actual_length field of the URB to reflect the number of bytes that have ++ * actually been transferred via the host channel. ++ */ ++static void update_urb_state_xfer_intr(dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_hcd_urb_t * urb, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_halt_status_e halt_status) ++{ ++ uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd, ++ halt_status, NULL); ++ /* non DWORD-aligned buffer case handling. */ ++ if (hc->align_buff && bytes_transferred && hc->ep_is_in) { ++ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ bytes_transferred); ++ } ++ ++ urb->actual_length += bytes_transferred; ++ ++#ifdef DEBUG ++ { ++ hctsiz_data_t hctsiz; ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", ++ __func__, (hc->ep_is_in ? "IN" : "OUT"), ++ hc->hc_num); ++ DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n", ++ hc->start_pkt_count); ++ DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt); ++ DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet); ++ DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n", ++ bytes_transferred); ++ DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", ++ urb->actual_length); ++ DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n", ++ urb->length); ++ } ++#endif ++} ++ ++/** ++ * Handles a host channel NAK interrupt. This handler may be called in either ++ * DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "NAK Received--\n", hc->hc_num); ++ ++ /* ++ * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and ++ * interrupt. Re-start the SSPLIT transfer. ++ */ ++ if (hc->do_split) { ++ if (hc->complete_split) { ++ qtd->error_count = 0; ++ } ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ goto handle_nak_done; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ if (hcd->core_if->dma_enable && hc->ep_is_in) { ++ /* ++ * NAK interrupts are enabled on bulk/control IN ++ * transfers in DMA mode for the sole purpose of ++ * resetting the error count after a transaction error ++ * occurs. The core will continue transferring data. ++ */ ++ qtd->error_count = 0; ++ goto handle_nak_done; ++ } ++ ++ /* ++ * NAK interrupts normally occur during OUT transfers in DMA ++ * or Slave mode. For IN transfers, more requests will be ++ * queued as request queue space is available. ++ */ ++ qtd->error_count = 0; ++ ++ if (!hc->qh->ping_state) { ++ update_urb_state_xfer_intr(hc, hc_regs, ++ qtd->urb, qtd, ++ DWC_OTG_HC_XFER_NAK); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH) ++ hc->qh->ping_state = 1; ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will ++ * start/continue. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ break; ++ case UE_INTERRUPT: ++ qtd->error_count = 0; ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); ++ break; ++ case UE_ISOCHRONOUS: ++ /* Should never get called for isochronous transfers. */ ++ DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n"); ++ break; ++ } ++ ++handle_nak_done: ++ disable_hc_int(hc_regs, nak); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel ACK interrupt. This interrupt is enabled when ++ * performing the PING protocol in Slave mode, when errors occur during ++ * either Slave mode or DMA mode, and during Start Split transactions. ++ */ ++static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "ACK Received--\n", hc->hc_num); ++ ++ if (hc->do_split) { ++ /* ++ * Handle ACK on SSPLIT. ++ * ACK should not occur in CSPLIT. ++ */ ++ if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) { ++ qtd->ssplit_out_xfer_count = hc->xfer_len; ++ } ++ if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) { ++ /* Don't need complete for isochronous out transfers. */ ++ qtd->complete_split = 1; ++ } ++ ++ /* ISOC OUT */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { ++ switch (hc->xact_pos) { ++ case DWC_HCSPLIT_XACTPOS_ALL: ++ break; ++ case DWC_HCSPLIT_XACTPOS_END: ++ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ break; ++ case DWC_HCSPLIT_XACTPOS_BEGIN: ++ case DWC_HCSPLIT_XACTPOS_MID: ++ /* ++ * For BEGIN or MID, calculate the length for ++ * the next microframe to determine the correct ++ * SSPLIT token, either MID or END. ++ */ ++ { ++ struct dwc_otg_hcd_iso_packet_desc ++ *frame_desc; ++ ++ frame_desc = ++ &qtd->urb-> ++ iso_descs[qtd->isoc_frame_index]; ++ qtd->isoc_split_offset += 188; ++ ++ if ((frame_desc->length - ++ qtd->isoc_split_offset) <= 188) { ++ qtd->isoc_split_pos = ++ DWC_HCSPLIT_XACTPOS_END; ++ } else { ++ qtd->isoc_split_pos = ++ DWC_HCSPLIT_XACTPOS_MID; ++ } ++ ++ } ++ break; ++ } ++ } else { ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); ++ } ++ } else { ++ qtd->error_count = 0; ++ ++ if (hc->qh->ping_state) { ++ hc->qh->ping_state = 0; ++ /* ++ * Halt the channel so the transfer can be re-started ++ * from the appropriate point. This only happens in ++ * Slave mode. In DMA mode, the ping_state is cleared ++ * when the transfer is started because the core ++ * automatically executes the PING, then the transfer. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); ++ } ++ } ++ ++ /* ++ * If the ACK occurred when _not_ in the PING state, let the channel ++ * continue transferring data after clearing the error count. ++ */ ++ ++ disable_hc_int(hc_regs, ack); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel NYET interrupt. This interrupt should only occur on ++ * Bulk and Control OUT endpoints and for complete split transactions. If a ++ * NYET occurs at the same time as a Transfer Complete interrupt, it is ++ * handled in the xfercomp interrupt handler, not here. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "NYET Received--\n", hc->hc_num); ++ ++ /* ++ * NYET on CSPLIT ++ * re-do the CSPLIT immediately on non-periodic ++ */ ++ if (hc->do_split && hc->complete_split) { ++ if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ && hcd->core_if->dma_enable) { ++ qtd->complete_split = 0; ++ qtd->isoc_split_offset = 0; ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); ++ } ++ else ++ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); ++ goto handle_nyet_done; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ int frnum = dwc_otg_hcd_get_frame_number(hcd); ++ ++ if (dwc_full_frame_num(frnum) != ++ dwc_full_frame_num(hc->qh->sched_frame)) { ++ /* ++ * No longer in the same full speed frame. ++ * Treat this as a transaction error. ++ */ ++#if 0 ++ /** @todo Fix system performance so this can ++ * be treated as an error. Right now complete ++ * splits cannot be scheduled precisely enough ++ * due to other system activity, so this error ++ * occurs regularly in Slave mode. ++ */ ++ qtd->error_count++; ++#endif ++ qtd->complete_split = 0; ++ halt_channel(hcd, hc, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ /** @todo add support for isoc release */ ++ goto handle_nyet_done; ++ } ++ } ++ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); ++ goto handle_nyet_done; ++ } ++ ++ hc->qh->ping_state = 1; ++ qtd->error_count = 0; ++ ++ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, ++ DWC_OTG_HC_XFER_NYET); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ ++ /* ++ * Halt the channel and re-start the transfer so the PING ++ * protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); ++ ++handle_nyet_done: ++ disable_hc_int(hc_regs, nyet); ++ return 1; ++} ++ ++/** ++ * Handles a host channel babble interrupt. This handler may be called in ++ * either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "Babble Error--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_BABBLE_ERR); ++ goto handle_babble_done; ++ } ++ ++ if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_OVERFLOW); ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR); ++ } else { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_BABBLE_ERR); ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ ++handle_babble_done: ++ disable_hc_int(hc_regs, bblerr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel AHB error interrupt. This handler is only called in ++ * DMA mode. ++ */ ++static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcchar_data_t hcchar; ++ hcsplt_data_t hcsplt; ++ hctsiz_data_t hctsiz; ++ uint32_t hcdma; ++ char *pipetype, *speed; ++ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "AHB Error--\n", hc->hc_num); ++ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcdma = DWC_READ_REG32(&hc_regs->hcdma); ++ ++ DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); ++ DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); ++ DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma); ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n"); ++ DWC_ERROR(" Device address: %d\n", ++ dwc_otg_hcd_get_dev_addr(&urb->pipe_info)); ++ DWC_ERROR(" Endpoint: %d, %s\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), ++ (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT")); ++ ++ switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { ++ case UE_CONTROL: ++ pipetype = "CONTROL"; ++ break; ++ case UE_BULK: ++ pipetype = "BULK"; ++ break; ++ case UE_INTERRUPT: ++ pipetype = "INTERRUPT"; ++ break; ++ case UE_ISOCHRONOUS: ++ pipetype = "ISOCHRONOUS"; ++ break; ++ default: ++ pipetype = "UNKNOWN"; ++ break; ++ } ++ ++ DWC_ERROR(" Endpoint type: %s\n", pipetype); ++ ++ switch (hc->speed) { ++ case DWC_OTG_EP_SPEED_HIGH: ++ speed = "HIGH"; ++ break; ++ case DWC_OTG_EP_SPEED_FULL: ++ speed = "FULL"; ++ break; ++ case DWC_OTG_EP_SPEED_LOW: ++ speed = "LOW"; ++ break; ++ default: ++ speed = "UNKNOWN"; ++ break; ++ }; ++ ++ DWC_ERROR(" Speed: %s\n", speed); ++ ++ DWC_ERROR(" Max packet size: %d\n", ++ dwc_otg_hcd_get_mps(&urb->pipe_info)); ++ DWC_ERROR(" Data buffer length: %d\n", urb->length); ++ DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->buf, (void *)urb->dma); ++ DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ DWC_ERROR(" Interval: %d\n", urb->interval); ++ ++ /* Core haltes the channel for Descriptor DMA mode */ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_AHB_ERR); ++ goto handle_ahberr_done; ++ } ++ ++ hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO); ++ ++ /* ++ * Force a channel halt. Don't call halt_channel because that won't ++ * write to the HCCHARn register in DMA mode to force the halt. ++ */ ++ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR); ++handle_ahberr_done: ++ disable_hc_int(hc_regs, ahberr); ++ return 1; ++} ++ ++/** ++ * Handles a host channel transaction error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "Transaction Error--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ goto handle_xacterr_done; ++ } ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ qtd->error_count++; ++ if (!hc->qh->ping_state) { ++ ++ update_urb_state_xfer_intr(hc, hc_regs, ++ qtd->urb, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) { ++ hc->qh->ping_state = 1; ++ } ++ } ++ ++ /* ++ * Halt the channel so the transfer can be re-started from ++ * the appropriate point or the PING protocol will start. ++ */ ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); ++ break; ++ case UE_INTERRUPT: ++ qtd->error_count++; ++ if (hc->do_split && hc->complete_split) { ++ qtd->complete_split = 0; ++ } ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR); ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_XACT_ERR); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++handle_xacterr_done: ++ disable_hc_int(hc_regs, xacterr); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel frame overrun interrupt. This handler may be called ++ * in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "Frame Overrun--\n", hc->hc_num); ++ ++ switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { ++ case UE_CONTROL: ++ case UE_BULK: ++ break; ++ case UE_INTERRUPT: ++ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN); ++ break; ++ case UE_ISOCHRONOUS: ++ { ++ dwc_otg_halt_status_e halt_status; ++ halt_status = ++ update_isoc_urb_state(hcd, hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_FRAME_OVERRUN); ++ ++ halt_channel(hcd, hc, qtd, halt_status); ++ } ++ break; ++ } ++ ++ disable_hc_int(hc_regs, frmovrun); ++ ++ return 1; ++} ++ ++/** ++ * Handles a host channel data toggle error interrupt. This handler may be ++ * called in either DMA mode or Slave mode. ++ */ ++static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "Data Toggle Error--\n", hc->hc_num); ++ ++ if (hc->ep_is_in) { ++ qtd->error_count = 0; ++ } else { ++ DWC_ERROR("Data Toggle Error on OUT transfer," ++ "channel %d\n", hc->hc_num); ++ } ++ ++ disable_hc_int(hc_regs, datatglerr); ++ ++ return 1; ++} ++ ++#ifdef DEBUG ++/** ++ * This function is for debug only. It checks that a valid halt status is set ++ * and that HCCHARn.chdis is clear. If there's a problem, corrective action is ++ * taken and a warning is issued. ++ * @return 1 if halt status is ok, 0 otherwise. ++ */ ++static inline int halt_status_ok(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcchar_data_t hcchar; ++ hctsiz_data_t hctsiz; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ hcsplt_data_t hcsplt; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) { ++ /* ++ * This code is here only as a check. This condition should ++ * never happen. Ignore the halt if it does occur. ++ */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); ++ DWC_WARN ++ ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, " ++ "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " ++ "hcint 0x%08x, hcintmsk 0x%08x, " ++ "hcsplt 0x%08x, qtd->complete_split %d\n", __func__, ++ hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32, ++ hcintmsk.d32, hcsplt.d32, qtd->complete_split); ++ ++ DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n", ++ __func__, hc->hc_num); ++ DWC_WARN("\n"); ++ clear_hc_int(hc_regs, chhltd); ++ return 0; ++ } ++ ++ /* ++ * This code is here only as a check. hcchar.chdis should ++ * never be set when the halt interrupt occurs. Halt the ++ * channel again if it does occur. ++ */ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ if (hcchar.b.chdis) { ++ DWC_WARN("%s: hcchar.chdis set unexpectedly, " ++ "hcchar 0x%08x, trying to halt again\n", ++ __func__, hcchar.d32); ++ clear_hc_int(hc_regs, chhltd); ++ hc->halt_pending = 0; ++ halt_channel(hcd, hc, qtd, hc->halt_status); ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++/** ++ * Handles a host Channel Halted interrupt in DMA mode. This handler ++ * determines the reason the channel halted and proceeds accordingly. ++ */ ++static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ int out_nak_enh = 0; ++ ++ /* For core with OUT NAK enhancement, the flow for high- ++ * speed CONTROL/BULK OUT is handled a little differently. ++ */ ++ if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) { ++ if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in && ++ (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || ++ hc->ep_type == DWC_OTG_EP_TYPE_BULK)) { ++ out_nak_enh = 1; ++ } ++ } ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || ++ (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR ++ && !hcd->core_if->dma_desc_enable)) { ++ /* ++ * Just release the channel. A dequeue can happen on a ++ * transfer timeout. In the case of an AHB Error, the channel ++ * was forced to halt because there's no way to gracefully ++ * recover. ++ */ ++ if (hcd->core_if->dma_desc_enable) ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ hc->halt_status); ++ else ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ return; ++ } ++ ++ /* Read the HCINTn register to determine the cause for the halt. */ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ ++ if (hcint.b.xfercomp) { ++ /** @todo This is here because of a possible hardware bug. Spec ++ * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT ++ * interrupt w/ACK bit set should occur, but I only see the ++ * XFERCOMP bit, even with it masked out. This is a workaround ++ * for that behavior. Should fix this when hardware is fixed. ++ */ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) { ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } ++ handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.stall) { ++ handle_hc_stall_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) { ++ if (out_nak_enh) { ++ if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) { ++ DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n"); ++ qtd->error_count = 0; ++ } else { ++ DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n"); ++ } ++ } ++ ++ /* ++ * Must handle xacterr before nak or ack. Could get a xacterr ++ * at the same time as either of these on a BULK/CONTROL OUT ++ * that started with a PING. The xacterr takes precedence. ++ */ ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) { ++ handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { ++ handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.bblerr) { ++ handle_hc_babble_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.frmovrun) { ++ handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd); ++ } else if (!out_nak_enh) { ++ if (hcint.b.nyet) { ++ /* ++ * Must handle nyet before nak or ack. Could get a nyet at the ++ * same time as either of those on a BULK/CONTROL OUT that ++ * started with a PING. The nyet takes precedence. ++ */ ++ handle_hc_nyet_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.nak && !hcintmsk.b.nak) { ++ /* ++ * If nak is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the nak is handled by ++ * the nak interrupt handler, not here. Handle nak here for ++ * BULK/CONTROL OUT transfers, which halt on a NAK to allow ++ * rewinding the buffer pointer. ++ */ ++ handle_hc_nak_intr(hcd, hc, hc_regs, qtd); ++ } else if (hcint.b.ack && !hcintmsk.b.ack) { ++ /* ++ * If ack is not masked, it's because a non-split IN transfer ++ * is in an error state. In that case, the ack is handled by ++ * the ack interrupt handler, not here. Handle ack here for ++ * split transfers. Start splits halt on ACK. ++ */ ++ handle_hc_ack_intr(hcd, hc, hc_regs, qtd); ++ } else { ++ if (hc->ep_type == DWC_OTG_EP_TYPE_INTR || ++ hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * A periodic transfer halted with no other channel ++ * interrupts set. Assume it was halted by the core ++ * because it could not be completed in its scheduled ++ * (micro)frame. ++ */ ++#ifdef DEBUG ++ DWC_PRINTF ++ ("%s: Halt channel %d (assume incomplete periodic transfer)\n", ++ __func__, hc->hc_num); ++#endif ++ halt_channel(hcd, hc, qtd, ++ DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE); ++ } else { ++ DWC_ERROR ++ ("%s: Channel %d, DMA Mode -- ChHltd set, but reason " ++ "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n", ++ __func__, hc->hc_num, hcint.d32, ++ DWC_READ_REG32(&hcd-> ++ core_if->core_global_regs-> ++ gintsts)); ++ } ++ ++ } ++ } else { ++ DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n", ++ hcint.d32); ++ } ++} ++ ++/** ++ * Handles a host channel Channel Halted interrupt. ++ * ++ * In slave mode, this handler is called only when the driver specifically ++ * requests a halt. This occurs during handling other host channel interrupts ++ * (e.g. nak, xacterr, stall, nyet, etc.). ++ * ++ * In DMA mode, this is the interrupt that occurs when the core has finished ++ * processing a transfer on a channel. Other host channel interrupts (except ++ * ahberr) are disabled in DMA mode. ++ */ ++static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) ++{ ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " ++ "Channel Halted--\n", hc->hc_num); ++ ++ if (hcd->core_if->dma_enable) { ++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); ++ } else { ++#ifdef DEBUG ++ if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { ++ return 1; ++ } ++#endif ++ release_channel(hcd, hc, qtd, hc->halt_status); ++ } ++ ++ return 1; ++} ++ ++/** Handles interrupt for a specific Host Channel */ ++int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) ++{ ++ int retval = 0; ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; ++ dwc_hc_t *hc; ++ dwc_otg_hc_regs_t *hc_regs; ++ dwc_otg_qtd_t *qtd; ++ ++ DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num); ++ ++ hc = dwc_otg_hcd->hc_ptr_array[num]; ++ hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num]; ++ qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); ++ ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ DWC_DEBUGPL(DBG_HCDV, ++ " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", ++ hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); ++ hcint.d32 = hcint.d32 & hcintmsk.d32; ++ ++ if (!dwc_otg_hcd->core_if->dma_enable) { ++ if (hcint.b.chhltd && hcint.d32 != 0x2) { ++ hcint.b.chhltd = 0; ++ } ++ } ++ ++ if (hcint.b.xfercomp) { ++ retval |= ++ handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ /* ++ * If NYET occurred at same time as Xfer Complete, the NYET is ++ * handled by the Xfer Complete interrupt handler. Don't want ++ * to call the NYET interrupt handler in this case. ++ */ ++ hcint.b.nyet = 0; ++ } ++ if (hcint.b.chhltd) { ++ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.ahberr) { ++ retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.stall) { ++ retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.nak) { ++ retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.ack) { ++ retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.nyet) { ++ retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.xacterr) { ++ retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.bblerr) { ++ retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.frmovrun) { ++ retval |= ++ handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ if (hcint.b.datatglerr) { ++ retval |= ++ handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ } ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +new file mode 100644 +index 0000000..4a985a6 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +@@ -0,0 +1,893 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ ++ * $Revision: #20 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1872981 $ ++ * ++ * 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_DEVICE_ONLY ++ ++/** ++ * @file ++ * ++ * This file contains the implementation of the HCD. In Linux, the HCD ++ * implements the hc_driver API. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++#include <../drivers/usb/core/hcd.h> ++#else ++#include ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) ++#define USB_URB_EP_LINKING 1 ++#else ++#define USB_URB_EP_LINKING 0 ++#endif ++ ++#include "dwc_otg_hcd_if.h" ++#include "dwc_otg_dbg.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_hcd.h" ++/** ++ * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is ++ * qualified with its direction (possible 32 endpoints per device). ++ */ ++#define dwc_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \ ++ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4) ++ ++static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; ++ ++/** @name Linux HC Driver API Functions */ ++/** @{ */ ++/* manage i/o requests, device state */ ++static int dwc_otg_urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep, ++#endif ++ struct urb *urb, gfp_t mem_flags); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); ++#endif ++#else /* kernels at or post 2.6.30 */ ++static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, ++ struct urb *urb, int status); ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */ ++ ++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#endif ++static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); ++extern int hcd_start(struct usb_hcd *hcd); ++extern void hcd_stop(struct usb_hcd *hcd); ++static int get_frame_number(struct usb_hcd *hcd); ++extern int hub_status_data(struct usb_hcd *hcd, char *buf); ++extern int hub_control(struct usb_hcd *hcd, ++ u16 typeReq, ++ u16 wValue, u16 wIndex, char *buf, u16 wLength); ++ ++struct wrapper_priv_data { ++ dwc_otg_hcd_t *dwc_otg_hcd; ++}; ++ ++/** @} */ ++ ++static struct hc_driver dwc_otg_hc_driver = { ++ ++ .description = dwc_otg_hcd_name, ++ .product_desc = "DWC OTG Controller", ++ .hcd_priv_size = sizeof(struct wrapper_priv_data), ++ ++ .irq = dwc_otg_hcd_irq, ++ ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ //.reset = ++ .start = hcd_start, ++ //.suspend = ++ //.resume = ++ .stop = hcd_stop, ++ ++ .urb_enqueue = dwc_otg_urb_enqueue, ++ .urb_dequeue = dwc_otg_urb_dequeue, ++ .endpoint_disable = endpoint_disable, ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++ .endpoint_reset = endpoint_reset, ++#endif ++ .get_frame_number = get_frame_number, ++ ++ .hub_status_data = hub_status_data, ++ .hub_control = hub_control, ++ //.bus_suspend = ++ //.bus_resume = ++}; ++ ++/** Gets the dwc_otg_hcd from a struct usb_hcd */ ++static inline dwc_otg_hcd_t *hcd_to_dwc_otg_hcd(struct usb_hcd *hcd) ++{ ++ struct wrapper_priv_data *p; ++ p = (struct wrapper_priv_data *)(hcd->hcd_priv); ++ return p->dwc_otg_hcd; ++} ++ ++/** Gets the struct usb_hcd that contains a dwc_otg_hcd_t. */ ++static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t * dwc_otg_hcd) ++{ ++ return dwc_otg_hcd_get_priv_data(dwc_otg_hcd); ++} ++ ++/** Gets the usb_host_endpoint associated with an URB. */ ++inline struct usb_host_endpoint *dwc_urb_to_endpoint(struct urb *urb) ++{ ++ struct usb_device *dev = urb->dev; ++ int ep_num = usb_pipeendpoint(urb->pipe); ++ ++ if (usb_pipein(urb->pipe)) ++ return dev->ep_in[ep_num]; ++ else ++ return dev->ep_out[ep_num]; ++} ++ ++static int _disconnect(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ ++ usb_hcd->self.is_b_host = 0; ++ return 0; ++} ++ ++static int _start(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ ++ usb_hcd->self.is_b_host = dwc_otg_hcd_is_b_host(hcd); ++ hcd_start(usb_hcd); ++ ++ return 0; ++} ++ ++static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr, ++ uint32_t * port_addr) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ struct usb_bus *bus; ++#if 1 //GRAYG - temporary ++ if (NULL == urb_handle) ++ DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG ++ if (NULL == urb->dev) ++ DWC_ERROR("**** %s - URB has no device\n", __func__);//GRAYG ++ if (NULL == port_addr) ++ DWC_ERROR("**** %s - NULL port_address\n", __func__);//GRAYG ++#endif ++ if (urb->dev->tt) { ++ if (NULL == urb->dev->tt->hub) { ++ DWC_ERROR("**** %s - (URB's transactor has no TT - giving no hub)\n", ++ __func__); //GRAYG ++ //*hub_addr = (u8)usb_pipedevice(urb->pipe); //GRAYG ++ *hub_addr = 0; //GRAYG ++ // we probably shouldn't have a transaction translator if ++ // there's no associated hub? ++ } else { ++ bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd)); ++ if (urb->dev->tt->hub == bus->root_hub) ++ *hub_addr = 0; ++ else ++ *hub_addr = urb->dev->tt->hub->devnum; ++ } ++ *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1; ++ } else { ++ *hub_addr = 0; ++ *port_addr = urb->dev->ttport; ++ } ++ return 0; ++} ++ ++static int _speed(dwc_otg_hcd_t * hcd, void *urb_handle) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ return urb->dev->speed; ++} ++ ++static int _get_b_hnp_enable(dwc_otg_hcd_t * hcd) ++{ ++ struct usb_hcd *usb_hcd = dwc_otg_hcd_to_hcd(hcd); ++ return usb_hcd->self.b_hnp_enable; ++} ++ ++static void allocate_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, ++ struct urb *urb) ++{ ++ hcd_to_bus(hcd)->bandwidth_allocated += bw / urb->interval; ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ hcd_to_bus(hcd)->bandwidth_isoc_reqs++; ++ } else { ++ hcd_to_bus(hcd)->bandwidth_int_reqs++; ++ } ++} ++ ++static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, ++ struct urb *urb) ++{ ++ hcd_to_bus(hcd)->bandwidth_allocated -= bw / urb->interval; ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ hcd_to_bus(hcd)->bandwidth_isoc_reqs--; ++ } else { ++ hcd_to_bus(hcd)->bandwidth_int_reqs--; ++ } ++} ++ ++/** ++ * Sets the final status of an URB and returns it to the device driver. Any ++ * required cleanup of the URB is performed. ++ */ ++static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, ++ dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status) ++{ ++ struct urb *urb = (struct urb *)urb_handle; ++ ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n", ++ __func__, urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ++ usb_pipein(urb->pipe) ? "IN" : "OUT", status); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ DWC_PRINTF(" ISO Desc %d status: %d\n", ++ i, urb->iso_frame_desc[i].status); ++ } ++ } ++ } ++ ++ urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb); ++ /* Convert status value. */ ++ switch (status) { ++ case -DWC_E_PROTOCOL: ++ status = -EPROTO; ++ break; ++ case -DWC_E_IN_PROGRESS: ++ status = -EINPROGRESS; ++ break; ++ case -DWC_E_PIPE: ++ status = -EPIPE; ++ break; ++ case -DWC_E_IO: ++ status = -EIO; ++ break; ++ case -DWC_E_TIMEOUT: ++ status = -ETIMEDOUT; ++ break; ++ case -DWC_E_OVERFLOW: ++ status = -EOVERFLOW; ++ break; ++ default: ++ if (status) { ++ DWC_PRINTF("Uknown urb status %d\n", status); ++ ++ } ++ } ++ ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ ++ urb->error_count = dwc_otg_hcd_urb_get_error_count(dwc_otg_urb); ++ for (i = 0; i < urb->number_of_packets; ++i) { ++ urb->iso_frame_desc[i].actual_length = ++ dwc_otg_hcd_urb_get_iso_desc_actual_length ++ (dwc_otg_urb, i); ++ urb->iso_frame_desc[i].status = ++ dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); ++ } ++ } ++ ++ urb->status = status; ++ urb->hcpriv = NULL; ++ if (!status) { ++ if ((urb->transfer_flags & URB_SHORT_NOT_OK) && ++ (urb->actual_length < urb->transfer_buffer_length)) { ++ urb->status = -EREMOTEIO; ++ } ++ } ++ ++ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) || ++ (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { ++ struct usb_host_endpoint *ep = dwc_urb_to_endpoint(urb); ++ if (ep) { ++ free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd), ++ dwc_otg_hcd_get_ep_bandwidth(hcd, ++ ep->hcpriv), ++ urb); ++ } ++ } ++ ++ DWC_FREE(dwc_otg_urb); ++ ++#if USB_URB_EP_LINKING ++ usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb); ++#endif ++ DWC_SPINUNLOCK(hcd->lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); ++#else ++ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); ++#endif ++ DWC_SPINLOCK(hcd->lock); ++ ++ return 0; ++} ++ ++static struct dwc_otg_hcd_function_ops hcd_fops = { ++ .start = _start, ++ .disconnect = _disconnect, ++ .hub_info = _hub_info, ++ .speed = _speed, ++ .complete = _complete, ++ .get_b_hnp_enable = _get_b_hnp_enable, ++}; ++ ++/** ++ * Initializes the HCD. This function allocates memory for and initializes the ++ * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the ++ * USB bus with the core and calls the hc_driver->start() function. It returns ++ * a negative error on failure. ++ */ ++int hcd_init(dwc_bus_dev_t *_dev) ++{ ++ struct usb_hcd *hcd = NULL; ++ dwc_otg_hcd_t *dwc_otg_hcd = NULL; ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); ++ int retval = 0; ++ u64 dmamask; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev); ++ ++ /* Set device flags indicating whether the HCD supports DMA. */ ++ if (dwc_otg_is_dma_enable(otg_dev->core_if)) ++ dmamask = DMA_BIT_MASK(32); ++ else ++ dmamask = 0; ++ ++#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE) ++ dma_set_mask(&_dev->dev, dmamask); ++ dma_set_coherent_mask(&_dev->dev, dmamask); ++#elif defined(PCI_INTERFACE) ++ pci_set_dma_mask(_dev, dmamask); ++ pci_set_consistent_dma_mask(_dev, dmamask); ++#endif ++ ++ /* ++ * Allocate memory for the base HCD plus the DWC OTG HCD. ++ * Initialize the base HCD. ++ */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id); ++#else ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev)); ++ hcd->has_tt = 1; ++// hcd->uses_new_polling = 1; ++// hcd->poll_rh = 0; ++#endif ++ if (!hcd) { ++ retval = -ENOMEM; ++ goto error1; ++ } ++ ++ hcd->regs = otg_dev->os_dep.base; ++ ++ /* Initialize the DWC OTG HCD. */ ++ dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); ++ if (!dwc_otg_hcd) { ++ goto error2; ++ } ++ ((struct wrapper_priv_data *)(hcd->hcd_priv))->dwc_otg_hcd = ++ dwc_otg_hcd; ++ otg_dev->hcd = dwc_otg_hcd; ++ ++ if (dwc_otg_hcd_init(dwc_otg_hcd, otg_dev->core_if)) { ++ goto error2; ++ } ++ ++ otg_dev->hcd->otg_dev = otg_dev; ++ hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later ++ hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if); ++#endif ++ /* Don't support SG list at this point */ ++ hcd->self.sg_tablesize = 0; ++#endif ++ /* ++ * Finish generic HCD initialization and start the HCD. This function ++ * allocates the DMA buffer pool, registers the USB bus, requests the ++ * IRQ line, and calls hcd_start method. ++ */ ++#ifdef PLATFORM_INTERFACE ++ retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED); ++#else ++ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED); ++#endif ++ if (retval < 0) { ++ goto error2; ++ } ++ ++ dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd); ++ return 0; ++ ++error2: ++ usb_put_hcd(hcd); ++error1: ++ return retval; ++} ++ ++/** ++ * Removes the HCD. ++ * Frees memory and resources associated with the HCD and deregisters the bus. ++ */ ++void hcd_remove(dwc_bus_dev_t *_dev) ++{ ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ struct usb_hcd *hcd; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD REMOVE otg_dev=%p\n", otg_dev); ++ ++ if (!otg_dev) { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); ++ return; ++ } ++ ++ dwc_otg_hcd = otg_dev->hcd; ++ ++ if (!dwc_otg_hcd) { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); ++ return; ++ } ++ ++ hcd = dwc_otg_hcd_to_hcd(dwc_otg_hcd); ++ ++ if (!hcd) { ++ DWC_DEBUGPL(DBG_ANY, ++ "%s: dwc_otg_hcd_to_hcd(dwc_otg_hcd) NULL!\n", ++ __func__); ++ return; ++ } ++ usb_remove_hcd(hcd); ++ dwc_otg_hcd_set_priv_data(dwc_otg_hcd, NULL); ++ dwc_otg_hcd_remove(dwc_otg_hcd); ++ usb_put_hcd(hcd); ++} ++ ++/* ========================================================================= ++ * Linux HC Driver Functions ++ * ========================================================================= */ ++ ++/** Initializes the DWC_otg controller and its root hub and prepares it for host ++ * mode operation. Activates the root port. Returns 0 on success and a negative ++ * error code on failure. */ ++int hcd_start(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ struct usb_bus *bus; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD START\n"); ++ bus = hcd_to_bus(hcd); ++ ++ hcd->state = HC_STATE_RUNNING; ++ if (dwc_otg_hcd_start(dwc_otg_hcd, &hcd_fops)) { ++ return 0; ++ } ++ ++ /* Initialize and connect root hub if one is not already attached */ ++ if (bus->root_hub) { ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Has Root Hub\n"); ++ /* Inform the HUB driver to resume. */ ++ usb_hcd_resume_root_hub(hcd); ++ } ++ ++ return 0; ++} ++ ++/** ++ * Halts the DWC_otg host mode operations in a clean manner. USB transfers are ++ * stopped. ++ */ ++void hcd_stop(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ dwc_otg_hcd_stop(dwc_otg_hcd); ++} ++ ++/** Returns the current frame number. */ ++static int get_frame_number(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ return dwc_otg_hcd_get_frame_number(dwc_otg_hcd); ++} ++ ++#ifdef DEBUG ++static void dump_urb_info(struct urb *urb, char *fn_name) ++{ ++ DWC_PRINTF("%s, urb %p\n", fn_name, urb); ++ DWC_PRINTF(" Device address: %d\n", usb_pipedevice(urb->pipe)); ++ DWC_PRINTF(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe), ++ (usb_pipein(urb->pipe) ? "IN" : "OUT")); ++ DWC_PRINTF(" Endpoint type: %s\n", ( { ++ char *pipetype; ++ switch (usb_pipetype(urb->pipe)) { ++case PIPE_CONTROL: ++pipetype = "CONTROL"; break; case PIPE_BULK: ++pipetype = "BULK"; break; case PIPE_INTERRUPT: ++pipetype = "INTERRUPT"; break; case PIPE_ISOCHRONOUS: ++pipetype = "ISOCHRONOUS"; break; default: ++ pipetype = "UNKNOWN"; break;}; ++ pipetype;} ++ )) ; ++ DWC_PRINTF(" Speed: %s\n", ( { ++ char *speed; switch (urb->dev->speed) { ++case USB_SPEED_HIGH: ++speed = "HIGH"; break; case USB_SPEED_FULL: ++speed = "FULL"; break; case USB_SPEED_LOW: ++speed = "LOW"; break; default: ++ speed = "UNKNOWN"; break;}; ++ speed;} ++ )) ; ++ DWC_PRINTF(" Max packet size: %d\n", ++ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))); ++ DWC_PRINTF(" Data buffer length: %d\n", urb->transfer_buffer_length); ++ DWC_PRINTF(" Transfer buffer: %p, Transfer DMA: %p\n", ++ urb->transfer_buffer, (void *)urb->transfer_dma); ++ DWC_PRINTF(" Setup buffer: %p, Setup DMA: %p\n", ++ urb->setup_packet, (void *)urb->setup_dma); ++ DWC_PRINTF(" Interval: %d\n", urb->interval); ++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { ++ int i; ++ for (i = 0; i < urb->number_of_packets; i++) { ++ DWC_PRINTF(" ISO Desc %d:\n", i); ++ DWC_PRINTF(" offset: %d, length %d\n", ++ urb->iso_frame_desc[i].offset, ++ urb->iso_frame_desc[i].length); ++ } ++ } ++} ++#endif ++ ++/** Starts processing a USB transfer request specified by a USB Request Block ++ * (URB). mem_flags indicates the type of memory allocation to use while ++ * processing this URB. */ ++static int dwc_otg_urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep, ++#endif ++ struct urb *urb, gfp_t mem_flags) ++{ ++ int retval = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep = urb->ep; ++#endif ++#if USB_URB_EP_LINKING ++ dwc_irqflags_t irqflags; ++#endif ++ void **ref_ep_hcpriv = &ep->hcpriv; ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ dwc_otg_hcd_urb_t *dwc_otg_urb; ++ int i; ++ int alloc_bandwidth = 0; ++ uint8_t ep_type = 0; ++ uint32_t flags = 0; ++ void *buf; ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "dwc_otg_urb_enqueue"); ++ } ++#endif ++ ++ if (!urb->transfer_buffer && urb->transfer_buffer_length) ++ return -EINVAL; ++ ++ if ((usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) ++ || (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { ++ if (!dwc_otg_hcd_is_bandwidth_allocated ++ (dwc_otg_hcd, ref_ep_hcpriv)) { ++ alloc_bandwidth = 1; ++ } ++ } ++ ++ switch (usb_pipetype(urb->pipe)) { ++ case PIPE_CONTROL: ++ ep_type = USB_ENDPOINT_XFER_CONTROL; ++ break; ++ case PIPE_ISOCHRONOUS: ++ ep_type = USB_ENDPOINT_XFER_ISOC; ++ break; ++ case PIPE_BULK: ++ ep_type = USB_ENDPOINT_XFER_BULK; ++ break; ++ case PIPE_INTERRUPT: ++ ep_type = USB_ENDPOINT_XFER_INT; ++ break; ++ default: ++ DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe)); ++ } ++ ++ /* # of packets is often 0 - do we really need to call this then? */ ++ dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd, ++ urb->number_of_packets, ++ mem_flags == GFP_ATOMIC ? 1 : 0); ++ ++ if(dwc_otg_urb == NULL) ++ return -ENOMEM; ++ ++ urb->hcpriv = dwc_otg_urb; ++ if (!dwc_otg_urb && urb->number_of_packets) ++ return -ENOMEM; ++ ++ dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe), ++ usb_pipeendpoint(urb->pipe), ep_type, ++ usb_pipein(urb->pipe), ++ usb_maxpacket(urb->dev, urb->pipe, ++ !(usb_pipein(urb->pipe)))); ++ ++ buf = urb->transfer_buffer; ++ if (hcd->self.uses_dma) { ++ /* ++ * Calculate virtual address from physical address, ++ * because some class driver may not fill transfer_buffer. ++ * In Buffer DMA mode virual address is used, ++ * when handling non DWORD aligned buffers. ++ */ ++ //buf = phys_to_virt(urb->transfer_dma); ++ // DMA addresses are bus addresses not physical addresses! ++ buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma); ++ } ++ ++ if (!(urb->transfer_flags & URB_NO_INTERRUPT)) ++ flags |= URB_GIVEBACK_ASAP; ++ if (urb->transfer_flags & URB_ZERO_PACKET) ++ flags |= URB_SEND_ZERO_PACKET; ++ ++ dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf, ++ urb->transfer_dma, ++ urb->transfer_buffer_length, ++ urb->setup_packet, ++ urb->setup_dma, flags, urb->interval); ++ ++ for (i = 0; i < urb->number_of_packets; ++i) { ++ dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i, ++ urb-> ++ iso_frame_desc[i].offset, ++ urb-> ++ iso_frame_desc[i].length); ++ } ++ ++#if USB_URB_EP_LINKING ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags); ++ retval = usb_hcd_link_urb_to_ep(hcd, urb); ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags); ++ if (0 == retval) ++#endif ++ { ++ retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, ++ /*(dwc_otg_qh_t **)*/ ++ ref_ep_hcpriv, ++ mem_flags == GFP_ATOMIC ? 1 : 0); ++ if (0 == retval) { ++ if (alloc_bandwidth) { ++ allocate_bus_bandwidth(hcd, ++ dwc_otg_hcd_get_ep_bandwidth( ++ dwc_otg_hcd, *ref_ep_hcpriv), ++ urb); ++ } ++ } else { ++#if USB_URB_EP_LINKING ++ dwc_irqflags_t irqflags; ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval); ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags); ++ usb_hcd_unlink_urb_from_ep(hcd, urb); ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags); ++#endif ++ if (retval == -DWC_E_NO_DEVICE) { ++ retval = -ENODEV; ++ } ++ } ++ } ++ return retval; ++} ++ ++/** Aborts/cancels a USB transfer request. Always returns 0 to indicate ++ * success. */ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ++#else ++static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ++#endif ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_hcd_t *dwc_otg_hcd; ++ int rc; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); ++ ++ dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++#ifdef DEBUG ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ dump_urb_info(urb, "dwc_otg_urb_dequeue"); ++ } ++#endif ++ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ rc = usb_hcd_check_unlink_urb(hcd, urb, status); ++ if (0 == rc) { ++ if(urb->hcpriv != NULL) { ++ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, ++ (dwc_otg_hcd_urb_t *)urb->hcpriv); ++ ++ DWC_FREE(urb->hcpriv); ++ urb->hcpriv = NULL; ++ } ++ } ++ ++ if (0 == rc) { ++ /* Higher layer software sets URB status. */ ++#if USB_URB_EP_LINKING ++ usb_hcd_unlink_urb_from_ep(hcd, urb); ++#endif ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ usb_hcd_giveback_urb(hcd, urb); ++#else ++ usb_hcd_giveback_urb(hcd, urb, status); ++#endif ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINTF("Called usb_hcd_giveback_urb() \n"); ++ DWC_PRINTF(" 1urb->status = %d\n", urb->status); ++ } ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n"); ++ } else { ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n", ++ rc); ++ } ++ ++ return rc; ++} ++ ++/* Frees resources in the DWC_otg controller related to a given endpoint. Also ++ * clears state in the HCD related to the endpoint. Any URBs for the endpoint ++ * must already be dequeued. */ ++static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD EP DISABLE: _bEndpointAddress=0x%02x, " ++ "endpoint=%d\n", ep->desc.bEndpointAddress, ++ dwc_ep_addr_to_endpoint(ep->desc.bEndpointAddress)); ++ dwc_otg_hcd_endpoint_disable(dwc_otg_hcd, ep->hcpriv, 250); ++ ep->hcpriv = NULL; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++/* Resets endpoint specific parameter values, in current version used to reset ++ * the data toggle(as a WA). This function can be called from usb_clear_halt routine */ ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ dwc_irqflags_t flags; ++ struct usb_device *udev = NULL; ++ int epnum = usb_endpoint_num(&ep->desc); ++ int is_out = usb_endpoint_dir_out(&ep->desc); ++ int is_control = usb_endpoint_xfer_control(&ep->desc); ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep); ++ ++ if (dev) ++ udev = to_usb_device(dev); ++ else ++ return; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum); ++ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ usb_settoggle(udev, epnum, is_out, 0); ++ if (is_control) ++ usb_settoggle(udev, epnum, !is_out, 0); ++ ++ if (ep->hcpriv) { ++ dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++} ++#endif ++ ++/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if ++ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid ++ * interrupt. ++ * ++ * This function is called by the USB core when an interrupt occurs */ ++static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ int32_t retval = dwc_otg_hcd_handle_intr(dwc_otg_hcd); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** Creates Status Change bitmap for the root hub and root port. The bitmap is ++ * returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1 ++ * is the status change indicator for the single root port. Returns 1 if either ++ * change indicator is 1, otherwise returns 0. */ ++int hub_status_data(struct usb_hcd *hcd, char *buf) ++{ ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ ++ buf[0] = 0; ++ buf[0] |= (dwc_otg_hcd_is_status_changed(dwc_otg_hcd, 1)) << 1; ++ ++ return (buf[0] != 0); ++} ++ ++/** Handles hub class-specific requests. */ ++int hub_control(struct usb_hcd *hcd, ++ u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) ++{ ++ int retval; ++ ++ retval = dwc_otg_hcd_hub_control(hcd_to_dwc_otg_hcd(hcd), ++ typeReq, wValue, wIndex, buf, wLength); ++ ++ switch (retval) { ++ case -DWC_E_INVALID: ++ retval = -EINVAL; ++ break; ++ } ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +new file mode 100644 +index 0000000..08c1669 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +@@ -0,0 +1,922 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ ++ * $Revision: #44 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ ++ * ++ * 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_DEVICE_ONLY ++ ++/** ++ * @file ++ * ++ * This file contains the functions to manage Queue Heads and Queue ++ * Transfer Descriptors. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++extern bool microframe_schedule; ++ ++/** ++ * Free each QTD in the QH's QTD-list then free the QH. QH should already be ++ * removed from a list. QTD list should already be empty if called from URB ++ * Dequeue. ++ * ++ * @param hcd HCD instance. ++ * @param qh The QH to free. ++ */ ++void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ ++ /* Free each QTD in the QTD list */ ++ DWC_SPINLOCK(hcd->lock); ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); ++ dwc_otg_hcd_qtd_free(qtd); ++ } ++ ++ if (hcd->core_if->dma_desc_enable) { ++ dwc_otg_hcd_qh_free_ddma(hcd, qh); ++ } else if (qh->dw_align_buf) { ++ uint32_t buf_size; ++ if (qh->ep_type == UE_ISOCHRONOUS) { ++ buf_size = 4096; ++ } else { ++ buf_size = hcd->core_if->core_params->max_transfer_size; ++ } ++ DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); ++ } ++ ++ DWC_FREE(qh); ++ DWC_SPINUNLOCK(hcd->lock); ++ return; ++} ++ ++#define BitStuffTime(bytecount) ((8 * 7* bytecount) / 6) ++#define HS_HOST_DELAY 5 /* nanoseconds */ ++#define FS_LS_HOST_DELAY 1000 /* nanoseconds */ ++#define HUB_LS_SETUP 333 /* nanoseconds */ ++#define NS_TO_US(ns) ((ns + 500) / 1000) ++ /* convert & round nanoseconds to microseconds */ ++ ++static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount) ++{ ++ unsigned long retval; ++ ++ switch (speed) { ++ case USB_SPEED_HIGH: ++ if (is_isoc) { ++ retval = ++ ((38 * 8 * 2083) + ++ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + ++ HS_HOST_DELAY; ++ } else { ++ retval = ++ ((55 * 8 * 2083) + ++ (2083 * (3 + BitStuffTime(bytecount)))) / 1000 + ++ HS_HOST_DELAY; ++ } ++ break; ++ case USB_SPEED_FULL: ++ if (is_isoc) { ++ retval = ++ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; ++ if (is_in) { ++ retval = 7268 + FS_LS_HOST_DELAY + retval; ++ } else { ++ retval = 6265 + FS_LS_HOST_DELAY + retval; ++ } ++ } else { ++ retval = ++ (8354 * (31 + 10 * BitStuffTime(bytecount))) / 1000; ++ retval = 9107 + FS_LS_HOST_DELAY + retval; ++ } ++ break; ++ case USB_SPEED_LOW: ++ if (is_in) { ++ retval = ++ (67667 * (31 + 10 * BitStuffTime(bytecount))) / ++ 1000; ++ retval = ++ 64060 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + ++ retval; ++ } else { ++ retval = ++ (66700 * (31 + 10 * BitStuffTime(bytecount))) / ++ 1000; ++ retval = ++ 64107 + (2 * HUB_LS_SETUP) + FS_LS_HOST_DELAY + ++ retval; ++ } ++ break; ++ default: ++ DWC_WARN("Unknown device speed\n"); ++ retval = -1; ++ } ++ ++ return NS_TO_US(retval); ++} ++ ++/** ++ * Initializes a QH structure. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * @param urb Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ */ ++#define SCHEDULE_SLOP 10 ++void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) ++{ ++ char *speed, *type; ++ int dev_speed; ++ uint32_t hub_addr, hub_port; ++ ++ dwc_memset(qh, 0, sizeof(dwc_otg_qh_t)); ++ ++ /* Initialize QH */ ++ qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); ++ qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; ++ ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ qh->maxp = dwc_otg_hcd_get_mps(&urb->pipe_info); ++ DWC_CIRCLEQ_INIT(&qh->qtd_list); ++ DWC_LIST_INIT(&qh->qh_list_entry); ++ qh->channel = NULL; ++ ++ /* FS/LS Enpoint on HS Hub ++ * NOT virtual root hub */ ++ dev_speed = hcd->fops->speed(hcd, urb->priv); ++ ++ hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port); ++ qh->do_split = 0; ++ if (microframe_schedule) ++ qh->speed = dev_speed; ++ ++ ++ if (((dev_speed == USB_SPEED_LOW) || ++ (dev_speed == USB_SPEED_FULL)) && ++ (hub_addr != 0 && hub_addr != 1)) { ++ DWC_DEBUGPL(DBG_HCD, ++ "QH init: EP %d: TT found at hub addr %d, for port %d\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, ++ hub_port); ++ qh->do_split = 1; ++ } ++ ++ if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) { ++ /* Compute scheduling parameters once and save them. */ ++ hprt0_data_t hprt; ++ ++ /** @todo Account for split transfers in the bus time. */ ++ int bytecount = ++ dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); ++ ++ qh->usecs = ++ calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), ++ qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS), ++ bytecount); ++ /* Start in a slightly future (micro)frame. */ ++ qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, ++ SCHEDULE_SLOP); ++ qh->interval = urb->interval; ++ ++#if 0 ++ /* Increase interrupt polling rate for debugging. */ ++ if (qh->ep_type == UE_INTERRUPT) { ++ qh->interval = 8; ++ } ++#endif ++ hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0); ++ if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && ++ ((dev_speed == USB_SPEED_LOW) || ++ (dev_speed == USB_SPEED_FULL))) { ++ qh->interval *= 8; ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ ++ } ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD QH Initialized\n"); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - qh = %p\n", qh); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Device Address = %d\n", ++ dwc_otg_hcd_get_dev_addr(&urb->pipe_info)); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Endpoint %d, %s\n", ++ dwc_otg_hcd_get_ep_num(&urb->pipe_info), ++ dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"); ++ switch (dev_speed) { ++ case USB_SPEED_LOW: ++ qh->dev_speed = DWC_OTG_EP_SPEED_LOW; ++ speed = "low"; ++ break; ++ case USB_SPEED_FULL: ++ qh->dev_speed = DWC_OTG_EP_SPEED_FULL; ++ speed = "full"; ++ break; ++ case USB_SPEED_HIGH: ++ qh->dev_speed = DWC_OTG_EP_SPEED_HIGH; ++ speed = "high"; ++ break; ++ default: ++ speed = "?"; ++ break; ++ } ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Speed = %s\n", speed); ++ ++ switch (qh->ep_type) { ++ case UE_ISOCHRONOUS: ++ type = "isochronous"; ++ break; ++ case UE_INTERRUPT: ++ type = "interrupt"; ++ break; ++ case UE_CONTROL: ++ type = "control"; ++ break; ++ case UE_BULK: ++ type = "bulk"; ++ break; ++ default: ++ type = "?"; ++ break; ++ } ++ ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", type); ++ ++#ifdef DEBUG ++ if (qh->ep_type == UE_INTERRUPT) { ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - usecs = %d\n", ++ qh->usecs); ++ DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - interval = %d\n", ++ qh->interval); ++ } ++#endif ++ ++} ++ ++/** ++ * This function allocates and initializes a QH. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param urb Holds the information about the device/endpoint that we need ++ * to initialize the QH. ++ * @param atomic_alloc Flag to do atomic allocation if needed ++ * ++ * @return Returns pointer to the newly allocated QH, or NULL on error. */ ++dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, ++ dwc_otg_hcd_urb_t * urb, int atomic_alloc) ++{ ++ dwc_otg_qh_t *qh; ++ ++ /* Allocate memory */ ++ /** @todo add memflags argument */ ++ qh = dwc_otg_hcd_qh_alloc(atomic_alloc); ++ if (qh == NULL) { ++ DWC_ERROR("qh allocation failed"); ++ return NULL; ++ } ++ ++ qh_init(hcd, qh, urb); ++ ++ if (hcd->core_if->dma_desc_enable ++ && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { ++ dwc_otg_hcd_qh_free(hcd, qh); ++ return NULL; ++ } ++ ++ return qh; ++} ++ ++/* microframe_schedule=0 start */ ++ ++/** ++ * Checks that a channel is available for a periodic transfer. ++ * ++ * @return 0 if successful, negative error code otherise. ++ */ ++static int periodic_channel_available(dwc_otg_hcd_t * hcd) ++{ ++ /* ++ * Currently assuming that there is a dedicated host channnel for each ++ * periodic transaction plus at least one host channel for ++ * non-periodic transactions. ++ */ ++ int status; ++ int num_channels; ++ ++ num_channels = hcd->core_if->core_params->host_channels; ++ if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) ++ && (hcd->periodic_channels < num_channels - 1)) { ++ status = 0; ++ } else { ++ DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", ++ __func__, num_channels, hcd->periodic_channels, hcd->non_periodic_channels); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Checks that there is sufficient bandwidth for the specified QH in the ++ * periodic schedule. For simplicity, this calculation assumes that all the ++ * transfers in the periodic schedule may occur in the same (micro)frame. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH containing periodic bandwidth required. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status; ++ int16_t max_claimed_usecs; ++ ++ status = 0; ++ ++ if ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) || qh->do_split) { ++ /* ++ * High speed mode. ++ * Max periodic usecs is 80% x 125 usec = 100 usec. ++ */ ++ ++ max_claimed_usecs = 100 - qh->usecs; ++ } else { ++ /* ++ * Full speed mode. ++ * Max periodic usecs is 90% x 1000 usec = 900 usec. ++ */ ++ max_claimed_usecs = 900 - qh->usecs; ++ } ++ ++ if (hcd->periodic_usecs > max_claimed_usecs) { ++ DWC_INFO("%s: already claimed usecs %d, required usecs %d\n", __func__, hcd->periodic_usecs, qh->usecs); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/* microframe_schedule=0 end */ ++ ++/** ++ * Microframe scheduler ++ * track the total use in hcd->frame_usecs ++ * keep each qh use in qh->frame_usecs ++ * when surrendering the qh then donate the time back ++ */ ++const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 }; ++ ++/* ++ * called from dwc_otg_hcd.c:dwc_otg_hcd_init ++ */ ++int init_hcd_usecs(dwc_otg_hcd_t *_hcd) ++{ ++ int i; ++ for (i=0; i<8; i++) { ++ _hcd->frame_usecs[i] = max_uframe_usecs[i]; ++ } ++ return 0; ++} ++ ++static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) ++{ ++ int i; ++ unsigned short utime; ++ int t_left; ++ int ret; ++ int done; ++ ++ ret = -1; ++ utime = _qh->usecs; ++ t_left = utime; ++ i = 0; ++ done = 0; ++ while (done == 0) { ++ /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */ ++ if (utime <= _hcd->frame_usecs[i]) { ++ _hcd->frame_usecs[i] -= utime; ++ _qh->frame_usecs[i] += utime; ++ t_left -= utime; ++ ret = i; ++ done = 1; ++ return ret; ++ } else { ++ i++; ++ if (i == 8) { ++ done = 1; ++ ret = -1; ++ } ++ } ++ } ++ return ret; ++ } ++ ++/* ++ * use this for FS apps that can span multiple uframes ++ */ ++static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) ++{ ++ int i; ++ int j; ++ unsigned short utime; ++ int t_left; ++ int ret; ++ int done; ++ unsigned short xtime; ++ ++ ret = -1; ++ utime = _qh->usecs; ++ t_left = utime; ++ i = 0; ++ done = 0; ++loop: ++ while (done == 0) { ++ if(_hcd->frame_usecs[i] <= 0) { ++ i++; ++ if (i == 8) { ++ done = 1; ++ ret = -1; ++ } ++ goto loop; ++ } ++ ++ /* ++ * we need n consecutive slots ++ * so use j as a start slot j plus j+1 must be enough time (for now) ++ */ ++ xtime= _hcd->frame_usecs[i]; ++ for (j = i+1 ; j < 8 ; j++ ) { ++ /* ++ * if we add this frame remaining time to xtime we may ++ * be OK, if not we need to test j for a complete frame ++ */ ++ if ((xtime+_hcd->frame_usecs[j]) < utime) { ++ if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) { ++ j = 8; ++ ret = -1; ++ continue; ++ } ++ } ++ if (xtime >= utime) { ++ ret = i; ++ j = 8; /* stop loop with a good value ret */ ++ continue; ++ } ++ /* add the frame time to x time */ ++ xtime += _hcd->frame_usecs[j]; ++ /* we must have a fully available next frame or break */ ++ if ((xtime < utime) ++ && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) { ++ ret = -1; ++ j = 8; /* stop loop with a bad value ret */ ++ continue; ++ } ++ } ++ if (ret >= 0) { ++ t_left = utime; ++ for (j = i; (t_left>0) && (j < 8); j++ ) { ++ t_left -= _hcd->frame_usecs[j]; ++ if ( t_left <= 0 ) { ++ _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left; ++ _hcd->frame_usecs[j]= -t_left; ++ ret = i; ++ done = 1; ++ } else { ++ _qh->frame_usecs[j] += _hcd->frame_usecs[j]; ++ _hcd->frame_usecs[j] = 0; ++ } ++ } ++ } else { ++ i++; ++ if (i == 8) { ++ done = 1; ++ ret = -1; ++ } ++ } ++ } ++ return ret; ++} ++ ++static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) ++{ ++ int ret; ++ ret = -1; ++ ++ if (_qh->speed == USB_SPEED_HIGH) { ++ /* if this is a hs transaction we need a full frame */ ++ ret = find_single_uframe(_hcd, _qh); ++ } else { ++ /* if this is a fs transaction we may need a sequence of frames */ ++ ret = find_multi_uframe(_hcd, _qh); ++ } ++ return ret; ++} ++ ++/** ++ * Checks that the max transfer size allowed in a host channel is large enough ++ * to handle the maximum data transfer in a single (micro)frame for a periodic ++ * transfer. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for a periodic endpoint. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int check_max_xfer_size(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status; ++ uint32_t max_xfer_size; ++ uint32_t max_channel_xfer_size; ++ ++ status = 0; ++ ++ max_xfer_size = dwc_max_packet(qh->maxp) * dwc_hb_mult(qh->maxp); ++ max_channel_xfer_size = hcd->core_if->core_params->max_transfer_size; ++ ++ if (max_xfer_size > max_channel_xfer_size) { ++ DWC_INFO("%s: Periodic xfer length %d > " "max xfer length for channel %d\n", ++ __func__, max_xfer_size, max_channel_xfer_size); //NOTICE ++ status = -DWC_E_NO_SPACE; ++ } ++ ++ return status; ++} ++ ++/** ++ * Schedules an interrupt or isochronous transfer in the periodic schedule. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for the periodic transfer. The QH should already contain the ++ * scheduling information. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status = 0; ++ ++ if (microframe_schedule) { ++ int frame; ++ status = find_uframe(hcd, qh); ++ frame = -1; ++ if (status == 0) { ++ frame = 7; ++ } else { ++ if (status > 0 ) ++ frame = status-1; ++ } ++ ++ /* Set the new frame up */ ++ if (frame > -1) { ++ qh->sched_frame &= ~0x7; ++ qh->sched_frame |= (frame & 7); ++ } ++ ++ if (status != -1) ++ status = 0; ++ } else { ++ status = periodic_channel_available(hcd); ++ if (status) { ++ DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ status = check_periodic_bandwidth(hcd, qh); ++ } ++ if (status) { ++ DWC_INFO("%s: Insufficient periodic bandwidth for " ++ "periodic transfer.\n", __func__); ++ return status; ++ } ++ status = check_max_xfer_size(hcd, qh); ++ if (status) { ++ DWC_INFO("%s: Channel max transfer size too small " ++ "for periodic transfer.\n", __func__); ++ return status; ++ } ++ ++ if (hcd->core_if->dma_desc_enable) { ++ /* Don't rely on SOF and start in ready schedule */ ++ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry); ++ } ++ else { ++ /* Always start in the inactive schedule. */ ++ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry); ++ } ++ ++ if (!microframe_schedule) { ++ /* Reserve the periodic channel. */ ++ hcd->periodic_channels++; ++ } ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs += qh->usecs; ++ ++ return status; ++} ++ ++/** ++ * This function adds a QH to either the non periodic or periodic schedule if ++ * it is not already in the schedule. If the QH is already in the schedule, no ++ * action is taken. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int status = 0; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ /* QH already in a schedule. */ ++ return status; ++ } ++ ++ /* Add the new QH to the appropriate schedule */ ++ if (dwc_qh_is_non_per(qh)) { ++ /* Always start in the inactive schedule. */ ++ DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive, ++ &qh->qh_list_entry); ++ } else { ++ status = schedule_periodic(hcd, qh); ++ if ( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ hcd->periodic_qh_count++; ++ } ++ ++ return status; ++} ++ ++/** ++ * Removes an interrupt or isochronous transfer from the periodic schedule. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh QH for the periodic transfer. ++ */ ++static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int i; ++ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ ++ /* Update claimed usecs per (micro)frame. */ ++ hcd->periodic_usecs -= qh->usecs; ++ ++ if (!microframe_schedule) { ++ /* Release the periodic channel reservation. */ ++ hcd->periodic_channels--; ++ } else { ++ for (i = 0; i < 8; i++) { ++ hcd->frame_usecs[i] += qh->frame_usecs[i]; ++ qh->frame_usecs[i] = 0; ++ } ++ } ++} ++ ++/** ++ * Removes a QH from either the non-periodic or periodic schedule. Memory is ++ * not freed. ++ * ++ * @param hcd The HCD state structure. ++ * @param qh QH to remove from schedule. */ ++void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { ++ /* QH is not in a schedule. */ ++ return; ++ } ++ ++ if (dwc_qh_is_non_per(qh)) { ++ if (hcd->non_periodic_qh_ptr == &qh->qh_list_entry) { ++ hcd->non_periodic_qh_ptr = ++ hcd->non_periodic_qh_ptr->next; ++ } ++ DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ } else { ++ deschedule_periodic(hcd, qh); ++ hcd->periodic_qh_count--; ++ if( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } ++ } ++} ++ ++/** ++ * Deactivates a QH. For non-periodic QHs, removes the QH from the active ++ * non-periodic schedule. The QH is added to the inactive non-periodic ++ * schedule if any QTDs are still attached to the QH. ++ * ++ * For periodic QHs, the QH is removed from the periodic queued schedule. If ++ * there are any QTDs still attached to the QH, the QH is added to either the ++ * periodic inactive schedule or the periodic ready schedule and its next ++ * scheduled frame is calculated. The QH is placed in the ready schedule if ++ * the scheduled frame has been reached already. Otherwise it's placed in the ++ * inactive schedule. If there are no QTDs attached to the QH, the QH is ++ * completely removed from the periodic schedule. ++ */ ++void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ int sched_next_periodic_split) ++{ ++ if (dwc_qh_is_non_per(qh)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule. */ ++ dwc_otg_hcd_qh_add(hcd, qh); ++ } ++ } else { ++ uint16_t frame_number = dwc_otg_hcd_get_frame_number(hcd); ++ ++ if (qh->do_split) { ++ /* Schedule the next continuing periodic split transfer */ ++ if (sched_next_periodic_split) { ++ ++ qh->sched_frame = frame_number; ++ if (dwc_frame_num_le(frame_number, ++ dwc_frame_num_inc ++ (qh->start_split_frame, ++ 1))) { ++ /* ++ * Allow one frame to elapse after start ++ * split microframe before scheduling ++ * complete split, but DONT if we are ++ * doing the next start split in the ++ * same frame for an ISOC out. ++ */ ++ if ((qh->ep_type != UE_ISOCHRONOUS) || ++ (qh->ep_is_in != 0)) { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->sched_frame, 1); ++ } ++ } ++ } else { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->start_split_frame, ++ qh->interval); ++ if (dwc_frame_num_le ++ (qh->sched_frame, frame_number)) { ++ qh->sched_frame = frame_number; ++ } ++ qh->sched_frame |= 0x7; ++ qh->start_split_frame = qh->sched_frame; ++ } ++ } else { ++ qh->sched_frame = ++ dwc_frame_num_inc(qh->sched_frame, qh->interval); ++ if (dwc_frame_num_le(qh->sched_frame, frame_number)) { ++ qh->sched_frame = frame_number; ++ } ++ } ++ ++ if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* ++ * Remove from periodic_sched_queued and move to ++ * appropriate queue. ++ */ ++ if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) || ++ (!microframe_schedule && qh->sched_frame == frame_number)) { ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, ++ &qh->qh_list_entry); ++ } else { ++ DWC_LIST_MOVE_HEAD ++ (&hcd->periodic_sched_inactive, ++ &qh->qh_list_entry); ++ } ++ } ++ } ++} ++ ++/** ++ * This function allocates and initializes a QTD. ++ * ++ * @param urb The URB to create a QTD from. Each URB-QTD pair will end up ++ * pointing to each other so each pair should have a unique correlation. ++ * @param atomic_alloc Flag to do atomic alloc if needed ++ * ++ * @return Returns pointer to the newly allocated QTD, or NULL on error. */ ++dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc) ++{ ++ dwc_otg_qtd_t *qtd; ++ ++ qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc); ++ if (qtd == NULL) { ++ return NULL; ++ } ++ ++ dwc_otg_hcd_qtd_init(qtd, urb); ++ return qtd; ++} ++ ++/** ++ * Initializes a QTD structure. ++ * ++ * @param qtd The QTD to initialize. ++ * @param urb The URB to use for initialization. */ ++void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb) ++{ ++ dwc_memset(qtd, 0, sizeof(dwc_otg_qtd_t)); ++ qtd->urb = urb; ++ if (dwc_otg_hcd_get_pipe_type(&urb->pipe_info) == UE_CONTROL) { ++ /* ++ * The only time the QTD data toggle is used is on the data ++ * phase of control transfers. This phase always starts with ++ * DATA1. ++ */ ++ qtd->data_toggle = DWC_OTG_HC_PID_DATA1; ++ qtd->control_phase = DWC_OTG_CONTROL_SETUP; ++ } ++ ++ /* start split */ ++ qtd->complete_split = 0; ++ qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL; ++ qtd->isoc_split_offset = 0; ++ qtd->in_process = 0; ++ ++ /* Store the qtd ptr in the urb to reference what QTD. */ ++ urb->qtd = qtd; ++ return; ++} ++ ++/** ++ * This function adds a QTD to the QTD-list of a QH. It will find the correct ++ * QH to place the QTD into. If it does not find a QH, then it will create a ++ * new QH. If the QH to which the QTD is added is not currently scheduled, it ++ * is placed into the proper schedule based on its EP type. ++ * ++ * @param[in] qtd The QTD to add ++ * @param[in] hcd The DWC HCD structure ++ * @param[out] qh out parameter to return queue head ++ * @param atomic_alloc Flag to do atomic alloc if needed ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, ++ dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc) ++{ ++ int retval = 0; ++ dwc_irqflags_t flags; ++ ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ /* ++ * Get the QH which holds the QTD-list to insert to. Create QH if it ++ * doesn't exist. ++ */ ++ if (*qh == NULL) { ++ *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc); ++ if (*qh == NULL) { ++ retval = -1; ++ goto done; ++ } ++ } ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ retval = dwc_otg_hcd_qh_add(hcd, *qh); ++ if (retval == 0) { ++ DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd, ++ qtd_list_entry); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); ++ ++done: ++ ++ return retval; ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h +new file mode 100644 +index 0000000..a7e9076 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h +@@ -0,0 +1,185 @@ ++#ifndef _DWC_OS_DEP_H_ ++#define _DWC_OS_DEP_H_ ++ ++/** ++ * @file ++ * ++ * This file contains OS dependent structures. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#ifdef PCI_INTERFACE ++# include ++#endif ++ ++#ifdef LM_INTERFACE ++# include ++# include ++# include ++# include ++# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) ++# include ++# include ++# include ++# include ++# else ++/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - ++ here we assume that the machine architecture provides definitions ++ in its own header ++*/ ++# include ++# include ++# endif ++#endif ++ ++#ifdef PLATFORM_INTERFACE ++#include ++#include ++#endif ++ ++/** The OS page size */ ++#define DWC_OS_PAGE_SIZE PAGE_SIZE ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ++typedef int gfp_t; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++# define IRQF_SHARED SA_SHIRQ ++#endif ++ ++typedef struct os_dependent { ++ /** Base address returned from ioremap() */ ++ void *base; ++ ++ /** Register offset for Diagnostic API */ ++ uint32_t reg_offset; ++ ++#ifdef LM_INTERFACE ++ struct lm_device *lmdev; ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *pcidev; ++ ++ /** Start address of a PCI region */ ++ resource_size_t rsrc_start; ++ ++ /** Length address of a PCI region */ ++ resource_size_t rsrc_len; ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *platformdev; ++#endif ++ ++} os_dependent_t; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++ ++ ++/* Type for the our device on the chosen bus */ ++#if defined(LM_INTERFACE) ++typedef struct lm_device dwc_bus_dev_t; ++#elif defined(PCI_INTERFACE) ++typedef struct pci_dev dwc_bus_dev_t; ++#elif defined(PLATFORM_INTERFACE) ++typedef struct platform_device dwc_bus_dev_t; ++#endif ++ ++/* Helper macro to retrieve drvdata from the device on the chosen bus */ ++#if defined(LM_INTERFACE) ++#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev) ++#elif defined(PCI_INTERFACE) ++#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev) ++#elif defined(PLATFORM_INTERFACE) ++#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev) ++#endif ++ ++/** ++ * Helper macro returning the otg_device structure of a given struct device ++ * ++ * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev) ++ */ ++#ifdef LM_INTERFACE ++#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ ++ struct lm_device *lm_dev = \ ++ container_of(_dev, struct lm_device, dev); \ ++ _var = lm_get_drvdata(lm_dev); \ ++ } while (0) ++ ++#elif defined(PCI_INTERFACE) ++#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ ++ _var = dev_get_drvdata(_dev); \ ++ } while (0) ++ ++#elif defined(PLATFORM_INTERFACE) ++#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ ++ struct platform_device *platform_dev = \ ++ container_of(_dev, struct platform_device, dev); \ ++ _var = platform_get_drvdata(platform_dev); \ ++ } while (0) ++#endif ++ ++ ++/** ++ * Helper macro returning the struct dev of the given struct os_dependent ++ * ++ * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep) ++ */ ++#ifdef LM_INTERFACE ++#define DWC_OTG_OS_GETDEV(_osdep) \ ++ ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev) ++#elif defined(PCI_INTERFACE) ++#define DWC_OTG_OS_GETDEV(_osdep) \ ++ ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev) ++#elif defined(PLATFORM_INTERFACE) ++#define DWC_OTG_OS_GETDEV(_osdep) \ ++ ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev) ++#endif ++ ++ ++ ++ ++#endif /* _DWC_OS_DEP_H_ */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c +new file mode 100644 +index 0000000..c97d65c +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c +@@ -0,0 +1,2708 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ ++ * $Revision: #101 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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_HOST_ONLY ++ ++/** @file ++ * This file implements PCD Core. All code in this file is portable and doesn't ++ * use any OS specific functions. ++ * PCD Core provides Interface, defined in ++ * header file, which can be used to implement OS specific PCD interface. ++ * ++ * An important function of the PCD is managing interrupts generated ++ * by the DWC_otg controller. The implementation of the DWC_otg device ++ * mode interrupt service routines is in dwc_otg_pcd_intr.c. ++ * ++ * @todo Add Device Mode test modes (Test J mode, Test K mode, etc). ++ * @todo Does it work when the request size is greater than DEPTSIZ ++ * transfer size ++ * ++ */ ++ ++#include "dwc_otg_pcd.h" ++ ++#ifdef DWC_UTE_CFI ++#include "dwc_otg_cfi.h" ++ ++extern int init_cfi(cfiobject_t * cfiobj); ++#endif ++ ++/** ++ * Choose endpoint from ep arrays using usb_ep structure. ++ */ ++static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} ++ ++/** ++ * This function completes a request. It call's the request call back. ++ */ ++void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req, ++ int32_t status) ++{ ++ unsigned stopped = ep->stopped; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req); ++ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ ++ /* don't modify queue heads during completion callback */ ++ ep->stopped = 1; ++ /* spin_unlock/spin_lock now done in fops->complete() */ ++ ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status, ++ req->actual); ++ ++ if (ep->pcd->request_pending > 0) { ++ --ep->pcd->request_pending; ++ } ++ ++ ep->stopped = stopped; ++ DWC_FREE(req); ++} ++ ++/** ++ * This function terminates all the requsts in the EP request queue. ++ */ ++void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req; ++ ++ ep->stopped = 1; ++ ++ /* called with irqs blocked?? */ ++ while (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ dwc_otg_request_done(ep, req, -DWC_E_SHUTDOWN); ++ } ++} ++ ++void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, ++ const struct dwc_otg_pcd_function_ops *fops) ++{ ++ pcd->fops = fops; ++} ++ ++/** ++ * PCD Callback function for initializing the PCD when switching to ++ * device mode. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_start_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ /* ++ * Initialized the Core for Device mode. ++ */ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dwc_otg_core_dev_init(core_if); ++ /* Set core_if's lock pointer to the pcd->lock */ ++ core_if->lock = pcd->lock; ++ } ++ return 1; ++} ++ ++/** CFI-specific buffer allocation function for EP */ ++#ifdef DWC_UTE_CFI ++uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, ++ size_t buflen, int flags) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ ep = get_ep_from_handle(pcd, pep); ++ if (!ep) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen, ++ flags); ++} ++#else ++uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, ++ size_t buflen, int flags); ++#endif ++ ++/** ++ * PCD Callback function for notifying the PCD when resuming from ++ * suspend. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_resume_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ ++ if (pcd->fops->resume) { ++ pcd->fops->resume(pcd); ++ } ++ ++ /* Stop the SRP timeout timer. */ ++ if ((GET_CORE_IF(pcd)->core_params->phy_type != DWC_PHY_TYPE_PARAM_FS) ++ || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) { ++ if (GET_CORE_IF(pcd)->srp_timer_started) { ++ GET_CORE_IF(pcd)->srp_timer_started = 0; ++ DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer); ++ } ++ } ++ return 1; ++} ++ ++/** ++ * PCD Callback function for notifying the PCD device is suspended. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_suspend_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ ++ if (pcd->fops->suspend) { ++ DWC_SPINUNLOCK(pcd->lock); ++ pcd->fops->suspend(pcd); ++ DWC_SPINLOCK(pcd->lock); ++ } ++ ++ return 1; ++} ++ ++/** ++ * PCD Callback function for stopping the PCD when switching to Host ++ * mode. ++ * ++ * @param p void pointer to the dwc_otg_pcd_t ++ */ ++static int32_t dwc_otg_pcd_stop_cb(void *p) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ extern void dwc_otg_pcd_stop(dwc_otg_pcd_t * _pcd); ++ ++ dwc_otg_pcd_stop(pcd); ++ return 1; ++} ++ ++/** ++ * PCD Callback structure for handling mode switching. ++ */ ++static dwc_otg_cil_callbacks_t pcd_callbacks = { ++ .start = dwc_otg_pcd_start_cb, ++ .stop = dwc_otg_pcd_stop_cb, ++ .suspend = dwc_otg_pcd_suspend_cb, ++ .resume_wakeup = dwc_otg_pcd_resume_cb, ++ .p = 0, /* Set at registration */ ++}; ++ ++/** ++ * This function allocates a DMA Descriptor chain for the Endpoint ++ * buffer to be used for a transfer to/from the specified endpoint. ++ */ ++dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, ++ uint32_t count) ++{ ++ return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), ++ dma_desc_addr); ++} ++ ++/** ++ * This function frees a DMA Descriptor chain that was allocated by ep_alloc_desc. ++ */ ++void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, ++ uint32_t dma_desc_addr, uint32_t count) ++{ ++ DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, ++ dma_desc_addr); ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ ++ dsts_data_t dsts = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ int i, j; ++ uint32_t len; ++ ++ if (dwc_ep->is_in) ++ dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval; ++ else ++ dwc_ep->desc_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ ++ /** Allocate descriptors for double buffering */ ++ dwc_ep->iso_desc_addr = ++ dwc_otg_ep_alloc_desc_chain(&dwc_ep->iso_dma_desc_addr, ++ dwc_ep->desc_cnt * 2); ++ if (dwc_ep->desc_addr) { ++ DWC_WARN("%s, can't allocate DMA descriptor chain\n", __func__); ++ return; ++ } ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr; ++ dma_addr_t dma_ad; ++ uint32_t data_per_desc; ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[dwc_ep->num]; ++ int offset; ++ ++ addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; ++ dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma)); ++ ++ /** Buffer 0 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr0; ++ ++ sts.b_iso_out.bs = BS_HOST_READY; ++ sts.b_iso_out.rxsts = 0; ++ sts.b_iso_out.l = 0; ++ sts.b_iso_out.sp = 0; ++ sts.b_iso_out.ioc = 0; ++ sts.b_iso_out.pid = 0; ++ sts.b_iso_out.framenum = 0; ++ ++ offset = 0; ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ /** Buffer 1 descriptors setup */ ++ sts.b_iso_out.ioc = 0; ++ dma_ad = dwc_ep->dma_addr1; ++ ++ offset = 0; ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ ++ data_per_desc = ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ } ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ sts.b_iso_out.l = 1; ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = 0; ++ ++ /** Write dma_ad into DOEPDMA register */ ++ DWC_WRITE_REG32(&(out_regs->doepdma), ++ (uint32_t) dwc_ep->iso_dma_desc_addr); ++ ++ } ++ /** ISO IN EP */ ++ else { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc = dwc_ep->iso_desc_addr; ++ dma_addr_t dma_ad; ++ dwc_otg_dev_in_ep_regs_t *in_regs = ++ core_if->dev_if->in_ep_regs[dwc_ep->num]; ++ unsigned int frmnumber; ++ fifosize_data_t txfifosize, rxfifosize; ++ ++ txfifosize.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]-> ++ dtxfsts); ++ rxfifosize.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ ++ addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ ++ dma_ad = dwc_ep->dma_addr0; ++ ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ sts.b_iso_in.bs = BS_HOST_READY; ++ sts.b_iso_in.txsts = 0; ++ sts.b_iso_in.sp = ++ (dwc_ep->data_per_frame % dwc_ep->maxpacket) ? 1 : 0; ++ sts.b_iso_in.ioc = 0; ++ sts.b_iso_in.pid = dwc_ep->pkt_per_frm; ++ ++ frmnumber = dwc_ep->next_frame; ++ ++ sts.b_iso_in.framenum = frmnumber; ++ sts.b_iso_in.txbytes = dwc_ep->data_per_frame; ++ sts.b_iso_in.l = 0; ++ ++ /** Buffer 0 descriptors setup */ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ dma_ad += dwc_ep->data_per_frame; ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ } ++ ++ sts.b_iso_in.ioc = 1; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++dma_desc; ++ ++ /** Buffer 1 descriptors setup */ ++ sts.b_iso_in.ioc = 0; ++ dma_ad = dwc_ep->dma_addr1; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ dma_desc++; ++ ++ dma_ad += dwc_ep->data_per_frame; ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ ++ sts.b_iso_in.ioc = 0; ++ } ++ sts.b_iso_in.ioc = 1; ++ sts.b_iso_in.l = 1; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval; ++ ++ /** Write dma_ad into diepdma register */ ++ DWC_WRITE_REG32(&(in_regs->diepdma), ++ (uint32_t) dwc_ep->iso_dma_desc_addr); ++ } ++ /** Enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.usbactep = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++} ++ ++/** ++ * This function initializes a descriptor chain for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ if (core_if->dma_enable == 0 || core_if->dma_desc_enable != 0) { ++ return; ++ } else { ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ ++ ep->xfer_len = ++ ep->data_per_frame * ep->buf_proc_intrvl / ep->bInterval; ++ ep->pkt_cnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ ep->xfer_count = 0; ++ ep->xfer_buff = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; ++ ep->dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; ++ ++ if (ep->is_in) { ++ /* Program the transfer size and packet count ++ * as follows: xfersize = N * maxpacket + ++ * short_packet pktcnt = N + (short_packet ++ * exist ? 1 : 0) ++ */ ++ deptsiz.b.mc = ep->pkt_per_frm; ++ deptsiz.b.xfersize = ep->xfer_len; ++ deptsiz.b.pktcnt = ++ (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dieptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->in_ep_regs[ep->num]-> ++ diepdma), (uint32_t) ep->dma_addr); ++ ++ } else { ++ deptsiz.b.pktcnt = ++ (ep->xfer_len + (ep->maxpacket - 1)) / ++ ep->maxpacket; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ doeptsiz, deptsiz.d32); ++ ++ /* Write the DMA register */ ++ DWC_WRITE_REG32(& ++ (core_if->dev_if->out_ep_regs[ep->num]-> ++ doepdma), (uint32_t) ep->dma_addr); ++ ++ } ++ /** Enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ } ++} ++ ++/** ++ * This function does the setup for a data transfer for an EP and ++ * starts the transfer. For an IN transfer, the packets will be ++ * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, ++ * the packets are unloaded from the Rx FIFO in the ISR. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * ep) ++{ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ if (ep->is_in) { ++ ep->desc_cnt = ep->pkt_cnt / ep->pkt_per_frm; ++ } else { ++ ep->desc_cnt = ep->pkt_cnt; ++ } ++ dwc_otg_iso_ep_start_ddma_transfer(core_if, ep); ++ } else { ++ if (core_if->pti_enh_enable) { ++ dwc_otg_iso_ep_start_buf_transfer(core_if, ep); ++ } else { ++ ep->cur_pkt_addr = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep-> ++ xfer_buff0; ++ ep->cur_pkt_dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep-> ++ dma_addr0; ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ep); ++ } ++ } ++ } else { ++ ep->cur_pkt_addr = ++ (ep->proc_buf_num) ? ep->xfer_buff1 : ep->xfer_buff0; ++ ep->cur_pkt_dma_addr = ++ (ep->proc_buf_num) ? ep->dma_addr1 : ep->dma_addr0; ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ep); ++ } ++} ++ ++/** ++ * This function stops transfer for an EP and ++ * resets the ep's variables. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ */ ++ ++void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ depctl_data_t depctl = {.d32 = 0 }; ++ volatile uint32_t *addr; ++ ++ if (ep->is_in == 1) { ++ addr = &core_if->dev_if->in_ep_regs[ep->num]->diepctl; ++ } else { ++ addr = &core_if->dev_if->out_ep_regs[ep->num]->doepctl; ++ } ++ ++ /* disable the ep */ ++ depctl.d32 = DWC_READ_REG32(addr); ++ ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ ++ if (core_if->dma_desc_enable && ++ ep->iso_desc_addr && ep->iso_dma_desc_addr) { ++ dwc_otg_ep_free_desc_chain(ep->iso_desc_addr, ++ ep->iso_dma_desc_addr, ++ ep->desc_cnt * 2); ++ } ++ ++ /* reset varibales */ ++ ep->dma_addr0 = 0; ++ ep->dma_addr1 = 0; ++ ep->xfer_buff0 = 0; ++ ep->xfer_buff1 = 0; ++ ep->data_per_frame = 0; ++ ep->data_pattern_frame = 0; ++ ep->sync_frame = 0; ++ ep->buf_proc_intrvl = 0; ++ ep->bInterval = 0; ++ ep->proc_buf_num = 0; ++ ep->pkt_per_frm = 0; ++ ep->pkt_per_frm = 0; ++ ep->desc_cnt = 0; ++ ep->iso_desc_addr = 0; ++ ep->iso_dma_desc_addr = 0; ++} ++ ++int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf0, uint8_t * buf1, dwc_dma_t dma0, ++ dwc_dma_t dma1, int sync_frame, int dp_frame, ++ int data_per_frame, int start_frame, ++ int buf_proc_intrvl, void *req_handle, ++ int atomic_alloc) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags = 0; ++ dwc_ep_t *dwc_ep; ++ int32_t frm_data; ++ dsts_data_t dsts; ++ dwc_otg_core_if_t *core_if; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ core_if = GET_CORE_IF(pcd); ++ dwc_ep = &ep->dwc_ep; ++ ++ if (ep->iso_req_handle) { ++ DWC_WARN("ISO request in progress\n"); ++ } ++ ++ dwc_ep->dma_addr0 = dma0; ++ dwc_ep->dma_addr1 = dma1; ++ ++ dwc_ep->xfer_buff0 = buf0; ++ dwc_ep->xfer_buff1 = buf1; ++ ++ dwc_ep->data_per_frame = data_per_frame; ++ ++ /** @todo - pattern data support is to be implemented in the future */ ++ dwc_ep->data_pattern_frame = dp_frame; ++ dwc_ep->sync_frame = sync_frame; ++ ++ dwc_ep->buf_proc_intrvl = buf_proc_intrvl; ++ ++ dwc_ep->bInterval = 1 << (ep->desc->bInterval - 1); ++ ++ dwc_ep->proc_buf_num = 0; ++ ++ dwc_ep->pkt_per_frm = 0; ++ frm_data = ep->dwc_ep.data_per_frame; ++ while (frm_data > 0) { ++ dwc_ep->pkt_per_frm++; ++ frm_data -= ep->dwc_ep.maxpacket; ++ } ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ if (start_frame == -1) { ++ dwc_ep->next_frame = dsts.b.soffn + 1; ++ if (dwc_ep->bInterval != 1) { ++ dwc_ep->next_frame = ++ dwc_ep->next_frame + (dwc_ep->bInterval - 1 - ++ dwc_ep->next_frame % ++ dwc_ep->bInterval); ++ } ++ } else { ++ dwc_ep->next_frame = start_frame; ++ } ++ ++ if (!core_if->pti_enh_enable) { ++ dwc_ep->pkt_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ } else { ++ dwc_ep->pkt_cnt = ++ (dwc_ep->data_per_frame * ++ (dwc_ep->buf_proc_intrvl / dwc_ep->bInterval) ++ - 1 + dwc_ep->maxpacket) / dwc_ep->maxpacket; ++ } ++ ++ if (core_if->dma_desc_enable) { ++ dwc_ep->desc_cnt = ++ dwc_ep->buf_proc_intrvl * dwc_ep->pkt_per_frm / ++ dwc_ep->bInterval; ++ } ++ ++ if (atomic_alloc) { ++ dwc_ep->pkt_info = ++ DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } else { ++ dwc_ep->pkt_info = ++ DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } ++ if (!dwc_ep->pkt_info) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_NO_MEMORY; ++ } ++ if (core_if->pti_enh_enable) { ++ dwc_memset(dwc_ep->pkt_info, 0, ++ sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ } ++ ++ dwc_ep->cur_pkt = 0; ++ ep->iso_req_handle = req_handle; ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ dwc_otg_iso_ep_start_transfer(core_if, dwc_ep); ++ return 0; ++} ++ ++int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle) ++{ ++ dwc_irqflags_t flags = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ dwc_ep = &ep->dwc_ep; ++ ++ dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep); ++ ++ DWC_FREE(dwc_ep->pkt_info); ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (ep->iso_req_handle != req_handle) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ ep->iso_req_handle = 0; ++ return 0; ++} ++ ++/** ++ * This function is used for perodical data exchnage between PCD and gadget drivers. ++ * for Isochronous EPs ++ * ++ * - Every time a sync period completes this function is called to ++ * perform data exchange between PCD and gadget ++ */ ++void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, ++ void *req_handle) ++{ ++ int i; ++ dwc_ep_t *dwc_ep; ++ ++ dwc_ep = &ep->dwc_ep; ++ ++ DWC_SPINUNLOCK(ep->pcd->lock); ++ pcd->fops->isoc_complete(pcd, ep->priv, ep->iso_req_handle, ++ dwc_ep->proc_buf_num ^ 0x1); ++ DWC_SPINLOCK(ep->pcd->lock); ++ ++ for (i = 0; i < dwc_ep->pkt_cnt; ++i) { ++ dwc_ep->pkt_info[i].status = 0; ++ dwc_ep->pkt_info[i].offset = 0; ++ dwc_ep->pkt_info[i].length = 0; ++ } ++} ++ ++int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *iso_req_handle) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ dwc_ep = &ep->dwc_ep; ++ ++ return dwc_ep->pkt_cnt; ++} ++ ++void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *iso_req_handle, int packet, ++ int *status, int *actual, int *offset) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) ++ DWC_WARN("bad ep\n"); ++ ++ dwc_ep = &ep->dwc_ep; ++ ++ *status = dwc_ep->pkt_info[packet].status; ++ *actual = dwc_ep->pkt_info[packet].length; ++ *offset = dwc_ep->pkt_info[packet].offset; ++} ++ ++#endif /* DWC_EN_ISOC */ ++ ++static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep, ++ uint32_t is_in, uint32_t ep_num) ++{ ++ /* Init EP structure */ ++ pcd_ep->desc = 0; ++ pcd_ep->pcd = pcd; ++ pcd_ep->stopped = 1; ++ pcd_ep->queue_sof = 0; ++ ++ /* Init DWC ep structure */ ++ pcd_ep->dwc_ep.is_in = is_in; ++ pcd_ep->dwc_ep.num = ep_num; ++ pcd_ep->dwc_ep.active = 0; ++ pcd_ep->dwc_ep.tx_fifo_num = 0; ++ /* Control until ep is actvated */ ++ pcd_ep->dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; ++ pcd_ep->dwc_ep.maxpacket = MAX_PACKET_SIZE; ++ pcd_ep->dwc_ep.dma_addr = 0; ++ pcd_ep->dwc_ep.start_xfer_buff = 0; ++ pcd_ep->dwc_ep.xfer_buff = 0; ++ pcd_ep->dwc_ep.xfer_len = 0; ++ pcd_ep->dwc_ep.xfer_count = 0; ++ pcd_ep->dwc_ep.sent_zlp = 0; ++ pcd_ep->dwc_ep.total_len = 0; ++ pcd_ep->dwc_ep.desc_addr = 0; ++ pcd_ep->dwc_ep.dma_desc_addr = 0; ++ DWC_CIRCLEQ_INIT(&pcd_ep->queue); ++} ++ ++/** ++ * Initialize ep's ++ */ ++static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd) ++{ ++ int i; ++ uint32_t hwcfg1; ++ dwc_otg_pcd_ep_t *ep; ++ int in_ep_cntr, out_ep_cntr; ++ uint32_t num_in_eps = (GET_CORE_IF(pcd))->dev_if->num_in_eps; ++ uint32_t num_out_eps = (GET_CORE_IF(pcd))->dev_if->num_out_eps; ++ ++ /** ++ * Initialize the EP0 structure. ++ */ ++ ep = &pcd->ep0; ++ dwc_otg_pcd_init_ep(pcd, ep, 0, 0); ++ ++ in_ep_cntr = 0; ++ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 3; ++ for (i = 1; in_ep_cntr < num_in_eps; i++) { ++ if ((hwcfg1 & 0x1) == 0) { ++ dwc_otg_pcd_ep_t *ep = &pcd->in_ep[in_ep_cntr]; ++ in_ep_cntr++; ++ /** ++ * @todo NGS: Add direction to EP, based on contents ++ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? ++ * sprintf(";r ++ */ ++ dwc_otg_pcd_init_ep(pcd, ep, 1 /* IN */ , i); ++ ++ DWC_CIRCLEQ_INIT(&ep->queue); ++ } ++ hwcfg1 >>= 2; ++ } ++ ++ out_ep_cntr = 0; ++ hwcfg1 = (GET_CORE_IF(pcd))->hwcfg1.d32 >> 2; ++ for (i = 1; out_ep_cntr < num_out_eps; i++) { ++ if ((hwcfg1 & 0x1) == 0) { ++ dwc_otg_pcd_ep_t *ep = &pcd->out_ep[out_ep_cntr]; ++ out_ep_cntr++; ++ /** ++ * @todo NGS: Add direction to EP, based on contents ++ * of HWCFG1. Need a copy of HWCFG1 in pcd structure? ++ * sprintf(";r ++ */ ++ dwc_otg_pcd_init_ep(pcd, ep, 0 /* OUT */ , i); ++ DWC_CIRCLEQ_INIT(&ep->queue); ++ } ++ hwcfg1 >>= 2; ++ } ++ ++ pcd->ep0state = EP0_DISCONNECT; ++ pcd->ep0.dwc_ep.maxpacket = MAX_EP0_SIZE; ++ pcd->ep0.dwc_ep.type = DWC_OTG_EP_TYPE_CONTROL; ++} ++ ++/** ++ * This function is called when the SRP timer expires. The SRP should ++ * complete within 6 seconds. ++ */ ++static void srp_timeout(void *ptr) ++{ ++ gotgctl_data_t gotgctl; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ volatile uint32_t *addr = &core_if->core_global_regs->gotgctl; ++ ++ gotgctl.d32 = DWC_READ_REG32(addr); ++ ++ core_if->srp_timer_started = 0; ++ ++ if (core_if->adp_enable) { ++ if (gotgctl.b.bsesvld == 0) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ DWC_PRINTF("SRP Timeout BSESSVLD = 0\n"); ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ DWC_PRINTF("SRP Timeout BSESSVLD = 1\n"); ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++ ++ if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) && ++ (core_if->core_params->i2c_enable)) { ++ DWC_PRINTF("SRP Timeout\n"); ++ ++ if ((core_if->srp_success) && (gotgctl.b.bsesvld)) { ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ ++ /* Clear Session Request */ ++ gotgctl.d32 = 0; ++ gotgctl.b.sesreq = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, ++ gotgctl.d32, 0); ++ ++ core_if->srp_success = 0; ++ } else { ++ __DWC_ERROR("Device not connected/responding\n"); ++ gotgctl.b.sesreq = 0; ++ DWC_WRITE_REG32(addr, gotgctl.d32); ++ } ++ } else if (gotgctl.b.sesreq) { ++ DWC_PRINTF("SRP Timeout\n"); ++ ++ __DWC_ERROR("Device not connected/responding\n"); ++ gotgctl.b.sesreq = 0; ++ DWC_WRITE_REG32(addr, gotgctl.d32); ++ } else { ++ DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32); ++ } ++} ++ ++/** ++ * Tasklet ++ * ++ */ ++extern void start_next_request(dwc_otg_pcd_ep_t * ep); ++ ++static void start_xfer_tasklet_func(void *data) ++{ ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ int i; ++ depctl_data_t diepctl; ++ ++ DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n"); ++ ++ diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0.queue_sof) { ++ pcd->ep0.queue_sof = 0; ++ start_next_request(&pcd->ep0); ++ // break; ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; i++) { ++ depctl_data_t diepctl; ++ diepctl.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ ++ if (pcd->in_ep[i].queue_sof) { ++ pcd->in_ep[i].queue_sof = 0; ++ start_next_request(&pcd->in_ep[i]); ++ // break; ++ } ++ } ++ ++ return; ++} ++ ++/** ++ * This function initialized the PCD portion of the driver. ++ * ++ */ ++dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_pcd_t *pcd = NULL; ++ dwc_otg_dev_if_t *dev_if; ++ int i; ++ ++ /* ++ * Allocate PCD structure ++ */ ++ pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t)); ++ ++ if (pcd == NULL) { ++ return NULL; ++ } ++ ++ pcd->lock = DWC_SPINLOCK_ALLOC(); ++ DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n", ++ pcd, core_if);//GRAYG ++ if (!pcd->lock) { ++ DWC_ERROR("Could not allocate lock for pcd"); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ /* Set core_if's lock pointer to hcd->lock */ ++ core_if->lock = pcd->lock; ++ pcd->core_if = core_if; ++ ++ dev_if = core_if->dev_if; ++ dev_if->isoc_ep = NULL; ++ ++ if (core_if->hwcfg4.b.ded_fifo_en) { ++ DWC_PRINTF("Dedicated Tx FIFOs mode\n"); ++ } else { ++ DWC_PRINTF("Shared Tx FIFO mode\n"); ++ } ++ ++ /* ++ * Initialized the Core for Device mode here if there is nod ADP support. ++ * Otherwise it will be done later in dwc_otg_adp_start routine. ++ */ ++ if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) { ++ dwc_otg_core_dev_init(core_if); ++ } ++ ++ /* ++ * Register the PCD Callbacks. ++ */ ++ dwc_otg_cil_register_pcd_callbacks(core_if, &pcd_callbacks, pcd); ++ ++ /* ++ * Initialize the DMA buffer for SETUP packets ++ */ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ pcd->setup_pkt = ++ DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, ++ &pcd->setup_pkt_dma_handle); ++ if (pcd->setup_pkt == NULL) { ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ pcd->status_buf = ++ DWC_DMA_ALLOC(sizeof(uint16_t), ++ &pcd->status_buf_dma_handle); ++ if (pcd->status_buf == NULL) { ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ pcd->setup_pkt, pcd->setup_pkt_dma_handle); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ dev_if->setup_desc_addr[0] = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[0], 1); ++ dev_if->setup_desc_addr[1] = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[1], 1); ++ dev_if->in_desc_addr = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_in_desc_addr, 1); ++ dev_if->out_desc_addr = ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_out_desc_addr, 1); ++ pcd->data_terminated = 0; ++ ++ if (dev_if->setup_desc_addr[0] == 0 ++ || dev_if->setup_desc_addr[1] == 0 ++ || dev_if->in_desc_addr == 0 ++ || dev_if->out_desc_addr == 0) { ++ ++ if (dev_if->out_desc_addr) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, 1); ++ if (dev_if->in_desc_addr) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); ++ if (dev_if->setup_desc_addr[1]) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr[1], 1); ++ if (dev_if->setup_desc_addr[0]) ++ dwc_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr[0], 1); ++ ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, ++ pcd->setup_pkt, ++ pcd->setup_pkt_dma_handle); ++ DWC_DMA_FREE(sizeof(*pcd->status_buf), ++ pcd->status_buf, ++ pcd->status_buf_dma_handle); ++ ++ DWC_FREE(pcd); ++ ++ return NULL; ++ } ++ } ++ } else { ++ pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5); ++ if (pcd->setup_pkt == NULL) { ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ ++ pcd->status_buf = DWC_ALLOC(sizeof(uint16_t)); ++ if (pcd->status_buf == NULL) { ++ DWC_FREE(pcd->setup_pkt); ++ DWC_FREE(pcd); ++ return NULL; ++ } ++ } ++ ++ dwc_otg_pcd_reinit(pcd); ++ ++ /* Allocate the cfi object for the PCD */ ++#ifdef DWC_UTE_CFI ++ pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t)); ++ if (NULL == pcd->cfi) ++ goto fail; ++ if (init_cfi(pcd->cfi)) { ++ CFI_INFO("%s: Failed to init the CFI object\n", __func__); ++ goto fail; ++ } ++#endif ++ ++ /* Initialize tasklets */ ++ pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet", ++ start_xfer_tasklet_func, pcd); ++ pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet", ++ do_test_mode, pcd); ++ ++ /* Initialize SRP timer */ ++ core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if); ++ ++ if (core_if->core_params->dev_out_nak) { ++ /** ++ * Initialize xfer timeout timer. Implemented for ++ * 2.93a feature "Device DDMA OUT NAK Enhancement" ++ */ ++ for(i = 0; i < MAX_EPS_CHANNELS; i++) { ++ pcd->core_if->ep_xfer_timer[i] = ++ DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout, ++ &pcd->core_if->ep_xfer_info[i]); ++ } ++ } ++ ++ return pcd; ++#ifdef DWC_UTE_CFI ++fail: ++#endif ++ if (pcd->setup_pkt) ++ DWC_FREE(pcd->setup_pkt); ++ if (pcd->status_buf) ++ DWC_FREE(pcd->status_buf); ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi) ++ DWC_FREE(pcd->cfi); ++#endif ++ if (pcd) ++ DWC_FREE(pcd); ++ return NULL; ++ ++} ++ ++/** ++ * Remove PCD specific data ++ */ ++void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ int i; ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); ++ pcd->core_if->ep_xfer_info[i].state = 0; ++ } ++ } ++ ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, ++ pcd->setup_pkt_dma_handle); ++ DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, ++ pcd->status_buf_dma_handle); ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr ++ [0], 1); ++ dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr ++ [1], 1); ++ dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); ++ dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, ++ 1); ++ } ++ } else { ++ DWC_FREE(pcd->setup_pkt); ++ DWC_FREE(pcd->status_buf); ++ } ++ DWC_SPINLOCK_FREE(pcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ pcd->core_if->lock = NULL; ++ ++ DWC_TASK_FREE(pcd->start_xfer_tasklet); ++ DWC_TASK_FREE(pcd->test_mode_tasklet); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ if (pcd->core_if->ep_xfer_timer[i]) { ++ DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]); ++ } ++ } ++ } ++ ++/* Release the CFI object's dynamic memory */ ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi->ops.release) { ++ pcd->cfi->ops.release(pcd->cfi); ++ } ++#endif ++ ++ DWC_FREE(pcd); ++} ++ ++/** ++ * Returns whether registered pcd is dual speed or not ++ */ ++uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) || ++ ((core_if->hwcfg2.b.hs_phy_type == 2) && ++ (core_if->hwcfg2.b.fs_phy_type == 1) && ++ (core_if->core_params->ulpi_fs_ls))) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/** ++ * Returns whether registered pcd is OTG capable or not ++ */ ++uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ gusbcfg_data_t usbcfg = {.d32 = 0 }; ++ ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++/** ++ * This function assigns periodic Tx FIFO to an periodic EP ++ * in shared Tx FIFO mode ++ */ ++static uint32_t assign_tx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t TxMsk = 1; ++ int i; ++ ++ for (i = 0; i < core_if->hwcfg4.b.num_in_eps; ++i) { ++ if ((TxMsk & core_if->tx_msk) == 0) { ++ core_if->tx_msk |= TxMsk; ++ return i + 1; ++ } ++ TxMsk <<= 1; ++ } ++ return 0; ++} ++ ++/** ++ * This function assigns periodic Tx FIFO to an periodic EP ++ * in shared Tx FIFO mode ++ */ ++static uint32_t assign_perio_tx_fifo(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t PerTxMsk = 1; ++ int i; ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; ++i) { ++ if ((PerTxMsk & core_if->p_tx_msk) == 0) { ++ core_if->p_tx_msk |= PerTxMsk; ++ return i + 1; ++ } ++ PerTxMsk <<= 1; ++ } ++ return 0; ++} ++ ++/** ++ * This function releases periodic Tx FIFO ++ * in shared Tx FIFO mode ++ */ ++static void release_perio_tx_fifo(dwc_otg_core_if_t * core_if, ++ uint32_t fifo_num) ++{ ++ core_if->p_tx_msk = ++ (core_if->p_tx_msk & (1 << (fifo_num - 1))) ^ core_if->p_tx_msk; ++} ++ ++/** ++ * This function releases periodic Tx FIFO ++ * in shared Tx FIFO mode ++ */ ++static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num) ++{ ++ core_if->tx_msk = ++ (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk; ++} ++ ++/** ++ * This function is being called from gadget ++ * to enable PCD endpoint. ++ */ ++int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, ++ const uint8_t * ep_desc, void *usb_ep) ++{ ++ int num, dir; ++ dwc_otg_pcd_ep_t *ep = NULL; ++ const usb_endpoint_descriptor_t *desc; ++ dwc_irqflags_t flags; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ int retval = 0; ++ int i, epcount; ++ ++ desc = (const usb_endpoint_descriptor_t *)ep_desc; ++ ++ if (!desc) { ++ pcd->ep0.priv = usb_ep; ++ ep = &pcd->ep0; ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ num = UE_GET_ADDR(desc->bEndpointAddress); ++ dir = UE_GET_DIR(desc->bEndpointAddress); ++ ++ if (!desc->wMaxPacketSize) { ++ DWC_WARN("bad maxpacketsize\n"); ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ if (dir == UE_DIR_IN) { ++ epcount = pcd->core_if->dev_if->num_in_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->in_ep[i].dwc_ep.num) { ++ ep = &pcd->in_ep[i]; ++ break; ++ } ++ } ++ } else { ++ epcount = pcd->core_if->dev_if->num_out_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->out_ep[i].dwc_ep.num) { ++ ep = &pcd->out_ep[i]; ++ break; ++ } ++ } ++ } ++ ++ if (!ep) { ++ DWC_WARN("bad address\n"); ++ retval = -DWC_E_INVALID; ++ goto out; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ ep->desc = desc; ++ ep->priv = usb_ep; ++ ++ /* ++ * Activate the EP ++ */ ++ ep->stopped = 0; ++ ++ ep->dwc_ep.is_in = (dir == UE_DIR_IN); ++ ep->dwc_ep.maxpacket = UGETW(desc->wMaxPacketSize); ++ ++ ep->dwc_ep.type = desc->bmAttributes & UE_XFERTYPE; ++ ++ if (ep->dwc_ep.is_in) { ++ if (!GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ ep->dwc_ep.tx_fifo_num = 0; ++ ++ if (ep->dwc_ep.type == UE_ISOCHRONOUS) { ++ /* ++ * if ISOC EP then assign a Periodic Tx FIFO. ++ */ ++ ep->dwc_ep.tx_fifo_num = ++ assign_perio_tx_fifo(GET_CORE_IF(pcd)); ++ } ++ } else { ++ /* ++ * if Dedicated FIFOs mode is on then assign a Tx FIFO. ++ */ ++ ep->dwc_ep.tx_fifo_num = ++ assign_tx_fifo(GET_CORE_IF(pcd)); ++ } ++ ++ /* Calculating EP info controller base address */ ++ if (ep->dwc_ep.tx_fifo_num ++ && GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ gdfifocfg.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ dptxfsiz.d32 = ++ (DWC_READ_REG32 ++ (&GET_CORE_IF(pcd)->core_global_regs-> ++ dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16); ++ gdfifocfg.b.epinfobase = ++ gdfifocfgbase.d32 + dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } ++ } ++ /* Set initial data PID. */ ++ if (ep->dwc_ep.type == UE_BULK) { ++ ep->dwc_ep.data_pid_start = 0; ++ } ++ ++ /* Alloc DMA Descriptors */ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++#ifndef DWC_UTE_PER_IO ++ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { ++#endif ++ ep->dwc_ep.desc_addr = ++ dwc_otg_ep_alloc_desc_chain(&ep-> ++ dwc_ep.dma_desc_addr, ++ MAX_DMA_DESC_CNT); ++ if (!ep->dwc_ep.desc_addr) { ++ DWC_WARN("%s, can't allocate DMA descriptor\n", ++ __func__); ++ retval = -DWC_E_SHUTDOWN; ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ goto out; ++ } ++#ifndef DWC_UTE_PER_IO ++ } ++#endif ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n", ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc); ++#ifdef DWC_UTE_PER_IO ++ ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1); ++#endif ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1); ++ ep->dwc_ep.frame_num = 0xFFFFFFFF; ++ } ++ ++ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi->ops.ep_enable) { ++ pcd->cfi->ops.ep_enable(pcd->cfi, pcd, ep); ++ } ++#endif ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++out: ++ return retval; ++} ++ ++/** ++ * This function is being called from gadget ++ * to disable PCD endpoint. ++ */ ++int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ dwc_otg_dev_dma_desc_t *desc_addr; ++ dwc_dma_t dma_desc_addr; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || !ep->desc) { ++ DWC_DEBUGPL(DBG_PCD, "bad ep address\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ dwc_otg_request_nuke(ep); ++ ++ dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]); ++ pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0; ++ } ++ ep->desc = NULL; ++ ep->stopped = 1; ++ ++ gdfifocfg.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ ++ if (ep->dwc_ep.is_in) { ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Flush the Tx FIFO */ ++ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ++ ep->dwc_ep.tx_fifo_num); ++ } ++ release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); ++ release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Decreasing EPinfo Base Addr */ ++ dptxfsiz.d32 = ++ (DWC_READ_REG32 ++ (&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16); ++ gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } ++ } ++ ++ /* Free DMA Descriptors */ ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ if (ep->dwc_ep.type != UE_ISOCHRONOUS) { ++ desc_addr = ep->dwc_ep.desc_addr; ++ dma_desc_addr = ep->dwc_ep.dma_desc_addr; ++ ++ /* Cannot call dma_free_coherent() with IRQs disabled */ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ dwc_otg_ep_free_desc_chain(desc_addr, dma_desc_addr, ++ MAX_DMA_DESC_CNT); ++ ++ goto out_unlocked; ++ } ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++out_unlocked: ++ DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ return 0; ++ ++} ++ ++/******************************************************************************/ ++#ifdef DWC_UTE_PER_IO ++ ++/** ++ * Free the request and its extended parts ++ * ++ */ ++void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req) ++{ ++ DWC_FREE(req->ext_req.per_io_frame_descs); ++ DWC_FREE(req); ++} ++ ++/** ++ * Start the next request in the endpoint's queue. ++ * ++ */ ++int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd, ++ dwc_otg_pcd_ep_t * ep) ++{ ++ int i; ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_ep_t *dwcep = NULL; ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_pkt_desc_port *ddesc_iso; ++ uint16_t nat; ++ depctl_data_t diepctl; ++ ++ dwcep = &ep->dwc_ep; ++ ++ if (dwcep->xiso_active_xfers > 0) { ++#if 0 //Disable this to decrease s/w overhead that is crucial for Isoc transfers ++ DWC_WARN("There are currently active transfers for EP%d \ ++ (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers, ++ dwcep->xiso_queued_xfers); ++#endif ++ return 0; ++ } ++ ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ereq = &req->ext_req; ++ ep->stopped = 0; ++ ++ /* Get the frame number */ ++ dwcep->xiso_frame_num = ++ dwc_otg_get_frame_number(GET_CORE_IF(pcd)); ++ DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num); ++ ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (dwcep->is_in) { ++ /* Setup DMA Descriptor chain for IN Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ if ( i > 0 ) ++ dwcep->xiso_frame_num = ++ (dwcep->xiso_bInterval + ++ dwcep->xiso_frame_num) & 0x3FFF; ++ dwcep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ dwcep->desc_addr[i].status.b_iso_in.txbytes = ++ ddesc_iso[i].length; ++ dwcep->desc_addr[i].status.b_iso_in.framenum = ++ dwcep->xiso_frame_num; ++ dwcep->desc_addr[i].status.b_iso_in.bs = ++ BS_HOST_READY; ++ dwcep->desc_addr[i].status.b_iso_in.txsts = 0; ++ dwcep->desc_addr[i].status.b_iso_in.sp = ++ (ddesc_iso[i].length % ++ dwcep->maxpacket) ? 1 : 0; ++ dwcep->desc_addr[i].status.b_iso_in.ioc = 0; ++ dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1; ++ dwcep->desc_addr[i].status.b_iso_in.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ dwcep->desc_addr[i].status.b_iso_in.ioc = 1; ++ dwcep->desc_addr[i].status.b_iso_in.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ dwcep->xiso_active_xfers++; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[dwcep->num]->diepdma, ++ dwcep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[dwcep->num]->diepctl, 0, ++ diepctl.d32); ++ } else { ++ /* Setup DMA Descriptor chain for OUT Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ dwcep->xiso_frame_num = (dwcep->xiso_bInterval + ++ dwcep->xiso_frame_num) & 0x3FFF; ++ dwcep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ dwcep->desc_addr[i].status.b_iso_out.rxbytes = ++ ddesc_iso[i].length; ++ dwcep->desc_addr[i].status.b_iso_out.framenum = ++ dwcep->xiso_frame_num; ++ dwcep->desc_addr[i].status.b_iso_out.bs = ++ BS_HOST_READY; ++ dwcep->desc_addr[i].status.b_iso_out.rxsts = 0; ++ dwcep->desc_addr[i].status.b_iso_out.sp = ++ (ddesc_iso[i].length % ++ dwcep->maxpacket) ? 1 : 0; ++ dwcep->desc_addr[i].status.b_iso_out.ioc = 0; ++ dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1; ++ dwcep->desc_addr[i].status.b_iso_out.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ dwcep->desc_addr[i].status.b_iso_out.ioc = 1; ++ dwcep->desc_addr[i].status.b_iso_out.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ dwcep->xiso_active_xfers++; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[dwcep->num]-> ++ doepdma, dwcep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[dwcep->num]-> ++ doepctl, 0, diepctl.d32); ++ } ++ ++ } else { ++ ep->stopped = 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * - Remove the request from the queue ++ */ ++void complete_xiso_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req = NULL; ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_pkt_desc_port *ddesc_iso = NULL; ++ dwc_ep_t *dwcep = NULL; ++ int i; ++ ++ //DWC_DEBUG(); ++ dwcep = &ep->dwc_ep; ++ ++ /* Get the first pending request from the queue */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ dwcep->xiso_active_xfers--; ++ dwcep->xiso_queued_xfers--; ++ /* Remove this request from the queue */ ++ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ ep->stopped = 1; ++ ereq = &req->ext_req; ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (dwcep->xiso_active_xfers < 0) { ++ DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num, ++ dwcep->xiso_active_xfers); ++ } ++ ++ /* Fill the Isoc descs of portable extended req from dma descriptors */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ if (dwcep->is_in) { /* IN endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ dwcep->desc_addr[i].status.b_iso_in.txbytes; ++ ddesc_iso[i].status = ++ dwcep->desc_addr[i].status.b_iso_in.txsts; ++ } else { /* OUT endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ dwcep->desc_addr[i].status.b_iso_out.rxbytes; ++ ddesc_iso[i].status = ++ dwcep->desc_addr[i].status.b_iso_out.rxsts; ++ } ++ } ++ ++ DWC_SPINUNLOCK(ep->pcd->lock); ++ ++ /* Call the completion function in the non-portable logic */ ++ ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0, ++ &req->ext_req); ++ ++ DWC_SPINLOCK(ep->pcd->lock); ++ ++ /* Free the request - specific freeing needed for extended request object */ ++ dwc_pcd_xiso_ereq_free(ep, req); ++ ++ /* Start the next request */ ++ dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep); ++ ++ return; ++} ++ ++/** ++ * Create and initialize the Isoc pkt descriptors of the extended request. ++ * ++ */ ++static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req, ++ void *ereq_nonport, ++ int atomic_alloc) ++{ ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_xreq_port *req_mapped = NULL; ++ struct dwc_iso_pkt_desc_port *ipds = NULL; /* To be created in this function */ ++ uint32_t pkt_count; ++ int i; ++ ++ ereq = &req->ext_req; ++ req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport; ++ pkt_count = req_mapped->pio_pkt_count; ++ ++ /* Create the isoc descs */ ++ if (atomic_alloc) { ++ ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count); ++ } else { ++ ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count); ++ } ++ ++ if (!ipds) { ++ DWC_ERROR("Failed to allocate isoc descriptors"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Initialize the extended request fields */ ++ ereq->per_io_frame_descs = ipds; ++ ereq->error_count = 0; ++ ereq->pio_alloc_pkt_count = pkt_count; ++ ereq->pio_pkt_count = pkt_count; ++ ereq->tr_sub_flags = req_mapped->tr_sub_flags; ++ ++ /* Init the Isoc descriptors */ ++ for (i = 0; i < pkt_count; i++) { ++ ipds[i].length = req_mapped->per_io_frame_descs[i].length; ++ ipds[i].offset = req_mapped->per_io_frame_descs[i].offset; ++ ipds[i].status = req_mapped->per_io_frame_descs[i].status; /* 0 */ ++ ipds[i].actual_length = ++ req_mapped->per_io_frame_descs[i].actual_length; ++ } ++ ++ return 0; ++} ++ ++static void prn_ext_request(struct dwc_iso_xreq_port *ereq) ++{ ++ struct dwc_iso_pkt_desc_port *xfd = NULL; ++ int i; ++ ++ DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs); ++ DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags); ++ DWC_DEBUG("error_count=%d", ereq->error_count); ++ DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count); ++ DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count); ++ DWC_DEBUG("res=%d", ereq->res); ++ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ xfd = &ereq->per_io_frame_descs[0]; ++ DWC_DEBUG("FD #%d", i); ++ ++ DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length); ++ DWC_DEBUG("xfd->length=%d", xfd->length); ++ DWC_DEBUG("xfd->offset=%d", xfd->offset); ++ DWC_DEBUG("xfd->status=%d", xfd->status); ++ } ++} ++ ++/** ++ * ++ */ ++int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc, ++ void *ereq_nonport) ++{ ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ int res; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ /* We support this extension only for DDMA mode */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ++ if (!GET_CORE_IF(pcd)->dma_desc_enable) ++ return -DWC_E_INVALID; ++ ++ /* Create a dwc_otg_pcd_request_t object */ ++ if (atomic_alloc) { ++ req = DWC_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = DWC_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Create the Isoc descs for this request which shall be the exact match ++ * of the structure sent to us from the non-portable logic */ ++ res = ++ dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc); ++ if (res) { ++ DWC_WARN("Failed to init the Isoc descriptors"); ++ DWC_FREE(req); ++ return res; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ ++ //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = buflen; ++ ++ /* Add this request to the tail */ ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ ep->dwc_ep.xiso_queued_xfers++; ++ ++//DWC_DEBUG("CP_0"); ++//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags); ++//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport); ++//prn_ext_request(&req->ext_req); ++ ++ //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ /* If the req->status == ASAP then check if there is any active transfer ++ * for this endpoint. If no active transfers, then get the first entry ++ * from the queue and start that transfer ++ */ ++ if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) { ++ res = dwc_otg_pcd_xiso_start_next_request(pcd, ep); ++ if (res) { ++ DWC_WARN("Failed to start the next Isoc transfer"); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ DWC_FREE(req); ++ return res; ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return 0; ++} ++ ++#endif ++/* END ifdef DWC_UTE_PER_IO ***************************************************/ ++int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc) ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_pcd_request_t *req; ++ dwc_otg_pcd_ep_t *ep; ++ uint32_t max_transfer; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if (atomic_alloc) { ++ req = DWC_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = DWC_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -DWC_E_NO_MEMORY; ++ } ++ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ if (!GET_CORE_IF(pcd)->core_params->opt) { ++ if (ep->dwc_ep.num != 0) { ++ DWC_ERROR("queue req %p, len %d buf %p\n", ++ req_handle, buflen, buf); ++ } ++ } ++ ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ req->dw_align_buf = NULL; ++ if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable ++ && !GET_CORE_IF(pcd)->dma_desc_enable) ++ req->dw_align_buf = DWC_DMA_ALLOC(buflen, ++ &req->dw_align_buf_dma); ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ /* ++ * After adding request to the queue for IN ISOC wait for In Token Received ++ * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token ++ * Received when EP is disabled interrupt to obtain starting microframe ++ * (odd/even) start transfer ++ */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ if (req != 0) { ++ depctl_data_t depctl = {.d32 = ++ DWC_READ_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]-> ++ diepctl) }; ++ ++pcd->request_pending; ++ ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->dwc_ep.is_in) { ++ depctl.b.cnak = 1; ++ DWC_WRITE_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]-> ++ diepctl, depctl.d32); ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return 0; ++ } ++ ++ /* ++ * For EP0 IN without premature status, zlp is required? ++ */ ++ if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) { ++ DWC_DEBUGPL(DBG_PCDV, "%d-OUT ZLP\n", ep->dwc_ep.num); ++ //_req->zero = 1; ++ } ++ ++ /* Start the transfer */ ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue) && !ep->stopped) { ++ /* EP0 Transfer? */ ++ if (ep->dwc_ep.num == 0) { ++ switch (pcd->ep0state) { ++ case EP0_IN_DATA_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_IN_DATA_PHASE\n", ++ __func__); ++ break; ++ ++ case EP0_OUT_DATA_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_OUT_DATA_PHASE\n", ++ __func__); ++ if (pcd->request_config) { ++ /* Complete STATUS PHASE */ ++ ep->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ } ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ DWC_DEBUGPL(DBG_PCD, ++ "%s ep0: EP0_IN_STATUS_PHASE\n", ++ __func__); ++ break; ++ ++ default: ++ DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", ++ pcd->ep0state); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_SHUTDOWN; ++ } ++ ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ ep->dwc_ep.xfer_len = buflen; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = ep->dwc_ep.xfer_len; ++ ++ if (zero) { ++ if ((ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.xfer_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ ++ } ++ ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } // non-ep0 endpoints ++ else { ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ /* store the request length */ ++ ep->dwc_ep.cfi_req_len = buflen; ++ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ++ ep, req); ++ } else { ++#endif ++ max_transfer = ++ GET_CORE_IF(ep->pcd)->core_params-> ++ max_transfer_size; ++ ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf){ ++ if (ep->dwc_ep.is_in) ++ dwc_memcpy(req->dw_align_buf, ++ buf, buflen); ++ ep->dwc_ep.dma_addr = ++ req->dw_align_buf_dma; ++ ep->dwc_ep.start_xfer_buff = ++ req->dw_align_buf; ++ ep->dwc_ep.xfer_buff = ++ req->dw_align_buf; ++ } else { ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ } ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = buflen; ++ ++ ep->dwc_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = ++ DDMA_MAX_TRANSFER_SIZE - ++ (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->dwc_ep.is_in) { ++ if (ep->dwc_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->dwc_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->dwc_ep.maxxfer > ++ out_max_xfer) { ++ ep->dwc_ep.maxxfer = ++ out_max_xfer; ++ } ++ } ++ } ++ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { ++ ep->dwc_ep.maxxfer -= ++ (ep->dwc_ep.maxxfer % ++ ep->dwc_ep.maxpacket); ++ } ++ ++ if (zero) { ++ if ((ep->dwc_ep.total_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.total_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ dwc_otg_ep_start_transfer(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } ++ } ++ ++ if (req != 0) { ++ ++pcd->request_pending; ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->dwc_ep.is_in && ep->stopped ++ && !(GET_CORE_IF(pcd)->dma_enable)) { ++ /** @todo NGS Create a function for this. */ ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.intktxfemp = 1; ++ if (GET_CORE_IF(pcd)->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->dev_global_regs->diepeachintmsk ++ [ep->dwc_ep.num], 0, ++ diepmsk.d32); ++ } else { ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->dev_global_regs-> ++ diepmsk, 0, diepmsk.d32); ++ } ++ ++ } ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return 0; ++} ++ ++int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle) ++{ ++ dwc_irqflags_t flags; ++ dwc_otg_pcd_request_t *req; ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { ++ DWC_WARN("bad argument\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ /* make sure it's actually queued on this endpoint */ ++ DWC_CIRCLEQ_FOREACH(req, &ep->queue, queue_entry) { ++ if (req->priv == (void *)req_handle) { ++ break; ++ } ++ } ++ ++ if (req->priv != (void *)req_handle) { ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return -DWC_E_INVALID; ++ } ++ ++ if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) { ++ dwc_otg_request_done(ep, req, -DWC_E_RESTART); ++ } else { ++ req = NULL; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return req ? 0 : -DWC_E_SHUTDOWN; ++ ++} ++ ++/** ++ * dwc_otg_pcd_ep_wedge - sets the halt feature and ignores clear requests ++ * ++ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT) ++ * requests. If the gadget driver clears the halt status, it will ++ * automatically unwedge the endpoint. ++ * ++ * Returns zero on success, else negative DWC error code. ++ */ ++int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ int retval = 0; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if ((!ep->desc && ep != &pcd->ep0) || ++ (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { ++ DWC_WARN("%s, bad ep\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ retval = -DWC_E_AGAIN; ++ } else { ++ /* This code needs to be reviewed */ ++ if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) { ++ dtxfsts_data_t txstatus; ++ fifosize_data_t txfifosize; ++ ++ txfifosize.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->dwc_ep. ++ tx_fifo_num]); ++ txstatus.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->in_ep_regs[ep->dwc_ep.num]-> ++ dtxfsts); ++ ++ if (txstatus.b.txfspcavail < txfifosize.b.depth) { ++ DWC_WARN("%s() Data In Tx Fifo\n", __func__); ++ retval = -DWC_E_AGAIN; ++ } else { ++ if (ep->dwc_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } ++ } else { ++ if (ep->dwc_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return retval; ++} ++ ++int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ int retval = 0; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ ++ if (!ep || (!ep->desc && ep != &pcd->ep0) || ++ (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { ++ DWC_WARN("%s, bad ep\n", __func__); ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_WARN("%d %s XFer In process\n", ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT"); ++ retval = -DWC_E_AGAIN; ++ } else if (value == 0) { ++ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ } else if (value == 1) { ++ if (ep->dwc_ep.is_in == 1 && GET_CORE_IF(pcd)->dma_desc_enable) { ++ dtxfsts_data_t txstatus; ++ fifosize_data_t txfifosize; ++ ++ txfifosize.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs-> ++ dtxfsiz[ep->dwc_ep.tx_fifo_num]); ++ txstatus.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]->dtxfsts); ++ ++ if (txstatus.b.txfspcavail < txfifosize.b.depth) { ++ DWC_WARN("%s() Data In Tx Fifo\n", __func__); ++ retval = -DWC_E_AGAIN; ++ } else { ++ if (ep->dwc_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), ++ &ep->dwc_ep); ++ } ++ } else { ++ if (ep->dwc_ep.num == 0) { ++ pcd->ep0state = EP0_STALL; ++ } ++ ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ } ++ } else if (value == 2) { ++ ep->dwc_ep.stall_clear_flag = 0; ++ } else if (value == 3) { ++ ep->dwc_ep.stall_clear_flag = 1; ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ return retval; ++} ++ ++/** ++ * This function initiates remote wakeup of the host from suspend state. ++ */ ++void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set) ++{ ++ dctl_data_t dctl = { 0 }; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dsts_data_t dsts; ++ ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ if (!dsts.b.suspsts) { ++ DWC_WARN("Remote wakeup while is not in suspend state\n"); ++ } ++ /* Check if DEVICE_REMOTE_WAKEUP feature enabled */ ++ if (pcd->remote_wakeup_enable) { ++ if (set) { ++ ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn; ++ ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ dwc_otg_initiate_srp(core_if); ++ } ++ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ ++ dwc_mdelay(2); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, dctl.d32, 0); ++ DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); ++ } ++ } else { ++ DWC_DEBUGPL(DBG_PCD, "Remote Wakeup is disabled\n"); ++ } ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * This function initiates remote wakeup of the host from L1 sleep state. ++ */ ++void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set) ++{ ++ glpmcfg_data_t lpmcfg; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ ++ /* Check if we are in L1 state */ ++ if (!lpmcfg.b.prt_sleep_sts) { ++ DWC_DEBUGPL(DBG_PCD, "Device is not in sleep state\n"); ++ return; ++ } ++ ++ /* Check if host allows remote wakeup */ ++ if (!lpmcfg.b.rem_wkup_en) { ++ DWC_DEBUGPL(DBG_PCD, "Host does not allow remote wakeup\n"); ++ return; ++ } ++ ++ /* Check if Resume OK */ ++ if (!lpmcfg.b.sleep_state_resumeok) { ++ DWC_DEBUGPL(DBG_PCD, "Sleep state resume is not OK\n"); ++ return; ++ } ++ ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ ++ if (set) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.rmtwkupsig = 1; ++ /* Set RmtWkUpSig bit to start remote wakup signaling. ++ * Hardware will automatically clear this bit. ++ */ ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ } ++ ++} ++#endif ++ ++/** ++ * Performs remote wakeup. ++ */ ++void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_irqflags_t flags; ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ if (core_if->lx_state == DWC_OTG_L1) { ++ dwc_otg_pcd_rem_wkup_from_sleep(pcd, set); ++ } else { ++#endif ++ dwc_otg_pcd_rem_wkup_from_suspend(pcd, set); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ } ++#endif ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return; ++} ++ ++void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl = { 0 }; ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dctl.b.sftdiscon = 1; ++ DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ dwc_udelay(no_of_usecs); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0); ++ ++ } else{ ++ DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n"); ++ } ++ return; ++ ++} ++ ++int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) ++{ ++ dsts_data_t dsts; ++ gotgctl_data_t gotgctl; ++ ++ /* ++ * This function starts the Protocol if no session is in progress. If ++ * a session is already in progress, but the device is suspended, ++ * remote wakeup signaling is started. ++ */ ++ ++ /* Check if valid session */ ++ gotgctl.d32 = ++ DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); ++ if (gotgctl.b.bsesvld) { ++ /* Check if suspend state */ ++ dsts.d32 = ++ DWC_READ_REG32(& ++ (GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts)); ++ if (dsts.b.suspsts) { ++ dwc_otg_pcd_remote_wakeup(pcd, 1); ++ } ++ } else { ++ dwc_otg_pcd_initiate_srp(pcd); ++ } ++ ++ return 0; ++ ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param pcd the pcd structure. ++ */ ++void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd) ++{ ++ dwc_irqflags_t flags; ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ dwc_otg_initiate_srp(GET_CORE_IF(pcd)); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++} ++ ++int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd) ++{ ++ return dwc_otg_get_frame_number(GET_CORE_IF(pcd)); ++} ++ ++int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd) ++{ ++ return GET_CORE_IF(pcd)->core_params->lpm_enable; ++} ++ ++uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->b_hnp_enable; ++} ++ ++uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->a_hnp_support; ++} ++ ++uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->a_alt_hnp_support; ++} ++ ++int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd) ++{ ++ return pcd->remote_wakeup_enable; ++} ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h +new file mode 100644 +index 0000000..8ef7ba6 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h +@@ -0,0 +1,266 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ ++ * $Revision: #48 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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_HOST_ONLY ++#if !defined(__DWC_PCD_H__) ++#define __DWC_PCD_H__ ++ ++#include "dwc_otg_os_dep.h" ++#include "usb.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_pcd_if.h" ++struct cfiobject; ++ ++/** ++ * @file ++ * ++ * This file contains the structures, constants, and interfaces for ++ * the Perpherial Contoller Driver (PCD). ++ * ++ * The Peripheral Controller Driver (PCD) for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. For ++ * the Mass Storage Function driver the File-backed USB Storage Gadget ++ * (FBS) driver will be used. The FBS driver supports the ++ * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only ++ * transports. ++ * ++ */ ++ ++/** Invalid DMA Address */ ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++ ++/** Max Transfer size for any EP */ ++#define DDMA_MAX_TRANSFER_SIZE 65535 ++ ++/** ++ * Get the pointer to the core_if from the pcd pointer. ++ */ ++#define GET_CORE_IF( _pcd ) (_pcd->core_if) ++ ++/** ++ * States of EP0. ++ */ ++typedef enum ep0_state { ++ EP0_DISCONNECT, /* no host */ ++ EP0_IDLE, ++ EP0_IN_DATA_PHASE, ++ EP0_OUT_DATA_PHASE, ++ EP0_IN_STATUS_PHASE, ++ EP0_OUT_STATUS_PHASE, ++ EP0_STALL, ++} ep0state_e; ++ ++/** Fordward declaration.*/ ++struct dwc_otg_pcd; ++ ++/** DWC_otg iso request structure. ++ * ++ */ ++typedef struct usb_iso_request dwc_otg_pcd_iso_request_t; ++ ++#ifdef DWC_UTE_PER_IO ++ ++/** ++ * This shall be the exact analogy of the same type structure defined in the ++ * usb_gadget.h. Each descriptor contains ++ */ ++struct dwc_iso_pkt_desc_port { ++ uint32_t offset; ++ uint32_t length; /* expected length */ ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct dwc_iso_xreq_port { ++ /** transfer/submission flag */ ++ uint32_t tr_sub_flags; ++ /** Start the request ASAP */ ++#define DWC_EREQ_TF_ASAP 0x00000002 ++ /** Just enqueue the request w/o initiating a transfer */ ++#define DWC_EREQ_TF_ENQUEUE 0x00000004 ++ ++ /** ++ * count of ISO packets attached to this request - shall ++ * not exceed the pio_alloc_pkt_count ++ */ ++ uint32_t pio_pkt_count; ++ /** count of ISO packets allocated for this request */ ++ uint32_t pio_alloc_pkt_count; ++ /** number of ISO packet errors */ ++ uint32_t error_count; ++ /** reserved for future extension */ ++ uint32_t res; ++ /** Will be allocated and freed in the UTE gadget and based on the CFC value */ ++ struct dwc_iso_pkt_desc_port *per_io_frame_descs; ++}; ++#endif ++/** DWC_otg request structure. ++ * This structure is a list of requests. ++ */ ++typedef struct dwc_otg_pcd_request { ++ void *priv; ++ void *buf; ++ dwc_dma_t dma; ++ uint32_t length; ++ uint32_t actual; ++ unsigned sent_zlp:1; ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ **/ ++ uint8_t *dw_align_buf; ++ dwc_dma_t dw_align_buf_dma; ++ ++ DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry; ++#ifdef DWC_UTE_PER_IO ++ struct dwc_iso_xreq_port ext_req; ++ //void *priv_ereq_nport; /* */ ++#endif ++} dwc_otg_pcd_request_t; ++ ++DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request); ++ ++/** PCD EP structure. ++ * This structure describes an EP, there is an array of EPs in the PCD ++ * structure. ++ */ ++typedef struct dwc_otg_pcd_ep { ++ /** USB EP Descriptor */ ++ const usb_endpoint_descriptor_t *desc; ++ ++ /** queue of dwc_otg_pcd_requests. */ ++ struct req_list queue; ++ unsigned stopped:1; ++ unsigned disabling:1; ++ unsigned dma:1; ++ unsigned queue_sof:1; ++ ++#ifdef DWC_EN_ISOC ++ /** ISOC req handle passed */ ++ void *iso_req_handle; ++#endif //_EN_ISOC_ ++ ++ /** DWC_otg ep data. */ ++ dwc_ep_t dwc_ep; ++ ++ /** Pointer to PCD */ ++ struct dwc_otg_pcd *pcd; ++ ++ void *priv; ++} dwc_otg_pcd_ep_t; ++ ++/** DWC_otg PCD Structure. ++ * This structure encapsulates the data for the dwc_otg PCD. ++ */ ++struct dwc_otg_pcd { ++ const struct dwc_otg_pcd_function_ops *fops; ++ /** The DWC otg device pointer */ ++ struct dwc_otg_device *otg_dev; ++ /** Core Interface */ ++ dwc_otg_core_if_t *core_if; ++ /** State of EP0 */ ++ ep0state_e ep0state; ++ /** EP0 Request is pending */ ++ unsigned ep0_pending:1; ++ /** Indicates when SET CONFIGURATION Request is in process */ ++ unsigned request_config:1; ++ /** The state of the Remote Wakeup Enable. */ ++ unsigned remote_wakeup_enable:1; ++ /** The state of the B-Device HNP Enable. */ ++ unsigned b_hnp_enable:1; ++ /** The state of A-Device HNP Support. */ ++ unsigned a_hnp_support:1; ++ /** The state of the A-Device Alt HNP support. */ ++ unsigned a_alt_hnp_support:1; ++ /** Count of pending Requests */ ++ unsigned request_pending; ++ ++ /** SETUP packet for EP0 ++ * This structure is allocated as a DMA buffer on PCD initialization ++ * with enough space for up to 3 setup packets. ++ */ ++ union { ++ usb_device_request_t req; ++ uint32_t d32[2]; ++ } *setup_pkt; ++ ++ dwc_dma_t setup_pkt_dma_handle; ++ ++ /* Additional buffer and flag for CTRL_WR premature case */ ++ uint8_t *backup_buf; ++ unsigned data_terminated; ++ ++ /** 2-byte dma buffer used to return status from GET_STATUS */ ++ uint16_t *status_buf; ++ dwc_dma_t status_buf_dma_handle; ++ ++ /** EP0 */ ++ dwc_otg_pcd_ep_t ep0; ++ ++ /** Array of IN EPs. */ ++ dwc_otg_pcd_ep_t in_ep[MAX_EPS_CHANNELS - 1]; ++ /** Array of OUT EPs. */ ++ dwc_otg_pcd_ep_t out_ep[MAX_EPS_CHANNELS - 1]; ++ /** number of valid EPs in the above array. */ ++// unsigned num_eps : 4; ++ dwc_spinlock_t *lock; ++ ++ /** Tasklet to defer starting of TEST mode transmissions until ++ * Status Phase has been completed. ++ */ ++ dwc_tasklet_t *test_mode_tasklet; ++ ++ /** Tasklet to delay starting of xfer in DMA mode */ ++ dwc_tasklet_t *start_xfer_tasklet; ++ ++ /** The test mode to enter when the tasklet is executed. */ ++ unsigned test_mode; ++ /** The cfi_api structure that implements most of the CFI API ++ * and OTG specific core configuration functionality ++ */ ++#ifdef DWC_UTE_CFI ++ struct cfiobject *cfi; ++#endif ++ ++}; ++ ++//FIXME this functions should be static, and this prototypes should be removed ++extern void dwc_otg_request_nuke(dwc_otg_pcd_ep_t * ep); ++extern void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, ++ dwc_otg_pcd_request_t * req, int32_t status); ++ ++void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, ++ void *req_handle); ++ ++extern void do_test_mode(void *data); ++#endif ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h +new file mode 100644 +index 0000000..c8d2e0e +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h +@@ -0,0 +1,360 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ ++ * $Revision: #11 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ ++ * ++ * 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_HOST_ONLY ++ ++#if !defined(__DWC_PCD_IF_H__) ++#define __DWC_PCD_IF_H__ ++ ++//#include "dwc_os.h" ++#include "dwc_otg_core_if.h" ++ ++/** @file ++ * This file defines DWC_OTG PCD Core API. ++ */ ++ ++struct dwc_otg_pcd; ++typedef struct dwc_otg_pcd dwc_otg_pcd_t; ++ ++/** Maxpacket size for EP0 */ ++#define MAX_EP0_SIZE 64 ++/** Maxpacket size for any EP */ ++#define MAX_PACKET_SIZE 1024 ++ ++/** @name Function Driver Callbacks */ ++/** @{ */ ++ ++/** This function will be called whenever a previously queued request has ++ * completed. The status value will be set to -DWC_E_SHUTDOWN to indicated a ++ * failed or aborted transfer, or -DWC_E_RESTART to indicate the device was reset, ++ * or -DWC_E_TIMEOUT to indicate it timed out, or -DWC_E_INVALID to indicate invalid ++ * parameters. */ ++typedef int (*dwc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ uint32_t actual); ++/** ++ * This function will be called whenever a previousle queued ISOC request has ++ * completed. Count of ISOC packets could be read using dwc_otg_pcd_get_iso_packet_count ++ * function. ++ * The status of each ISOC packet could be read using dwc_otg_pcd_get_iso_packet_* ++ * functions. ++ */ ++typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int proc_buf_num); ++/** This function should handle any SETUP request that cannot be handled by the ++ * PCD Core. This includes most GET_DESCRIPTORs, SET_CONFIGS, Any ++ * class-specific requests, etc. The function must non-blocking. ++ * ++ * Returns 0 on success. ++ * Returns -DWC_E_NOT_SUPPORTED if the request is not supported. ++ * Returns -DWC_E_INVALID if the setup request had invalid parameters or bytes. ++ * Returns -DWC_E_SHUTDOWN on any other error. */ ++typedef int (*dwc_setup_cb_t) (dwc_otg_pcd_t * pcd, uint8_t * bytes); ++/** This is called whenever the device has been disconnected. The function ++ * driver should take appropriate action to clean up all pending requests in the ++ * PCD Core, remove all endpoints (except ep0), and initialize back to reset ++ * state. */ ++typedef int (*dwc_disconnect_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has been connected. */ ++typedef int (*dwc_connect_cb_t) (dwc_otg_pcd_t * pcd, int speed); ++/** This function is called when device has been suspended */ ++typedef int (*dwc_suspend_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has received LPM tokens, i.e. ++ * device has been sent to sleep state. */ ++typedef int (*dwc_sleep_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called when device has been resumed ++ * from suspend(L2) or L1 sleep state. */ ++typedef int (*dwc_resume_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called whenever hnp params has been changed. ++ * User can call get_b_hnp_enable, get_a_hnp_support, get_a_alt_hnp_support functions ++ * to get hnp parameters. */ ++typedef int (*dwc_hnp_params_changed_cb_t) (dwc_otg_pcd_t * pcd); ++/** This function is called whenever USB RESET is detected. */ ++typedef int (*dwc_reset_cb_t) (dwc_otg_pcd_t * pcd); ++ ++typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes); ++ ++/** ++ * ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param ereq_port Pointer to the extended request structure created in the ++ * portable part. ++ */ ++typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ void *ereq_port); ++/** Function Driver Ops Data Structure */ ++struct dwc_otg_pcd_function_ops { ++ dwc_connect_cb_t connect; ++ dwc_disconnect_cb_t disconnect; ++ dwc_setup_cb_t setup; ++ dwc_completion_cb_t complete; ++ dwc_isoc_completion_cb_t isoc_complete; ++ dwc_suspend_cb_t suspend; ++ dwc_sleep_cb_t sleep; ++ dwc_resume_cb_t resume; ++ dwc_reset_cb_t reset; ++ dwc_hnp_params_changed_cb_t hnp_changed; ++ cfi_setup_cb_t cfi_setup; ++#ifdef DWC_UTE_PER_IO ++ xiso_completion_cb_t xisoc_complete; ++#endif ++}; ++/** @} */ ++ ++/** @name Function Driver Functions */ ++/** @{ */ ++ ++/** Call this function to get pointer on dwc_otg_pcd_t, ++ * this pointer will be used for all PCD API functions. ++ * ++ * @param core_if The DWC_OTG Core ++ */ ++extern dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if); ++ ++/** Frees PCD allocated by dwc_otg_pcd_init ++ * ++ * @param pcd The PCD ++ */ ++extern void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd); ++ ++/** Call this to bind the function driver to the PCD Core. ++ * ++ * @param pcd Pointer on dwc_otg_pcd_t returned by dwc_otg_pcd_init function. ++ * @param fops The Function Driver Ops data structure containing pointers to all callbacks. ++ */ ++extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, ++ const struct dwc_otg_pcd_function_ops *fops); ++ ++/** Enables an endpoint for use. This function enables an endpoint in ++ * the PCD. The endpoint is described by the ep_desc which has the ++ * same format as a USB ep descriptor. The ep_handle parameter is used to refer ++ * to the endpoint from other API functions and in callbacks. Normally this ++ * should be called after a SET_CONFIGURATION/SET_INTERFACE to configure the ++ * core for that interface. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. ++ * ++ * @param pcd The PCD ++ * @param ep_desc Endpoint descriptor ++ * @param usb_ep Handle on endpoint, that will be used to identify endpoint. ++ */ ++extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, ++ const uint8_t * ep_desc, void *usb_ep); ++ ++/** Disable the endpoint referenced by ep_handle. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error occurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle); ++ ++/** Queue a data transfer request on the endpoint referenced by ep_handle. ++ * After the transfer is completes, the complete callback will be called with ++ * the request status. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param buf The buffer for the data ++ * @param dma_buf The DMA buffer for the data ++ * @param buflen The length of the data transfer ++ * @param zero Specifies whether to send zero length last packet. ++ * @param req_handle Set this handle to any value to use to reference this ++ * request in the ep_dequeue function or from the complete callback ++ * @param atomic_alloc If driver need to perform atomic allocations ++ * for internal data structures. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, ++ uint32_t buflen, int zero, void *req_handle, ++ int atomic_alloc); ++#ifdef DWC_UTE_PER_IO ++/** ++ * ++ * @param ereq_nonport Pointer to the extended request part of the ++ * usb_request structure defined in usb_gadget.h file. ++ */ ++extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, ++ uint32_t buflen, int zero, ++ void *req_handle, int atomic_alloc, ++ void *ereq_nonport); ++ ++#endif ++ ++/** De-queue the specified data transfer that has not yet completed. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle); ++ ++/** Halt (STALL) an endpoint or clear it. ++ * ++ * Returns -DWC_E_INVALID if invalid parameters were passed. ++ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns -DWC_E_AGAIN if the STALL cannot be sent and must be tried again later ++ * Returns 0 on success. */ ++extern int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value); ++ ++/** This function */ ++extern int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle); ++ ++/** This function should be called on every hardware interrupt */ ++extern int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd); ++ ++/** This function returns current frame number */ ++extern int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd); ++ ++/** ++ * Start isochronous transfers on the endpoint referenced by ep_handle. ++ * For isochronous transfers duble buffering is used. ++ * After processing each of buffers comlete callback will be called with ++ * status for each transaction. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param buf0 The virtual address of first data buffer ++ * @param buf1 The virtual address of second data buffer ++ * @param dma0 The DMA address of first data buffer ++ * @param dma1 The DMA address of second data buffer ++ * @param sync_frame Data pattern frame number ++ * @param dp_frame Data size for pattern frame ++ * @param data_per_frame Data size for regular frame ++ * @param start_frame Frame number to start transfers, if -1 then start transfers ASAP. ++ * @param buf_proc_intrvl Interval of ISOC Buffer processing ++ * @param req_handle Handle of ISOC request ++ * @param atomic_alloc Specefies whether to perform atomic allocation for ++ * internal data structures. ++ * ++ * Returns -DWC_E_NO_MEMORY if there is no enough memory. ++ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function. ++ * Returns -DW_E_SHUTDOWN for any other error. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf0, uint8_t * buf1, ++ dwc_dma_t dma0, dwc_dma_t dma1, ++ int sync_frame, int dp_frame, ++ int data_per_frame, int start_frame, ++ int buf_proc_intrvl, void *req_handle, ++ int atomic_alloc); ++ ++/** Stop ISOC transfers on endpoint referenced by ep_handle. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param req_handle Handle of ISOC request ++ * ++ * Returns -DWC_E_INVALID if incorrect arguments are passed to the function ++ * Returns 0 on success ++ */ ++int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle); ++ ++/** Get ISOC packet status. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param iso_req_handle Isochronoush request handle ++ * @param packet Number of packet ++ * @param status Out parameter for returning status ++ * @param actual Out parameter for returning actual length ++ * @param offset Out parameter for returning offset ++ * ++ */ ++extern void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, ++ void *ep_handle, ++ void *iso_req_handle, int packet, ++ int *status, int *actual, ++ int *offset); ++ ++/** Get ISOC packet count. ++ * ++ * @param pcd The PCD ++ * @param ep_handle The handle of the endpoint ++ * @param iso_req_handle ++ */ ++extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, ++ void *ep_handle, ++ void *iso_req_handle); ++ ++/** This function starts the SRP Protocol if no session is in progress. If ++ * a session is already in progress, but the device is suspended, ++ * remote wakeup signaling is started. ++ */ ++extern int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd); ++ ++/** This function returns 1 if LPM support is enabled, and 0 otherwise. */ ++extern int dwc_otg_pcd_is_lpm_enabled(dwc_otg_pcd_t * pcd); ++ ++/** This function returns 1 if remote wakeup is allowed and 0, otherwise. */ ++extern int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd); ++ ++/** Initiate SRP */ ++extern void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd); ++ ++/** Starts remote wakeup signaling. */ ++extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set); ++ ++/** Starts micorsecond soft disconnect. */ ++extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs); ++/** This function returns whether device is dualspeed.*/ ++extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd); ++ ++/** This function returns whether device is otg. */ ++extern uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd); ++ ++/** These functions allow to get hnp parameters */ ++extern uint32_t get_b_hnp_enable(dwc_otg_pcd_t * pcd); ++extern uint32_t get_a_hnp_support(dwc_otg_pcd_t * pcd); ++extern uint32_t get_a_alt_hnp_support(dwc_otg_pcd_t * pcd); ++ ++/** CFI specific Interface functions */ ++/** Allocate a cfi buffer */ ++extern uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, ++ dwc_dma_t * addr, size_t buflen, ++ int flags); ++ ++/******************************************************************************/ ++ ++/** @} */ ++ ++#endif /* __DWC_PCD_IF_H__ */ ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +new file mode 100644 +index 0000000..27061d3 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +@@ -0,0 +1,5147 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ ++ * $Revision: #116 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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_HOST_ONLY ++ ++#include "dwc_otg_pcd.h" ++ ++#ifdef DWC_UTE_CFI ++#include "dwc_otg_cfi.h" ++#endif ++ ++#ifdef DWC_UTE_PER_IO ++extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep); ++#endif ++//#define PRINT_CFI_DMA_DESCS ++ ++#define DEBUG_EP0 ++ ++/** ++ * This function updates OTG. ++ */ ++static void dwc_otg_pcd_update_otg(dwc_otg_pcd_t * pcd, const unsigned reset) ++{ ++ ++ if (reset) { ++ pcd->b_hnp_enable = 0; ++ pcd->a_hnp_support = 0; ++ pcd->a_alt_hnp_support = 0; ++ } ++ ++ if (pcd->fops->hnp_changed) { ++ pcd->fops->hnp_changed(pcd); ++ } ++} ++ ++/** @file ++ * This file contains the implementation of the PCD Interrupt handlers. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate function. These interrupt ++ * handling functions are described below. ++ * All interrupt registers are processed from LSB to MSB. ++ */ ++ ++/** ++ * This function prints the ep0 state for debug purposes. ++ */ ++static inline void print_ep0_state(dwc_otg_pcd_t * pcd) ++{ ++#ifdef DEBUG ++ char str[40]; ++ ++ switch (pcd->ep0state) { ++ case EP0_DISCONNECT: ++ dwc_strcpy(str, "EP0_DISCONNECT"); ++ break; ++ case EP0_IDLE: ++ dwc_strcpy(str, "EP0_IDLE"); ++ break; ++ case EP0_IN_DATA_PHASE: ++ dwc_strcpy(str, "EP0_IN_DATA_PHASE"); ++ break; ++ case EP0_OUT_DATA_PHASE: ++ dwc_strcpy(str, "EP0_OUT_DATA_PHASE"); ++ break; ++ case EP0_IN_STATUS_PHASE: ++ dwc_strcpy(str, "EP0_IN_STATUS_PHASE"); ++ break; ++ case EP0_OUT_STATUS_PHASE: ++ dwc_strcpy(str, "EP0_OUT_STATUS_PHASE"); ++ break; ++ case EP0_STALL: ++ dwc_strcpy(str, "EP0_STALL"); ++ break; ++ default: ++ dwc_strcpy(str, "EP0_INVALID"); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, "%s(%d)\n", str, pcd->ep0state); ++#endif ++} ++ ++/** ++ * This function calculate the size of the payload in the memory ++ * for out endpoints and prints size for debug purposes(used in ++ * 2.93a DevOutNak feature). ++ */ ++static inline void print_memory_payload(dwc_otg_pcd_t * pcd, dwc_ep_t * ep) ++{ ++#ifdef DEBUG ++ deptsiz_data_t deptsiz_init = {.d32 = 0 }; ++ deptsiz_data_t deptsiz_updt = {.d32 = 0 }; ++ int pack_num; ++ unsigned payload; ++ ++ deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num]; ++ deptsiz_updt.d32 = ++ DWC_READ_REG32(&pcd->core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ /* Payload will be */ ++ payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize; ++ /* Packet count is decremented every time a packet ++ * is written to the RxFIFO not in to the external memory ++ * So, if payload == 0, then it means no packet was sent to ext memory*/ ++ pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Payload for EP%d-%s\n", ++ ep->num, (ep->is_in ? "IN" : "OUT")); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Number of transfered bytes = 0x%08x\n", payload); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Number of transfered packets = %d\n", pack_num); ++#endif ++} ++ ++ ++#ifdef DWC_UTE_CFI ++static inline void print_desc(struct dwc_otg_dma_desc *ddesc, ++ const uint8_t * epname, int descnum) ++{ ++ CFI_INFO ++ ("%s DMA_DESC(%d) buf=0x%08x bytes=0x%04x; sp=0x%x; l=0x%x; sts=0x%02x; bs=0x%02x\n", ++ epname, descnum, ddesc->buf, ddesc->status.b.bytes, ++ ddesc->status.b.sp, ddesc->status.b.l, ddesc->status.b.sts, ++ ddesc->status.b.bs); ++} ++#endif ++ ++/** ++ * This function returns pointer to in ep struct with number ep_num ++ */ ++static inline dwc_otg_pcd_ep_t *get_in_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num) ++{ ++ int i; ++ int num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; ++ if (ep_num == 0) { ++ return &pcd->ep0; ++ } else { ++ for (i = 0; i < num_in_eps; ++i) { ++ if (pcd->in_ep[i].dwc_ep.num == ep_num) ++ return &pcd->in_ep[i]; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * This function returns pointer to out ep struct with number ep_num ++ */ ++static inline dwc_otg_pcd_ep_t *get_out_ep(dwc_otg_pcd_t * pcd, uint32_t ep_num) ++{ ++ int i; ++ int num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; ++ if (ep_num == 0) { ++ return &pcd->ep0; ++ } else { ++ for (i = 0; i < num_out_eps; ++i) { ++ if (pcd->out_ep[i].dwc_ep.num == ep_num) ++ return &pcd->out_ep[i]; ++ } ++ return 0; ++ } ++} ++ ++/** ++ * This functions gets a pointer to an EP from the wIndex address ++ * value of the control request. ++ */ ++dwc_otg_pcd_ep_t *get_ep_by_addr(dwc_otg_pcd_t * pcd, u16 wIndex) ++{ ++ dwc_otg_pcd_ep_t *ep; ++ uint32_t ep_num = UE_GET_ADDR(wIndex); ++ ++ if (ep_num == 0) { ++ ep = &pcd->ep0; ++ } else if (UE_GET_DIR(wIndex) == UE_DIR_IN) { /* in ep */ ++ ep = &pcd->in_ep[ep_num - 1]; ++ } else { ++ ep = &pcd->out_ep[ep_num - 1]; ++ } ++ ++ return ep; ++} ++ ++/** ++ * This function checks the EP request queue, if the queue is not ++ * empty the next request is started. ++ */ ++void start_next_request(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req = 0; ++ uint32_t max_transfer = ++ GET_CORE_IF(ep->pcd)->core_params->max_transfer_size; ++ ++#ifdef DWC_UTE_CFI ++ struct dwc_otg_pcd *pcd; ++ pcd = ep->pcd; ++#endif ++ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ ep->dwc_ep.cfi_req_len = req->length; ++ pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req); ++ } else { ++#endif ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf) { ++ ep->dwc_ep.dma_addr = req->dw_align_buf_dma; ++ ep->dwc_ep.start_xfer_buff = req->dw_align_buf; ++ ep->dwc_ep.xfer_buff = req->dw_align_buf; ++ } else { ++ ep->dwc_ep.dma_addr = req->dma; ++ ep->dwc_ep.start_xfer_buff = req->buf; ++ ep->dwc_ep.xfer_buff = req->buf; ++ } ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = req->length; ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ++ ep->dwc_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE ++ - (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->dwc_ep.is_in) { ++ if (ep->dwc_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->dwc_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->dwc_ep.maxxfer > out_max_xfer) { ++ ep->dwc_ep.maxxfer = ++ out_max_xfer; ++ } ++ } ++ } ++ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { ++ ep->dwc_ep.maxxfer -= ++ (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket); ++ } ++ if (req->sent_zlp) { ++ if ((ep->dwc_ep.total_len % ++ ep->dwc_ep.maxpacket == 0) ++ && (ep->dwc_ep.total_len != 0)) { ++ ep->dwc_ep.sent_zlp = 1; ++ } ++ ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep); ++ } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ DWC_PRINTF("There are no more ISOC requests \n"); ++ ep->dwc_ep.frame_num = 0xFFFFFFFF; ++ } ++} ++ ++/** ++ * This function handles the SOF Interrupts. At this time the SOF ++ * Interrupt is disabled. ++ */ ++int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++ gintsts_data_t gintsts; ++ ++ DWC_DEBUGPL(DBG_PCD, "SOF\n"); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.sofintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Rx Status Queue Level Interrupt, which ++ * indicates that there is a least one packet in the Rx FIFO. The ++ * packets are moved from the FIFO to memory, where they will be ++ * processed when the Endpoint Interrupt Register indicates Transfer ++ * Complete or SETUP Phase Done. ++ * ++ * Repeat the following until the Rx Status Queue is empty: ++ * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet ++ * info ++ * -# If Receive FIFO is empty then skip to step Clear the interrupt ++ * and exit ++ * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the ++ * SETUP data to the buffer ++ * -# If OUT Data Packet call dwc_otg_read_packet to copy the data ++ * to the destination buffer ++ */ ++int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ gintmsk_data_t gintmask = {.d32 = 0 }; ++ device_grxsts_data_t status; ++ dwc_otg_pcd_ep_t *ep; ++ gintsts_data_t gintsts; ++#ifdef DEBUG ++ static char *dpid_str[] = { "D0", "D2", "D1", "MDATA" }; ++#endif ++ ++ //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); ++ /* Disable the Rx Status Queue Level interrupt */ ++ gintmask.b.rxstsqlvl = 1; ++ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0); ++ ++ /* Get the Status from the top of the FIFO */ ++ status.d32 = DWC_READ_REG32(&global_regs->grxstsp); ++ ++ DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s " ++ "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, ++ dpid_str[status.b.dpid], ++ status.b.pktsts, status.b.fn, status.b.fn); ++ /* Get pointer to EP structure */ ++ ep = get_out_ep(pcd, status.b.epnum); ++ ++ switch (status.b.pktsts) { ++ case DWC_DSTS_GOUT_NAK: ++ DWC_DEBUGPL(DBG_PCDV, "Global OUT NAK\n"); ++ break; ++ case DWC_STS_DATA_UPDT: ++ DWC_DEBUGPL(DBG_PCDV, "OUT Data Packet\n"); ++ if (status.b.bcnt && ep->dwc_ep.xfer_buff) { ++ /** @todo NGS Check for buffer overflow? */ ++ dwc_otg_read_packet(core_if, ++ ep->dwc_ep.xfer_buff, ++ status.b.bcnt); ++ ep->dwc_ep.xfer_count += status.b.bcnt; ++ ep->dwc_ep.xfer_buff += status.b.bcnt; ++ } ++ break; ++ case DWC_STS_XFER_COMP: ++ DWC_DEBUGPL(DBG_PCDV, "OUT Complete\n"); ++ break; ++ case DWC_DSTS_SETUP_COMP: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Setup Complete\n"); ++#endif ++ break; ++ case DWC_DSTS_SETUP_UPDT: ++ dwc_otg_read_setup_packet(core_if, pcd->setup_pkt->d32); ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, ++ "SETUP PKT: %02x.%02x v%04x i%04x l%04x\n", ++ pcd->setup_pkt->req.bmRequestType, ++ pcd->setup_pkt->req.bRequest, ++ UGETW(pcd->setup_pkt->req.wValue), ++ UGETW(pcd->setup_pkt->req.wIndex), ++ UGETW(pcd->setup_pkt->req.wLength)); ++#endif ++ ep->dwc_ep.xfer_count += status.b.bcnt; ++ break; ++ default: ++ DWC_DEBUGPL(DBG_PCDV, "Invalid Packet Status (0x%0x)\n", ++ status.b.pktsts); ++ break; ++ } ++ ++ /* Enable the Rx Status Queue Level interrupt */ ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32); ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.rxstsqlvl = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__); ++ return 1; ++} ++ ++/** ++ * This function examines the Device IN Token Learning Queue to ++ * determine the EP number of the last IN token received. This ++ * implementation is for the Mass Storage device where there are only ++ * 2 IN EPs (Control-IN and BULK-IN). ++ * ++ * The EP numbers for the first six IN Tokens are in DTKNQR1 and there ++ * are 8 EP Numbers in each of the other possible DTKNQ Registers. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * ++ */ ++static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_device_global_regs_t *dev_global_regs = ++ core_if->dev_if->dev_global_regs; ++ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ int ndx = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ int epnum = 0; ++ ++ //DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ in_tkn_epnums[i] = DWC_READ_REG32(addr); ++ DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, ++ in_tkn_epnums[i]); ++ if (addr == &dev_global_regs->dvbusdis) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ /* Get the EP numbers */ ++ in_tkn_epnums[0] = dtknqr1.b.epnums0_5; ++ ndx = dtknqr1.b.intknwptr - 1; ++ ++ //DWC_DEBUGPL(DBG_PCDV,"ndx=%d\n",ndx); ++ if (ndx == -1) { ++ /** @todo Find a simpler way to calculate the max ++ * queue position.*/ ++ int cnt = TOKEN_Q_DEPTH; ++ if (TOKEN_Q_DEPTH <= 6) { ++ cnt = TOKEN_Q_DEPTH - 1; ++ } else if (TOKEN_Q_DEPTH <= 14) { ++ cnt = TOKEN_Q_DEPTH - 7; ++ } else if (TOKEN_Q_DEPTH <= 22) { ++ cnt = TOKEN_Q_DEPTH - 15; ++ } else { ++ cnt = TOKEN_Q_DEPTH - 23; ++ } ++ epnum = (in_tkn_epnums[DTKNQ_REG_CNT - 1] >> (cnt * 4)) & 0xF; ++ } else { ++ if (ndx <= 5) { ++ epnum = (in_tkn_epnums[0] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 13) { ++ ndx -= 6; ++ epnum = (in_tkn_epnums[1] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 21) { ++ ndx -= 14; ++ epnum = (in_tkn_epnums[2] >> (ndx * 4)) & 0xF; ++ } else if (ndx <= 29) { ++ ndx -= 22; ++ epnum = (in_tkn_epnums[3] >> (ndx * 4)) & 0xF; ++ } ++ } ++ //DWC_DEBUGPL(DBG_PCD,"epnum=%d\n",epnum); ++ return epnum; ++} ++ ++/** ++ * This interrupt occurs when the non-periodic Tx FIFO is half-empty. ++ * The active request is checked for the next packet to be loaded into ++ * the non-periodic Tx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ gnptxsts_data_t txstatus = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ int epnum = 0; ++ dwc_otg_pcd_ep_t *ep = 0; ++ uint32_t len = 0; ++ int dwords; ++ ++ /* Get the epnum from the IN Token Learning Queue. */ ++ epnum = get_ep_of_last_in_token(core_if); ++ ep = get_in_ep(pcd, epnum); ++ ++ DWC_DEBUGPL(DBG_PCD, "NP TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32); ++ ++ while (txstatus.b.nptxqspcavail > 0 && ++ txstatus.b.nptxfspcavail > dwords && ++ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); ++ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", ++ DWC_READ_REG32(&global_regs->gnptxsts)); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.nptxfempty = 1; ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function is called when dedicated Tx FIFO Empty interrupt occurs. ++ * The active request is checked for the next packet to be loaded into ++ * apropriate Tx FIFO. ++ */ ++static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep = 0; ++ uint32_t len = 0; ++ int dwords; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* While there is space in the queue and space in the FIFO and ++ * More data to tranfer, Write packets to the Tx FIFO */ ++ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail > dwords && ++ ep->dwc_ep.xfer_count < ep->dwc_ep.xfer_len && ++ ep->dwc_ep.xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, &ep->dwc_ep, 0); ++ ++ len = ep->dwc_ep.xfer_len - ep->dwc_ep.xfer_count; ++ if (len > ep->dwc_ep.maxpacket) { ++ len = ep->dwc_ep.maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} ++ ++/** ++ * This function is called when the Device is disconnected. It stops ++ * any active requests and informs the Gadget driver of the ++ * disconnect. ++ */ ++void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd) ++{ ++ int i, num_in_eps, num_out_eps; ++ dwc_otg_pcd_ep_t *ep; ++ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_SPINLOCK(pcd->lock); ++ ++ num_in_eps = GET_CORE_IF(pcd)->dev_if->num_in_eps; ++ num_out_eps = GET_CORE_IF(pcd)->dev_if->num_out_eps; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() \n", __func__); ++ /* don't disconnect drivers more than once */ ++ if (pcd->ep0state == EP0_DISCONNECT) { ++ DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__); ++ DWC_SPINUNLOCK(pcd->lock); ++ return; ++ } ++ pcd->ep0state = EP0_DISCONNECT; ++ ++ /* Reset the OTG state. */ ++ dwc_otg_pcd_update_otg(pcd, 1); ++ ++ /* Disable the NP Tx Fifo Empty Interrupt. */ ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Flush the FIFOs */ ++ /**@todo NGS Flush Periodic FIFOs */ ++ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), 0x10); ++ dwc_otg_flush_rx_fifo(GET_CORE_IF(pcd)); ++ ++ /* prevent new request submissions, kill any outstanding requests */ ++ ep = &pcd->ep0; ++ dwc_otg_request_nuke(ep); ++ /* prevent new request submissions, kill any outstanding requests */ ++ for (i = 0; i < num_in_eps; i++) { ++ dwc_otg_pcd_ep_t *ep = &pcd->in_ep[i]; ++ dwc_otg_request_nuke(ep); ++ } ++ /* prevent new request submissions, kill any outstanding requests */ ++ for (i = 0; i < num_out_eps; i++) { ++ dwc_otg_pcd_ep_t *ep = &pcd->out_ep[i]; ++ dwc_otg_request_nuke(ep); ++ } ++ ++ /* report disconnect; the driver is already quiesced */ ++ if (pcd->fops->disconnect) { ++ DWC_SPINUNLOCK(pcd->lock); ++ pcd->fops->disconnect(pcd); ++ DWC_SPINLOCK(pcd->lock); ++ } ++ DWC_SPINUNLOCK(pcd->lock); ++} ++ ++/** ++ * This interrupt indicates that ... ++ */ ++int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr"); ++ intr_mask.b.i2cintr = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.i2cintr = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that ... ++ */ ++int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++#if defined(VERBOSE) ++ DWC_PRINTF("Early Suspend Detected\n"); ++#endif ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.erlysuspend = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This function configures EPO to receive SETUP packets. ++ * ++ * @todo NGS: Update the comments from the HW FS. ++ * ++ * -# Program the following fields in the endpoint specific registers ++ * for Control OUT EP 0, in order to receive a setup packet ++ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back ++ * setup packets) ++ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back ++ * to back setup packets) ++ * - In DMA mode, DOEPDMA0 Register with a memory address to ++ * store any setup packets received ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param pcd Programming view of the PCD. ++ */ ++static inline void ep0_out_start(dwc_otg_core_if_t * core_if, ++ dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ depctl_data_t doepctl = {.d32 = 0 }; ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__, ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++#endif ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ if (doepctl.b.epena) { ++ return; ++ } ++ } ++ ++ doeptsize0.b.supcnt = 3; ++ doeptsize0.b.pktcnt = 1; ++ doeptsize0.b.xfersize = 8 * 3; ++ ++ if (core_if->dma_enable) { ++ if (!core_if->dma_desc_enable) { ++ /** put here as for Hermes mode deptisz register should not be written */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, ++ doeptsize0.d32); ++ ++ /** @todo dma needs to handle multiple setup packets (up to 3) */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, ++ pcd->setup_pkt_dma_handle); ++ } else { ++ dev_if->setup_desc_index = ++ (dev_if->setup_desc_index + 1) & 1; ++ dma_desc = ++ dev_if->setup_desc_addr[dev_if->setup_desc_index]; ++ ++ /** DMA Descriptor Setup */ ++ dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.sr = 0; ++ dma_desc->status.b.mtrf = 0; ++ } ++ dma_desc->status.b.l = 1; ++ dma_desc->status.b.ioc = 1; ++ dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket; ++ dma_desc->buf = pcd->setup_pkt_dma_handle; ++ dma_desc->status.b.sts = 0; ++ dma_desc->status.b.bs = BS_HOST_READY; ++ ++ /** DOEPDMA0 Register write */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, ++ dev_if->dma_setup_desc_addr ++ [dev_if->setup_desc_index]); ++ } ++ ++ } else { ++ /** put here as for Hermes mode deptisz register should not be written */ ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, ++ doeptsize0.d32); ++ } ++ ++ /** DOEPCTL0 Register write cnak will be set after setup interrupt */ ++ doepctl.d32 = 0; ++ doepctl.b.epena = 1; ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ doepctl.b.cnak = 1; ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } else { ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32); ++ } ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); ++ DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", ++ DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); ++#endif ++} ++ ++/** ++ * This interrupt occurs when a USB Reset is detected. When the USB ++ * Reset Interrupt occurs the device state is set to DEFAULT and the ++ * EP0 state is set to IDLE. ++ * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) ++ * -# Unmask the following interrupt bits ++ * - DAINTMSK.INEP0 = 1 (Control 0 IN endpoint) ++ * - DAINTMSK.OUTEP0 = 1 (Control 0 OUT endpoint) ++ * - DOEPMSK.SETUP = 1 ++ * - DOEPMSK.XferCompl = 1 ++ * - DIEPMSK.XferCompl = 1 ++ * - DIEPMSK.TimeOut = 1 ++ * -# Program the following fields in the endpoint specific registers ++ * for Control OUT EP 0, in order to receive a setup packet ++ * - DOEPTSIZ0.Packet Count = 3 (To receive up to 3 back to back ++ * setup packets) ++ * - DOEPTSIZE0.Transfer Size = 24 Bytes (To receive up to 3 back ++ * to back setup packets) ++ * - In DMA mode, DOEPDMA0 Register with a memory address to ++ * store any setup packets received ++ * At this point, all the required initialization, except for enabling ++ * the control 0 OUT endpoint is done, for receiving SETUP packets. ++ */ ++int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ depctl_data_t doepctl = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ daint_data_t daintmsk = {.d32 = 0 }; ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ grstctl_t resetctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ int i = 0; ++ gintsts_data_t gintsts; ++ pcgcctl_data_t power = {.d32 = 0 }; ++ ++ power.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ if (power.b.stoppclk) { ++ power.d32 = 0; ++ power.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ ++ power.b.pwrclmp = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ ++ power.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); ++ } ++ ++ core_if->lx_state = DWC_OTG_L0; ++ ++ DWC_PRINTF("USB RESET\n"); ++#ifdef DWC_EN_ISOC ++ for (i = 1; i < 16; ++i) { ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ ep = get_in_ep(pcd, i); ++ if (ep != 0) { ++ dwc_ep = &ep->dwc_ep; ++ dwc_ep->next_frame = 0xffffffff; ++ } ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ /* reset the HNP settings */ ++ dwc_otg_pcd_update_otg(pcd, 1); ++ ++ /* Clear the Remote Wakeup Signalling */ ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ ++ /* Set NAK for all OUT EPs */ ++ doepctl.b.snak = 1; ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ } ++ ++ /* Flush the NP Tx FIFO */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); ++ /* Flush the Learning Queue */ ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (core_if->multiproc_int_enable) { ++ daintmsk.b.inep0 = 1; ++ daintmsk.b.outep0 = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, ++ daintmsk.d32); ++ ++ doepmsk.b.setup = 1; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ doepmsk.b.stsphsercvd = 1; ++ } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; ++/* ++ doepmsk.b.babble = 1; ++ doepmsk.b.nyet = 1; ++ ++ if (core_if->dma_enable) { ++ doepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0], ++ doepmsk.d32); ++ ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++ ++/* if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++/* ++ if (core_if->dma_enable) { ++ diepmsk.b.nak = 1; ++ } ++*/ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0], ++ diepmsk.d32); ++ } else { ++ daintmsk.b.inep0 = 1; ++ daintmsk.b.outep0 = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, ++ daintmsk.d32); ++ ++ doepmsk.b.setup = 1; ++ doepmsk.b.xfercompl = 1; ++ doepmsk.b.ahberr = 1; ++ doepmsk.b.epdisabled = 1; ++ ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { ++ doepmsk.b.stsphsercvd = 1; ++ } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); ++ ++ diepmsk.b.xfercompl = 1; ++ diepmsk.b.timeout = 1; ++ diepmsk.b.epdisabled = 1; ++ diepmsk.b.ahberr = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++/* ++ if (core_if->dma_desc_enable) { ++ diepmsk.b.bna = 1; ++ } ++*/ ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); ++ } ++ ++ /* Reset Device Address */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.devaddr = 0; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* setup EP0 to receive SETUP packets */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) ++ ep0_out_start(core_if, pcd); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.usbreset = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * Get the device speed from the device status register and convert it ++ * to USB speed constant. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static int get_device_speed(dwc_otg_core_if_t * core_if) ++{ ++ dsts_data_t dsts; ++ int speed = 0; ++ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); ++ ++ switch (dsts.b.enumspd) { ++ case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: ++ speed = USB_SPEED_HIGH; ++ break; ++ case DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ: ++ case DWC_DSTS_ENUMSPD_FS_PHY_48MHZ: ++ speed = USB_SPEED_FULL; ++ break; ++ ++ case DWC_DSTS_ENUMSPD_LS_PHY_6MHZ: ++ speed = USB_SPEED_LOW; ++ break; ++ } ++ ++ return speed; ++} ++ ++/** ++ * Read the device status register and set the device speed in the ++ * data structure. ++ * Set up EP0 to receive SETUP packets by calling dwc_ep0_activate. ++ */ ++int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ gintsts_data_t gintsts; ++ gusbcfg_data_t gusbcfg; ++ dwc_otg_core_global_regs_t *global_regs = ++ GET_CORE_IF(pcd)->core_global_regs; ++ uint8_t utmi16b, utmi8b; ++ int speed; ++ DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); ++ ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { ++ utmi16b = 6; //vahrama old value was 6; ++ utmi8b = 9; ++ } else { ++ utmi16b = 4; ++ utmi8b = 8; ++ } ++ dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } ++ ++#ifdef DEBUG_EP0 ++ print_ep0_state(pcd); ++#endif ++ ++ if (pcd->ep0state == EP0_DISCONNECT) { ++ pcd->ep0state = EP0_IDLE; ++ } else if (pcd->ep0state == EP0_STALL) { ++ pcd->ep0state = EP0_IDLE; ++ } ++ ++ pcd->ep0state = EP0_IDLE; ++ ++ ep0->stopped = 0; ++ ++ speed = get_device_speed(GET_CORE_IF(pcd)); ++ pcd->fops->connect(pcd, speed); ++ ++ /* Set USB turnaround time based on device speed and PHY interface. */ ++ gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); ++ if (speed == USB_SPEED_HIGH) { ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_ULPI) { ++ /* ULPI interface */ ++ gusbcfg.b.usbtrdtim = 9; ++ } ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_UTMI) { ++ /* UTMI+ interface */ ++ if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } else if (GET_CORE_IF(pcd)->hwcfg4. ++ b.utmi_phy_data_width == 1) { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } else if (GET_CORE_IF(pcd)-> ++ core_params->phy_utmi_width == 8) { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } else { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } ++ } ++ if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == ++ DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI) { ++ /* UTMI+ OR ULPI interface */ ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ gusbcfg.b.usbtrdtim = 9; ++ } else { ++ /* UTMI+ interface */ ++ if (GET_CORE_IF(pcd)-> ++ core_params->phy_utmi_width == 16) { ++ gusbcfg.b.usbtrdtim = utmi16b; ++ } else { ++ gusbcfg.b.usbtrdtim = utmi8b; ++ } ++ } ++ } ++ } else { ++ /* Full or low speed */ ++ gusbcfg.b.usbtrdtim = 9; ++ } ++ DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.enumdone = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the ISO OUT Packet was dropped due to ++ * Rx FIFO full or Rx Status Queue Full. If this interrupt occurs ++ * read all the data from the Rx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ ++ DWC_WARN("INTERRUPT Handler not implemented for %s\n", ++ "ISOC Out Dropped"); ++ ++ intr_mask.b.isooutdrop = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.isooutdrop = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates the end of the portion of the micro-frame ++ * for periodic transactions. If there is a periodic transaction for ++ * the next frame, load the packets into the EP periodic Tx FIFO. ++ */ ++int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP"); ++ ++ intr_mask.b.eopframe = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.eopframe = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that EP of the packet on the top of the ++ * non-periodic Tx FIFO does not match EP of the IN Token received. ++ * ++ * The "Device IN Token Queue" Registers are read to determine the ++ * order the IN Tokens have been received. The non-periodic Tx FIFO ++ * is flushed, so it can be reloaded in the order seen in the IN Token ++ * Queue. ++ */ ++int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 1; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (!gintsts.b.ginnakeff) { ++ /* Disable EP Mismatch interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.epmismatch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0); ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ /* Set the global non-periodic IN NAK handshake */ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.sgnpinnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } else { ++ DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n"); ++ } ++ /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective() ++ * handler after Global IN NAK Effective interrupt will be asserted */ ++ } ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.epmismatch = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This interrupt is valid only in DMA mode. This interrupt indicates that the ++ * core has stopped fetching data for IN endpoints due to the unavailability of ++ * TxFIFO space or Request Queue space. This interrupt is used by the ++ * application for an endpoint mismatch algorithm. ++ * ++ * @param pcd The PCD ++ */ ++int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk_data; ++ dctl_data_t dctl; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Mask GINTSTS.FETSUSP interrupt */ ++ gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gintmsk_data.b.fetsusp = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.fetsusp = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++/** ++ * This funcion stalls EP0. ++ */ ++static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ usb_device_request_t *ctrl = &pcd->setup_pkt->req; ++ DWC_WARN("req %02x.%02x protocol STALL; err %d\n", ++ ctrl->bmRequestType, ctrl->bRequest, err_val); ++ ++ ep0->dwc_ep.is_in = 1; ++ dwc_otg_ep_set_stall(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ pcd->ep0.stopped = 1; ++ pcd->ep0state = EP0_IDLE; ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++} ++ ++/** ++ * This functions delegates the setup command to the gadget driver. ++ */ ++static inline void do_gadget_setup(dwc_otg_pcd_t * pcd, ++ usb_device_request_t * ctrl) ++{ ++ int ret = 0; ++ DWC_SPINUNLOCK(pcd->lock); ++ ret = pcd->fops->setup(pcd, (uint8_t *) ctrl); ++ DWC_SPINLOCK(pcd->lock); ++ if (ret < 0) { ++ ep0_do_stall(pcd, ret); ++ } ++ ++ /** @todo This is a g_file_storage gadget driver specific ++ * workaround: a DELAYED_STATUS result from the fsg_setup ++ * routine will result in the gadget queueing a EP0 IN status ++ * phase for a two-stage control transfer. Exactly the same as ++ * a SET_CONFIGURATION/SET_INTERFACE except that this is a class ++ * specific request. Need a generic way to know when the gadget ++ * driver will queue the status phase. Can we assume when we ++ * call the gadget driver setup() function that it will always ++ * queue and require the following flag? Need to look into ++ * this. ++ */ ++ ++ if (ret == 256 + 999) { ++ pcd->request_config = 1; ++ } ++} ++ ++#ifdef DWC_UTE_CFI ++/** ++ * This functions delegates the CFI setup commands to the gadget driver. ++ * This function will return a negative value to indicate a failure. ++ */ ++static inline int cfi_gadget_setup(dwc_otg_pcd_t * pcd, ++ struct cfi_usb_ctrlrequest *ctrl_req) ++{ ++ int ret = 0; ++ ++ if (pcd->fops && pcd->fops->cfi_setup) { ++ DWC_SPINUNLOCK(pcd->lock); ++ ret = pcd->fops->cfi_setup(pcd, ctrl_req); ++ DWC_SPINLOCK(pcd->lock); ++ if (ret < 0) { ++ ep0_do_stall(pcd, ret); ++ return ret; ++ } ++ } ++ ++ return ret; ++} ++#endif ++ ++/** ++ * This function starts the Zero-Length Packet for the IN status phase ++ * of a 2 stage control transfer. ++ */ ++static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ if (pcd->ep0state == EP0_STALL) { ++ return; ++ } ++ ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ ++ /* Prepare for more SETUP Packets */ ++ DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n"); ++ if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) ++ && (pcd->core_if->dma_desc_enable) ++ && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "Data terminated wait next packet in out_desc_addr\n"); ++ pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr); ++ pcd->data_terminated = 1; ++ } ++ ep0->dwc_ep.xfer_len = 0; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.is_in = 1; ++ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ ++ /* Prepare for more SETUP Packets */ ++ //ep0_out_start(GET_CORE_IF(pcd), pcd); ++} ++ ++/** ++ * This function starts the Zero-Length Packet for the OUT status phase ++ * of a 2 stage control transfer. ++ */ ++static inline void do_setup_out_status_phase(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ if (pcd->ep0state == EP0_STALL) { ++ DWC_DEBUGPL(DBG_PCD, "EP0 STALLED\n"); ++ return; ++ } ++ pcd->ep0state = EP0_OUT_STATUS_PHASE; ++ ++ DWC_DEBUGPL(DBG_PCD, "EP0 OUT ZLP\n"); ++ ep0->dwc_ep.xfer_len = 0; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.is_in = 0; ++ ep0->dwc_ep.dma_addr = pcd->setup_pkt_dma_handle; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ ++ /* Prepare for more SETUP Packets */ ++ if (GET_CORE_IF(pcd)->dma_enable == 0) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } ++} ++ ++/** ++ * Clear the EP halt (STALL) and if pending requests start the ++ * transfer. ++ */ ++static inline void pcd_clear_halt(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) ++{ ++ if (ep->dwc_ep.stall_clear_flag == 0) ++ dwc_otg_ep_clear_stall(GET_CORE_IF(pcd), &ep->dwc_ep); ++ ++ /* Reactive the EP */ ++ dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); ++ if (ep->stopped) { ++ ep->stopped = 0; ++ /* If there is a request in the EP queue start it */ ++ ++ /** @todo FIXME: this causes an EP mismatch in DMA mode. ++ * epmismatch not yet implemented. */ ++ ++ /* ++ * Above fixme is solved by implmenting a tasklet to call the ++ * start_next_request(), outside of interrupt context at some ++ * time after the current time, after a clear-halt setup packet. ++ * Still need to implement ep mismatch in the future if a gadget ++ * ever uses more than one endpoint at once ++ */ ++ ep->queue_sof = 1; ++ DWC_TASK_SCHEDULE(pcd->start_xfer_tasklet); ++ } ++ /* Start Control Status Phase */ ++ do_setup_in_status_phase(pcd); ++} ++ ++/** ++ * This function is called when the SET_FEATURE TEST_MODE Setup packet ++ * is sent from the host. The Device Control register is written with ++ * the Test Mode bits set to the specified Test Mode. This is done as ++ * a tasklet so that the "Status" phase of the control transfer ++ * completes before transmitting the TEST packets. ++ * ++ * @todo This has not been tested since the tasklet struct was put ++ * into the PCD struct! ++ * ++ */ ++void do_test_mode(void *data) ++{ ++ dctl_data_t dctl; ++ dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) data; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ int test_mode = pcd->test_mode; ++ ++// DWC_WARN("%s() has not been tested since being rewritten!\n", __func__); ++ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ switch (test_mode) { ++ case 1: // TEST_J ++ dctl.b.tstctl = 1; ++ break; ++ ++ case 2: // TEST_K ++ dctl.b.tstctl = 2; ++ break; ++ ++ case 3: // TEST_SE0_NAK ++ dctl.b.tstctl = 3; ++ break; ++ ++ case 4: // TEST_PACKET ++ dctl.b.tstctl = 4; ++ break; ++ ++ case 5: // TEST_FORCE_ENABLE ++ dctl.b.tstctl = 5; ++ break; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++} ++ ++/** ++ * This function process the GET_STATUS Setup Commands. ++ */ ++static inline void do_get_status(dwc_otg_pcd_t * pcd) ++{ ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ uint16_t *status = pcd->status_buf; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, ++ "GET_STATUS %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++#endif ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */ ++ DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex)); ++ DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver); ++ DWC_PRINTF("OTG CAP - %d, %d\n", ++ core_if->core_params->otg_cap, ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ if (core_if->otg_ver == 1 ++ && core_if->core_params->otg_cap == ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ uint8_t *otgsts = (uint8_t*)pcd->status_buf; ++ *otgsts = (core_if->otg_sts & 0x1); ++ pcd->ep0_pending = 1; ++ ep0->dwc_ep.start_xfer_buff = ++ (uint8_t *) otgsts; ++ ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts; ++ ep0->dwc_ep.dma_addr = ++ pcd->status_buf_dma_handle; ++ ep0->dwc_ep.xfer_len = 1; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ return; ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ } else { ++ *status = 0x1; /* Self powered */ ++ *status |= pcd->remote_wakeup_enable << 1; ++ break; ++ } ++ case UT_INTERFACE: ++ *status = 0; ++ break; ++ ++ case UT_ENDPOINT: ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0 || UGETW(ctrl.wLength) > 2) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ /** @todo check for EP stall */ ++ *status = ep->stopped; ++ break; ++ } ++ pcd->ep0_pending = 1; ++ ep0->dwc_ep.start_xfer_buff = (uint8_t *) status; ++ ep0->dwc_ep.xfer_buff = (uint8_t *) status; ++ ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle; ++ ep0->dwc_ep.xfer_len = 2; ++ ep0->dwc_ep.xfer_count = 0; ++ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; ++ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); ++} ++ ++/** ++ * This function process the SET_FEATURE Setup Commands. ++ */ ++static inline void do_set_feature(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep = 0; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_PCD, "SET_FEATURE:%02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++ DWC_DEBUGPL(DBG_PCD, "otg_cap=%d\n", otg_cap_param); ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 1; ++ break; ++ ++ case UF_TEST_MODE: ++ /* Setup the Test Mode tasklet to do the Test ++ * Packet generation after the SETUP Status ++ * phase has completed. */ ++ ++ /** @todo This has not been tested since the ++ * tasklet struct was put into the PCD ++ * struct! */ ++ pcd->test_mode = UGETW(ctrl.wIndex) >> 8; ++ DWC_TASK_SCHEDULE(pcd->test_mode_tasklet); ++ break; ++ ++ case UF_DEVICE_B_HNP_ENABLE: ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n"); ++ ++ /* dev may initiate HNP */ ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->b_hnp_enable = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ DWC_DEBUGPL(DBG_PCD, "Request B HNP\n"); ++ /**@todo Is the gotgctl.devhnpen cleared ++ * by a USB Reset? */ ++ gotgctl.b.devhnpen = 1; ++ gotgctl.b.hnpreq = 1; ++ DWC_WRITE_REG32(&global_regs->gotgctl, ++ gotgctl.d32); ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ case UF_DEVICE_A_HNP_SUPPORT: ++ /* RH port supports HNP */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n"); ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->a_hnp_support = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ case UF_DEVICE_A_ALT_HNP_SUPPORT: ++ /* other RH port does */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n"); ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ pcd->a_alt_hnp_support = 1; ++ dwc_otg_pcd_update_otg(pcd, 0); ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ ++ case UT_INTERFACE: ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ case UT_ENDPOINT: ++ if (UGETW(ctrl.wValue) == UF_ENDPOINT_HALT) { ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ep->stopped = 1; ++ dwc_otg_ep_set_stall(core_if, &ep->dwc_ep); ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ } ++} ++ ++/** ++ * This function process the CLEAR_FEATURE Setup Commands. ++ */ ++static inline void do_clear_feature(dwc_otg_pcd_t * pcd) ++{ ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep = 0; ++ ++ DWC_DEBUGPL(DBG_PCD, ++ "CLEAR_FEATURE:%02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++ ++ switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { ++ case UT_DEVICE: ++ switch (UGETW(ctrl.wValue)) { ++ case UF_DEVICE_REMOTE_WAKEUP: ++ pcd->remote_wakeup_enable = 0; ++ break; ++ ++ case UF_TEST_MODE: ++ /** @todo Add CLEAR_FEATURE for TEST modes. */ ++ break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ do_setup_in_status_phase(pcd); ++ break; ++ ++ case UT_ENDPOINT: ++ ep = get_ep_by_addr(pcd, UGETW(ctrl.wIndex)); ++ if (ep == 0) { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ ++ pcd_clear_halt(pcd, ep); ++ ++ break; ++ } ++} ++ ++/** ++ * This function process the SET_ADDRESS Setup Commands. ++ */ ++static inline void do_set_address(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ ++ if (ctrl.bmRequestType == UT_DEVICE) { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ ++#ifdef DEBUG_EP0 ++// DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); ++#endif ++ dcfg.b.devaddr = UGETW(ctrl.wValue); ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); ++ do_setup_in_status_phase(pcd); ++ } ++} ++ ++/** ++ * This function processes SETUP commands. In Linux, the USB Command ++ * processing is done in two places - the first being the PCD and the ++ * second in the Gadget Driver (for example, the File-Backed Storage ++ * Gadget Driver). ++ * ++ *
Parameter NameMeaning
otg_capSpecifies the OTG capabilities. The driver will automatically detect the ++ value for this parameter if none is specified. ++ - 0: HNP and SRP capable (default, if available) ++ - 1: SRP Only capable ++ - 2: No HNP/SRP capable ++
dma_enableSpecifies 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) ++
dma_burst_sizeThe DMA Burst size (applicable only for External DMA Mode). ++ - Values: 1, 4, 8 16, 32, 64, 128, 256 (default 32) ++
speedSpecifies 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. ++ - 0: High Speed (default) ++ - 1: Full Speed ++
host_support_fs_ls_low_powerSpecifies 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 ++
host_ls_low_power_phy_clkSpecifies 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. ++ - 0: 48 MHz (default) ++ - 1: 6 MHz ++
enable_dynamic_fifo Specifies whether FIFOs may be resized by the driver software. ++ - 0: Use cC FIFO size parameters ++ - 1: Allow dynamic FIFO sizing (default) ++
data_fifo_sizeTotal number of 4-byte words in the data FIFO memory. This memory ++ includes the Rx FIFO, non-periodic Tx FIFO, and periodic Tx FIFOs. ++ - Values: 32 to 32768 (default 8192) ++ ++ Note: The total FIFO memory depth in the FPGA configuration is 8192. ++
dev_rx_fifo_sizeNumber of 4-byte words in the Rx FIFO in device mode when dynamic ++ FIFO sizing is enabled. ++ - Values: 16 to 32768 (default 1064) ++
dev_nperio_tx_fifo_sizeNumber of 4-byte words in the non-periodic Tx FIFO in device mode when ++ dynamic FIFO sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++
dev_perio_tx_fifo_size_n (n = 1 to 15)Number of 4-byte words in each of the periodic Tx FIFOs in device mode ++ when dynamic FIFO sizing is enabled. ++ - Values: 4 to 768 (default 256) ++
host_rx_fifo_sizeNumber of 4-byte words in the Rx FIFO in host mode when dynamic FIFO ++ sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++
host_nperio_tx_fifo_sizeNumber of 4-byte words in the non-periodic Tx FIFO in host mode when ++ dynamic FIFO sizing is enabled in the core. ++ - Values: 16 to 32768 (default 1024) ++
host_perio_tx_fifo_sizeNumber of 4-byte words in the host periodic Tx FIFO when dynamic FIFO ++ sizing is enabled. ++ - Values: 16 to 32768 (default 1024) ++
max_transfer_sizeThe maximum transfer size supported in bytes. ++ - Values: 2047 to 65,535 (default 65,535) ++
max_packet_countThe maximum number of packets in a transfer. ++ - Values: 15 to 511 (default 511) ++
host_channelsThe number of host channel registers to use. ++ - Values: 1 to 16 (default 12) ++ ++ Note: The FPGA configuration supports a maximum of 12 host channels. ++
dev_endpointsThe number of endpoints in addition to EP0 available for device mode ++ operations. ++ - Values: 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. ++
phy_typeSpecifies the type of PHY interface to use. By default, the driver will ++ automatically detect the phy_type. ++ - 0: Full Speed ++ - 1: UTMI+ (default, if available) ++ - 2: ULPI ++
phy_utmi_widthSpecifies the UTMI+ Data Width. This parameter is applicable for a ++ phy_type of UTMI+. 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. ++ - Values: 8 or 16 bits (default 16) ++
phy_ulpi_ddrSpecifies 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 ++
i2c_enableSpecifies whether to use the I2C interface for full speed PHY. This ++ parameter is only applicable if PHY_TYPE is FS. ++ - 0: Disabled (default) ++ - 1: Enabled ++
ulpi_fs_lsSpecifies whether to use ULPI FS/LS mode only. ++ - 0: Disabled (default) ++ - 1: Enabled ++
ts_dlineSpecifies whether term select D-Line pulsing for all PHYs is enabled. ++ - 0: Disabled (default) ++ - 1: Enabled ++
en_multiple_tx_fifoSpecifies whether dedicatedto tx fifos are enabled for non periodic IN EPs. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Disabled ++ - 1: Enabled (default, if available) ++
dev_tx_fifo_size_n (n = 1 to 15)Number of 4-byte words in each of the Tx FIFOs in device mode ++ when dynamic FIFO sizing is enabled. ++ - Values: 4 to 768 (default 256) ++
tx_thr_lengthTransmit Threshold length in 32 bit double words ++ - Values: 8 to 128 (default 64) ++
rx_thr_lengthReceive Threshold length in 32 bit double words ++ - Values: 8 to 128 (default 64) ++
thr_ctlSpecifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of ++ this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and ++ Rx transfers accordingly. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - Values: 0 to 7 (default 0) ++ Bit values indicate: ++ - 0: Thresholding disabled ++ - 1: Thresholding enabled ++
dma_desc_enableSpecifies whether to enable Descriptor DMA mode. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Descriptor DMA disabled ++ - 1: Descriptor DMA (default, if available) ++
mpi_enableSpecifies whether to enable MPI enhancement mode. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: MPI disabled (default) ++ - 1: MPI enable ++
pti_enableSpecifies whether to enable PTI enhancement support. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: PTI disabled (default) ++ - 1: PTI enable ++
lpm_enableSpecifies whether to enable LPM support. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: LPM disabled ++ - 1: LPM enable (default, if available) ++
ic_usb_capSpecifies whether to enable IC_USB capability. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: IC_USB disabled (default, if available) ++ - 1: IC_USB enable ++
ahb_thr_ratioSpecifies AHB Threshold ratio. ++ - Values: 0 to 3 (default 0) ++
power_downSpecifies Power Down(Hibernation) Mode. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Power Down disabled (default) ++ - 2: Power Down enabled ++
reload_ctlSpecifies whether dynamic reloading of the HFIR register is allowed during ++ run time. The driver will automatically detect the value for this parameter if ++ none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0 ++ the core might misbehave. ++ - 0: Reload Control disabled (default) ++ - 1: Reload Control enabled ++
dev_out_nakSpecifies whether Device OUT NAK enhancement enabled or no. ++ The driver will automatically detect the value for this parameter if ++ none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1. ++ - 0: The core does not set NAK after Bulk OUT transfer complete (default) ++ - 1: The core sets NAK after Bulk OUT transfer complete ++
cont_on_bnaSpecifies whether Enable Continue on BNA enabled or no. ++ After receiving BNA interrupt the core disables the endpoint,when the ++ endpoint is re-enabled by the application the ++ - 0: Core starts processing from the DOEPDMA descriptor (default) ++ - 1: Core starts processing from the descriptor which received the BNA. ++ This parameter is valid only when OTG_EN_DESC_DMA == 1b1. ++
ahb_singleThis bit when programmed supports SINGLE transfers for remainder data ++ in a transfer for DMA mode of operation. ++ - 0: The remainder data will be sent using INCR burst size (default) ++ - 1: The remainder data will be sent using SINGLE burst size. ++
adp_enableSpecifies whether ADP feature is enabled. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: ADP feature disabled (default) ++ - 1: ADP feature enabled ++
otg_verSpecifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3 ++ USB OTG device. ++ - 0: OTG 2.0 support disabled (default) ++ - 1: OTG 2.0 support enabled ++
++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ * ++ *
Command Driver Description
GET_STATUS PCD Command is processed as ++ * defined in chapter 9 of the USB 2.0 Specification chapter 9 ++ *
CLEAR_FEATURE PCD The Device and Endpoint ++ * requests are the ENDPOINT_HALT feature is procesed, all others the ++ * interface requests are ignored.
SET_FEATURE PCD The Device and Endpoint ++ * requests are processed by the PCD. Interface requests are passed ++ * to the Gadget Driver.
SET_ADDRESS PCD Program the DCFG reg, ++ * with device address received
GET_DESCRIPTOR Gadget Driver Return the ++ * requested descriptor
SET_DESCRIPTOR Gadget Driver Optional - ++ * not implemented by any of the existing Gadget Drivers.
SET_CONFIGURATION Gadget Driver Disable ++ * all EPs and enable EPs for new configuration.
GET_CONFIGURATION Gadget Driver Return ++ * the current configuration
SET_INTERFACE Gadget Driver Disable all ++ * EPs and enable EPs for new configuration.
GET_INTERFACE Gadget Driver Return the ++ * current interface.
SYNC_FRAME PCD Display debug ++ * message.
++ * ++ * When the SETUP Phase Done interrupt occurs, the PCD SETUP commands are ++ * processed by pcd_setup. Calling the Function Driver's setup function from ++ * pcd_setup processes the gadget SETUP commands. ++ */ ++static inline void pcd_setup(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ usb_device_request_t ctrl = pcd->setup_pkt->req; ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ ++#ifdef DWC_UTE_CFI ++ int retval = 0; ++ struct cfi_usb_ctrlrequest cfi_req; ++#endif ++ ++ doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz); ++ ++ /** In BDMA more then 1 setup packet is not supported till 3.00a */ ++ if (core_if->dma_enable && core_if->dma_desc_enable == 0 ++ && (doeptsize0.b.supcnt < 2) ++ && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ DWC_ERROR ++ ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n"); ++ } ++ if ((core_if->snpsid >= OTG_CORE_REV_3_00a) ++ && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) { ++ ctrl = ++ (pcd->setup_pkt + ++ (3 - doeptsize0.b.supcnt - 1 + ++ ep0->dwc_ep.stp_rollover))->req; ++ } ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", ++ ctrl.bmRequestType, ctrl.bRequest, ++ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), ++ UGETW(ctrl.wLength)); ++#endif ++ ++ /* Clean up the request queue */ ++ dwc_otg_request_nuke(ep0); ++ ep0->stopped = 0; ++ ++ if (ctrl.bmRequestType & UE_DIR_IN) { ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_DATA_PHASE; ++ } else { ++ ep0->dwc_ep.is_in = 0; ++ pcd->ep0state = EP0_OUT_DATA_PHASE; ++ } ++ ++ if (UGETW(ctrl.wLength) == 0) { ++ ep0->dwc_ep.is_in = 1; ++ pcd->ep0state = EP0_IN_STATUS_PHASE; ++ } ++ ++ if (UT_GET_TYPE(ctrl.bmRequestType) != UT_STANDARD) { ++ ++#ifdef DWC_UTE_CFI ++ DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t)); ++ ++ //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ++ ctrl.bRequestType, ctrl.bRequest); ++ if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) { ++ if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) { ++ retval = cfi_setup(pcd, &cfi_req); ++ if (retval < 0) { ++ ep0_do_stall(pcd, retval); ++ pcd->ep0_pending = 0; ++ return; ++ } ++ ++ /* if need gadget setup then call it and check the retval */ ++ if (pcd->cfi->need_gadget_att) { ++ retval = ++ cfi_gadget_setup(pcd, ++ &pcd-> ++ cfi->ctrl_req); ++ if (retval < 0) { ++ pcd->ep0_pending = 0; ++ return; ++ } ++ } ++ ++ if (pcd->cfi->need_status_in_complete) { ++ do_setup_in_status_phase(pcd); ++ } ++ return; ++ } ++ } ++#endif ++ ++ /* handle non-standard (class/vendor) requests in the gadget driver */ ++ do_gadget_setup(pcd, &ctrl); ++ return; ++ } ++ ++ /** @todo NGS: Handle bad setup packet? */ ++ ++/////////////////////////////////////////// ++//// --- Standard Request handling --- //// ++ ++ switch (ctrl.bRequest) { ++ case UR_GET_STATUS: ++ do_get_status(pcd); ++ break; ++ ++ case UR_CLEAR_FEATURE: ++ do_clear_feature(pcd); ++ break; ++ ++ case UR_SET_FEATURE: ++ do_set_feature(pcd); ++ break; ++ ++ case UR_SET_ADDRESS: ++ do_set_address(pcd); ++ break; ++ ++ case UR_SET_INTERFACE: ++ case UR_SET_CONFIG: ++// _pcd->request_config = 1; /* Configuration changed */ ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ case UR_SYNCH_FRAME: ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ ++ default: ++ /* Call the Gadget Driver's setup functions */ ++ do_gadget_setup(pcd, &ctrl); ++ break; ++ } ++} ++ ++/** ++ * This function completes the ep0 control transfer. ++ */ ++static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs = ++ dev_if->in_ep_regs[ep->dwc_ep.num]; ++#ifdef DEBUG_EP0 ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs = ++ dev_if->out_ep_regs[ep->dwc_ep.num]; ++#endif ++ deptsiz0_data_t deptsiz; ++ dev_dma_desc_sts_t desc_sts; ++ dwc_otg_pcd_request_t *req; ++ int is_last = 0; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ ++#ifdef DWC_UTE_CFI ++ struct cfi_usb_ctrlrequest *ctrlreq; ++ int retval = -DWC_E_NOT_SUPPORTED; ++#endif ++ ++ desc_sts.b.bytes = 0; ++ ++ if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ if (ep->dwc_ep.is_in) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Do setup OUT status phase\n"); ++#endif ++ do_setup_out_status_phase(pcd); ++ } else { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Do setup IN status phase\n"); ++#endif ++ ++#ifdef DWC_UTE_CFI ++ ctrlreq = &pcd->cfi->ctrl_req; ++ ++ if (UT_GET_TYPE(ctrlreq->bRequestType) == UT_VENDOR) { ++ if (ctrlreq->bRequest > 0xB0 ++ && ctrlreq->bRequest < 0xBF) { ++ ++ /* Return if the PCD failed to handle the request */ ++ if ((retval = ++ pcd->cfi->ops. ++ ctrl_write_complete(pcd->cfi, ++ pcd)) < 0) { ++ CFI_INFO ++ ("ERROR setting a new value in the PCD(%d)\n", ++ retval); ++ ep0_do_stall(pcd, retval); ++ pcd->ep0_pending = 0; ++ return 0; ++ } ++ ++ /* If the gadget needs to be notified on the request */ ++ if (pcd->cfi->need_gadget_att == 1) { ++ //retval = do_gadget_setup(pcd, &pcd->cfi->ctrl_req); ++ retval = ++ cfi_gadget_setup(pcd, ++ &pcd->cfi-> ++ ctrl_req); ++ ++ /* Return from the function if the gadget failed to process ++ * the request properly - this should never happen !!! ++ */ ++ if (retval < 0) { ++ CFI_INFO ++ ("ERROR setting a new value in the gadget(%d)\n", ++ retval); ++ pcd->ep0_pending = 0; ++ return 0; ++ } ++ } ++ ++ CFI_INFO("%s: RETVAL=%d\n", __func__, ++ retval); ++ /* If we hit here then the PCD and the gadget has properly ++ * handled the request - so send the ZLP IN to the host. ++ */ ++ /* @todo: MAS - decide whether we need to start the setup ++ * stage based on the need_setup value of the cfi object ++ */ ++ do_setup_in_status_phase(pcd); ++ pcd->ep0_pending = 0; ++ return 1; ++ } ++ } ++#endif ++ ++ do_setup_in_status_phase(pcd); ++ } ++ pcd->ep0_pending = 0; ++ return 1; ++ } ++ ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ return 0; ++ } ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ++ if (pcd->ep0state == EP0_OUT_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ is_last = 1; ++ } else if (ep->dwc_ep.is_in) { ++ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); ++ if (core_if->dma_desc_enable != 0) ++ desc_sts = dev_if->in_desc_addr->status; ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "%d len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++#endif ++ ++ if (((core_if->dma_desc_enable == 0) ++ && (deptsiz.b.xfersize == 0)) ++ || ((core_if->dma_desc_enable != 0) ++ && (desc_sts.b.bytes == 0))) { ++ req->actual = ep->dwc_ep.xfer_count; ++ /* Is a Zero Len Packet needed? */ ++ if (req->sent_zlp) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "Setup Rx ZLP\n"); ++#endif ++ req->sent_zlp = 0; ++ } ++ do_setup_out_status_phase(pcd); ++ } ++ } else { ++ /* ep0-OUT */ ++#ifdef DEBUG_EP0 ++ deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz); ++ DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++#endif ++ req->actual = ep->dwc_ep.xfer_count; ++ ++ /* Is a Zero Len Packet needed? */ ++ if (req->sent_zlp) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "Setup Tx ZLP\n"); ++#endif ++ req->sent_zlp = 0; ++ } ++ /* For older cores do setup in status phase in Slave/BDMA modes, ++ * starting from 3.00 do that only in slave, and for DMA modes ++ * just re-enable ep 0 OUT here*/ ++ if (core_if->dma_enable == 0 ++ || (core_if->dma_desc_enable == 0 ++ && core_if->snpsid <= OTG_CORE_REV_2_94a)) { ++ do_setup_in_status_phase(pcd); ++ } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "Enable out ep before in status phase\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++ dwc_otg_request_done(ep, req, 0); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ return 1; ++ } ++ return 0; ++} ++ ++#ifdef DWC_UTE_CFI ++/** ++ * This function calculates traverses all the CFI DMA descriptors and ++ * and accumulates the bytes that are left to be transfered. ++ * ++ * @return The total bytes left to transfered, or a negative value as failure ++ */ ++static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep) ++{ ++ int32_t ret = 0; ++ int i; ++ struct dwc_otg_dma_desc *ddesc = NULL; ++ struct cfi_ep *cfiep; ++ ++ /* See if the pcd_ep has its respective cfi_ep mapped */ ++ cfiep = get_cfi_ep_by_pcd_ep(ep->pcd->cfi, ep); ++ if (!cfiep) { ++ CFI_INFO("%s: Failed to find ep\n", __func__); ++ return -1; ++ } ++ ++ ddesc = ep->dwc_ep.descs; ++ ++ for (i = 0; (i < cfiep->desc_count) && (i < MAX_DMA_DESCS_PER_EP); i++) { ++ ++#if defined(PRINT_CFI_DMA_DESCS) ++ print_desc(ddesc, ep->ep.name, i); ++#endif ++ ret += ddesc->status.b.bytes; ++ ddesc++; ++ } ++ ++ if (ret) ++ CFI_INFO("!!!!!!!!!! WARNING (%s) - residue=%d\n", __func__, ++ ret); ++ ++ return ret; ++} ++#endif ++ ++/** ++ * This function completes the request for the EP. If there are ++ * additional requests for the EP in the queue they will be started. ++ */ ++static void complete_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs = ++ dev_if->in_ep_regs[ep->dwc_ep.num]; ++ deptsiz_data_t deptsiz; ++ dev_dma_desc_sts_t desc_sts; ++ dwc_otg_pcd_request_t *req = 0; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ uint32_t byte_count = 0; ++ int is_last = 0; ++ int i; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s() %d-%s\n", __func__, ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT")); ++ ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending); ++ ++ if (ep->dwc_ep.is_in) { ++ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable == 0) { ++ if (deptsiz.b.xfersize == 0 ++ && deptsiz.b.pktcnt == 0) { ++ byte_count = ++ ep->dwc_ep.xfer_len - ++ ep->dwc_ep.xfer_count; ++ ++ ep->dwc_ep.xfer_buff += byte_count; ++ ep->dwc_ep.dma_addr += byte_count; ++ ep->dwc_ep.xfer_count += byte_count; ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%d-%s len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep. ++ is_in ? "IN" : "OUT"), ++ ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ ++ if (ep->dwc_ep.xfer_len < ++ ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer ++ (core_if, &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer ++ (core_if, &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ if (ep->dwc_ep.type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ req->actual = 0; ++ dwc_otg_request_done(ep, req, 0); ++ ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ ++ /* If there is a request in the queue start it. */ ++ start_next_request(ep); ++ } else ++ DWC_WARN ++ ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ } ++ } else { ++ dma_desc = ep->dwc_ep.desc_addr; ++ byte_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ++#ifdef DWC_UTE_CFI ++ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, ++ ep->dwc_ep.buff_mode); ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ int residue; ++ ++ residue = cfi_calc_desc_residue(ep); ++ if (residue < 0) ++ return; ++ ++ byte_count = residue; ++ } else { ++#endif ++ for (i = 0; i < ep->dwc_ep.desc_cnt; ++ ++i) { ++ desc_sts = dma_desc->status; ++ byte_count += desc_sts.b.bytes; ++ dma_desc++; ++ } ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ if (byte_count == 0) { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len; ++ is_last = 1; ++ } else { ++ DWC_WARN("Incomplete transfer\n"); ++ } ++ } ++ } else { ++ if (deptsiz.b.xfersize == 0 && deptsiz.b.pktcnt == 0) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "%d-%s len=%d xfersize=%d pktcnt=%d\n", ++ ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT", ++ ep->dwc_ep.xfer_len, ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); ++ ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, ++ &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length trasfer in case if it is queued ++ * a trasfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Desriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 legth. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ DWC_WARN ++ ("Incomplete transfer (%d-%s [siz=%d pkt=%d])\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ } ++ } ++ } else { ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs = ++ dev_if->out_ep_regs[ep->dwc_ep.num]; ++ desc_sts.d32 = 0; ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dma_desc = ep->dwc_ep.desc_addr; ++ byte_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ++#ifdef DWC_UTE_CFI ++ CFI_INFO("%s: BUFFER_MODE=%d\n", __func__, ++ ep->dwc_ep.buff_mode); ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ int residue; ++ residue = cfi_calc_desc_residue(ep); ++ if (residue < 0) ++ return; ++ byte_count = residue; ++ } else { ++#endif ++ ++ for (i = 0; i < ep->dwc_ep.desc_cnt; ++ ++i) { ++ desc_sts = dma_desc->status; ++ byte_count += desc_sts.b.bytes; ++ dma_desc++; ++ } ++ ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ /* Checking for interrupt Out transfers with not ++ * dword aligned mps sizes ++ */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR && ++ (ep->dwc_ep.maxpacket%4)) { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len - byte_count; ++ if ((ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket) ++ && (ep->dwc_ep.xfer_len / ++ ep->dwc_ep.maxpacket < ++ MAX_DMA_DESC_CNT)) ++ ep->dwc_ep.xfer_len -= ++ (ep->dwc_ep.desc_cnt - ++ 1) * ep->dwc_ep.maxpacket + ++ ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket; ++ else ++ ep->dwc_ep.xfer_len -= ++ ep->dwc_ep.desc_cnt * ++ ep->dwc_ep.maxpacket; ++ if (ep->dwc_ep.xfer_len > 0) { ++ dwc_otg_ep_start_transfer ++ (core_if, &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len - byte_count + ++ ((4 - ++ (ep->dwc_ep. ++ total_len & 0x3)) & 0x3); ++ is_last = 1; ++ } ++ } else { ++ deptsiz.d32 = 0; ++ deptsiz.d32 = ++ DWC_READ_REG32(&out_ep_regs->doeptsiz); ++ ++ byte_count = (ep->dwc_ep.xfer_len - ++ ep->dwc_ep.xfer_count - ++ deptsiz.b.xfersize); ++ ep->dwc_ep.xfer_buff += byte_count; ++ ep->dwc_ep.dma_addr += byte_count; ++ ep->dwc_ep.xfer_count += byte_count; ++ ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, ++ &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length trasfer in case if it is queued ++ * a trasfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Desriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 legth. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } ++ } else { ++ /* Check if the whole transfer was completed, ++ * if no, setup transfer for next portion of data ++ */ ++ if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { ++ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); ++ } else if (ep->dwc_ep.sent_zlp) { ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer with size divisible to EPs max ++ * packet size and with usb_request zero field ++ * is set, which means that after data is transfered, ++ * it is also should be transfered ++ * a 0 length packet at the end. For Slave and ++ * Buffer DMA modes in this case SW has ++ * to initiate 2 transfers one with transfer size, ++ * and the second with 0 size. For Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. ++ */ ++ ep->dwc_ep.sent_zlp = 0; ++ dwc_otg_ep_start_zl_transfer(core_if, ++ &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "addr %p, %d-%s len=%d cnt=%d xsize=%d pktcnt=%d\n", ++ &out_ep_regs->doeptsiz, ep->dwc_ep.num, ++ ep->dwc_ep.is_in ? "IN" : "OUT", ++ ep->dwc_ep.xfer_len, ep->dwc_ep.xfer_count, ++ deptsiz.b.xfersize, deptsiz.b.pktcnt); ++ } ++ ++ /* Complete the request */ ++ if (is_last) { ++#ifdef DWC_UTE_CFI ++ if (ep->dwc_ep.buff_mode != BM_STANDARD) { ++ req->actual = ep->dwc_ep.cfi_req_len - byte_count; ++ } else { ++#endif ++ req->actual = ep->dwc_ep.xfer_count; ++#ifdef DWC_UTE_CFI ++ } ++#endif ++ if (req->dw_align_buf) { ++ if (!ep->dwc_ep.is_in) { ++ dwc_memcpy(req->buf, req->dw_align_buf, req->length); ++ } ++ DWC_DMA_FREE(req->length, req->dw_align_buf, ++ req->dw_align_buf_dma); ++ } ++ ++ dwc_otg_request_done(ep, req, 0); ++ ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ ++ /* If there is a request in the queue start it. */ ++ start_next_request(ep); ++ } ++} ++ ++#ifdef DWC_EN_ISOC ++ ++/** ++ * This function BNA interrupt for Isochronous EPs ++ * ++ */ ++static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ volatile uint32_t *addr; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ int i; ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num); ++ ++ if (dwc_ep->is_in) { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b_iso_in.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ } else { ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ for (i = 0; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b_iso_out.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ } ++ ++ if (dwc_ep->is_in == 0) { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep-> ++ num]->doepctl; ++ } else { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ depctl.b.epena = 1; ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++} ++ ++/** ++ * This function sets latest iso packet information(non-PTI mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ dma_addr_t dma_addr; ++ uint32_t offset; ++ ++ if (ep->proc_buf_num) ++ dma_addr = ep->dma_addr1; ++ else ++ dma_addr = ep->dma_addr0; ++ ++ if (ep->is_in) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[ep->num]->dieptsiz); ++ offset = ep->data_per_frame; ++ } else { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ offset = ++ ep->data_per_frame + ++ (0x4 & (0x4 - (ep->data_per_frame & 0x3))); ++ } ++ ++ if (!deptsiz.b.xfersize) { ++ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; ++ ep->pkt_info[ep->cur_pkt].offset = ++ ep->cur_pkt_dma_addr - dma_addr; ++ ep->pkt_info[ep->cur_pkt].status = 0; ++ } else { ++ ep->pkt_info[ep->cur_pkt].length = ep->data_per_frame; ++ ep->pkt_info[ep->cur_pkt].offset = ++ ep->cur_pkt_dma_addr - dma_addr; ++ ep->pkt_info[ep->cur_pkt].status = -DWC_E_NO_DATA; ++ } ++ ep->cur_pkt_addr += offset; ++ ep->cur_pkt_dma_addr += offset; ++ ep->cur_pkt++; ++} ++ ++/** ++ * This function sets latest iso packet information(DDMA mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ iso_pkt_info_t *iso_packet; ++ uint32_t data_per_desc; ++ uint32_t offset; ++ int i, j; ++ ++ iso_packet = dwc_ep->pkt_info; ++ ++ /** Reinit closed DMA Descriptors*/ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ offset = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep-> ++ data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - ++ data_per_desc % ++ 4) : 0; ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + ++ (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Received data length */ ++ if (!sts.b_iso_out.rxbytes) { ++ iso_packet->length = ++ data_per_desc - ++ sts.b_iso_out.rxbytes; ++ } else { ++ iso_packet->length = ++ data_per_desc - ++ sts.b_iso_out.rxbytes + (4 - ++ dwc_ep->data_per_frame ++ % 4); ++ } ++ ++ iso_packet->offset = offset; ++ ++ offset += data_per_desc; ++ dma_desc++; ++ iso_packet++; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + ++ (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Received data length */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; ++ ++ iso_packet->offset = offset; ++ ++ offset += data_per_desc; ++ iso_packet++; ++ dma_desc++; ++ } ++ ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso_packet_decsriptor */ ++ iso_packet->status = ++ sts.b_iso_out.rxsts + (sts.b_iso_out.bs ^ BS_DMA_DONE); ++ if (iso_packet->status) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ /* Received data length */ ++ if (!sts.b_iso_out.rxbytes) { ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes; ++ } else { ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_out.rxbytes + ++ (4 - dwc_ep->data_per_frame % 4); ++ } ++ ++ iso_packet->offset = offset; ++ } else { ++/** ISO IN EP */ ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ sts.d32 = dma_desc->status.d32; ++ ++ /* Write status in iso packet descriptor */ ++ iso_packet->status = ++ sts.b_iso_in.txsts + ++ (sts.b_iso_in.bs ^ BS_DMA_DONE); ++ if (iso_packet->status != 0) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ ++ } ++ /* Bytes has been transfered */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_in.txbytes; ++ ++ dma_desc++; ++ iso_packet++; ++ } ++ ++ sts.d32 = dma_desc->status.d32; ++ while (sts.b_iso_in.bs == BS_DMA_BUSY) { ++ sts.d32 = dma_desc->status.d32; ++ } ++ ++ /* Write status in iso packet descriptor ??? do be done with ERROR codes */ ++ iso_packet->status = ++ sts.b_iso_in.txsts + (sts.b_iso_in.bs ^ BS_DMA_DONE); ++ if (iso_packet->status != 0) { ++ iso_packet->status = -DWC_E_NO_DATA; ++ } ++ ++ /* Bytes has been transfered */ ++ iso_packet->length = ++ dwc_ep->data_per_frame - sts.b_iso_in.txbytes; ++ } ++} ++ ++/** ++ * This function reinitialize DMA Descriptors for Isochronous transfer ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP to start the transfer on. ++ * ++ */ ++static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) ++{ ++ int i, j; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dma_addr_t dma_ad; ++ volatile uint32_t *addr; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ uint32_t data_per_desc; ++ ++ if (dwc_ep->is_in == 0) { ++ addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; ++ } else { ++ addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ ++ if (dwc_ep->proc_buf_num == 0) { ++ /** Buffer 0 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr0; ++ } else { ++ /** Buffer 1 descriptors setup */ ++ dma_ad = dwc_ep->dma_addr1; ++ } ++ ++ /** Reinit closed DMA Descriptors*/ ++ /** ISO OUT EP */ ++ if (dwc_ep->is_in == 0) { ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ sts.b_iso_out.bs = BS_HOST_READY; ++ sts.b_iso_out.rxsts = 0; ++ sts.b_iso_out.l = 0; ++ sts.b_iso_out.sp = 0; ++ sts.b_iso_out.ioc = 0; ++ sts.b_iso_out.pid = 0; ++ sts.b_iso_out.framenum = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; ++ i += dwc_ep->pkt_per_frm) { ++ for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep-> ++ data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - ++ data_per_desc % ++ 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dma_ad += data_per_desc; ++ dma_desc++; ++ } ++ } ++ ++ for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { ++ ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dma_desc++; ++ dma_ad += data_per_desc; ++ } ++ ++ sts.b_iso_out.ioc = 1; ++ sts.b_iso_out.l = dwc_ep->proc_buf_num; ++ ++ data_per_desc = ++ ((j + 1) * dwc_ep->maxpacket > ++ dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket : dwc_ep->maxpacket; ++ data_per_desc += ++ (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; ++ sts.b_iso_out.rxbytes = data_per_desc; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ } else { ++/** ISO IN EP */ ++ ++ dma_desc = ++ dwc_ep->iso_desc_addr + ++ dwc_ep->desc_cnt * dwc_ep->proc_buf_num; ++ ++ sts.b_iso_in.bs = BS_HOST_READY; ++ sts.b_iso_in.txsts = 0; ++ sts.b_iso_in.sp = 0; ++ sts.b_iso_in.ioc = 0; ++ sts.b_iso_in.pid = dwc_ep->pkt_per_frm; ++ sts.b_iso_in.framenum = dwc_ep->next_frame; ++ sts.b_iso_in.txbytes = dwc_ep->data_per_frame; ++ sts.b_iso_in.l = 0; ++ ++ for (i = 0; i < dwc_ep->desc_cnt - 1; i++) { ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ sts.b_iso_in.framenum += dwc_ep->bInterval; ++ dma_ad += dwc_ep->data_per_frame; ++ dma_desc++; ++ } ++ ++ sts.b_iso_in.ioc = 1; ++ sts.b_iso_in.l = dwc_ep->proc_buf_num; ++ ++ dma_desc->buf = dma_ad; ++ dma_desc->status.d32 = sts.d32; ++ ++ dwc_ep->next_frame = ++ sts.b_iso_in.framenum + dwc_ep->bInterval * 1; ++ } ++ dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; ++} ++ ++/** ++ * This function is to handle Iso EP transfer complete interrupt ++ * in case Iso out packet was dropped ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param dwc_ep The EP for wihich transfer complete was asserted ++ * ++ */ ++static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if, ++ dwc_ep_t * dwc_ep) ++{ ++ uint32_t dma_addr; ++ uint32_t drp_pkt; ++ uint32_t drp_pkt_cnt; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ int i; ++ ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doeptsiz); ++ ++ drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt; ++ drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm); ++ ++ /* Setting dropped packets status */ ++ for (i = 0; i < drp_pkt_cnt; ++i) { ++ dwc_ep->pkt_info[drp_pkt].status = -DWC_E_NO_DATA; ++ drp_pkt++; ++ deptsiz.b.pktcnt--; ++ } ++ ++ if (deptsiz.b.pktcnt > 0) { ++ deptsiz.b.xfersize = ++ dwc_ep->xfer_len - (dwc_ep->pkt_cnt - ++ deptsiz.b.pktcnt) * dwc_ep->maxpacket; ++ } else { ++ deptsiz.b.xfersize = 0; ++ deptsiz.b.pktcnt = 0; ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, ++ deptsiz.d32); ++ ++ if (deptsiz.b.pktcnt > 0) { ++ if (dwc_ep->proc_buf_num) { ++ dma_addr = ++ dwc_ep->dma_addr1 + dwc_ep->xfer_len - ++ deptsiz.b.xfersize; ++ } else { ++ dma_addr = ++ dwc_ep->dma_addr0 + dwc_ep->xfer_len - ++ deptsiz.b.xfersize;; ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doepdma, dma_addr); ++ ++ /** Re-enable endpoint, clear nak */ ++ depctl.d32 = 0; ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ ++ DWC_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doepctl, depctl.d32, ++ depctl.d32); ++ return 0; ++ } else { ++ return 1; ++ } ++} ++ ++/** ++ * This function sets iso packets information(PTI mode) ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ * @param ep The EP to start the transfer on. ++ * ++ */ ++static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) ++{ ++ int i, j; ++ dma_addr_t dma_ad; ++ iso_pkt_info_t *packet_info = ep->pkt_info; ++ uint32_t offset; ++ uint32_t frame_data; ++ deptsiz_data_t deptsiz; ++ ++ if (ep->proc_buf_num == 0) { ++ /** Buffer 0 descriptors setup */ ++ dma_ad = ep->dma_addr0; ++ } else { ++ /** Buffer 1 descriptors setup */ ++ dma_ad = ep->dma_addr1; ++ } ++ ++ if (ep->is_in) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ dieptsiz); ++ } else { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ doeptsiz); ++ } ++ ++ if (!deptsiz.b.xfersize) { ++ offset = 0; ++ for (i = 0; i < ep->pkt_cnt; i += ep->pkt_per_frm) { ++ frame_data = ep->data_per_frame; ++ for (j = 0; j < ep->pkt_per_frm; ++j) { ++ ++ /* Packet status - is not set as initially ++ * it is set to 0 and if packet was sent ++ successfully, status field will remain 0*/ ++ ++ /* Bytes has been transfered */ ++ packet_info->length = ++ (ep->maxpacket < ++ frame_data) ? ep->maxpacket : frame_data; ++ ++ /* Received packet offset */ ++ packet_info->offset = offset; ++ offset += packet_info->length; ++ frame_data -= packet_info->length; ++ ++ packet_info++; ++ } ++ } ++ return 1; ++ } else { ++ /* This is a workaround for in case of Transfer Complete with ++ * PktDrpSts interrupts merging - in this case Transfer complete ++ * interrupt for Isoc Out Endpoint is asserted without PktDrpSts ++ * set and with DOEPTSIZ register non zero. Investigations showed, ++ * that this happens when Out packet is dropped, but because of ++ * interrupts merging during first interrupt handling PktDrpSts ++ * bit is cleared and for next merged interrupts it is not reset. ++ * In this case SW hadles the interrupt as if PktDrpSts bit is set. ++ */ ++ if (ep->is_in) { ++ return 1; ++ } else { ++ return handle_iso_out_pkt_dropped(core_if, ep); ++ } ++ } ++} ++ ++/** ++ * This function is to handle Iso EP transfer complete interrupt ++ * ++ * @param pcd The PCD ++ * @param ep The EP for which transfer complete was asserted ++ * ++ */ ++static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(ep->pcd); ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ uint8_t is_last = 0; ++ ++ if (ep->dwc_ep.next_frame == 0xffffffff) { ++ DWC_WARN("Next frame is not set!\n"); ++ return; ++ } ++ ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ set_ddma_iso_pkts_info(core_if, dwc_ep); ++ reinit_ddma_iso_xfer(core_if, dwc_ep); ++ is_last = 1; ++ } else { ++ if (core_if->pti_enh_enable) { ++ if (set_iso_pkts_info(core_if, dwc_ep)) { ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ dwc_otg_iso_ep_start_buf_transfer ++ (core_if, dwc_ep); ++ is_last = 1; ++ } ++ } else { ++ set_current_pkt_info(core_if, dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ is_last = 1; ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ dwc_otg_iso_ep_start_frm_transfer(core_if, ++ dwc_ep); ++ } ++ } ++ } else { ++ set_current_pkt_info(core_if, dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ is_last = 1; ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = dwc_ep->dma_addr0; ++ } ++ ++ } ++ dwc_otg_iso_ep_start_frm_transfer(core_if, dwc_ep); ++ } ++ if (is_last) ++ dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle); ++} ++#endif /* DWC_EN_ISOC */ ++ ++/** ++ * This function handle BNA interrupt for Non Isochronous EPs ++ * ++ */ ++static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_ep_t *dwc_ep = &ep->dwc_ep; ++ volatile uint32_t *addr; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_otg_pcd_t *pcd = ep->pcd; ++ dwc_otg_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = ep->pcd->core_if; ++ int i, start; ++ ++ if (!dwc_ep->desc_cnt) ++ DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num, ++ (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt); ++ ++ if (core_if->core_params->cont_on_bna && !dwc_ep->is_in ++ && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) { ++ uint32_t doepdma; ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[dwc_ep->num]; ++ doepdma = DWC_READ_REG32(&(out_regs->doepdma)); ++ start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t); ++ dma_desc = &(dwc_ep->desc_addr[start]); ++ } else { ++ start = 0; ++ dma_desc = dwc_ep->desc_addr; ++ } ++ ++ ++ for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ ++ if (dwc_ep->is_in == 0) { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]-> ++ doepctl; ++ } else { ++ addr = ++ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; ++ } ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(addr, 0, depctl.d32); ++} ++ ++/** ++ * This function handles EP0 Control transfers. ++ * ++ * The state of the control transfers are tracked in ++ * ep0state. ++ */ ++static void handle_ep0(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; ++ dev_dma_desc_sts_t desc_sts; ++ deptsiz0_data_t deptsiz; ++ uint32_t byte_count; ++ ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); ++ print_ep0_state(pcd); ++#endif ++ ++// DWC_PRINTF("HANDLE EP0\n"); ++ ++ switch (pcd->ep0state) { ++ case EP0_DISCONNECT: ++ break; ++ ++ case EP0_IDLE: ++ pcd->request_config = 0; ++ ++ pcd_setup(pcd); ++ break; ++ ++ case EP0_IN_DATA_PHASE: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n", ++ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); ++#endif ++ ++ if (core_if->dma_enable != 0) { ++ /* ++ * For EP0 we can only program 1 packet at a time so we ++ * need to do the make calculations after each complete. ++ * Call write_packet to make the calculations, as in ++ * slave mode, and use those values to determine if we ++ * can complete. ++ */ ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[0]-> ++ dieptsiz); ++ byte_count = ++ ep0->dwc_ep.xfer_len - deptsiz.b.xfersize; ++ } else { ++ desc_sts = ++ core_if->dev_if->in_desc_addr->status; ++ byte_count = ++ ep0->dwc_ep.xfer_len - desc_sts.b.bytes; ++ } ++ ep0->dwc_ep.xfer_count += byte_count; ++ ep0->dwc_ep.xfer_buff += byte_count; ++ ep0->dwc_ep.dma_addr += byte_count; ++ } ++ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); ++ } else if (ep0->dwc_ep.sent_zlp) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ ep0->dwc_ep.sent_zlp = 0; ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); ++ } else { ++ ep0_complete_request(ep0); ++ DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); ++ } ++ break; ++ case EP0_OUT_DATA_PHASE: ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n", ++ ep0->dwc_ep.num, (ep0->dwc_ep.is_in ? "IN" : "OUT"), ++ ep0->dwc_ep.type, ep0->dwc_ep.maxpacket); ++#endif ++ if (core_if->dma_enable != 0) { ++ if (core_if->dma_desc_enable == 0) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->out_ep_regs[0]-> ++ doeptsiz); ++ byte_count = ++ ep0->dwc_ep.maxpacket - deptsiz.b.xfersize; ++ } else { ++ desc_sts = ++ core_if->dev_if->out_desc_addr->status; ++ byte_count = ++ ep0->dwc_ep.maxpacket - desc_sts.b.bytes; ++ } ++ ep0->dwc_ep.xfer_count += byte_count; ++ ep0->dwc_ep.xfer_buff += byte_count; ++ ep0->dwc_ep.dma_addr += byte_count; ++ } ++ if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); ++ } else if (ep0->dwc_ep.sent_zlp) { ++ dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), ++ &ep0->dwc_ep); ++ ep0->dwc_ep.sent_zlp = 0; ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); ++ } else { ++ ep0_complete_request(ep0); ++ DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); ++ } ++ break; ++ ++ case EP0_IN_STATUS_PHASE: ++ case EP0_OUT_STATUS_PHASE: ++ DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n"); ++ ep0_complete_request(ep0); ++ pcd->ep0state = EP0_IDLE; ++ ep0->stopped = 1; ++ ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */ ++ ++ /* Prepare for more SETUP Packets */ ++ if (core_if->dma_enable) { ++ ep0_out_start(core_if, pcd); ++ } ++ break; ++ ++ case EP0_STALL: ++ DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n"); ++ break; ++ } ++#ifdef DEBUG_EP0 ++ print_ep0_state(pcd); ++#endif ++} ++ ++/** ++ * Restart transfer ++ */ ++static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if; ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++#ifdef DWC_EN_ISOC ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ return; ++ } ++#endif /* DWC_EN_ISOC */ ++ ++ core_if = GET_CORE_IF(pcd); ++ dev_if = core_if->dev_if; ++ ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ ++ DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x" ++ " stopped=%d\n", ep->dwc_ep.xfer_buff, ++ ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ep->stopped); ++ /* ++ * If xfersize is 0 and pktcnt in not 0, resend the last packet. ++ */ ++ if (dieptsiz.b.pktcnt && dieptsiz.b.xfersize == 0 && ++ ep->dwc_ep.start_xfer_buff != 0) { ++ if (ep->dwc_ep.total_len <= ep->dwc_ep.maxpacket) { ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.xfer_buff = ep->dwc_ep.start_xfer_buff; ++ ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; ++ } else { ++ ep->dwc_ep.xfer_count -= ep->dwc_ep.maxpacket; ++ /* convert packet size to dwords. */ ++ ep->dwc_ep.xfer_buff -= ep->dwc_ep.maxpacket; ++ ep->dwc_ep.xfer_len = ep->dwc_ep.xfer_count; ++ } ++ ep->stopped = 0; ++ DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x " ++ "xfer_len=%0x stopped=%d\n", ++ ep->dwc_ep.xfer_buff, ++ ep->dwc_ep.xfer_count, ep->dwc_ep.xfer_len, ++ ep->stopped); ++ if (epnum == 0) { ++ dwc_otg_ep0_start_transfer(core_if, &ep->dwc_ep); ++ } else { ++ dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); ++ } ++ } ++} ++ ++/* ++ * This function create new nextep sequnce based on Learn Queue. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void predict_nextep_seq( dwc_otg_core_if_t * core_if) ++{ ++ dwc_otg_device_global_regs_t *dev_global_regs = ++ core_if->dev_if->dev_global_regs; ++ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ uint8_t seqnum[MAX_EPS_CHANNELS]; ++ uint8_t intkn_seq[TOKEN_Q_DEPTH]; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint8_t temp; ++ int ndx = 0; ++ int start = 0; ++ int end = 0; ++ int sort_done = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ ++ ++ DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ in_tkn_epnums[i] = DWC_READ_REG32(addr); ++ DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, ++ in_tkn_epnums[i]); ++ if (addr == &dev_global_regs->dvbusdis) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ if (dtknqr1.b.wrap_bit) { ++ ndx = dtknqr1.b.intknwptr; ++ end = ndx -1; ++ if (end < 0) ++ end = TOKEN_Q_DEPTH -1; ++ } else { ++ ndx = 0; ++ end = dtknqr1.b.intknwptr -1; ++ if (end < 0) ++ end = 0; ++ } ++ start = ndx; ++ ++ /* Fill seqnum[] by initial values: EP number + 31 */ ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ seqnum[i] = i +31; ++ } ++ ++ /* Fill intkn_seq[] from in_tkn_epnums[0] */ ++ for (i=0; i < 6; i++) ++ intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf; ++ ++ if (TOKEN_Q_DEPTH > 6) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i=6; i < 14; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 14) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i=14; i < 22; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 22) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i=22; i < 30; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf; ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__, ++ start, end); ++ for (i=0; idev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == 0xff ) ++ seqnum[i] = 0xff; ++ } ++ ++ /* Sort seqnum[] */ ++ sort_done = 0; ++ while (!sort_done) { ++ sort_done = 1; ++ for (i=0; idev_if->num_in_eps; i++) { ++ if (seqnum[i] > seqnum[i+1]) { ++ temp = seqnum[i]; ++ seqnum[i] = seqnum[i+1]; ++ seqnum[i+1] = temp; ++ sort_done = 0; ++ } ++ } ++ } ++ ++ ndx = start + seqnum[0]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ core_if->first_in_nextep_seq = intkn_seq[ndx]; ++ ++ /* Update seqnum[] by EP numbers */ ++ for (i=0; i<=core_if->dev_if->num_in_eps; i++) { ++ ndx = start + i; ++ if (seqnum[i] < 31) { ++ ndx = start + seqnum[i]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ seqnum[i] = intkn_seq[ndx]; ++ } else { ++ if (seqnum[i] < 0xff) { ++ seqnum[i] = seqnum[i] - 31; ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Update nextep_seq[] based on seqnum[] */ ++ for (i=0; idev_if->num_in_eps; i++) { ++ if (seqnum[i] != 0xff) { ++ if (seqnum[i+1] != 0xff) { ++ core_if->nextep_seq[seqnum[i]] = seqnum[i+1]; ++ } else { ++ core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq; ++ break; ++ } ++ } else { ++ break; ++ } ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]); ++ } ++ ++ /* Flush the Learning Queue */ ++ resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl); ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ ++} ++ ++/** ++ * handle the IN EP disable interrupt. ++ */ ++static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ gintmsk_data_t gintmsk_data; ++ depctl_data_t depctl; ++ uint32_t diepdma; ++ uint32_t remain_to_transfer = 0; ++ uint8_t i; ++ uint32_t xfer_size; ++ ++ ep = get_in_ep(pcd, epnum); ++ dwc_ep = &ep->dwc_ep; ++ ++ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); ++ complete_ep(ep); ++ return; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl)); ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ ++ DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", ++ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++ ++ if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) { ++ if (ep->stopped) { ++ if (core_if->en_multiple_tx_fifo) ++ /* Flush the Tx FIFO */ ++ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); ++ /* Clear the Global IN NP NAK */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ } else { ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); ++ } ++ return; ++ } ++ ++ if (core_if->start_predict > 2) { // NP IN EP ++ core_if->start_predict--; ++ return; ++ } ++ ++ core_if->start_predict--; ++ ++ if (core_if->start_predict == 1) { // All NP IN Ep's disabled now ++ ++ predict_nextep_seq(core_if); ++ ++ /* Update all active IN EP's NextEP field based of nextep_seq[] */ ++ for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP ++ depctl.b.nextep = core_if->nextep_seq[i]; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ } ++ /* Flush Shared NP TxFIFO */ ++ dwc_otg_flush_tx_fifo(core_if, 0); ++ /* Rewind buffers */ ++ if (!core_if->dma_desc_enable) { ++ i = core_if->first_in_nextep_seq; ++ do { ++ ep = get_in_ep(pcd, i); ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count; ++ if (xfer_size > ep->dwc_ep.maxxfer) ++ xfer_size = ep->dwc_ep.maxxfer; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ if (xfer_size == 0) { ++ remain_to_transfer = 0; ++ } else { ++ if ((xfer_size % ep->dwc_ep.maxpacket) == 0) { ++ remain_to_transfer = ++ dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket; ++ } else { ++ remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket) ++ + (xfer_size % ep->dwc_ep.maxpacket); ++ } ++ } ++ diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma); ++ dieptsiz.b.xfersize = remain_to_transfer; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32); ++ diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ } else { // dma_desc_enable ++ DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__); ++ } ++ ++ /* Restart transfers in predicted sequences */ ++ i = core_if->first_in_nextep_seq; ++ do { ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Unmask EP Mismatch interrupt */ ++ gintmsk_data.d32 = 0; ++ gintmsk_data.b.epmismatch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32); ++ ++ core_if->start_predict = 0; ++ ++ } ++} ++ ++/** ++ * Handler for the IN EP timeout handshake interrupt. ++ */ ++static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ ++#ifdef DEBUG ++ deptsiz_data_t dieptsiz = {.d32 = 0 }; ++ uint32_t num = 0; ++#endif ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_otg_pcd_ep_t *ep; ++ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ ep = get_in_ep(pcd, epnum); ++ ++ /* Disable the NP Tx Fifo Empty Interrrupt */ ++ if (!core_if->dma_enable) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } ++ /** @todo NGS Check EP type. ++ * Implement for Periodic EPs */ ++ /* ++ * Non-periodic EP ++ */ ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ ++ /* Set Global IN NAK */ ++ dctl.b.sgnpinnak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ ep->stopped = 1; ++ ++#ifdef DEBUG ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz); ++ DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", ++ dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++#endif ++ ++#ifdef DISABLE_PERIODIC_EP ++ /* ++ * Set the NAK bit for this EP to ++ * start the disable process. ++ */ ++ diepctl.d32 = 0; ++ diepctl.b.snak = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, ++ diepctl.d32); ++ ep->disabling = 1; ++ ep->stopped = 1; ++#endif ++} ++ ++/** ++ * Handler for the IN EP NAK interrupt. ++ */ ++static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ diepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "IN EP NAK"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nak = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP Babble interrupt. ++ */ ++static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "OUT EP Babble"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.babble = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP NAK interrupt. ++ */ ++static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nak = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * Handler for the OUT EP NYET interrupt. ++ */ ++static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd, ++ const uint32_t epnum) ++{ ++ /** @todo implement ISR */ ++ dwc_otg_core_if_t *core_if; ++ doepmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NYET"); ++ core_if = GET_CORE_IF(pcd); ++ intr_mask.b.nyet = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[epnum], intr_mask.d32, 0); ++ } else { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ intr_mask.d32, 0); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that an IN EP has a pending Interrupt. ++ * The sequence for handling the IN EP interrupt is shown below: ++ * -# Read the Device All Endpoint Interrupt register ++ * -# Repeat the following for each IN EP interrupt bit set (from ++ * LSB to MSB). ++ * -# Read the Device Endpoint Interrupt (DIEPINTn) register ++ * -# If "Transfer Complete" call the request complete function ++ * -# If "Endpoint Disabled" complete the EP disable procedure. ++ * -# If "AHB Error Interrupt" log error ++ * -# If "Time-out Handshake" log error ++ * -# If "IN Token Received when TxFIFO Empty" write packet to Tx ++ * FIFO. ++ * -# If "IN Token EP Mismatch" (disable, this is handled by EP ++ * Mismatch Interrupt) ++ */ ++static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) ++{ ++#define CLEAR_IN_EP_INTR(__core_if,__epnum,__intr) \ ++do { \ ++ diepint_data_t diepint = {.d32=0}; \ ++ diepint.b.__intr = 1; \ ++ DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ ++ diepint.d32); \ ++} while (0) ++ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ diepint_data_t diepint = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ uint32_t ep_intr; ++ uint32_t epnum = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, pcd); ++ ++ /* Read in the device interrupt bits */ ++ ep_intr = dwc_otg_read_dev_all_in_ep_intr(core_if); ++ ++ /* Service the Device IN interrupts for each endpoint */ ++ while (ep_intr) { ++ if (ep_intr & 0x1) { ++ uint32_t empty_msk; ++ /* Get EP pointer */ ++ ep = get_in_ep(pcd, epnum); ++ dwc_ep = &ep->dwc_ep; ++ ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ empty_msk = ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n", ++ epnum, empty_msk, depctl.d32); ++ ++ DWC_DEBUGPL(DBG_PCD, ++ "EP%d-%s: type=%d, mps=%d\n", ++ dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"), ++ dwc_ep->type, dwc_ep->maxpacket); ++ ++ diepint.d32 = ++ dwc_otg_read_dev_in_ep_intr(core_if, dwc_ep); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP %d Interrupt Register - 0x%x\n", epnum, ++ diepint.d32); ++ /* Transfer complete */ ++ if (diepint.b.xfercompl) { ++ /* Disable the NP Tx FIFO Empty ++ * Interrupt */ ++ if (core_if->en_multiple_tx_fifo == 0) { ++ intr_mask.b.nptxfempty = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } else { ++ /* Disable the Tx FIFO Empty Interrupt for this EP */ ++ uint32_t fifoemptymsk = ++ 0x1 << dwc_ep->num; ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ fifoemptymsk, 0); ++ } ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, xfercompl); ++ ++ /* Complete the transfer */ ++ if (epnum == 0) { ++ handle_ep0(pcd); ++ } ++#ifdef DWC_EN_ISOC ++ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_iso_ep(pcd, ep); ++ } ++#endif /* DWC_EN_ISOC */ ++#ifdef DWC_UTE_PER_IO ++ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++ } ++#endif /* DWC_UTE_PER_IO */ ++ else { ++ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC && ++ dwc_ep->bInterval > 1) { ++ dwc_ep->frame_num += dwc_ep->bInterval; ++ if (dwc_ep->frame_num > 0x3FFF) ++ { ++ dwc_ep->frm_overrun = 1; ++ dwc_ep->frame_num &= 0x3FFF; ++ } else ++ dwc_ep->frm_overrun = 0; ++ } ++ complete_ep(ep); ++ if(diepint.b.nak) ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } ++ /* Endpoint disable */ ++ if (diepint.b.epdisabled) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d IN disabled\n", ++ epnum); ++ handle_in_ep_disable_intr(pcd, epnum); ++ ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, epdisabled); ++ } ++ /* AHB Error */ ++ if (diepint.b.ahberr) { ++ DWC_ERROR("EP%d IN AHB Error\n", epnum); ++ /* Clear the bit in DIEPINTn for this interrupt */ ++ CLEAR_IN_EP_INTR(core_if, epnum, ahberr); ++ } ++ /* TimeOUT Handshake (non-ISOC IN EPs) */ ++ if (diepint.b.timeout) { ++ DWC_ERROR("EP%d IN Time-out\n", epnum); ++ handle_in_ep_timeout_intr(pcd, epnum); ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, timeout); ++ } ++ /** IN Token received with TxF Empty */ ++ if (diepint.b.intktxfemp) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN TKN TxFifo Empty\n", ++ epnum); ++ if (!ep->stopped && epnum != 0) { ++ ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.intktxfemp = 1; ++ ++ if (core_if->multiproc_int_enable) { ++ DWC_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepeachintmsk ++ [epnum], diepmsk.d32, 0); ++ } else { ++ DWC_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepmsk, ++ diepmsk.d32, 0); ++ } ++ } else if (core_if->dma_desc_enable ++ && epnum == 0 ++ && pcd->ep0state == ++ EP0_OUT_STATUS_PHASE) { ++ // EP0 IN set STALL ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl); ++ ++ /* set the disable and stall bits */ ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ } ++ depctl.b.stall = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32); ++ } ++ CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp); ++ } ++ /** IN Token Received with EP mismatch */ ++ if (diepint.b.intknepmis) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN TKN EP Mismatch\n", epnum); ++ CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); ++ } ++ /** IN Endpoint NAK Effective */ ++ if (diepint.b.inepnakeff) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d IN EP NAK Effective\n", ++ epnum); ++ /* Periodic EP */ ++ if (ep->disabling) { ++ depctl.d32 = 0; ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32, ++ depctl.d32); ++ } ++ CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff); ++ ++ } ++ ++ /** IN EP Tx FIFO Empty Intr */ ++ if (diepint.b.emptyintr) { ++ DWC_DEBUGPL(DBG_ANY, ++ "EP%d Tx FIFO Empty Intr \n", ++ epnum); ++ write_empty_tx_fifo(pcd, epnum); ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, emptyintr); ++ ++ } ++ ++ /** IN EP BNA Intr */ ++ if (diepint.b.bna) { ++ CLEAR_IN_EP_INTR(core_if, epnum, bna); ++ if (core_if->dma_desc_enable) { ++#ifdef DWC_EN_ISOC ++ if (dwc_ep->type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This checking is performed to prevent first "false" BNA ++ * handling occuring right after reconnect ++ */ ++ if (dwc_ep->next_frame != ++ 0xffffffff) ++ dwc_otg_pcd_handle_iso_bna(ep); ++ } else ++#endif /* DWC_EN_ISOC */ ++ { ++ dwc_otg_pcd_handle_noniso_bna(ep); ++ } ++ } ++ } ++ /* NAK Interrutp */ ++ if (diepint.b.nak) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n", ++ epnum); ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ depctl_data_t depctl; ++ if (ep->dwc_ep.frame_num == 0xFFFFFFFF) { ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ if (ep->dwc_ep.bInterval > 1) { ++ depctl.d32 = 0; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (ep->dwc_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32); ++ } ++ start_next_request(ep); ++ } ++ ep->dwc_ep.frame_num += ep->dwc_ep.bInterval; ++ if (dwc_ep->frame_num > 0x3FFF) { ++ dwc_ep->frm_overrun = 1; ++ dwc_ep->frame_num &= 0x3FFF; ++ } else ++ dwc_ep->frm_overrun = 0; ++ } ++ ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); ++ } ++ } ++ epnum++; ++ ep_intr >>= 1; ++ } ++ ++ return 1; ++#undef CLEAR_IN_EP_INTR ++} ++ ++/** ++ * This interrupt indicates that an OUT EP has a pending Interrupt. ++ * The sequence for handling the OUT EP interrupt is shown below: ++ * -# Read the Device All Endpoint Interrupt register ++ * -# Repeat the following for each OUT EP interrupt bit set (from ++ * LSB to MSB). ++ * -# Read the Device Endpoint Interrupt (DOEPINTn) register ++ * -# If "Transfer Complete" call the request complete function ++ * -# If "Endpoint Disabled" complete the EP disable procedure. ++ * -# If "AHB Error Interrupt" log error ++ * -# If "Setup Phase Done" process Setup Packet (See Standard USB ++ * Command Processing) ++ */ ++static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) ++{ ++#define CLEAR_OUT_EP_INTR(__core_if,__epnum,__intr) \ ++do { \ ++ doepint_data_t doepint = {.d32=0}; \ ++ doepint.b.__intr = 1; \ ++ DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ ++ doepint.d32); \ ++} while (0) ++ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ uint32_t ep_intr; ++ doepint_data_t doepint = {.d32 = 0 }; ++ uint32_t epnum = 0; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_ep_t *dwc_ep; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); ++ ++ /* Read in the device interrupt bits */ ++ ep_intr = dwc_otg_read_dev_all_out_ep_intr(core_if); ++ ++ while (ep_intr) { ++ if (ep_intr & 0x1) { ++ /* Get EP pointer */ ++ ep = get_out_ep(pcd, epnum); ++ dwc_ep = &ep->dwc_ep; ++ ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP%d-%s: type=%d, mps=%d\n", ++ dwc_ep->num, (dwc_ep->is_in ? "IN" : "OUT"), ++ dwc_ep->type, dwc_ep->maxpacket); ++#endif ++ doepint.d32 = ++ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep); ++ /* Moved this interrupt upper due to core deffect of asserting ++ * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */ ++ if (doepint.b.stsphsercvd) { ++ deptsiz0_data_t deptsiz; ++ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doeptsiz); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a ++ && core_if->dma_enable ++ && core_if->dma_desc_enable == 0 ++ && doepint.b.xfercompl ++ && deptsiz.b.xfersize == 24) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, ++ xfercompl); ++ doepint.b.xfercompl = 0; ++ ep0_out_start(core_if, pcd); ++ } ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= ++ OTG_CORE_REV_3_00a)) { ++ do_setup_in_status_phase(pcd); ++ } ++ } ++ /* Transfer complete */ ++ if (doepint.b.xfercompl) { ++ ++ if (epnum == 0) { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n", ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint), ++ doepint.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n", ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl)); ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a ++ && core_if->dma_enable == 0) { ++ doepint_data_t doepint; ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (pcd->ep0state == EP0_IDLE && doepint.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ goto exit_xfercompl; ++ } ++ } ++ /* In case of DDMA look at SR bit to go to the Data Stage */ ++ if (core_if->dma_desc_enable) { ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ if (pcd->ep0state == EP0_IDLE) { ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ if(pcd->data_terminated) { ++ pcd->data_terminated = 0; ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8); ++ } ++ if (status.b.sr) { ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n"); ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } else { ++ dwc_otg_pcd_request_t *req; ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ diepint_data_t diepint0; ++ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ ++ if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) { ++ DWC_ERROR("EP0 is stalled/disconnected\n"); ++ } ++ ++ /* Clear IN xfercompl if set */ ++ if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_DATA_PHASE)) { ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len ++ && (pcd->ep0state == EP0_OUT_DATA_PHASE)) ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ if (pcd->ep0state == EP0_OUT_STATUS_PHASE) ++ status.d32 = status.d32 = core_if->dev_if-> ++ out_desc_addr->status.d32; ++ ++ if (status.b.sr) { ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ dwc_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->dwc_ep.xfer_count, 8); ++ } ++ req->actual = ep->dwc_ep.xfer_count; ++ dwc_otg_request_done(ep, req, -ECONNRESET); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable ++ && core_if->dma_desc_enable == 0) { ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doepint); ++ doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doeptsiz); ++ if (pcd->ep0state == EP0_IDLE) { ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ } ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (doeptsize0.b.supcnt == 3) { ++ DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n"); ++ ep->dwc_ep.stp_rollover = 1; ++ } ++ if (doepint.b.setup) { ++retry: ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ ep->dwc_ep.stp_rollover = 0; ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_ANY, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if(doepint.b.setup) ++ goto retry; ++ ep0_out_start(core_if, pcd); ++ } ++ } else { ++ dwc_otg_pcd_request_t *req; ++ diepint_data_t diepint0 = {.d32 = 0}; ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ depctl_data_t diepctl0; ++ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0state == EP0_IN_DATA_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ if (diepint0.b.xfercompl) { ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ if (diepctl0.b.epena) { ++ diepint_data_t diepint = {.d32 = 0}; ++ diepctl0.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl, diepctl0.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.inepnakeff); ++ diepint.b.inepnakeff = 1; ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint.d32); ++ diepctl0.d32 = 0; ++ diepctl0.b.epdis = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl, ++ diepctl0.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.epdisabled); ++ diepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint, ++ diepint.d32); ++ } ++ } ++ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doepint); ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ dwc_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->dwc_ep.xfer_count, 8); ++ } ++ req->actual = ep->dwc_ep.xfer_count; ++ dwc_otg_request_done(ep, req, -ECONNRESET); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++exit_xfercompl: ++ DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n", ++ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32); ++ } else { ++ if (core_if->dma_desc_enable == 0 ++ || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++ } ++#ifdef DWC_EN_ISOC ++ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (doepint.b.pktdrpsts == 0) { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, ++ epnum, ++ xfercompl); ++ complete_iso_ep(pcd, ep); ++ } else { ++ ++ doepint_data_t doepint = {.d32 = 0 }; ++ doepint.b.xfercompl = 1; ++ doepint.b.pktdrpsts = 1; ++ DWC_WRITE_REG32 ++ (&core_if->dev_if->out_ep_regs ++ [epnum]->doepint, ++ doepint.d32); ++ if (handle_iso_out_pkt_dropped ++ (core_if, dwc_ep)) { ++ complete_iso_ep(pcd, ++ ep); ++ } ++ } ++#endif /* DWC_EN_ISOC */ ++#ifdef DWC_UTE_PER_IO ++ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++#endif /* DWC_UTE_PER_IO */ ++ } else { ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, ++ xfercompl); ++ ++ if (core_if->core_params->dev_out_nak) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]); ++ pcd->core_if->ep_xfer_info[epnum].state = 0; ++#ifdef DEBUG ++ print_memory_payload(pcd, dwc_ep); ++#endif ++ } ++ complete_ep(ep); ++ } ++ ++ } ++ ++ /* Endpoint disable */ ++ if (doepint.b.epdisabled) { ++ ++ /* Clear the bit in DOEPINTn for this interrupt */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled); ++ if (core_if->core_params->dev_out_nak) { ++#ifdef DEBUG ++ print_memory_payload(pcd, dwc_ep); ++#endif ++ /* In case of timeout condition */ ++ if (core_if->ep_xfer_info[epnum].state == 2) { ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ /* Unmask goutnakeff interrupt which was masked ++ * during handle nak out interrupt */ ++ gintmsk.b.goutnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ ++ complete_ep(ep); ++ } ++ } ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ++ { ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0}; ++ dwc_otg_pcd_request_t *req = 0; ++ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ } else { ++ dwc_otg_request_done(ep, req, 0); ++ start_next_request(ep); ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ } ++ } ++ } ++ /* AHB Error */ ++ if (doepint.b.ahberr) { ++ DWC_ERROR("EP%d OUT AHB Error\n", epnum); ++ DWC_ERROR("EP%d DEPDMA=0x%08x \n", ++ epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma); ++ CLEAR_OUT_EP_INTR(core_if, epnum, ahberr); ++ } ++ /* Setup Phase Done (contorl EPs) */ ++ if (doepint.b.setup) { ++#ifdef DEBUG_EP0 ++ DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum); ++#endif ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ ++ handle_ep0(pcd); ++ } ++ ++ /** OUT EP BNA Intr */ ++ if (doepint.b.bna) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, bna); ++ if (core_if->dma_desc_enable) { ++#ifdef DWC_EN_ISOC ++ if (dwc_ep->type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ /* ++ * This checking is performed to prevent first "false" BNA ++ * handling occuring right after reconnect ++ */ ++ if (dwc_ep->next_frame != ++ 0xffffffff) ++ dwc_otg_pcd_handle_iso_bna(ep); ++ } else ++#endif /* DWC_EN_ISOC */ ++ { ++ dwc_otg_pcd_handle_noniso_bna(ep); ++ } ++ } ++ } ++ /* Babble Interrupt */ ++ if (doepint.b.babble) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n", ++ epnum); ++ handle_out_ep_babble_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, babble); ++ } ++ if (doepint.b.outtknepdis) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \ ++ disabled\n",epnum); ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ doepmsk_data_t doepmsk = {.d32 = 0}; ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ if (ep->dwc_ep.bInterval > 1) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl); ++ if (ep->dwc_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl, depctl.d32); ++ } ++ start_next_request(ep); ++ doepmsk.b.outtknepdis = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ doepmsk.d32, 0); ++ } ++ CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis); ++ } ++ ++ /* NAK Interrutp */ ++ if (doepint.b.nak) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum); ++ handle_out_ep_nak_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, nak); ++ } ++ /* NYET Interrutp */ ++ if (doepint.b.nyet) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT NYET\n", epnum); ++ handle_out_ep_nyet_intr(pcd, epnum); ++ ++ CLEAR_OUT_EP_INTR(core_if, epnum, nyet); ++ } ++ } ++ ++ epnum++; ++ ep_intr >>= 1; ++ } ++ ++ return 1; ++ ++#undef CLEAR_OUT_EP_INTR ++} ++static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun) ++{ ++ int retval = 0; ++ if(!frm_overrun && curr_fr >= trgt_fr) ++ retval = 1; ++ else if (frm_overrun ++ && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2))) ++ retval = 1; ++ return retval; ++} ++/** ++ * Incomplete ISO IN Transfer Interrupt. ++ * This interrupt indicates one of the following conditions occurred ++ * while transmitting an ISOC transaction. ++ * - Corrupted IN Token for ISOC EP. ++ * - Packet not complete in FIFO. ++ * The follow actions will be taken: ++ * -# Determine the EP ++ * -# Set incomplete flag in dwc_ep structure ++ * -# Disable EP; when "Endpoint Disabled" interrupt is received ++ * Flush FIFO ++ */ ++int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ ++#ifdef DWC_EN_ISOC ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ int i; ++ ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i].dwc_ep; ++ if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ ++ if (depctl.b.epdis && deptsiz.d32) { ++ set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ ++ dsts.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts); ++ dwc_ep->next_frame = dsts.b.soffn; ++ ++ dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF ++ (pcd), ++ dwc_ep); ++ } ++ } ++ } ++ ++#else ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ dwc_otg_dev_if_t *dev_if; ++ int i; ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n"); ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i-1].dwc_ep; ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num, ++ dwc_ep->frm_overrun)) ++ { ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32); ++ } ++ } ++ } ++ ++ /*intr_mask.b.incomplisoin = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); */ ++#endif //DWC_EN_ISOC ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.incomplisoin = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * Incomplete ISO OUT Transfer Interrupt. ++ * ++ * This interrupt indicates that the core has dropped an ISO OUT ++ * packet. The following conditions can be the cause: ++ * - FIFO Full, the entire packet would not fit in the FIFO. ++ * - CRC Error ++ * - Corrupted Token ++ * The follow actions will be taken: ++ * -# Determine the EP ++ * -# Set incomplete flag in dwc_ep structure ++ * -# Read any data from the FIFO ++ * -# Disable EP. When "Endpoint Disabled" interrupt is received ++ * re-enable EP. ++ */ ++int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) ++{ ++ ++ gintsts_data_t gintsts; ++ ++#ifdef DWC_EN_ISOC ++ dwc_otg_dev_if_t *dev_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dsts_data_t dsts = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ int i; ++ ++ dev_if = GET_CORE_IF(pcd)->dev_if; ++ ++ for (i = 1; i <= dev_if->num_out_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i].dwc_ep; ++ if (pcd->out_ep[i].dwc_ep.active && ++ pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ deptsiz.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz); ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ ++ if (depctl.b.epdis && deptsiz.d32) { ++ set_current_pkt_info(GET_CORE_IF(pcd), ++ &pcd->out_ep[i].dwc_ep); ++ if (dwc_ep->cur_pkt >= dwc_ep->pkt_cnt) { ++ dwc_ep->cur_pkt = 0; ++ dwc_ep->proc_buf_num = ++ (dwc_ep->proc_buf_num ^ 1) & 0x1; ++ ++ if (dwc_ep->proc_buf_num) { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff1; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr1; ++ } else { ++ dwc_ep->cur_pkt_addr = ++ dwc_ep->xfer_buff0; ++ dwc_ep->cur_pkt_dma_addr = ++ dwc_ep->dma_addr0; ++ } ++ ++ } ++ ++ dsts.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts); ++ dwc_ep->next_frame = dsts.b.soffn; ++ ++ dwc_otg_iso_ep_start_frm_transfer(GET_CORE_IF ++ (pcd), ++ dwc_ep); ++ } ++ } ++ } ++#else ++ /** @todo implement ISR */ ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep = NULL; ++ int i; ++ core_if = GET_CORE_IF(pcd); ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ dwc_ep = &pcd->out_ep[i].dwc_ep; ++ depctl.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); ++ if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) { ++ core_if->dev_if->isoc_ep = dwc_ep; ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz); ++ break; ++ } ++ } ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ if (!intr_mask.b.goutnakeff) { ++ /* Unmask it */ ++ intr_mask.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32); ++ } ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ ++ depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++#endif /* DWC_EN_ISOC */ ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.incomplisoout = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * This function handles the Global IN NAK Effective interrupt. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ depctl_data_t diepctl = {.d32 = 0 }; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ int i; ++ ++ DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n"); ++ ++ /* Disable all active IN EPs */ ++ for (i = 0; i <= dev_if->num_in_eps; i++) { ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (!(diepctl.b.eptype & 1) && diepctl.b.epena) { ++ if (core_if->start_predict > 0) ++ core_if->start_predict++; ++ diepctl.b.epdis = 1; ++ diepctl.b.snak = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32); ++ } ++ } ++ ++ ++ /* Disable the Global IN NAK Effective Interrupt */ ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.ginnakeff = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * OUT NAK Effective. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; ++ gintsts_data_t gintsts; ++ depctl_data_t doepctl; ++ int i; ++ ++ /* Disable the Global OUT NAK Effective Interrupt */ ++ intr_mask.b.goutnakeff = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ ++ /* If DEV OUT NAK enabled*/ ++ if (pcd->core_if->core_params->dev_out_nak) { ++ /* Run over all out endpoints to determine the ep number on ++ * which the timeout has happened ++ */ ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ if ( pcd->core_if->ep_xfer_info[i].state == 2 ) ++ break; ++ } ++ if (i > dev_if->num_out_eps) { ++ dctl_data_t dctl; ++ dctl.d32 = ++ DWC_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ goto out; ++ } ++ ++ /* Disable the endpoint */ ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ return 1; ++ } ++ /* We come here from Incomplete ISO OUT handler */ ++ if (dev_if->isoc_ep) { ++ dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep; ++ uint32_t epnum = dwc_ep->num; ++ doepint_data_t doepint; ++ doepint.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint); ++ dev_if->isoc_ep = NULL; ++ doepctl.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); ++ DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, ++ doepctl.d32); ++ return 1; ++ } else ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "Global OUT NAK Effective\n"); ++ ++out: ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, ++ gintsts.d32); ++ ++ return 1; ++} ++ ++/** ++ * PCD interrupt handler. ++ * ++ * The PCD handles the device interrupts. Many conditions can cause a ++ * device interrupt. When an interrupt occurs, the device interrupt ++ * service routine determines the cause of the interrupt and ++ * dispatches handling to the appropriate function. These interrupt ++ * handling functions are described below. ++ * ++ * All interrupt registers are processed from LSB to MSB. ++ * ++ */ ++int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++#ifdef VERBOSE ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++#endif ++ gintsts_data_t gintr_status; ++ int32_t retval = 0; ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n", ++ __func__, ++ DWC_READ_REG32(&global_regs->gintsts), ++ DWC_READ_REG32(&global_regs->gintmsk)); ++#endif ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ DWC_SPINLOCK(pcd->lock); ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n", ++ __func__, ++ DWC_READ_REG32(&global_regs->gintsts), ++ DWC_READ_REG32(&global_regs->gintmsk)); ++#endif ++ ++ gintr_status.d32 = dwc_otg_read_core_intr(core_if); ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s: gintsts&gintmsk=%08x\n", ++ __func__, gintr_status.d32); ++ ++ if (gintr_status.b.sofintr) { ++ retval |= dwc_otg_pcd_handle_sof_intr(pcd); ++ } ++ if (gintr_status.b.rxstsqlvl) { ++ retval |= ++ dwc_otg_pcd_handle_rx_status_q_level_intr(pcd); ++ } ++ if (gintr_status.b.nptxfempty) { ++ retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd); ++ } ++ if (gintr_status.b.goutnakeff) { ++ retval |= dwc_otg_pcd_handle_out_nak_effective(pcd); ++ } ++ if (gintr_status.b.i2cintr) { ++ retval |= dwc_otg_pcd_handle_i2c_intr(pcd); ++ } ++ if (gintr_status.b.erlysuspend) { ++ retval |= dwc_otg_pcd_handle_early_suspend_intr(pcd); ++ } ++ if (gintr_status.b.usbreset) { ++ retval |= dwc_otg_pcd_handle_usb_reset_intr(pcd); ++ } ++ if (gintr_status.b.enumdone) { ++ retval |= dwc_otg_pcd_handle_enum_done_intr(pcd); ++ } ++ if (gintr_status.b.isooutdrop) { ++ retval |= ++ dwc_otg_pcd_handle_isoc_out_packet_dropped_intr ++ (pcd); ++ } ++ if (gintr_status.b.eopframe) { ++ retval |= ++ dwc_otg_pcd_handle_end_periodic_frame_intr(pcd); ++ } ++ if (gintr_status.b.inepint) { ++ if (!core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); ++ } ++ } ++ if (gintr_status.b.outepintr) { ++ if (!core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); ++ } ++ } ++ if (gintr_status.b.epmismatch) { ++ retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd); ++ } ++ if (gintr_status.b.fetsusp) { ++ retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd); ++ } ++ if (gintr_status.b.ginnakeff) { ++ retval |= dwc_otg_pcd_handle_in_nak_effective(pcd); ++ } ++ if (gintr_status.b.incomplisoin) { ++ retval |= ++ dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd); ++ } ++ if (gintr_status.b.incomplisoout) { ++ retval |= ++ dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd); ++ } ++ ++ /* In MPI mode Device Endpoints interrupts are asserted ++ * without setting outepintr and inepint bits set, so these ++ * Interrupt handlers are called without checking these bit-fields ++ */ ++ if (core_if->multiproc_int_enable) { ++ retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); ++ retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); ++ } ++#ifdef VERBOSE ++ DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__, ++ DWC_READ_REG32(&global_regs->gintsts)); ++#endif ++ DWC_SPINUNLOCK(pcd->lock); ++ } ++ return retval; ++} ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c +new file mode 100644 +index 0000000..a591d89 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c +@@ -0,0 +1,1358 @@ ++ /* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ ++ * $Revision: #21 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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_HOST_ONLY ++ ++/** @file ++ * This file implements the Peripheral Controller Driver. ++ * ++ * The Peripheral Controller Driver (PCD) is responsible for ++ * translating requests from the Function Driver into the appropriate ++ * actions on the DWC_otg controller. It isolates the Function Driver ++ * from the specifics of the controller by providing an API to the ++ * Function Driver. ++ * ++ * The Peripheral Controller Driver for Linux will implement the ++ * Gadget API, so that the existing Gadget drivers can be used. ++ * (Gadget Driver is the Linux terminology for a Function Driver.) ++ * ++ * The Linux Gadget API is defined in the header file ++ * . The USB EP operations API is ++ * defined in the structure usb_ep_ops and the USB ++ * Controller API is defined in the structure ++ * usb_gadget_ops. ++ * ++ */ ++ ++#include "dwc_otg_os_dep.h" ++#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_dbg.h" ++ ++static struct gadget_wrapper { ++ dwc_otg_pcd_t *pcd; ++ ++ struct usb_gadget gadget; ++ struct usb_gadget_driver *driver; ++ ++ struct usb_ep ep0; ++ struct usb_ep in_ep[16]; ++ struct usb_ep out_ep[16]; ++ ++} *gadget_wrapper; ++ ++/* Display the contents of the buffer */ ++extern void dump_msg(const u8 * buf, unsigned int length); ++/** ++ * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case ++ * if the endpoint is not found ++ */ ++static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} ++ ++/* USB Endpoint Operations */ ++/* ++ * The following sections briefly describe the behavior of the Gadget ++ * API endpoint operations implemented in the DWC_otg driver ++ * software. Detailed descriptions of the generic behavior of each of ++ * these functions can be found in the Linux header file ++ * include/linux/usb_gadget.h. ++ * ++ * The Gadget API provides wrapper functions for each of the function ++ * pointers defined in usb_ep_ops. The Gadget Driver calls the wrapper ++ * function, which then calls the underlying PCD function. The ++ * following sections are named according to the wrapper ++ * functions. Within each section, the corresponding DWC_otg PCD ++ * function name is specified. ++ * ++ */ ++ ++/** ++ * This function is called by the Gadget Driver for each EP to be ++ * configured for the current configuration (SET_CONFIGURATION). ++ * ++ * This function initializes the dwc_otg_ep_t data structure, and then ++ * calls dwc_otg_ep_activate. ++ */ ++static int ep_enable(struct usb_ep *usb_ep, ++ const struct usb_endpoint_descriptor *ep_desc) ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, ep_desc); ++ ++ if (!usb_ep || !ep_desc || ep_desc->bDescriptorType != USB_DT_ENDPOINT) { ++ DWC_WARN("%s, bad ep or descriptor\n", __func__); ++ return -EINVAL; ++ } ++ if (usb_ep == &gadget_wrapper->ep0) { ++ DWC_WARN("%s, bad ep(0)\n", __func__); ++ return -EINVAL; ++ } ++ ++ /* Check FIFO size? */ ++ if (!ep_desc->wMaxPacketSize) { ++ DWC_WARN("%s, bad %s maxpacket\n", __func__, usb_ep->name); ++ return -ERANGE; ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_WARN("%s, bogus device state\n", __func__); ++ return -ESHUTDOWN; ++ } ++ ++ /* Delete after check - MAS */ ++#if 0 ++ nat = (uint32_t) ep_desc->wMaxPacketSize; ++ printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat); ++ nat = (nat >> 11) & 0x03; ++ printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat); ++#endif ++ retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd, ++ (const uint8_t *)ep_desc, ++ (void *)usb_ep); ++ if (retval) { ++ DWC_WARN("dwc_otg_pcd_ep_enable failed\n"); ++ return -EINVAL; ++ } ++ ++ usb_ep->maxpacket = le16_to_cpu(ep_desc->wMaxPacketSize); ++ ++ return 0; ++} ++ ++/** ++ * This function is called when an EP is disabled due to disconnect or ++ * change in configuration. Any pending requests will terminate with a ++ * status of -ESHUTDOWN. ++ * ++ * This function modifies the dwc_otg_ep_t data structure for this EP, ++ * and then calls dwc_otg_ep_deactivate. ++ */ ++static int ep_disable(struct usb_ep *usb_ep) ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, usb_ep); ++ if (!usb_ep) { ++ DWC_DEBUGPL(DBG_PCD, "%s, %s not enabled\n", __func__, ++ usb_ep ? usb_ep->name : NULL); ++ return -EINVAL; ++ } ++ ++ retval = dwc_otg_pcd_ep_disable(gadget_wrapper->pcd, usb_ep); ++ if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function allocates a request object to use with the specified ++ * endpoint. ++ * ++ * @param ep The endpoint to be used with with the request ++ * @param gfp_flags the GFP_* flags to use. ++ */ ++static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep, ++ gfp_t gfp_flags) ++{ ++ struct usb_request *usb_req; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d)\n", __func__, ep, gfp_flags); ++ if (0 == ep) { ++ DWC_WARN("%s() %s\n", __func__, "Invalid EP!\n"); ++ return 0; ++ } ++ usb_req = kmalloc(sizeof(*usb_req), gfp_flags); ++ if (0 == usb_req) { ++ DWC_WARN("%s() %s\n", __func__, "request allocation failed!\n"); ++ return 0; ++ } ++ memset(usb_req, 0, sizeof(*usb_req)); ++ usb_req->dma = DWC_DMA_ADDR_INVALID; ++ ++ return usb_req; ++} ++ ++/** ++ * This function frees a request object. ++ * ++ * @param ep The endpoint associated with the request ++ * @param req The request being freed ++ */ ++static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, ep, req); ++ ++ if (0 == ep || 0 == req) { ++ DWC_WARN("%s() %s\n", __func__, ++ "Invalid ep or req argument!\n"); ++ return; ++ } ++ ++ kfree(req); ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++/** ++ * This function allocates an I/O buffer to be used for a transfer ++ * to/from the specified endpoint. ++ * ++ * @param usb_ep The endpoint to be used with with the request ++ * @param bytes The desired number of bytes for the buffer ++ * @param dma Pointer to the buffer's DMA address; must be valid ++ * @param gfp_flags the GFP_* flags to use. ++ * @return address of a new buffer or null is buffer could not be allocated. ++ */ ++static void *dwc_otg_pcd_alloc_buffer(struct usb_ep *usb_ep, unsigned bytes, ++ dma_addr_t * dma, gfp_t gfp_flags) ++{ ++ void *buf; ++ dwc_otg_pcd_t *pcd = 0; ++ ++ pcd = gadget_wrapper->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%d,%p,%0x)\n", __func__, usb_ep, bytes, ++ dma, gfp_flags); ++ ++ /* Check dword alignment */ ++ if ((bytes & 0x3UL) != 0) { ++ DWC_WARN("%s() Buffer size is not a multiple of" ++ "DWORD size (%d)", __func__, bytes); ++ } ++ ++ buf = dma_alloc_coherent(NULL, bytes, dma, gfp_flags); ++ ++ /* Check dword alignment */ ++ if (((int)buf & 0x3UL) != 0) { ++ DWC_WARN("%s() Buffer is not DWORD aligned (%p)", ++ __func__, buf); ++ } ++ ++ return buf; ++} ++ ++/** ++ * This function frees an I/O buffer that was allocated by alloc_buffer. ++ * ++ * @param usb_ep the endpoint associated with the buffer ++ * @param buf address of the buffer ++ * @param dma The buffer's DMA address ++ * @param bytes The number of bytes of the buffer ++ */ ++static void dwc_otg_pcd_free_buffer(struct usb_ep *usb_ep, void *buf, ++ dma_addr_t dma, unsigned bytes) ++{ ++ dwc_otg_pcd_t *pcd = 0; ++ ++ pcd = gadget_wrapper->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%0x,%d)\n", __func__, buf, dma, bytes); ++ ++ dma_free_coherent(NULL, bytes, buf, dma); ++} ++#endif ++ ++/** ++ * This function is used to submit an I/O Request to an EP. ++ * ++ * - When the request completes the request's completion callback ++ * is called to return the request to the driver. ++ * - An EP, except control EPs, may have multiple requests ++ * pending. ++ * - Once submitted the request cannot be examined or modified. ++ * - Each request is turned into one or more packets. ++ * - A BULK EP can queue any amount of data; the transfer is ++ * packetized. ++ * - Zero length Packets are specified with the request 'zero' ++ * flag. ++ */ ++static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, ++ gfp_t gfp_flags) ++{ ++ dwc_otg_pcd_t *pcd; ++ struct dwc_otg_pcd_ep *ep = NULL; ++ int retval = 0, is_isoc_ep = 0; ++ dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n", ++ __func__, usb_ep, usb_req, gfp_flags); ++ ++ if (!usb_req || !usb_req->complete || !usb_req->buf) { ++ DWC_WARN("bad params\n"); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ pcd = gadget_wrapper->pcd; ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ DWC_WARN("bogus device state\n"); ++ return -ESHUTDOWN; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "%s queue req %p, len %d buf %p\n", ++ usb_ep->name, usb_req, usb_req->length, usb_req->buf); ++ ++ usb_req->status = -EINPROGRESS; ++ usb_req->actual = 0; ++ ++ ep = ep_from_handle(pcd, usb_ep); ++ if (ep == NULL) ++ is_isoc_ep = 0; ++ else ++ is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ dma_addr = usb_req->dma; ++#else ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev; ++ struct device *dev = NULL; ++ ++ if (otg_dev != NULL) ++ dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep); ++ ++ if (usb_req->length != 0 && ++ usb_req->dma == DWC_DMA_ADDR_INVALID) { ++ dma_addr = dma_map_single(dev, usb_req->buf, ++ usb_req->length, ++ ep->dwc_ep.is_in ? ++ DMA_TO_DEVICE: ++ DMA_FROM_DEVICE); ++ } ++ } ++#endif ++ ++#ifdef DWC_UTE_PER_IO ++ if (is_isoc_ep == 1) { ++ retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, ++ usb_req->length, usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req); ++ if (retval) ++ return -EINVAL; ++ ++ return 0; ++ } ++#endif ++ retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, ++ usb_req->length, usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0); ++ if (retval) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * This function cancels an I/O request from an EP. ++ */ ++static int ep_dequeue(struct usb_ep *usb_ep, struct usb_request *usb_req) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p)\n", __func__, usb_ep, usb_req); ++ ++ if (!usb_ep || !usb_req) { ++ DWC_WARN("bad argument\n"); ++ return -EINVAL; ++ } ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_WARN("bogus device state\n"); ++ return -ESHUTDOWN; ++ } ++ if (dwc_otg_pcd_ep_dequeue(gadget_wrapper->pcd, usb_ep, usb_req)) { ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++/** ++ * usb_ep_set_halt stalls an endpoint. ++ * ++ * usb_ep_clear_halt clears an endpoint halt and resets its data ++ * toggle. ++ * ++ * Both of these functions are implemented with the same underlying ++ * function. The behavior depends on the value argument. ++ * ++ * @param[in] usb_ep the Endpoint to halt or clear halt. ++ * @param[in] value ++ * - 0 means clear_halt. ++ * - 1 means set_halt, ++ * - 2 means clear stall lock flag. ++ * - 3 means set stall lock flag. ++ */ ++static int ep_halt(struct usb_ep *usb_ep, int value) ++{ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_PCD, "HALT %s %d\n", usb_ep->name, value); ++ ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ retval = dwc_otg_pcd_ep_halt(gadget_wrapper->pcd, usb_ep, value); ++ if (retval == -DWC_E_AGAIN) { ++ return -EAGAIN; ++ } else if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++//#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) ++#if 0 ++/** ++ * ep_wedge: sets the halt feature and ignores clear requests ++ * ++ * @usb_ep: the endpoint being wedged ++ * ++ * Use this to stall an endpoint and ignore CLEAR_FEATURE(HALT_ENDPOINT) ++ * requests. If the gadget driver clears the halt status, it will ++ * automatically unwedge the endpoint. ++ * ++ * Returns zero on success, else negative errno. * ++ * Check usb_ep_set_wedge() at "usb_gadget.h" for details ++ */ ++static int ep_wedge(struct usb_ep *usb_ep) ++{ ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_PCD, "WEDGE %s\n", usb_ep->name); ++ ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ return -EINVAL; ++ } ++ ++ retval = dwc_otg_pcd_ep_wedge(gadget_wrapper->pcd, usb_ep); ++ if (retval == -DWC_E_AGAIN) { ++ retval = -EAGAIN; ++ } else if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++#endif ++ ++#ifdef DWC_EN_ISOC ++/** ++ * This function is used to submit an ISOC Transfer Request to an EP. ++ * ++ * - Every time a sync period completes the request's completion callback ++ * is called to provide data to the gadget driver. ++ * - Once submitted the request cannot be modified. ++ * - Each request is turned into periodic data packets untill ISO ++ * Transfer is stopped.. ++ */ ++static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req, ++ gfp_t gfp_flags) ++{ ++ int retval = 0; ++ ++ if (!req || !req->process_buffer || !req->buf0 || !req->buf1) { ++ DWC_WARN("bad params\n"); ++ return -EINVAL; ++ } ++ ++ if (!usb_ep) { ++ DWC_PRINTF("bad params\n"); ++ return -EINVAL; ++ } ++ ++ req->status = -EINPROGRESS; ++ ++ retval = ++ dwc_otg_pcd_iso_ep_start(gadget_wrapper->pcd, usb_ep, req->buf0, ++ req->buf1, req->dma0, req->dma1, ++ req->sync_frame, req->data_pattern_frame, ++ req->data_per_frame, ++ req-> ++ flags & USB_REQ_ISO_ASAP ? -1 : ++ req->start_frame, req->buf_proc_intrvl, ++ req, gfp_flags == GFP_ATOMIC ? 1 : 0); ++ ++ if (retval) { ++ return -EINVAL; ++ } ++ ++ return retval; ++} ++ ++/** ++ * This function stops ISO EP Periodic Data Transfer. ++ */ ++static int iso_ep_stop(struct usb_ep *usb_ep, struct usb_iso_request *req) ++{ ++ int retval = 0; ++ if (!usb_ep) { ++ DWC_WARN("bad ep\n"); ++ } ++ ++ if (!gadget_wrapper->driver || ++ gadget_wrapper->gadget.speed == USB_SPEED_UNKNOWN) { ++ DWC_DEBUGPL(DBG_PCDV, "gadget.speed=%d\n", ++ gadget_wrapper->gadget.speed); ++ DWC_WARN("bogus device state\n"); ++ } ++ ++ dwc_otg_pcd_iso_ep_stop(gadget_wrapper->pcd, usb_ep, req); ++ if (retval) { ++ retval = -EINVAL; ++ } ++ ++ return retval; ++} ++ ++static struct usb_iso_request *alloc_iso_request(struct usb_ep *ep, ++ int packets, gfp_t gfp_flags) ++{ ++ struct usb_iso_request *pReq = NULL; ++ uint32_t req_size; ++ ++ req_size = sizeof(struct usb_iso_request); ++ req_size += ++ (2 * packets * (sizeof(struct usb_gadget_iso_packet_descriptor))); ++ ++ pReq = kmalloc(req_size, gfp_flags); ++ if (!pReq) { ++ DWC_WARN("Can't allocate Iso Request\n"); ++ return 0; ++ } ++ pReq->iso_packet_desc0 = (void *)(pReq + 1); ++ ++ pReq->iso_packet_desc1 = pReq->iso_packet_desc0 + packets; ++ ++ return pReq; ++} ++ ++static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) ++{ ++ kfree(req); ++} ++ ++static struct usb_isoc_ep_ops dwc_otg_pcd_ep_ops = { ++ .ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = dwc_otg_pcd_alloc_request, ++ .free_request = dwc_otg_pcd_free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ .alloc_buffer = dwc_otg_pcd_alloc_buffer, ++ .free_buffer = dwc_otg_pcd_free_buffer, ++#endif ++ ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_halt, ++ .fifo_status = 0, ++ .fifo_flush = 0, ++ }, ++ .iso_ep_start = iso_ep_start, ++ .iso_ep_stop = iso_ep_stop, ++ .alloc_iso_request = alloc_iso_request, ++ .free_iso_request = free_iso_request, ++}; ++ ++#else ++ ++ int (*enable) (struct usb_ep *ep, ++ const struct usb_endpoint_descriptor *desc); ++ int (*disable) (struct usb_ep *ep); ++ ++ struct usb_request *(*alloc_request) (struct usb_ep *ep, ++ gfp_t gfp_flags); ++ void (*free_request) (struct usb_ep *ep, struct usb_request *req); ++ ++ int (*queue) (struct usb_ep *ep, struct usb_request *req, ++ gfp_t gfp_flags); ++ int (*dequeue) (struct usb_ep *ep, struct usb_request *req); ++ ++ int (*set_halt) (struct usb_ep *ep, int value); ++ int (*set_wedge) (struct usb_ep *ep); ++ ++ int (*fifo_status) (struct usb_ep *ep); ++ void (*fifo_flush) (struct usb_ep *ep); ++static struct usb_ep_ops dwc_otg_pcd_ep_ops = { ++ .enable = ep_enable, ++ .disable = ep_disable, ++ ++ .alloc_request = dwc_otg_pcd_alloc_request, ++ .free_request = dwc_otg_pcd_free_request, ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ .alloc_buffer = dwc_otg_pcd_alloc_buffer, ++ .free_buffer = dwc_otg_pcd_free_buffer, ++#else ++ /* .set_wedge = ep_wedge, */ ++ .set_wedge = NULL, /* uses set_halt instead */ ++#endif ++ ++ .queue = ep_queue, ++ .dequeue = ep_dequeue, ++ ++ .set_halt = ep_halt, ++ .fifo_status = 0, ++ .fifo_flush = 0, ++ ++}; ++ ++#endif /* _EN_ISOC_ */ ++/* Gadget Operations */ ++/** ++ * The following gadget operations will be implemented in the DWC_otg ++ * PCD. Functions in the API that are not described below are not ++ * implemented. ++ * ++ * The Gadget API provides wrapper functions for each of the function ++ * pointers defined in usb_gadget_ops. The Gadget Driver calls the ++ * wrapper function, which then calls the underlying PCD function. The ++ * following sections are named according to the wrapper functions ++ * (except for ioctl, which doesn't have a wrapper function). Within ++ * each section, the corresponding DWC_otg PCD function name is ++ * specified. ++ * ++ */ ++ ++/** ++ *Gets the USB Frame number of the last SOF. ++ */ ++static int get_frame_number(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ return dwc_otg_pcd_get_frame_number(d->pcd); ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++static int test_lpm_enabled(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ ++ return dwc_otg_pcd_is_lpm_enabled(d->pcd); ++} ++#endif ++ ++/** ++ * Initiates Session Request Protocol (SRP) to wakeup the host if no ++ * session is in progress. If a session is already in progress, but ++ * the device is suspended, remote wakeup signaling is started. ++ * ++ */ ++static int wakeup(struct usb_gadget *gadget) ++{ ++ struct gadget_wrapper *d; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, gadget); ++ ++ if (gadget == 0) { ++ return -ENODEV; ++ } else { ++ d = container_of(gadget, struct gadget_wrapper, gadget); ++ } ++ dwc_otg_pcd_wakeup(d->pcd); ++ return 0; ++} ++ ++static const struct usb_gadget_ops dwc_otg_pcd_ops = { ++ .get_frame = get_frame_number, ++ .wakeup = wakeup, ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ .lpm_support = test_lpm_enabled, ++#endif ++ // current versions must always be self-powered ++}; ++ ++static int _setup(dwc_otg_pcd_t * pcd, uint8_t * bytes) ++{ ++ int retval = -DWC_E_NOT_SUPPORTED; ++ if (gadget_wrapper->driver && gadget_wrapper->driver->setup) { ++ retval = gadget_wrapper->driver->setup(&gadget_wrapper->gadget, ++ (struct usb_ctrlrequest ++ *)bytes); ++ } ++ ++ if (retval == -ENOTSUPP) { ++ retval = -DWC_E_NOT_SUPPORTED; ++ } else if (retval < 0) { ++ retval = -DWC_E_INVALID; ++ } ++ ++ return retval; ++} ++ ++#ifdef DWC_EN_ISOC ++static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int proc_buf_num) ++{ ++ int i, packet_count; ++ struct usb_gadget_iso_packet_descriptor *iso_packet = 0; ++ struct usb_iso_request *iso_req = req_handle; ++ ++ if (proc_buf_num) { ++ iso_packet = iso_req->iso_packet_desc1; ++ } else { ++ iso_packet = iso_req->iso_packet_desc0; ++ } ++ packet_count = ++ dwc_otg_pcd_get_iso_packet_count(pcd, ep_handle, req_handle); ++ for (i = 0; i < packet_count; ++i) { ++ int status; ++ int actual; ++ int offset; ++ dwc_otg_pcd_get_iso_packet_params(pcd, ep_handle, req_handle, ++ i, &status, &actual, &offset); ++ switch (status) { ++ case -DWC_E_NO_DATA: ++ status = -ENODATA; ++ break; ++ default: ++ if (status) { ++ DWC_PRINTF("unknown status in isoc packet\n"); ++ } ++ ++ } ++ iso_packet[i].status = status; ++ iso_packet[i].offset = offset; ++ iso_packet[i].actual_length = actual; ++ } ++ ++ iso_req->status = 0; ++ iso_req->process_buffer(ep_handle, iso_req); ++ ++ return 0; ++} ++#endif /* DWC_EN_ISOC */ ++ ++#ifdef DWC_UTE_PER_IO ++/** ++ * Copy the contents of the extended request to the Linux usb_request's ++ * extended part and call the gadget's completion. ++ * ++ * @param pcd Pointer to the pcd structure ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param req_handle Void pointer to the usb_request structure ++ * @param status Request status returned from the portable logic ++ * @param ereq_port Void pointer to the extended request structure ++ * created in the the portable part that contains the ++ * results of the processed iso packets. ++ */ ++static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, void *ereq_port) ++{ ++ struct dwc_ute_iso_req_ext *ereqorg = NULL; ++ struct dwc_iso_xreq_port *ereqport = NULL; ++ struct dwc_ute_iso_packet_descriptor *desc_org = NULL; ++ int i; ++ struct usb_request *req; ++ //struct dwc_ute_iso_packet_descriptor * ++ //int status = 0; ++ ++ req = (struct usb_request *)req_handle; ++ ereqorg = &req->ext_req; ++ ereqport = (struct dwc_iso_xreq_port *)ereq_port; ++ desc_org = ereqorg->per_io_frame_descs; ++ ++ if (req && req->complete) { ++ /* Copy the request data from the portable logic to our request */ ++ for (i = 0; i < ereqport->pio_pkt_count; i++) { ++ desc_org[i].actual_length = ++ ereqport->per_io_frame_descs[i].actual_length; ++ desc_org[i].status = ++ ereqport->per_io_frame_descs[i].status; ++ } ++ ++ switch (status) { ++ case -DWC_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -DWC_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -DWC_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -DWC_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ } ++ ++ /* And call the gadget's completion */ ++ req->complete(ep_handle, req); ++ } ++ ++ return 0; ++} ++#endif /* DWC_UTE_PER_IO */ ++ ++static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, uint32_t actual) ++{ ++ struct usb_request *req = (struct usb_request *)req_handle; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) ++ struct dwc_otg_pcd_ep *ep = NULL; ++#endif ++ ++ if (req && req->complete) { ++ switch (status) { ++ case -DWC_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -DWC_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -DWC_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -DWC_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ ++ } ++ ++ req->actual = actual; ++ DWC_SPINUNLOCK(pcd->lock); ++ req->complete(ep_handle, req); ++ DWC_SPINLOCK(pcd->lock); ++ } ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) ++ ep = ep_from_handle(pcd, ep_handle); ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ if (req->length != 0) { ++ dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev; ++ struct device *dev = NULL; ++ ++ if (otg_dev != NULL) ++ dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep); ++ ++ dma_unmap_single(dev, req->dma, req->length, ++ ep->dwc_ep.is_in ? ++ DMA_TO_DEVICE: DMA_FROM_DEVICE); ++ } ++ } ++#endif ++ ++ return 0; ++} ++ ++static int _connect(dwc_otg_pcd_t * pcd, int speed) ++{ ++ gadget_wrapper->gadget.speed = speed; ++ return 0; ++} ++ ++static int _disconnect(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->disconnect) { ++ gadget_wrapper->driver->disconnect(&gadget_wrapper->gadget); ++ } ++ return 0; ++} ++ ++static int _resume(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->resume) { ++ gadget_wrapper->driver->resume(&gadget_wrapper->gadget); ++ } ++ ++ return 0; ++} ++ ++static int _suspend(dwc_otg_pcd_t * pcd) ++{ ++ if (gadget_wrapper->driver && gadget_wrapper->driver->suspend) { ++ gadget_wrapper->driver->suspend(&gadget_wrapper->gadget); ++ } ++ return 0; ++} ++ ++/** ++ * This function updates the otg values in the gadget structure. ++ */ ++static int _hnp_changed(dwc_otg_pcd_t * pcd) ++{ ++ ++ if (!gadget_wrapper->gadget.is_otg) ++ return 0; ++ ++ gadget_wrapper->gadget.b_hnp_enable = get_b_hnp_enable(pcd); ++ gadget_wrapper->gadget.a_hnp_support = get_a_hnp_support(pcd); ++ gadget_wrapper->gadget.a_alt_hnp_support = get_a_alt_hnp_support(pcd); ++ return 0; ++} ++ ++static int _reset(dwc_otg_pcd_t * pcd) ++{ ++ return 0; ++} ++ ++#ifdef DWC_UTE_CFI ++static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req) ++{ ++ int retval = -DWC_E_INVALID; ++ if (gadget_wrapper->driver->cfi_feature_setup) { ++ retval = ++ gadget_wrapper->driver-> ++ cfi_feature_setup(&gadget_wrapper->gadget, ++ (struct cfi_usb_ctrlrequest *)cfi_req); ++ } ++ ++ return retval; ++} ++#endif ++ ++static const struct dwc_otg_pcd_function_ops fops = { ++ .complete = _complete, ++#ifdef DWC_EN_ISOC ++ .isoc_complete = _isoc_complete, ++#endif ++ .setup = _setup, ++ .disconnect = _disconnect, ++ .connect = _connect, ++ .resume = _resume, ++ .suspend = _suspend, ++ .hnp_changed = _hnp_changed, ++ .reset = _reset, ++#ifdef DWC_UTE_CFI ++ .cfi_setup = _cfi_setup, ++#endif ++#ifdef DWC_UTE_PER_IO ++ .xisoc_complete = _xisoc_complete, ++#endif ++}; ++ ++/** ++ * This function is the top level PCD interrupt handler. ++ */ ++static irqreturn_t dwc_otg_pcd_irq(int irq, void *dev) ++{ ++ dwc_otg_pcd_t *pcd = dev; ++ int32_t retval = IRQ_NONE; ++ ++ retval = dwc_otg_pcd_handle_intr(pcd); ++ if (retval != 0) { ++ S3C2410X_CLEAR_EINTPEND(); ++ } ++ return IRQ_RETVAL(retval); ++} ++ ++/** ++ * This function initialized the usb_ep structures to there default ++ * state. ++ * ++ * @param d Pointer on gadget_wrapper. ++ */ ++void gadget_add_eps(struct gadget_wrapper *d) ++{ ++ static const char *names[] = { ++ ++ "ep0", ++ "ep1in", ++ "ep2in", ++ "ep3in", ++ "ep4in", ++ "ep5in", ++ "ep6in", ++ "ep7in", ++ "ep8in", ++ "ep9in", ++ "ep10in", ++ "ep11in", ++ "ep12in", ++ "ep13in", ++ "ep14in", ++ "ep15in", ++ "ep1out", ++ "ep2out", ++ "ep3out", ++ "ep4out", ++ "ep5out", ++ "ep6out", ++ "ep7out", ++ "ep8out", ++ "ep9out", ++ "ep10out", ++ "ep11out", ++ "ep12out", ++ "ep13out", ++ "ep14out", ++ "ep15out" ++ }; ++ ++ int i; ++ struct usb_ep *ep; ++ int8_t dev_endpoints; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__); ++ ++ INIT_LIST_HEAD(&d->gadget.ep_list); ++ d->gadget.ep0 = &d->ep0; ++ d->gadget.speed = USB_SPEED_UNKNOWN; ++ ++ INIT_LIST_HEAD(&d->gadget.ep0->ep_list); ++ ++ /** ++ * Initialize the EP0 structure. ++ */ ++ ep = &d->ep0; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[0]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ dwc_otg_pcd_ep_enable(d->pcd, NULL, ep); ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ ++ /** ++ * Initialize the EP structures. ++ */ ++ dev_endpoints = d->pcd->core_if->dev_if->num_in_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { ++ ep = &d->in_ep[i]; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[d->pcd->in_ep[i].dwc_ep.num]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ } ++ ++ dev_endpoints = d->pcd->core_if->dev_if->num_out_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { ++ ep = &d->out_ep[i]; ++ ++ /* Init the usb_ep structure. */ ++ ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num]; ++ ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; ++ ++ /** ++ * @todo NGS: What should the max packet size be set to ++ * here? Before EP type is set? ++ */ ++ ep->maxpacket = MAX_PACKET_SIZE; ++ ++ list_add_tail(&ep->ep_list, &d->gadget.ep_list); ++ } ++ ++ /* remove ep0 from the list. There is a ep0 pointer. */ ++ list_del_init(&d->ep0.ep_list); ++ ++ d->ep0.maxpacket = MAX_EP0_SIZE; ++} ++ ++/** ++ * This function releases the Gadget device. ++ * required by device_unregister(). ++ * ++ * @todo Should this do something? Should it free the PCD? ++ */ ++static void dwc_otg_pcd_gadget_release(struct device *dev) ++{ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev); ++} ++ ++static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev) ++{ ++ static char pcd_name[] = "dwc_otg_pcd"; ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); ++ struct gadget_wrapper *d; ++ int retval; ++ ++ d = DWC_ALLOC(sizeof(*d)); ++ if (d == NULL) { ++ return NULL; ++ } ++ ++ memset(d, 0, sizeof(*d)); ++ ++ d->gadget.name = pcd_name; ++ d->pcd = otg_dev->pcd; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ strcpy(d->gadget.dev.bus_id, "gadget"); ++#else ++ dev_set_name(&d->gadget.dev, "%s", "gadget"); ++#endif ++ ++ d->gadget.dev.parent = &_dev->dev; ++ d->gadget.dev.release = dwc_otg_pcd_gadget_release; ++ d->gadget.ops = &dwc_otg_pcd_ops; ++ d->gadget.max_speed = dwc_otg_pcd_is_dualspeed(otg_dev->pcd) ? USB_SPEED_HIGH:USB_SPEED_FULL; ++ d->gadget.is_otg = dwc_otg_pcd_is_otg(otg_dev->pcd); ++ ++ d->driver = 0; ++ /* Register the gadget device */ ++ retval = device_register(&d->gadget.dev); ++ if (retval != 0) { ++ DWC_ERROR("device_register failed\n"); ++ DWC_FREE(d); ++ return NULL; ++ } ++ ++ return d; ++} ++ ++static void free_wrapper(struct gadget_wrapper *d) ++{ ++ if (d->driver) { ++ /* should have been done already by driver model core */ ++ DWC_WARN("driver '%s' is still registered\n", ++ d->driver->driver.name); ++ usb_gadget_unregister_driver(d->driver); ++ } ++ ++ device_unregister(&d->gadget.dev); ++ DWC_FREE(d); ++} ++ ++/** ++ * This function initialized the PCD portion of the driver. ++ * ++ */ ++int pcd_init(dwc_bus_dev_t *_dev) ++{ ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); ++ int retval = 0; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev); ++ ++ otg_dev->pcd = dwc_otg_pcd_init(otg_dev->core_if); ++ ++ if (!otg_dev->pcd) { ++ DWC_ERROR("dwc_otg_pcd_init failed\n"); ++ return -ENOMEM; ++ } ++ ++ otg_dev->pcd->otg_dev = otg_dev; ++ gadget_wrapper = alloc_wrapper(_dev); ++ ++ /* ++ * Initialize EP structures ++ */ ++ gadget_add_eps(gadget_wrapper); ++ /* ++ * Setup interupt handler ++ */ ++#ifdef PLATFORM_INTERFACE ++ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", ++ platform_get_irq(_dev, 0)); ++ retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq, ++ IRQF_SHARED, gadget_wrapper->gadget.name, ++ otg_dev->pcd); ++ if (retval != 0) { ++ DWC_ERROR("request of irq%d failed\n", ++ platform_get_irq(_dev, 0)); ++ free_wrapper(gadget_wrapper); ++ return -EBUSY; ++ } ++#else ++ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", ++ _dev->irq); ++ retval = request_irq(_dev->irq, dwc_otg_pcd_irq, ++ IRQF_SHARED | IRQF_DISABLED, ++ gadget_wrapper->gadget.name, otg_dev->pcd); ++ if (retval != 0) { ++ DWC_ERROR("request of irq%d failed\n", _dev->irq); ++ free_wrapper(gadget_wrapper); ++ return -EBUSY; ++ } ++#endif ++ ++ dwc_otg_pcd_start(gadget_wrapper->pcd, &fops); ++ ++ return retval; ++} ++ ++/** ++ * Cleanup the PCD. ++ */ ++void pcd_remove(dwc_bus_dev_t *_dev) ++{ ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); ++ dwc_otg_pcd_t *pcd = otg_dev->pcd; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev); ++ ++ /* ++ * Free the IRQ ++ */ ++#ifdef PLATFORM_INTERFACE ++ free_irq(platform_get_irq(_dev, 0), pcd); ++#else ++ free_irq(_dev->irq, pcd); ++#endif ++ dwc_otg_pcd_remove(otg_dev->pcd); ++ free_wrapper(gadget_wrapper); ++ otg_dev->pcd = 0; ++} ++ ++/** ++ * This function registers a gadget driver with the PCD. ++ * ++ * When a driver is successfully registered, it will receive control ++ * requests including set_configuration(), which enables non-control ++ * requests. then usb traffic follows until a disconnect is reported. ++ * then a host may connect again, or the driver might get unbound. ++ * ++ * @param driver The driver being registered ++ * @param bind The bind function of gadget driver ++ */ ++ ++int usb_gadget_probe_driver(struct usb_gadget_driver *driver) ++{ ++ int retval; ++ ++ DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", ++ driver->driver.name); ++ ++ if (!driver || driver->max_speed == USB_SPEED_UNKNOWN || ++ !driver->bind || ++ !driver->unbind || !driver->disconnect || !driver->setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EINVAL\n"); ++ return -EINVAL; ++ } ++ if (gadget_wrapper == 0) { ++ DWC_DEBUGPL(DBG_PCDV, "ENODEV\n"); ++ return -ENODEV; ++ } ++ if (gadget_wrapper->driver != 0) { ++ DWC_DEBUGPL(DBG_PCDV, "EBUSY (%p)\n", gadget_wrapper->driver); ++ return -EBUSY; ++ } ++ ++ /* hook up the driver */ ++ gadget_wrapper->driver = driver; ++ gadget_wrapper->gadget.dev.driver = &driver->driver; ++ ++ DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); ++ retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver); ++ if (retval) { ++ DWC_ERROR("bind to driver %s --> error %d\n", ++ driver->driver.name, retval); ++ gadget_wrapper->driver = 0; ++ gadget_wrapper->gadget.dev.driver = 0; ++ return retval; ++ } ++ DWC_DEBUGPL(DBG_ANY, "registered gadget driver '%s'\n", ++ driver->driver.name); ++ return 0; ++} ++EXPORT_SYMBOL(usb_gadget_probe_driver); ++ ++/** ++ * This function unregisters a gadget driver ++ * ++ * @param driver The driver being unregistered ++ */ ++int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) ++{ ++ //DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _driver); ++ ++ if (gadget_wrapper == 0) { ++ DWC_DEBUGPL(DBG_ANY, "%s Return(%d): s_pcd==0\n", __func__, ++ -ENODEV); ++ return -ENODEV; ++ } ++ if (driver == 0 || driver != gadget_wrapper->driver) { ++ DWC_DEBUGPL(DBG_ANY, "%s Return(%d): driver?\n", __func__, ++ -EINVAL); ++ return -EINVAL; ++ } ++ ++ driver->unbind(&gadget_wrapper->gadget); ++ gadget_wrapper->driver = 0; ++ ++ DWC_DEBUGPL(DBG_ANY, "unregistered driver '%s'\n", driver->driver.name); ++ return 0; ++} ++ ++EXPORT_SYMBOL(usb_gadget_unregister_driver); ++ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h +new file mode 100644 +index 0000000..0572642 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h +@@ -0,0 +1,2550 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $ ++ * $Revision: #98 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ ++ * ++ * 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 "dwc_otg_core_if.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. Offset: 000h */ ++ volatile uint32_t gotgctl; ++ /** OTG Interrupt Register. Offset: 004h */ ++ volatile uint32_t gotgint; ++ /**Core AHB Configuration Register. Offset: 008h */ ++ 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. Offset: 00Ch */ ++ volatile uint32_t gusbcfg; ++ /**Core Reset Register. Offset: 010h */ ++ volatile uint32_t grstctl; ++ /**Core Interrupt Register. Offset: 014h */ ++ volatile uint32_t gintsts; ++ /**Core Interrupt Mask Register. Offset: 018h */ ++ volatile uint32_t gintmsk; ++ /**Receive Status Queue Read Register (Read Only). Offset: 01Ch */ ++ volatile uint32_t grxstsr; ++ /**Receive Status Queue Read & POP Register (Read Only). Offset: 020h*/ ++ volatile uint32_t grxstsp; ++ /**Receive FIFO Size Register. Offset: 024h */ ++ volatile uint32_t grxfsiz; ++ /**Non Periodic Transmit FIFO Size Register. Offset: 028h */ ++ volatile uint32_t gnptxfsiz; ++ /**Non Periodic Transmit FIFO/Queue Status Register (Read ++ * Only). Offset: 02Ch */ ++ volatile uint32_t gnptxsts; ++ /**I2C Access Register. Offset: 030h */ ++ volatile uint32_t gi2cctl; ++ /**PHY Vendor Control Register. Offset: 034h */ ++ volatile uint32_t gpvndctl; ++ /**General Purpose Input/Output Register. Offset: 038h */ ++ volatile uint32_t ggpio; ++ /**User ID Register. Offset: 03Ch */ ++ volatile uint32_t guid; ++ /**Synopsys ID Register (Read Only). Offset: 040h */ ++ volatile uint32_t gsnpsid; ++ /**User HW Config1 Register (Read Only). Offset: 044h */ ++ volatile uint32_t ghwcfg1; ++ /**User HW Config2 Register (Read Only). Offset: 048h */ ++ 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). Offset: 04Ch */ ++ volatile uint32_t ghwcfg3; ++ /**User HW Config4 Register (Read Only). Offset: 050h*/ ++ volatile uint32_t ghwcfg4; ++ /** Core LPM Configuration register Offset: 054h*/ ++ volatile uint32_t glpmcfg; ++ /** Global PowerDn Register Offset: 058h */ ++ volatile uint32_t gpwrdn; ++ /** Global DFIFO SW Config Register Offset: 05Ch */ ++ volatile uint32_t gdfifocfg; ++ /** ADP Control Register Offset: 060h */ ++ volatile uint32_t adpctl; ++ /** Reserved Offset: 064h-0FFh */ ++ volatile uint32_t reserved39[39]; ++ /** Host Periodic Transmit FIFO Size Register. Offset: 100h */ ++ volatile uint32_t hptxfsiz; ++ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, ++ otherwise Device Transmit FIFO#n Register. ++ * Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15). */ ++ volatile uint32_t dtxfsiz[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 d32 value to the register. ++ */ ++typedef union gotgctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned sesreqscs:1; ++ unsigned sesreq:1; ++ unsigned vbvalidoven:1; ++ unsigned vbvalidovval:1; ++ unsigned avalidoven:1; ++ unsigned avalidovval:1; ++ unsigned bvalidoven:1; ++ unsigned bvalidovval:1; ++ unsigned hstnegscs:1; ++ unsigned hnpreq:1; ++ unsigned hstsethnpen:1; ++ unsigned devhnpen:1; ++ unsigned reserved12_15:4; ++ unsigned conidsts:1; ++ unsigned dbnctime:1; ++ unsigned asesvld:1; ++ unsigned bsesvld:1; ++ unsigned otgver:1; ++ unsigned reserved1:1; ++ unsigned multvalidbc:5; ++ unsigned chirpen:1; ++ unsigned reserved28_31:4; ++ } 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 d32 ++ * 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 reserved10_16:7; ++ ++ /** Host Negotiation Detected */ ++ unsigned hstnegdet:1; ++ /** A-Device Timeout Change */ ++ unsigned adevtoutchng:1; ++ /** Debounce Done */ ++ unsigned debdone:1; ++ /** Multi-Valued input changed */ ++ unsigned mvic:1; ++ ++ unsigned reserved31_21:11; ++ ++ } 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 d32 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_20:12; ++ unsigned remmemsupp:1; ++ unsigned notialldmawrit:1; ++ unsigned ahbsingle:1; ++ unsigned reserved24_31:8; ++ } 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 d32 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 reserved1: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 indicator_complement:1; ++ unsigned indicator_pass_through:1; ++ unsigned ulpi_int_prot_dis:1; ++ unsigned ic_usb_cap:1; ++ unsigned ic_traffic_pull_remove:1; ++ unsigned tx_end_delay:1; ++ unsigned force_host_mode:1; ++ unsigned force_dev_mode:1; ++ unsigned reserved31:1; ++ } b; ++} gusbcfg_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 ++ * d32 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)
++ * ++ * 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. The application must first ++ * ensure that the core is not in the middle of a ++ * transaction. 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. 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. 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. 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 d32 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 ulpickint:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned restoredone:1; ++ unsigned epmismatch:1; ++ unsigned inepintr:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; ++ 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 ++ * d32 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 ulpickint:1; ++ unsigned i2cintr:1; ++ unsigned erlysuspend:1; ++ unsigned usbsuspend:1; ++ unsigned usbreset:1; ++ unsigned enumdone:1; ++ unsigned isooutdrop:1; ++ unsigned eopframe:1; ++ unsigned restoredone:1; ++ unsigned epmismatch:1; ++ unsigned inepint:1; ++ unsigned outepintr:1; ++ unsigned incomplisoin:1; ++ unsigned incomplisoout:1; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; ++ 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 d32 ++ * element then read out the bits using the bit 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 reserved25_31: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 d32 ++ * element then read out the bits using the bit 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 reserved21_31: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 d32 element ++ * then read out the bits using the bit 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 ++ * d32 element then read out the bits using the bit ++ * 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 ++ * d32 element then read out the bits using the bit ++ * 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 d32 element then read out the ++ * bits using the bit 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 i2cdatse0:1; ++ unsigned reserved:1; ++ unsigned rw:1; ++ unsigned bsydne:1; ++ } b; ++} gi2cctl_data_t; ++ ++/** ++ * This union represents the bit fields in the PHY Vendor Control Register ++ * (GPVNDCTL). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gpvndctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned regdata:8; ++ unsigned vctrl:8; ++ unsigned regaddr16_21:6; ++ unsigned regwr:1; ++ unsigned reserved23_24:2; ++ unsigned newregreq:1; ++ unsigned vstsbsy:1; ++ unsigned vstsdone:1; ++ unsigned reserved28_30:3; ++ unsigned disulpidrvr:1; ++ } b; ++} gpvndctl_data_t; ++ ++/** ++ * This union represents the bit fields in the General Purpose ++ * Input/Output Register (GGPIO). ++ * Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union ggpio_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned gpi:16; ++ unsigned gpo:16; ++ } b; ++} ggpio_data_t; ++ ++/** ++ * This union represents the bit fields in the User ID Register ++ * (GUID). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union guid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} guid_data_t; ++ ++/** ++ * This union represents the bit fields in the Synopsys ID Register ++ * (GSNPSID). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gsnpsid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} gsnpsid_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config1 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit 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 d32 element then read ++ * out the bits using the bit 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 otg_enable_ic_usb:1; ++ } b; ++} hwcfg2_data_t; ++ ++/** ++ * This union represents the bit fields in the User HW Config3 ++ * Register. Read the register into the d32 element then read ++ * out the bits using the bit 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 adp_supp:1; ++ unsigned otg_enable_hsic:1; ++ unsigned bc_support: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 d32 element then read ++ * out the bits using the bit 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:1; ++ unsigned hiber:1; ++ unsigned xhiber:1; ++ unsigned reserved:6; ++ 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; ++ ++/** ++ * This union represents the bit fields of the Core LPM Configuration ++ * Register (GLPMCFG). Set the bits using bit fields then write ++ * the d32 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 ADP Timer, Control and ++ * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union adpctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Probe Discharge (PRB_DSCHG) ++ * These bits set the times for TADP_DSCHG. ++ * These bits are defined as follows: ++ * 2'b00 - 4 msec ++ * 2'b01 - 8 msec ++ * 2'b10 - 16 msec ++ * 2'b11 - 32 msec ++ */ ++ unsigned prb_dschg:2; ++ /** Probe Delta (PRB_DELTA) ++ * These bits set the resolution for RTIM value. ++ * The bits are defined in units of 32 kHz clock cycles as follows: ++ * 2'b00 - 1 cycles ++ * 2'b01 - 2 cycles ++ * 2'b10 - 3 cycles ++ * 2'b11 - 4 cycles ++ * For example if this value is chosen to 2'b01, it means that RTIM ++ * increments for every 3(three) 32Khz clock cycles. ++ */ ++ unsigned prb_delta:2; ++ /** Probe Period (PRB_PER) ++ * These bits sets the TADP_PRD as shown in Figure 4 as follows: ++ * 2'b00 - 0.625 to 0.925 sec (typical 0.775 sec) ++ * 2'b01 - 1.25 to 1.85 sec (typical 1.55 sec) ++ * 2'b10 - 1.9 to 2.6 sec (typical 2.275 sec) ++ * 2'b11 - Reserved ++ */ ++ unsigned prb_per:2; ++ /** These bits capture the latest time it took for VBUS to ramp from ++ * VADP_SINK to VADP_PRB. ++ * 0x000 - 1 cycles ++ * 0x001 - 2 cycles ++ * 0x002 - 3 cycles ++ * etc ++ * 0x7FF - 2048 cycles ++ * A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec. ++ */ ++ unsigned rtim:11; ++ /** Enable Probe (EnaPrb) ++ * When programmed to 1'b1, the core performs a probe operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enaprb:1; ++ /** Enable Sense (EnaSns) ++ * When programmed to 1'b1, the core performs a Sense operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enasns:1; ++ /** ADP Reset (ADPRes) ++ * When set, ADP controller is reset. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpres:1; ++ /** ADP Enable (ADPEn) ++ * When set, the core performs either ADP probing or sensing ++ * based on EnaPrb or EnaSns. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpen:1; ++ /** ADP Probe Interrupt (ADP_PRB_INT) ++ * When this bit is set, it means that the VBUS ++ * voltage is greater than VADP_PRB or VADP_PRB is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int:1; ++ /** ++ * ADP Sense Interrupt (ADP_SNS_INT) ++ * When this bit is set, it means that the VBUS voltage is greater than ++ * VADP_SNS value or VADP_SNS is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int:1; ++ /** ADP Tomeout Interrupt (ADP_TMOUT_INT) ++ * This bit is relevant only for an ADP probe. ++ * When this bit is set, it means that the ramp time has ++ * completed ie ADPCTL.RTIM has reached its terminal value ++ * of 0x7FF. This is a debug feature that allows software ++ * to read the ramp time after each cycle. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int:1; ++ /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_PRB_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int_msk:1; ++ /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_SNS_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int_msk:1; ++ /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int_msk:1; ++ /** Access Request ++ * 2'b00 - Read/Write Valid (updated by the core) ++ * 2'b01 - Read ++ * 2'b00 - Write ++ * 2'b00 - Reserved ++ */ ++ unsigned ar:2; ++ /** Reserved */ ++ unsigned reserved29_31:3; ++ } b; ++} adpctl_data_t; ++ ++//////////////////////////////////////////// ++// Device Registers ++/** ++ * Device Global Registers. Offsets 800h-BFFh ++ * ++ * The following structures define the size and relative field offsets ++ * for the Device Mode Registers. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_global_regs { ++ /** Device Configuration Register. Offset 800h */ ++ volatile uint32_t dcfg; ++ /** Device Control Register. Offset: 804h */ ++ volatile uint32_t dctl; ++ /** Device Status Register (Read Only). Offset: 808h */ ++ volatile uint32_t dsts; ++ /** Reserved. Offset: 80Ch */ ++ uint32_t unused; ++ /** Device IN Endpoint Common Interrupt Mask ++ * Register. Offset: 810h */ ++ volatile uint32_t diepmsk; ++ /** Device OUT Endpoint Common Interrupt Mask ++ * Register. Offset: 814h */ ++ volatile uint32_t doepmsk; ++ /** Device All Endpoints Interrupt Register. Offset: 818h */ ++ volatile uint32_t daint; ++ /** Device All Endpoints Interrupt Mask Register. Offset: ++ * 81Ch */ ++ volatile uint32_t daintmsk; ++ /** Device IN Token Queue Read Register-1 (Read Only). ++ * Offset: 820h */ ++ volatile uint32_t dtknqr1; ++ /** Device IN Token Queue Read Register-2 (Read Only). ++ * Offset: 824h */ ++ volatile uint32_t dtknqr2; ++ /** Device VBUS discharge Register. Offset: 828h */ ++ volatile uint32_t dvbusdis; ++ /** Device VBUS Pulse Register. Offset: 82Ch */ ++ volatile uint32_t dvbuspulse; ++ /** Device IN Token Queue Read Register-3 (Read Only). / ++ * Device Thresholding control register (Read/Write) ++ * Offset: 830h */ ++ volatile uint32_t dtknqr3_dthrctl; ++ /** Device IN Token Queue Read Register-4 (Read Only). / ++ * Device IN EPs empty Inr. Mask Register (Read/Write) ++ * Offset: 834h */ ++ volatile uint32_t dtknqr4_fifoemptymsk; ++ /** Device Each Endpoint Interrupt Register (Read Only). / ++ * Offset: 838h */ ++ volatile uint32_t deachint; ++ /** Device Each Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 83Ch */ ++ volatile uint32_t deachintmsk; ++ /** Device Each In Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 840h */ ++ volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS]; ++ /** Device Each Out Endpoint Interrupt mask Register (Read/Write). / ++ * Offset: 880h */ ++ volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS]; ++} dwc_otg_device_global_regs_t; ++ ++/** ++ * This union represents the bit fields in the Device Configuration ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. Write the ++ * d32 member to the dcfg register. ++ */ ++typedef union dcfg_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Device Speed */ ++ unsigned devspd:2; ++ /** Non Zero Length Status OUT Handshake */ ++ unsigned nzstsouthshk:1; ++#define DWC_DCFG_SEND_STALL 1 ++ ++ unsigned ena32khzs:1; ++ /** Device Addresses */ ++ unsigned devaddr:7; ++ /** Periodic Frame Interval */ ++ unsigned perfrint:2; ++#define DWC_DCFG_FRAME_INTERVAL_80 0 ++#define DWC_DCFG_FRAME_INTERVAL_85 1 ++#define DWC_DCFG_FRAME_INTERVAL_90 2 ++#define DWC_DCFG_FRAME_INTERVAL_95 3 ++ ++ /** Enable Device OUT NAK for bulk in DDMA mode */ ++ unsigned endevoutnak:1; ++ ++ unsigned reserved14_17:4; ++ /** In Endpoint Mis-match count */ ++ unsigned epmscnt:5; ++ /** Enable Descriptor DMA in Device mode */ ++ unsigned descdma:1; ++ unsigned perschintvl:2; ++ unsigned resvalid:6; ++ } b; ++} dcfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Control ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union dctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Remote Wakeup */ ++ unsigned rmtwkupsig:1; ++ /** Soft Disconnect */ ++ unsigned sftdiscon:1; ++ /** Global Non-Periodic IN NAK Status */ ++ unsigned gnpinnaksts:1; ++ /** Global OUT NAK Status */ ++ unsigned goutnaksts:1; ++ /** Test Control */ ++ unsigned tstctl:3; ++ /** Set Global Non-Periodic IN NAK */ ++ unsigned sgnpinnak:1; ++ /** Clear Global Non-Periodic IN NAK */ ++ unsigned cgnpinnak:1; ++ /** Set Global OUT NAK */ ++ unsigned sgoutnak:1; ++ /** Clear Global OUT NAK */ ++ unsigned cgoutnak:1; ++ /** Power-On Programming Done */ ++ unsigned pwronprgdone:1; ++ /** Reserved */ ++ unsigned reserved:1; ++ /** Global Multi Count */ ++ unsigned gmc:2; ++ /** Ignore Frame Number for ISOC EPs */ ++ unsigned ifrmnum:1; ++ /** NAK on Babble */ ++ unsigned nakonbble:1; ++ /** Enable Continue on BNA */ ++ unsigned encontonbna:1; ++ ++ unsigned reserved18_31:14; ++ } b; ++} dctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Device Status ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union dsts_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Suspend Status */ ++ unsigned suspsts:1; ++ /** Enumerated Speed */ ++ unsigned enumspd:2; ++#define DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0 ++#define DWC_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1 ++#define DWC_DSTS_ENUMSPD_LS_PHY_6MHZ 2 ++#define DWC_DSTS_ENUMSPD_FS_PHY_48MHZ 3 ++ /** Erratic Error */ ++ unsigned errticerr:1; ++ unsigned reserved4_7:4; ++ /** Frame or Microframe Number of the received SOF */ ++ unsigned soffn:14; ++ unsigned reserved22_31:10; ++ } b; ++} dsts_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN EP Interrupt ++ * Register and the Device IN EP Common Mask Register. ++ * ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union diepint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer complete mask */ ++ unsigned xfercompl:1; ++ /** Endpoint disable mask */ ++ unsigned epdisabled:1; ++ /** AHB Error mask */ ++ unsigned ahberr:1; ++ /** TimeOUT Handshake mask (non-ISOC EPs) */ ++ unsigned timeout:1; ++ /** IN Token received with TxF Empty mask */ ++ unsigned intktxfemp:1; ++ /** IN Token Received with EP mismatch mask */ ++ unsigned intknepmis:1; ++ /** IN Endpoint NAK Effective mask */ ++ unsigned inepnakeff:1; ++ /** Reserved */ ++ unsigned emptyintr:1; ++ ++ unsigned txfifoundrn:1; ++ ++ /** BNA Interrupt mask */ ++ unsigned bna:1; ++ ++ unsigned reserved10_12:3; ++ /** BNA Interrupt mask */ ++ unsigned nak:1; ++ ++ unsigned reserved14_31:18; ++ } b; ++} diepint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN EP ++ * Common/Dedicated Interrupt Mask Register. ++ */ ++typedef union diepint_data diepmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP Interrupt ++ * Registerand Device OUT EP Common Interrupt Mask Register. ++ * ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union doepint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer complete */ ++ unsigned xfercompl:1; ++ /** Endpoint disable */ ++ unsigned epdisabled:1; ++ /** AHB Error */ ++ unsigned ahberr:1; ++ /** Setup Phase Done (contorl EPs) */ ++ unsigned setup:1; ++ /** OUT Token Received when Endpoint Disabled */ ++ unsigned outtknepdis:1; ++ ++ unsigned stsphsercvd:1; ++ /** Back-to-Back SETUP Packets Received */ ++ unsigned back2backsetup:1; ++ ++ unsigned reserved7:1; ++ /** OUT packet Error */ ++ unsigned outpkterr:1; ++ /** BNA Interrupt */ ++ unsigned bna:1; ++ ++ unsigned reserved10:1; ++ /** Packet Drop Status */ ++ unsigned pktdrpsts:1; ++ /** Babble Interrupt */ ++ unsigned babble:1; ++ /** NAK Interrupt */ ++ unsigned nak:1; ++ /** NYET Interrupt */ ++ unsigned nyet:1; ++ /** Bit indicating setup packet received */ ++ unsigned sr:1; ++ ++ unsigned reserved16_31:16; ++ } b; ++} doepint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device OUT EP ++ * Common/Dedicated Interrupt Mask Register. ++ */ ++typedef union doepint_data doepmsk_data_t; ++ ++/** ++ * This union represents the bit fields in the Device All EP Interrupt ++ * and Mask Registers. ++ * - Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union daint_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** IN Endpoint bits */ ++ unsigned in:16; ++ /** OUT Endpoint bits */ ++ unsigned out:16; ++ } ep; ++ struct { ++ /** IN Endpoint bits */ ++ unsigned inep0:1; ++ unsigned inep1:1; ++ unsigned inep2:1; ++ unsigned inep3:1; ++ unsigned inep4:1; ++ unsigned inep5:1; ++ unsigned inep6:1; ++ unsigned inep7:1; ++ unsigned inep8:1; ++ unsigned inep9:1; ++ unsigned inep10:1; ++ unsigned inep11:1; ++ unsigned inep12:1; ++ unsigned inep13:1; ++ unsigned inep14:1; ++ unsigned inep15:1; ++ /** OUT Endpoint bits */ ++ unsigned outep0:1; ++ unsigned outep1:1; ++ unsigned outep2:1; ++ unsigned outep3:1; ++ unsigned outep4:1; ++ unsigned outep5:1; ++ unsigned outep6:1; ++ unsigned outep7:1; ++ unsigned outep8:1; ++ unsigned outep9:1; ++ unsigned outep10:1; ++ unsigned outep11:1; ++ unsigned outep12:1; ++ unsigned outep13:1; ++ unsigned outep14:1; ++ unsigned outep15:1; ++ } b; ++} daint_data_t; ++ ++/** ++ * This union represents the bit fields in the Device IN Token Queue ++ * Read Registers. ++ * - Read the register into the d32 member. ++ * - READ-ONLY Register ++ */ ++typedef union dtknq1_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** In Token Queue Write Pointer */ ++ unsigned intknwptr:5; ++ /** Reserved */ ++ unsigned reserved05_06:2; ++ /** write pointer has wrapped. */ ++ unsigned wrap_bit:1; ++ /** EP Numbers of IN Tokens 0 ... 4 */ ++ unsigned epnums0_5:24; ++ } b; ++} dtknq1_data_t; ++ ++/** ++ * This union represents Threshold control Register ++ * - Read and write the register into the d32 member. ++ * - READ-WRITABLE Register ++ */ ++typedef union dthrctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** non ISO Tx Thr. Enable */ ++ unsigned non_iso_thr_en:1; ++ /** ISO Tx Thr. Enable */ ++ unsigned iso_thr_en:1; ++ /** Tx Thr. Length */ ++ unsigned tx_thr_len:9; ++ /** AHB Threshold ratio */ ++ unsigned ahb_thr_ratio:2; ++ /** Reserved */ ++ unsigned reserved13_15:3; ++ /** Rx Thr. Enable */ ++ unsigned rx_thr_en:1; ++ /** Rx Thr. Length */ ++ unsigned rx_thr_len:9; ++ unsigned reserved26:1; ++ /** Arbiter Parking Enable*/ ++ unsigned arbprken:1; ++ /** Reserved */ ++ unsigned reserved28_31:4; ++ } b; ++} dthrctl_data_t; ++ ++/** ++ * Device Logical IN Endpoint-Specific Registers. Offsets ++ * 900h-AFCh ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_in_ep_regs { ++ /** Device IN Endpoint Control Register. Offset:900h + ++ * (ep_num * 20h) + 00h */ ++ volatile uint32_t diepctl; ++ /** Reserved. Offset:900h + (ep_num * 20h) + 04h */ ++ uint32_t reserved04; ++ /** Device IN Endpoint Interrupt Register. Offset:900h + ++ * (ep_num * 20h) + 08h */ ++ volatile uint32_t diepint; ++ /** Reserved. Offset:900h + (ep_num * 20h) + 0Ch */ ++ uint32_t reserved0C; ++ /** Device IN Endpoint Transfer Size ++ * Register. Offset:900h + (ep_num * 20h) + 10h */ ++ volatile uint32_t dieptsiz; ++ /** Device IN Endpoint DMA Address Register. Offset:900h + ++ * (ep_num * 20h) + 14h */ ++ volatile uint32_t diepdma; ++ /** Device IN Endpoint Transmit FIFO Status Register. Offset:900h + ++ * (ep_num * 20h) + 18h */ ++ volatile uint32_t dtxfsts; ++ /** Device IN Endpoint DMA Buffer Register. Offset:900h + ++ * (ep_num * 20h) + 1Ch */ ++ volatile uint32_t diepdmab; ++} dwc_otg_dev_in_ep_regs_t; ++ ++/** ++ * Device Logical OUT Endpoint-Specific Registers. Offsets: ++ * B00h-CFCh ++ * ++ * There will be one set of endpoint registers per logical endpoint ++ * implemented. ++ * ++ * These registers are visible only in Device mode and must not be ++ * accessed in Host mode, as the results are unknown. ++ */ ++typedef struct dwc_otg_dev_out_ep_regs { ++ /** Device OUT Endpoint Control Register. Offset:B00h + ++ * (ep_num * 20h) + 00h */ ++ volatile uint32_t doepctl; ++ /** Reserved. Offset:B00h + (ep_num * 20h) + 04h */ ++ uint32_t reserved04; ++ /** Device OUT Endpoint Interrupt Register. Offset:B00h + ++ * (ep_num * 20h) + 08h */ ++ volatile uint32_t doepint; ++ /** Reserved. Offset:B00h + (ep_num * 20h) + 0Ch */ ++ uint32_t reserved0C; ++ /** Device OUT Endpoint Transfer Size Register. Offset: ++ * B00h + (ep_num * 20h) + 10h */ ++ volatile uint32_t doeptsiz; ++ /** Device OUT Endpoint DMA Address Register. Offset:B00h ++ * + (ep_num * 20h) + 14h */ ++ volatile uint32_t doepdma; ++ /** Reserved. Offset:B00h + * (ep_num * 20h) + 18h */ ++ uint32_t unused; ++ /** Device OUT Endpoint DMA Buffer Register. Offset:B00h ++ * + (ep_num * 20h) + 1Ch */ ++ uint32_t doepdmab; ++} dwc_otg_dev_out_ep_regs_t; ++ ++/** ++ * This union represents the bit fields in the Device EP Control ++ * Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union depctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Maximum Packet Size ++ * IN/OUT EPn ++ * IN/OUT EP0 - 2 bits ++ * 2'b00: 64 Bytes ++ * 2'b01: 32 ++ * 2'b10: 16 ++ * 2'b11: 8 */ ++ unsigned mps:11; ++#define DWC_DEP0CTL_MPS_64 0 ++#define DWC_DEP0CTL_MPS_32 1 ++#define DWC_DEP0CTL_MPS_16 2 ++#define DWC_DEP0CTL_MPS_8 3 ++ ++ /** Next Endpoint ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved */ ++ unsigned nextep:4; ++ ++ /** USB Active Endpoint */ ++ unsigned usbactep:1; ++ ++ /** Endpoint DPID (INTR/Bulk IN and OUT endpoints) ++ * This field contains the PID of the packet going to ++ * be received or transmitted on this endpoint. The ++ * application should program the PID of the first ++ * packet going to be received or transmitted on this ++ * endpoint , after the endpoint is ++ * activated. Application use the SetD1PID and ++ * SetD0PID fields of this register to program either ++ * D0 or D1 PID. ++ * ++ * The encoding for this field is ++ * - 0: D0 ++ * - 1: D1 ++ */ ++ unsigned dpid:1; ++ ++ /** NAK Status */ ++ unsigned naksts:1; ++ ++ /** Endpoint Type ++ * 2'b00: Control ++ * 2'b01: Isochronous ++ * 2'b10: Bulk ++ * 2'b11: Interrupt */ ++ unsigned eptype:2; ++ ++ /** Snoop Mode ++ * OUT EPn/OUT EP0 ++ * IN EPn/IN EP0 - reserved */ ++ unsigned snp:1; ++ ++ /** Stall Handshake */ ++ unsigned stall:1; ++ ++ /** Tx Fifo Number ++ * IN EPn/IN EP0 ++ * OUT EPn/OUT EP0 - reserved */ ++ unsigned txfnum:4; ++ ++ /** Clear NAK */ ++ unsigned cnak:1; ++ /** Set NAK */ ++ unsigned snak:1; ++ /** Set DATA0 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA0. Set Even ++ * (micro)frame (SetEvenFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to even (micro) ++ * frame. ++ */ ++ unsigned setd0pid:1; ++ /** Set DATA1 PID (INTR/Bulk IN and OUT endpoints) ++ * Writing to this field sets the Endpoint DPID (DPID) ++ * field in this register to DATA1 Set Odd ++ * (micro)frame (SetOddFr) (ISO IN and OUT Endpoints) ++ * Writing to this field sets the Even/Odd ++ * (micro)frame (EO_FrNum) field to odd (micro) frame. ++ */ ++ unsigned setd1pid:1; ++ ++ /** Endpoint Disable */ ++ unsigned epdis:1; ++ /** Endpoint Enable */ ++ unsigned epena:1; ++ } b; ++} depctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Device EP Transfer ++ * Size Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union deptsiz_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer size */ ++ unsigned xfersize:19; ++/** Max packet count for EP (pow(2,10)-1) */ ++#define MAX_PKT_CNT 1023 ++ /** Packet Count */ ++ unsigned pktcnt:10; ++ /** Multi Count - Periodic IN endpoints */ ++ unsigned mc:2; ++ unsigned reserved:1; ++ } b; ++} deptsiz_data_t; ++ ++/** ++ * This union represents the bit fields in the Device EP 0 Transfer ++ * Size Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union deptsiz0_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Transfer size */ ++ unsigned xfersize:7; ++ /** Reserved */ ++ unsigned reserved7_18:12; ++ /** Packet Count */ ++ unsigned pktcnt:2; ++ /** Reserved */ ++ unsigned reserved21_28:8; ++ /**Setup Packet Count (DOEPTSIZ0 Only) */ ++ unsigned supcnt:2; ++ unsigned reserved31; ++ } b; ++} deptsiz0_data_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 d32 member then ++ * set/clear the bits using the bit, b_iso_out and ++ * b_iso_in elements. ++ */ ++typedef union dev_dma_desc_sts { ++ /** raw register data */ ++ uint32_t d32; ++ /** quadlet bits */ ++ struct { ++ /** Received number of bytes */ ++ unsigned bytes:16; ++ /** NAK bit - only for OUT EPs */ ++ unsigned nak:1; ++ unsigned reserved17_22:6; ++ /** 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; ++ ++/** ++ * The dwc_otg_dev_if structure contains information needed to manage ++ * the DWC_otg controller acting in device mode. It represents the ++ * programming view of the device-specific aspects of the controller. ++ */ ++typedef struct dwc_otg_dev_if { ++ /** Pointer to device Global registers. ++ * Device Global Registers starting at offset 800h ++ */ ++ dwc_otg_device_global_regs_t *dev_global_regs; ++#define DWC_DEV_GLOBAL_REG_OFFSET 0x800 ++ ++ /** ++ * Device Logical IN Endpoint-Specific Registers 900h-AFCh ++ */ ++ dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS]; ++#define DWC_DEV_IN_EP_REG_OFFSET 0x900 ++#define DWC_EP_REG_OFFSET 0x20 ++ ++ /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */ ++ dwc_otg_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS]; ++#define DWC_DEV_OUT_EP_REG_OFFSET 0xB00 ++ ++ /* Device configuration information */ ++ uint8_t speed; /**< Device Speed 0: Unknown, 1: LS, 2:FS, 3: HS */ ++ uint8_t num_in_eps; /**< Number # of Tx EP range: 0-15 exept ep0 */ ++ uint8_t num_out_eps; /**< Number # of Rx EP range: 0-15 exept ep 0*/ ++ ++ /** Size of periodic FIFOs (Bytes) */ ++ uint16_t perio_tx_fifo_size[MAX_PERIO_FIFOS]; ++ ++ /** Size of Tx FIFOs (Bytes) */ ++ uint16_t tx_fifo_size[MAX_TX_FIFOS]; ++ ++ /** Thresholding enable flags and length varaiables **/ ++ uint16_t rx_thr_en; ++ uint16_t iso_tx_thr_en; ++ uint16_t non_iso_tx_thr_en; ++ ++ uint16_t rx_thr_length; ++ uint16_t tx_thr_length; ++ ++ /** ++ * Pointers to the DMA Descriptors for EP0 Control ++ * transfers (virtual and physical) ++ */ ++ ++ /** 2 descriptors for SETUP packets */ ++ dwc_dma_t dma_setup_desc_addr[2]; ++ dwc_otg_dev_dma_desc_t *setup_desc_addr[2]; ++ ++ /** Pointer to Descriptor with latest SETUP packet */ ++ dwc_otg_dev_dma_desc_t *psetup; ++ ++ /** Index of current SETUP handler descriptor */ ++ uint32_t setup_desc_index; ++ ++ /** Descriptor for Data In or Status In phases */ ++ dwc_dma_t dma_in_desc_addr; ++ dwc_otg_dev_dma_desc_t *in_desc_addr; ++ ++ /** Descriptor for Data Out or Status Out phases */ ++ dwc_dma_t dma_out_desc_addr; ++ dwc_otg_dev_dma_desc_t *out_desc_addr; ++ ++ /** Setup Packet Detected - if set clear NAK when queueing */ ++ uint32_t spd; ++ /** Isoc ep pointer on which incomplete happens */ ++ void *isoc_ep; ++ ++} dwc_otg_dev_if_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. Offset: 400h */ ++ volatile uint32_t hcfg; ++ /** Host Frame Interval Register. Offset: 404h */ ++ volatile uint32_t hfir; ++ /** Host Frame Number / Frame Remaining Register. Offset: 408h */ ++ volatile uint32_t hfnum; ++ /** Reserved. Offset: 40Ch */ ++ uint32_t reserved40C; ++ /** Host Periodic Transmit FIFO/ Queue Status Register. Offset: 410h */ ++ volatile uint32_t hptxsts; ++ /** Host All Channels Interrupt Register. Offset: 414h */ ++ volatile uint32_t haint; ++ /** Host All Channels Interrupt Mask Register. Offset: 418h */ ++ volatile uint32_t haintmsk; ++ /** Host Frame List Base Address Register . Offset: 41Ch */ ++ 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 d32 member then set/clear the bits using ++ * the bit elements. Write the d32 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_6:4; ++ /** Enable 32-KHz Suspend Mode */ ++ unsigned ena32khzs:1; ++ /** Resume Validation Periiod */ ++ unsigned resvalid:8; ++ unsigned reserved16_22:7; ++ /** Enable Scatter/gather DMA in Host mode */ ++ unsigned descdma:1; ++ /** Frame List Entries */ ++ unsigned frlisten:2; ++ /** Enable Periodic Scheduling */ ++ unsigned perschedena:1; ++ unsigned reserved27_30:4; ++ unsigned modechtimen: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 hfirrldctrl:1; ++ unsigned reserved:15; ++ } 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 d32 member then set/clear the ++ * bits using the bit elements. Write the d32 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. 500h-5FCh ++ */ ++typedef struct dwc_otg_hc_regs { ++ /** Host Channel 0 Characteristic Register. Offset: 500h + (chan_num * 20h) + 00h */ ++ volatile uint32_t hcchar; ++ /** Host Channel 0 Split Control Register. Offset: 500h + (chan_num * 20h) + 04h */ ++ volatile uint32_t hcsplt; ++ /** Host Channel 0 Interrupt Register. Offset: 500h + (chan_num * 20h) + 08h */ ++ volatile uint32_t hcint; ++ /** Host Channel 0 Interrupt Mask Register. Offset: 500h + (chan_num * 20h) + 0Ch */ ++ volatile uint32_t hcintmsk; ++ /** Host Channel 0 Transfer Size Register. Offset: 500h + (chan_num * 20h) + 10h */ ++ volatile uint32_t hctsiz; ++ /** Host Channel 0 DMA Address Register. Offset: 500h + (chan_num * 20h) + 14h */ ++ volatile uint32_t hcdma; ++ volatile uint32_t reserved; ++ /** Host Channel 0 DMA Buffer Address Register. Offset: 500h + (chan_num * 20h) + 1Ch */ ++ 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 d32 member then set/clear the ++ * bits using the bit elements. Write the d32 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 d32 member then set/clear the ++ * bits using the bit elements. Write the d32 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 d32 member then set/clear the ++ * bits using the bit elements. Write the d32 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 d32 member then ++ * set/clear the bits using the bit 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 d32 member then set/clear the ++ * bits using the bit 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; ++ /** Reserved */ ++ unsigned reserved: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 resetaftsusp:1; ++ unsigned restoremode:1; ++ unsigned enbl_extnd_hiber:1; ++ unsigned extnd_hiber_pwrclmp:1; ++ unsigned extnd_hiber_switch:1; ++ unsigned ess_reg_restored:1; ++ unsigned prt_clk_sel:2; ++ unsigned port_power:1; ++ unsigned max_xcvrselect:2; ++ unsigned max_termsel:1; ++ unsigned mac_dev_addr:7; ++ unsigned p2hd_dev_enum_spd:2; ++ unsigned p2hd_prt_spd:2; ++ unsigned if_dev_mode:1; ++ } b; ++} pcgcctl_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Data FIFO Software ++ * Configuration Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union gdfifocfg_data { ++ /* raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** OTG Data FIFO depth */ ++ unsigned gdfifocfg:16; ++ /** Start address of EP info controller */ ++ unsigned epinfobase:16; ++ } b; ++} gdfifocfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Power Down Register ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union gpwrdn_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** PMU Interrupt Select */ ++ unsigned pmuintsel:1; ++ /** PMU Active */ ++ unsigned pmuactv:1; ++ /** Restore */ ++ unsigned restore:1; ++ /** Power Down Clamp */ ++ unsigned pwrdnclmp:1; ++ /** Power Down Reset */ ++ unsigned pwrdnrstn:1; ++ /** Power Down Switch */ ++ unsigned pwrdnswtch:1; ++ /** Disable VBUS */ ++ unsigned dis_vbus:1; ++ /** Line State Change */ ++ unsigned lnstschng:1; ++ /** Line state change mask */ ++ unsigned lnstchng_msk:1; ++ /** Reset Detected */ ++ unsigned rst_det:1; ++ /** Reset Detect mask */ ++ unsigned rst_det_msk:1; ++ /** Disconnect Detected */ ++ unsigned disconn_det:1; ++ /** Disconnect Detect mask */ ++ unsigned disconn_det_msk:1; ++ /** Connect Detected*/ ++ unsigned connect_det:1; ++ /** Connect Detected Mask*/ ++ unsigned connect_det_msk:1; ++ /** SRP Detected */ ++ unsigned srp_det:1; ++ /** SRP Detect mask */ ++ unsigned srp_det_msk:1; ++ /** Status Change Interrupt */ ++ unsigned sts_chngint:1; ++ /** Status Change Interrupt Mask */ ++ unsigned sts_chngint_msk:1; ++ /** Line State */ ++ unsigned linestate:2; ++ /** Indicates current mode(status of IDDIG signal) */ ++ unsigned idsts:1; ++ /** B Session Valid signal status*/ ++ unsigned bsessvld:1; ++ /** ADP Event Detected */ ++ unsigned adp_int:1; ++ /** Multi Valued ID pin */ ++ unsigned mult_val_id_bc:5; ++ /** Reserved 24_31 */ ++ unsigned reserved29_31:3; ++ } b; ++} gpwrdn_data_t; ++ ++#endif +diff --git a/drivers/usb/host/dwc_otg/test/Makefile b/drivers/usb/host/dwc_otg/test/Makefile +new file mode 100644 +index 0000000..fc45375 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/test/Makefile +@@ -0,0 +1,16 @@ ++ ++PERL=/usr/bin/perl ++PL_TESTS=test_sysfs.pl test_mod_param.pl ++ ++.PHONY : test ++test : perl_tests ++ ++perl_tests : ++ @echo ++ @echo Running perl tests ++ @for test in $(PL_TESTS); do \ ++ if $(PERL) ./$$test ; then \ ++ echo "=======> $$test, PASSED" ; \ ++ else echo "=======> $$test, FAILED" ; \ ++ fi \ ++ done +diff --git a/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm +new file mode 100644 +index 0000000..233b04a +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm +@@ -0,0 +1,337 @@ ++package dwc_otg_test; ++ ++use strict; ++use Exporter (); ++ ++use vars qw(@ISA @EXPORT ++$sysfsdir $paramdir $errors $params ++); ++ ++@ISA = qw(Exporter); ++ ++# ++# Globals ++# ++$sysfsdir = "/sys/devices/lm0"; ++$paramdir = "/sys/module/dwc_otg"; ++$errors = 0; ++ ++$params = [ ++ { ++ NAME => "otg_cap", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 2 ++ }, ++ { ++ NAME => "dma_enable", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "dma_burst_size", ++ DEFAULT => 32, ++ ENUM => [1, 4, 8, 16, 32, 64, 128, 256], ++ LOW => 1, ++ HIGH => 256 ++ }, ++ { ++ NAME => "host_speed", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "host_support_fs_ls_low_power", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "host_ls_low_power_phy_clk", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "dev_speed", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "enable_dynamic_fifo", ++ DEFAULT => 1, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ { ++ NAME => "data_fifo_size", ++ DEFAULT => 8192, ++ ENUM => [], ++ LOW => 32, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "dev_rx_fifo_size", ++ DEFAULT => 1064, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "dev_nperio_tx_fifo_size", ++ DEFAULT => 1024, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_1", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_2", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_3", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_4", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_5", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_6", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_7", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_8", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_9", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_10", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_11", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_12", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_13", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_14", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "dev_perio_tx_fifo_size_15", ++ DEFAULT => 256, ++ ENUM => [], ++ LOW => 4, ++ HIGH => 768 ++ }, ++ { ++ NAME => "host_rx_fifo_size", ++ DEFAULT => 1024, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "host_nperio_tx_fifo_size", ++ DEFAULT => 1024, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "host_perio_tx_fifo_size", ++ DEFAULT => 1024, ++ ENUM => [], ++ LOW => 16, ++ HIGH => 32768 ++ }, ++ { ++ NAME => "max_transfer_size", ++ DEFAULT => 65535, ++ ENUM => [], ++ LOW => 2047, ++ HIGH => 65535 ++ }, ++ { ++ NAME => "max_packet_count", ++ DEFAULT => 511, ++ ENUM => [], ++ LOW => 15, ++ HIGH => 511 ++ }, ++ { ++ NAME => "host_channels", ++ DEFAULT => 12, ++ ENUM => [], ++ LOW => 1, ++ HIGH => 16 ++ }, ++ { ++ NAME => "dev_endpoints", ++ DEFAULT => 6, ++ ENUM => [], ++ LOW => 1, ++ HIGH => 15 ++ }, ++ { ++ NAME => "phy_type", ++ DEFAULT => 1, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 2 ++ }, ++ { ++ NAME => "phy_utmi_width", ++ DEFAULT => 16, ++ ENUM => [8, 16], ++ LOW => 8, ++ HIGH => 16 ++ }, ++ { ++ NAME => "phy_ulpi_ddr", ++ DEFAULT => 0, ++ ENUM => [], ++ LOW => 0, ++ HIGH => 1 ++ }, ++ ]; ++ ++ ++# ++# ++sub check_arch { ++ $_ = `uname -m`; ++ chomp; ++ unless (m/armv4tl/) { ++ warn "# \n# Can't execute on $_. Run on integrator platform.\n# \n"; ++ return 0; ++ } ++ return 1; ++} ++ ++# ++# ++sub load_module { ++ my $params = shift; ++ print "\nRemoving Module\n"; ++ system "rmmod dwc_otg"; ++ print "Loading Module\n"; ++ if ($params ne "") { ++ print "Module Parameters: $params\n"; ++ } ++ if (system("modprobe dwc_otg $params")) { ++ warn "Unable to load module\n"; ++ return 0; ++ } ++ return 1; ++} ++ ++# ++# ++sub test_status { ++ my $arg = shift; ++ ++ print "\n"; ++ ++ if (defined $arg) { ++ warn "WARNING: $arg\n"; ++ } ++ ++ if ($errors > 0) { ++ warn "TEST FAILED with $errors errors\n"; ++ return 0; ++ } else { ++ print "TEST PASSED\n"; ++ return 0 if (defined $arg); ++ } ++ return 1; ++} ++ ++# ++# ++@EXPORT = qw( ++$sysfsdir ++$paramdir ++$params ++$errors ++check_arch ++load_module ++test_status ++); ++ ++1; +diff --git a/drivers/usb/host/dwc_otg/test/test_mod_param.pl b/drivers/usb/host/dwc_otg/test/test_mod_param.pl +new file mode 100644 +index 0000000..e887dce +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl +@@ -0,0 +1,133 @@ ++#!/usr/bin/perl -w ++# ++# Run this program on the integrator. ++# ++# - Tests module parameter default values. ++# - Tests setting of valid module parameter values via modprobe. ++# - Tests invalid module parameter values. ++# ----------------------------------------------------------------------------- ++use strict; ++use dwc_otg_test; ++ ++check_arch() or die; ++ ++# ++# ++sub test { ++ my ($param,$expected) = @_; ++ my $value = get($param); ++ ++ if ($value == $expected) { ++ print "$param = $value, okay\n"; ++ } ++ ++ else { ++ warn "ERROR: value of $param != $expected, $value\n"; ++ $errors ++; ++ } ++} ++ ++# ++# ++sub get { ++ my $param = shift; ++ my $tmp = `cat $paramdir/$param`; ++ chomp $tmp; ++ return $tmp; ++} ++ ++# ++# ++sub test_main { ++ ++ print "\nTesting Module Parameters\n"; ++ ++ load_module("") or die; ++ ++ # Test initial values ++ print "\nTesting Default Values\n"; ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{DEFAULT}); ++ } ++ ++ # Test low value ++ print "\nTesting Low Value\n"; ++ my $cmd_params = ""; ++ foreach (@{$params}) { ++ $cmd_params = $cmd_params . "$_->{NAME}=$_->{LOW} "; ++ } ++ load_module($cmd_params) or die; ++ ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{LOW}); ++ } ++ ++ # Test high value ++ print "\nTesting High Value\n"; ++ $cmd_params = ""; ++ foreach (@{$params}) { ++ $cmd_params = $cmd_params . "$_->{NAME}=$_->{HIGH} "; ++ } ++ load_module($cmd_params) or die; ++ ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{HIGH}); ++ } ++ ++ # Test Enum ++ print "\nTesting Enumerated\n"; ++ foreach (@{$params}) { ++ if (defined $_->{ENUM}) { ++ my $value; ++ foreach $value (@{$_->{ENUM}}) { ++ $cmd_params = "$_->{NAME}=$value"; ++ load_module($cmd_params) or die; ++ test ($_->{NAME}, $value); ++ } ++ } ++ } ++ ++ # Test Invalid Values ++ print "\nTesting Invalid Values\n"; ++ $cmd_params = ""; ++ foreach (@{$params}) { ++ $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{LOW}-1; ++ } ++ load_module($cmd_params) or die; ++ ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{DEFAULT}); ++ } ++ ++ $cmd_params = ""; ++ foreach (@{$params}) { ++ $cmd_params = $cmd_params . sprintf "$_->{NAME}=%d ", $_->{HIGH}+1; ++ } ++ load_module($cmd_params) or die; ++ ++ foreach (@{$params}) { ++ test ($_->{NAME}, $_->{DEFAULT}); ++ } ++ ++ print "\nTesting Enumerated\n"; ++ foreach (@{$params}) { ++ if (defined $_->{ENUM}) { ++ my $value; ++ foreach $value (@{$_->{ENUM}}) { ++ $value = $value + 1; ++ $cmd_params = "$_->{NAME}=$value"; ++ load_module($cmd_params) or die; ++ test ($_->{NAME}, $_->{DEFAULT}); ++ $value = $value - 2; ++ $cmd_params = "$_->{NAME}=$value"; ++ load_module($cmd_params) or die; ++ test ($_->{NAME}, $_->{DEFAULT}); ++ } ++ } ++ } ++ ++ test_status() or die; ++} ++ ++test_main(); ++0; +diff --git a/drivers/usb/host/dwc_otg/test/test_sysfs.pl b/drivers/usb/host/dwc_otg/test/test_sysfs.pl +new file mode 100644 +index 0000000..abcf284 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl +@@ -0,0 +1,193 @@ ++#!/usr/bin/perl -w ++# ++# Run this program on the integrator ++# - Tests select sysfs attributes. ++# - Todo ... test more attributes, hnp/srp, buspower/bussuspend, etc. ++# ----------------------------------------------------------------------------- ++use strict; ++use dwc_otg_test; ++ ++check_arch() or die; ++ ++# ++# ++sub test { ++ my ($attr,$expected) = @_; ++ my $string = get($attr); ++ ++ if ($string eq $expected) { ++ printf("$attr = $string, okay\n"); ++ } ++ else { ++ warn "ERROR: value of $attr != $expected, $string\n"; ++ $errors ++; ++ } ++} ++ ++# ++# ++sub set { ++ my ($reg, $value) = @_; ++ system "echo $value > $sysfsdir/$reg"; ++} ++ ++# ++# ++sub get { ++ my $attr = shift; ++ my $string = `cat $sysfsdir/$attr`; ++ chomp $string; ++ if ($string =~ m/\s\=\s/) { ++ my $tmp; ++ ($tmp, $string) = split /\s=\s/, $string; ++ } ++ return $string; ++} ++ ++# ++# ++sub test_main { ++ print("\nTesting Sysfs Attributes\n"); ++ ++ load_module("") or die; ++ ++ # Test initial values of regoffset/regvalue/guid/gsnpsid ++ print("\nTesting Default Values\n"); ++ ++ test("regoffset", "0xffffffff"); ++ test("regvalue", "invalid offset"); ++ test("guid", "0x12345678"); # this will fail if it has been changed ++ test("gsnpsid", "0x4f54200a"); ++ ++ # Test operation of regoffset/regvalue ++ print("\nTesting regoffset\n"); ++ set('regoffset', '5a5a5a5a'); ++ test("regoffset", "0xffffffff"); ++ ++ set('regoffset', '0'); ++ test("regoffset", "0x00000000"); ++ ++ set('regoffset', '40000'); ++ test("regoffset", "0x00000000"); ++ ++ set('regoffset', '3ffff'); ++ test("regoffset", "0x0003ffff"); ++ ++ set('regoffset', '1'); ++ test("regoffset", "0x00000001"); ++ ++ print("\nTesting regvalue\n"); ++ set('regoffset', '3c'); ++ test("regvalue", "0x12345678"); ++ set('regvalue', '5a5a5a5a'); ++ test("regvalue", "0x5a5a5a5a"); ++ set('regvalue','a5a5a5a5'); ++ test("regvalue", "0xa5a5a5a5"); ++ set('guid','12345678'); ++ ++ # Test HNP Capable ++ print("\nTesting HNP Capable bit\n"); ++ set('hnpcapable', '1'); ++ test("hnpcapable", "0x1"); ++ set('hnpcapable','0'); ++ test("hnpcapable", "0x0"); ++ ++ set('regoffset','0c'); ++ ++ my $old = get('gusbcfg'); ++ print("setting hnpcapable\n"); ++ set('hnpcapable', '1'); ++ test("hnpcapable", "0x1"); ++ test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<9))); ++ test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<9))); ++ ++ $old = get('gusbcfg'); ++ print("clearing hnpcapable\n"); ++ set('hnpcapable', '0'); ++ test("hnpcapable", "0x0"); ++ test ('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<9))); ++ test ('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<9))); ++ ++ # Test SRP Capable ++ print("\nTesting SRP Capable bit\n"); ++ set('srpcapable', '1'); ++ test("srpcapable", "0x1"); ++ set('srpcapable','0'); ++ test("srpcapable", "0x0"); ++ ++ set('regoffset','0c'); ++ ++ $old = get('gusbcfg'); ++ print("setting srpcapable\n"); ++ set('srpcapable', '1'); ++ test("srpcapable", "0x1"); ++ test('gusbcfg', sprintf "0x%08x", (oct ($old) | (1<<8))); ++ test('regvalue', sprintf "0x%08x", (oct ($old) | (1<<8))); ++ ++ $old = get('gusbcfg'); ++ print("clearing srpcapable\n"); ++ set('srpcapable', '0'); ++ test("srpcapable", "0x0"); ++ test('gusbcfg', sprintf "0x%08x", oct ($old) & (~(1<<8))); ++ test('regvalue', sprintf "0x%08x", oct ($old) & (~(1<<8))); ++ ++ # Test GGPIO ++ print("\nTesting GGPIO\n"); ++ set('ggpio','5a5a5a5a'); ++ test('ggpio','0x5a5a0000'); ++ set('ggpio','a5a5a5a5'); ++ test('ggpio','0xa5a50000'); ++ set('ggpio','11110000'); ++ test('ggpio','0x11110000'); ++ set('ggpio','00001111'); ++ test('ggpio','0x00000000'); ++ ++ # Test DEVSPEED ++ print("\nTesting DEVSPEED\n"); ++ set('regoffset','800'); ++ $old = get('regvalue'); ++ set('devspeed','0'); ++ test('devspeed','0x0'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3))); ++ set('devspeed','1'); ++ test('devspeed','0x1'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1)); ++ set('devspeed','2'); ++ test('devspeed','0x2'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 2)); ++ set('devspeed','3'); ++ test('devspeed','0x3'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 3)); ++ set('devspeed','4'); ++ test('devspeed','0x0'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3))); ++ set('devspeed','5'); ++ test('devspeed','0x1'); ++ test('regvalue',sprintf("0x%08x", oct($old) & ~(0x3) | 1)); ++ ++ ++ # mode Returns the current mode:0 for device mode1 for host mode Read ++ # hnp Initiate the Host Negotiation Protocol. Read returns the status. Read/Write ++ # srp Initiate the Session Request Protocol. Read returns the status. Read/Write ++ # buspower Get or Set the Power State of the bus (0 - Off or 1 - On) Read/Write ++ # bussuspend Suspend the USB bus. Read/Write ++ # busconnected Get the connection status of the bus Read ++ ++ # gotgctl Get or set the Core Control Status Register. Read/Write ++ ## gusbcfg Get or set the Core USB Configuration Register Read/Write ++ # grxfsiz Get or set the Receive FIFO Size Register Read/Write ++ # gnptxfsiz Get or set the non-periodic Transmit Size Register Read/Write ++ # gpvndctl Get or set the PHY Vendor Control Register Read/Write ++ ## ggpio Get the value in the lower 16-bits of the General Purpose IO Register or Set the upper 16 bits. Read/Write ++ ## guid Get or set the value of the User ID Register Read/Write ++ ## gsnpsid Get the value of the Synopsys ID Regester Read ++ ## devspeed Get or set the device speed setting in the DCFG register Read/Write ++ # enumspeed Gets the device enumeration Speed. Read ++ # hptxfsiz Get the value of the Host Periodic Transmit FIFO Read ++ # hprt0 Get or Set the value in the Host Port Control and Status Register Read/Write ++ ++ test_status("TEST NYI") or die; ++} ++ ++test_main(); ++0; +-- +1.8.1.6 + + +From 08a588f1e93ac1f3ca0eaa232928b0a3a67a6544 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:54:32 +0100 -Subject: [PATCH 003/102] bcm2708 watchdog driver +Subject: [PATCH 03/88] bcm2708 watchdog driver Signed-off-by: popcornmix --- @@ -53872,10 +65778,10 @@ index 0000000..dd33c35 1.8.1.6 -From 9daa48b3d2224886117d4b692ab7387fee2b4772 Mon Sep 17 00:00:00 2001 +From 9aa24fa38df74e7bb63e7c5f1e6f0cd7930926f4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:55:09 +0100 -Subject: [PATCH 004/102] bcm2708 framebuffer driver +Subject: [PATCH 04/88] bcm2708 framebuffer driver Signed-off-by: popcornmix --- @@ -53887,10 +65793,10 @@ Signed-off-by: popcornmix create mode 100644 drivers/video/bcm2708_fb.c diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig -index 4c1546f..044b867 100644 +index 2e937bd..9f4c58f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig -@@ -334,6 +334,20 @@ config FB_PM2_FIFO_DISCONNECT +@@ -310,6 +310,20 @@ config FB_PM2_FIFO_DISCONNECT help Support the Permedia2 FIFO disconnect feature. @@ -53912,7 +65818,7 @@ index 4c1546f..044b867 100644 tristate "ARM PrimeCell PL110 support" depends on FB && ARM && ARM_AMBA diff --git a/drivers/video/Makefile b/drivers/video/Makefile -index 9df3873..7fcb865 100644 +index e8bae8d..032f386 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -100,6 +100,7 @@ obj-$(CONFIG_FB_PVR2) += pvr2fb.o @@ -56910,15 +68816,15 @@ index 3c14e43..7626beb 100644 1.8.1.6 -From 9e81bcaf1ed9016ae8277c78d7605ab4a0644897 Mon Sep 17 00:00:00 2001 +From 0a4f13f76c049e4819d9f80cf754e0681c299c06 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Wed, 27 Mar 2013 23:10:07 +0000 -Subject: [PATCH 005/102] bcm2708 vchiq driver +Date: Tue, 2 Jul 2013 23:42:01 +0100 +Subject: [PATCH 05/88] bcm2708 vchiq driver Signed-off-by: popcornmix --- drivers/misc/Kconfig | 2 + - drivers/misc/Makefile | 2 + + drivers/misc/Makefile | 1 + drivers/misc/vc04_services/Kconfig | 10 + drivers/misc/vc04_services/Makefile | 18 + .../interface/vchi/connections/connection.h | 328 ++ @@ -56931,7 +68837,7 @@ Signed-off-by: popcornmix .../misc/vc04_services/interface/vchiq_arm/vchiq.h | 41 + .../vc04_services/interface/vchiq_arm/vchiq_2835.h | 42 + .../interface/vchiq_arm/vchiq_2835_arm.c | 538 +++ - .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2802 ++++++++++++++ + .../vc04_services/interface/vchiq_arm/vchiq_arm.c | 2806 ++++++++++++++ .../vc04_services/interface/vchiq_arm/vchiq_arm.h | 212 ++ .../interface/vchiq_arm/vchiq_build_info.h | 37 + .../vc04_services/interface/vchiq_arm/vchiq_cfg.h | 60 + @@ -56945,12 +68851,12 @@ Signed-off-by: popcornmix .../interface/vchiq_arm/vchiq_kern_lib.c | 454 +++ .../interface/vchiq_arm/vchiq_memdrv.h | 71 + .../interface/vchiq_arm/vchiq_pagelist.h | 58 + - .../vc04_services/interface/vchiq_arm/vchiq_proc.c | 240 ++ + .../vc04_services/interface/vchiq_arm/vchiq_proc.c | 243 ++ .../vc04_services/interface/vchiq_arm/vchiq_shim.c | 815 +++++ .../vc04_services/interface/vchiq_arm/vchiq_util.c | 120 + .../vc04_services/interface/vchiq_arm/vchiq_util.h | 82 + .../interface/vchiq_arm/vchiq_version.c | 59 + - 33 files changed, 12165 insertions(+) + 33 files changed, 12171 insertions(+) create mode 100644 drivers/misc/vc04_services/Kconfig create mode 100644 drivers/misc/vc04_services/Makefile create mode 100644 drivers/misc/vc04_services/interface/vchi/connections/connection.h @@ -56984,10 +68890,10 @@ Signed-off-by: popcornmix create mode 100644 drivers/misc/vc04_services/interface/vchiq_arm/vchiq_version.c diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig -index e83fdfe..f66f044 100644 +index c002d86..84d3100 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig -@@ -519,4 +519,6 @@ source "drivers/misc/carma/Kconfig" +@@ -536,4 +536,6 @@ source "drivers/misc/carma/Kconfig" source "drivers/misc/altera-stapl/Kconfig" source "drivers/misc/mei/Kconfig" source "drivers/misc/vmw_vmci/Kconfig" @@ -56995,15 +68901,14 @@ index e83fdfe..f66f044 100644 endmenu + diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index 35a1463..720ba76 100644 +index c235d5b..d72aaf2 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile -@@ -52,3 +52,5 @@ obj-$(CONFIG_INTEL_MEI) += mei/ - obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o +@@ -53,3 +53,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o + obj-$(CONFIG_SRAM) += sram.o +obj-y += vc04_services/ -+ diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig new file mode 100644 index 0000000..b48a3f3 @@ -59132,10 +71037,10 @@ index 0000000..2b5fa56 +} diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c new file mode 100644 -index 0000000..7298d85 +index 0000000..c7929e9 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c -@@ -0,0 +1,2802 @@ +@@ -0,0 +1,2806 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * @@ -61893,7 +73798,7 @@ index 0000000..7298d85 + top = proc_mkdir(pidstr, clients); + if (!top) + goto fail_top; -+ ++#if 0 + use_count = create_proc_read_entry("use_count", + 0444, top, + proc_read_use_count, @@ -61902,20 +73807,24 @@ index 0000000..7298d85 + goto fail_use_count; + + instance->proc_entry = top; -+ ++#endif + return 0; + +fail_use_count: ++#if 0 + remove_proc_entry(top->name, clients); ++#endif +fail_top: + return -ENOMEM; +} + +static void vchiq_proc_remove_instance(VCHIQ_INSTANCE_T instance) +{ ++#if 0 + struct proc_dir_entry *clients = vchiq_clients_top(); + remove_proc_entry("use_count", instance->proc_entry); + remove_proc_entry(instance->proc_entry->name, clients); ++#endif +} + +/**************************************************************************** @@ -68007,10 +79916,10 @@ index 0000000..54a3ece +#endif /* VCHIQ_PAGELIST_H */ diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c new file mode 100644 -index 0000000..1cda5a6 +index 0000000..bcee3e2 --- /dev/null +++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_proc.c -@@ -0,0 +1,240 @@ +@@ -0,0 +1,243 @@ +/** + * Copyright (c) 2010-2012 Broadcom. All rights reserved. + * @@ -68172,7 +80081,7 @@ index 0000000..1cda5a6 + struct proc_dir_entry *dir; + size_t i; + int ret = 0; -+ ++#if 0 + dir = proc_mkdir("log", proc_info.vc_cfg_dir); + if (!dir) + return -ENOMEM; @@ -68193,6 +80102,7 @@ index 0000000..1cda5a6 + + vchiq_proc_log_entries[i].dir = dir; + } ++#endif + return ret; +} + @@ -68228,6 +80138,7 @@ index 0000000..1cda5a6 +void vchiq_proc_deinit(void) +{ + /* log category entries */ ++#if 0 + if (proc_info.log_categories) { + size_t i; + for (i = 0; i < n_log_entries; i++) @@ -68244,6 +80155,7 @@ index 0000000..1cda5a6 + proc_info.vc_cfg_dir); + if (proc_info.vc_cfg_dir) + remove_proc_entry(proc_info.vc_cfg_dir->name, NULL); ++#endif +} + +struct proc_dir_entry *vchiq_clients_top(void) @@ -69355,10 +81267,10 @@ index 0000000..b6bfa21 1.8.1.6 -From a787744e338f7e109a1bae4eb784cf997d96457d Mon Sep 17 00:00:00 2001 +From a2d8faeec6f4dfa0f81df73ecf86d58f2d25bf8f Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Thu, 28 Mar 2013 00:10:21 +0000 -Subject: [PATCH 006/102] cma: Add vc_cma driver to enable use of CMA +Date: Wed, 3 Jul 2013 00:31:47 +0100 +Subject: [PATCH 06/88] cma: Add vc_cma driver to enable use of CMA Signed-off-by: popcornmix --- @@ -70605,16 +82517,15 @@ index 0000000..6d8b4df +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile -index 720ba76..d0567ef 100644 +index d72aaf2..24b40c3 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile -@@ -52,5 +52,5 @@ obj-$(CONFIG_INTEL_MEI) += mei/ - obj-$(CONFIG_MAX8997_MUIC) += max8997-muic.o +@@ -53,4 +53,4 @@ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lattice-ecp3-config.o + obj-$(CONFIG_SRAM) += sram.o -obj-y += vc04_services/ +obj-$(CONFIG_BCM2708_VCHIQ) += vc04_services/ - diff --git a/include/linux/broadcom/vc_cma.h b/include/linux/broadcom/vc_cma.h new file mode 100644 index 0000000..bdc9d79 @@ -70655,107 +82566,10 @@ index 0000000..bdc9d79 1.8.1.6 -From 515cec19ef56b649ed0acd06f0d2f9939a7011f9 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 007/102] Allow mac address to be set in smsc95xx - -Signed-off-by: popcornmix ---- - drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 56 insertions(+) - -diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c -index e6d2dea..9709314 100644 ---- a/drivers/net/usb/smsc95xx.c -+++ b/drivers/net/usb/smsc95xx.c -@@ -61,6 +61,7 @@ - #define SUSPEND_SUSPEND3 (0x08) - #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ - SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) -+#define MAC_ADDR_LEN (6) - - struct smsc95xx_priv { - u32 mac_cr; -@@ -76,6 +77,10 @@ struct smsc95xx_priv { - module_param(turbo_mode, bool, 0644); - MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); - -+static char *macaddr = ":"; -+module_param(macaddr, charp, 0); -+MODULE_PARM_DESC(macaddr, "MAC address"); -+ - static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, - u32 *data, int in_pm) - { -@@ -765,8 +770,59 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) - return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); - } - -+/* Check the macaddr module parameter for a MAC address */ -+static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac) -+{ -+ int i, j, got_num, num; -+ u8 mtbl[MAC_ADDR_LEN]; -+ -+ if (macaddr[0] == ':') -+ return 0; -+ -+ i = 0; -+ j = 0; -+ num = 0; -+ got_num = 0; -+ while (j < MAC_ADDR_LEN) { -+ if (macaddr[i] && macaddr[i] != ':') { -+ got_num++; -+ if ('0' <= macaddr[i] && macaddr[i] <= '9') -+ num = num * 16 + macaddr[i] - '0'; -+ else if ('A' <= macaddr[i] && macaddr[i] <= 'F') -+ num = num * 16 + 10 + macaddr[i] - 'A'; -+ else if ('a' <= macaddr[i] && macaddr[i] <= 'f') -+ num = num * 16 + 10 + macaddr[i] - 'a'; -+ else -+ break; -+ i++; -+ } else if (got_num == 2) { -+ mtbl[j++] = (u8) num; -+ num = 0; -+ got_num = 0; -+ i++; -+ } else { -+ break; -+ } -+ } -+ -+ if (j == MAC_ADDR_LEN) { -+ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: " -+ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2], -+ mtbl[3], mtbl[4], mtbl[5]); -+ for (i = 0; i < MAC_ADDR_LEN; i++) -+ dev_mac[i] = mtbl[i]; -+ return 1; -+ } else { -+ return 0; -+ } -+} -+ - static void smsc95xx_init_mac_address(struct usbnet *dev) - { -+ /* Check module parameters */ -+ if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr)) -+ return; -+ - /* try reading mac address from EEPROM */ - if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, - dev->net->dev_addr) == 0) { --- -1.8.1.6 - - -From 4f0eb4acebe6901a346935f58307d0d598be809f Mon Sep 17 00:00:00 2001 +From 9171ef805ac273e7eabf444b3338ed3a42d7070d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 008/102] bcm2708: alsa sound driver +Subject: [PATCH 07/88] bcm2708: alsa sound driver Signed-off-by: popcornmix --- @@ -73078,116 +84892,107 @@ index 0000000..af3e6eb 1.8.1.6 -From 92027c537ab1c45fc2ff9db94325128f80b9f848 Mon Sep 17 00:00:00 2001 +From debf621c3999ce1d7ff13cbcc8de7beaa85aa14d Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Fri, 27 Apr 2012 00:30:15 +0100 -Subject: [PATCH 009/102] Fix (hopefully) for DWC_MEMCPY kernel panics. Thanks - to Naren Sankar for finding this +Date: Tue, 26 Mar 2013 17:26:38 +0000 +Subject: [PATCH 08/88] Allow mac address to be set in smsc95xx +Signed-off-by: popcornmix --- - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 4 ++++ - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 3 +++ - 2 files changed, 7 insertions(+) + drivers/net/usb/smsc95xx.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -index 223d879..f07bb72 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -909,6 +909,10 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - return 0; - #endif +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index 3f38ba8..60076fe 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c +@@ -61,6 +61,7 @@ + #define SUSPEND_SUSPEND3 (0x08) + #define SUSPEND_ALLMODES (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \ + SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3) ++#define MAC_ADDR_LEN (6) -+ if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) -+ urb->actual_length = urb->length; + struct smsc95xx_priv { + u32 mac_cr; +@@ -76,6 +77,10 @@ struct smsc95xx_priv { + module_param(turbo_mode, bool, 0644); + MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); + ++static char *macaddr = ":"; ++module_param(macaddr, charp, 0); ++MODULE_PARM_DESC(macaddr, "MAC address"); + -+ - hc = DWC_CIRCLEQ_FIRST(&hcd->free_hc_list); - - /* Remove the host channel from the free list. */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index a5f8546..5261d2a 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -668,6 +668,9 @@ static int urb_enqueue(struct usb_hcd *hcd, - urb->number_of_packets, - mem_flags == GFP_ATOMIC ? 1 : 0); - -+ if(dwc_otg_urb == NULL) -+ return -ENOMEM; -+ - urb->hcpriv = dwc_otg_urb; - - dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe), --- -1.8.1.6 - - -From f0672dacf8cbda6a49568244926f39a23e3efd51 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 26 Mar 2013 17:36:22 +0000 -Subject: [PATCH 010/102] added support for TT in the USB driver. Thanks Naren - ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 5261d2a..e7b90c8 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -417,6 +417,9 @@ int hcd_init( - - hcd->regs = otg_dev->base; - -+ /* Integrate TT in root hub */ -+ hcd->has_tt = 1; -+ - /* Initialize the DWC OTG HCD. */ - dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); - if (!dwc_otg_hcd) { --- -1.8.1.6 - - -From 0438ec7c48a6b34e274e49bcdae026edfdd0d79c Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 8 May 2012 23:09:44 +0100 -Subject: [PATCH 011/102] Use dwc_alloc_atomic. Thanks bootc - ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -index 9459c4c..f6e7870 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -628,7 +628,7 @@ static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd, - * @return Returns the memory allocate or NULL on error. */ - static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(void) + static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, + u32 *data, int in_pm) { -- return (dwc_otg_qh_t *) dwc_alloc(sizeof(dwc_otg_qh_t)); -+ return (dwc_otg_qh_t *) dwc_alloc_atomic(sizeof(dwc_otg_qh_t)); +@@ -765,8 +770,59 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) + return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } - extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb); -@@ -640,7 +640,7 @@ extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd, - * @return Returns the memory allocate or NULL on error. */ - static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void) ++/* Check the macaddr module parameter for a MAC address */ ++static int smsc95xx_is_macaddr_param(struct usbnet *dev, u8 *dev_mac) ++{ ++ int i, j, got_num, num; ++ u8 mtbl[MAC_ADDR_LEN]; ++ ++ if (macaddr[0] == ':') ++ return 0; ++ ++ i = 0; ++ j = 0; ++ num = 0; ++ got_num = 0; ++ while (j < MAC_ADDR_LEN) { ++ if (macaddr[i] && macaddr[i] != ':') { ++ got_num++; ++ if ('0' <= macaddr[i] && macaddr[i] <= '9') ++ num = num * 16 + macaddr[i] - '0'; ++ else if ('A' <= macaddr[i] && macaddr[i] <= 'F') ++ num = num * 16 + 10 + macaddr[i] - 'A'; ++ else if ('a' <= macaddr[i] && macaddr[i] <= 'f') ++ num = num * 16 + 10 + macaddr[i] - 'a'; ++ else ++ break; ++ i++; ++ } else if (got_num == 2) { ++ mtbl[j++] = (u8) num; ++ num = 0; ++ got_num = 0; ++ i++; ++ } else { ++ break; ++ } ++ } ++ ++ if (j == MAC_ADDR_LEN) { ++ netif_dbg(dev, ifup, dev->net, "Overriding MAC address with: " ++ "%02x:%02x:%02x:%02x:%02x:%02x\n", mtbl[0], mtbl[1], mtbl[2], ++ mtbl[3], mtbl[4], mtbl[5]); ++ for (i = 0; i < MAC_ADDR_LEN; i++) ++ dev_mac[i] = mtbl[i]; ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ + static void smsc95xx_init_mac_address(struct usbnet *dev) { -- return (dwc_otg_qtd_t *) dwc_alloc(sizeof(dwc_otg_qtd_t)); -+ return (dwc_otg_qtd_t *) dwc_alloc_atomic(sizeof(dwc_otg_qtd_t)); - } - - /** Frees the memory for a QTD structure. QTD should already be removed from ++ /* Check module parameters */ ++ if (smsc95xx_is_macaddr_param(dev, dev->net->dev_addr)) ++ return; ++ + /* try reading mac address from EEPROM */ + if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, + dev->net->dev_addr) == 0) { -- 1.8.1.6 -From faeaa99f0396f7668a69d089231520160af30fd6 Mon Sep 17 00:00:00 2001 +From b4a73b853b9734a668aaacdb4b5935bcc883695b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 8 May 2012 23:12:13 +0100 -Subject: [PATCH 012/102] possible fix for sdcard missing status. Thank naren +Subject: [PATCH 09/88] possible fix for sdcard missing status. Thank naren --- drivers/mmc/host/sdhci-bcm2708.c | 9 +++++++++ @@ -73224,44 +85029,10 @@ index e79723d..a405114 100644 1.8.1.6 -From 202cf599e12400ddd32a135a12cd4323b445e457 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 15 May 2012 15:24:40 +0100 -Subject: [PATCH 013/102] Fix for DWC OTG HCD URB Dequeue has NULL URB panic. - Thanks Naren - ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index e7b90c8..2a3b689 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -761,10 +761,12 @@ static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) - dump_urb_info(urb, "urb_dequeue"); - } - #endif -- dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv); -+ if(urb->hcpriv != NULL) { -+ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv); - -- dwc_free(urb->hcpriv); -- urb->hcpriv = NULL; -+ urb->hcpriv = NULL; -+ dwc_free(urb->hcpriv); -+ } - - /* Higher layer software sets URB status. */ - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --- -1.8.1.6 - - -From 48a9242f91eb12c2b0ec299ba02b38b42bb8ad74 Mon Sep 17 00:00:00 2001 +From 93779f0e37d786e6360ea7b388ddbc76c3cf4daf Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 17 May 2012 14:44:19 +0100 -Subject: [PATCH 014/102] sdcard patch improvements from naren +Subject: [PATCH 10/88] sdcard patch improvements from naren --- drivers/mmc/host/sdhci-bcm2708.c | 23 +++++++---------------- @@ -73320,10 +85091,10 @@ index a405114..ae8edf7 100644 1.8.1.6 -From 30ef0d309e9857bdd32491cec9ba259a784456c5 Mon Sep 17 00:00:00 2001 +From c79be143c5db0159c96c8301b1ae4ce50bebeeb1 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 4 Jun 2012 04:27:48 +0200 -Subject: [PATCH 015/102] sdhci-bcm2708: speed up DMA sync +Subject: [PATCH 11/88] sdhci-bcm2708: speed up DMA sync Experiments show that it doesn't really take that long to sync, so we can reduce the poll interval slightly. Might improve performance a bit. @@ -73348,10 +85119,10 @@ index ae8edf7..a6bdc25 100644 1.8.1.6 -From b24cb9d394c67ce8a11c75570320e6e5301e2284 Mon Sep 17 00:00:00 2001 +From 7e3d10edf2cb0657e032863034b280697eb92d32 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:52:04 +0200 -Subject: [PATCH 016/102] sdhci-bcm2708: remove custom clock handling +Subject: [PATCH 12/88] sdhci-bcm2708: remove custom clock handling The custom clock handling code is redundant and buggy. The MMC/SDHCI subsystem does a better job than it, so remove it for good. @@ -73449,10 +85220,10 @@ index a6bdc25..0ed4d85 100644 1.8.1.6 -From 22d34115fdcdc516663d137c08b52ed339e4c452 Mon Sep 17 00:00:00 2001 +From 864e235c6c115a57215cfa40107b180a3d61e3a0 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:53:59 +0200 -Subject: [PATCH 017/102] sdhci-bcm2708: add additional quirks +Subject: [PATCH 13/88] sdhci-bcm2708: add additional quirks Some additional quirks are needed for correct operation. There's no SDHCI capabilities register documented, and it always reads @@ -73482,10 +85253,10 @@ index 0ed4d85..3001836 100644 1.8.1.6 -From 9d0529470e379160e517c24babc50488391f3f5e Mon Sep 17 00:00:00 2001 +From f012cd2c3be22b5ac4b6bd2e7fed17b5a47a376c Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:57:13 +0200 -Subject: [PATCH 018/102] sdhci-bcm2708: add allow_highspeed parameter +Subject: [PATCH 14/88] sdhci-bcm2708: add allow_highspeed parameter Add a parameter to disable high-speed mode for the few cards that still might have problems. High-speed mode is enabled by default. @@ -73533,10 +85304,10 @@ index 3001836..c64de21 100644 1.8.1.6 -From 8167bc0b11ed234c29c0c34780306d93554a70fa Mon Sep 17 00:00:00 2001 +From de4d917a430e9b1c6ee890eb02e707bdbb5551b7 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:58:40 +0200 -Subject: [PATCH 019/102] sdhci-bcm2708: assume 50 MHz eMMC clock +Subject: [PATCH 15/88] sdhci-bcm2708: assume 50 MHz eMMC clock 80 MHz clock isnt't suited well to be dividable to get SD clocks of 25 MHz (default mode) or 50 MHz (high speed mode). 50 MHz are perfect to @@ -73562,10 +85333,10 @@ index c64de21..d174938 100644 1.8.1.6 -From 5288822e3285c737fa871fbdc457615b49ac332f Mon Sep 17 00:00:00 2001 +From ca9519b849238cc00d7fdc045683476152cd680d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 16 Jun 2012 22:31:55 +0100 -Subject: [PATCH 020/102] Allow emmc clock to be specified as command line +Subject: [PATCH 16/88] Allow emmc clock to be specified as command line parameter --- @@ -73612,10 +85383,10 @@ index d174938..0ee983c 100644 1.8.1.6 -From da5034cbfc3f38828fdf3891a34130dccac74e67 Mon Sep 17 00:00:00 2001 +From 68681c00fe7e60b3d3205d24531b2a10d8596ea7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 16 Jun 2012 22:35:38 +0100 -Subject: [PATCH 021/102] sdhci-bcm2708: raise DMA sync timeout +Subject: [PATCH 17/88] sdhci-bcm2708: raise DMA sync timeout Commit d64b84c by accident reduced the maximum overall DMA sync timeout. The maximum overall timeout was reduced from 100ms to 30ms, @@ -73645,65 +85416,10 @@ index 0ee983c..b0cdd7d 100644 1.8.1.6 -From 5fbbabb6b4f61c6dd55566923a157a8d5270dd34 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 17 Jun 2012 00:14:54 +0100 -Subject: [PATCH 022/102] Explicitly set usb host channels to 8, as in the spec - ---- - drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -index 4a78b03..25aae5e 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -@@ -267,7 +267,8 @@ extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t * core_if, - 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 -+//#define dwc_param_host_channels_default 12 -+#define dwc_param_host_channels_default 8// Broadcom BCM2708 - - /** The number of endpoints in addition to EP0 available for device - * mode operations. --- -1.8.1.6 - - -From 7c036ab45bac4c4287a5520355f395da2af6987d Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 22 Jun 2012 12:55:39 +0100 -Subject: [PATCH 023/102] Fix unintended line swap that cause cause memory leak - in USB driver - ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 2a3b689..970b065 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -764,8 +764,8 @@ static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) - if(urb->hcpriv != NULL) { - dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv); - -- urb->hcpriv = NULL; - dwc_free(urb->hcpriv); -+ urb->hcpriv = NULL; - } - - /* Higher layer software sets URB status. */ --- -1.8.1.6 - - -From b3601db57b17c85bf02952030e4432304ada9382 Mon Sep 17 00:00:00 2001 +From db66a7b0ff1eb7b63ba25003405f7e67d59d497e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 22 Jun 2012 12:57:42 +0100 -Subject: [PATCH 024/102] Use ndelay rather than udelay. Thanks lb +Subject: [PATCH 18/88] Use ndelay rather than udelay. Thanks lb --- drivers/mmc/host/sdhci-bcm2708.c | 8 ++++---- @@ -73750,184 +85466,10 @@ index b0cdd7d..7bba950 100644 1.8.1.6 -From 07ce5aad531e581f8db8ba9409938fe99814faf6 Mon Sep 17 00:00:00 2001 +From 71392b4e1322e0cd972cb3e7b8efa88b37f3578e Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Tue, 26 Jun 2012 15:54:11 +0100 -Subject: [PATCH 025/102] Fixed issue with some keyboards giving too much data - resulting in overrun of the input buffer and memory corruption causing an - OOPS. We should be checking for the fact that we might get more data than we - want. Thanks Naren. - ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 4 ++-- - drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 6 +++--- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 13 ++++++++++--- - 3 files changed, 15 insertions(+), 8 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -index 21d1ab1..01c4780 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -@@ -886,7 +886,7 @@ uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, - if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) { - if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { - urb->actual_length += n_bytes - remain; -- if (remain || urb->actual_length == urb->length) { -+ if (remain || urb->actual_length >= urb->length) { - /* - * For Control Data stage do not set urb->status=0 to prevent - * URB callback. Set it when Status phase done. See below. -@@ -905,7 +905,7 @@ uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, - else { - /* BULK and INTR */ - urb->actual_length += n_bytes - remain; -- if (remain || urb->actual_length == urb->length) { -+ if (remain || urb->actual_length >= urb->length) { - urb->status = 0; - *xfer_done = 1; - } -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -index 6e4bc60..86fee99 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -@@ -567,7 +567,7 @@ static int update_urb_state_xfer_comp(dwc_hc_t * hc, - (urb->flags & URB_SEND_ZERO_PACKET) && (urb->actual_length == urb->length) && - !(urb->length % hc->max_packet)) { - xfer_done = 0; -- } else if (short_read || urb->actual_length == urb->length) { -+ } else if (short_read || urb->actual_length >= urb->length) { - xfer_done = 1; - urb->status = 0; - } -@@ -1876,10 +1876,10 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, - } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) { - if (out_nak_enh) { - if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) { -- DWC_DEBUG("XactErr with NYET/NAK/ACK\n"); -+ DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n"); - qtd->error_count = 0; - } else { -- DWC_DEBUG("XactErr without NYET/NAK/ACK\n"); -+ DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n"); - } - } - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 970b065..05fd421 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -190,6 +190,7 @@ static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr, - uint32_t * port_addr) - { - struct urb *urb = (struct urb *)urb_handle; -+ struct usb_bus *bus; - #if 1 //GRAYG - temporary - if (NULL == urb_handle) - DWC_ERROR("**** %s - NULL URB handle\n", __func__);//GRAYG -@@ -206,12 +207,18 @@ static int _hub_info(dwc_otg_hcd_t * hcd, void *urb_handle, uint32_t * hub_addr, - *hub_addr = 0; //GRAYG - // we probably shouldn't have a transaction translator if - // there's no associated hub? -- } else -- *hub_addr = urb->dev->tt->hub->devnum; -+ } else { -+ bus = hcd_to_bus(dwc_otg_hcd_to_hcd(hcd)); -+ if (urb->dev->tt->hub == bus->root_hub) -+ *hub_addr = 0; -+ else -+ *hub_addr = urb->dev->tt->hub->devnum; -+ } -+ *port_addr = urb->dev->tt->multi ? urb->dev->ttport : 1; - } else { - *hub_addr = 0; -+ *port_addr = urb->dev->ttport; - } -- *port_addr = urb->dev->ttport; - return 0; - } - --- -1.8.1.6 - - -From 877be29ed0dfa3ea964cf407da931a9dc358a85a Mon Sep 17 00:00:00 2001 -From: Bryan Kemp -Date: Sat, 7 Jul 2012 16:24:07 -0500 -Subject: [PATCH 026/102] Updating dwc_otg driver to fix issue releasing pcm - stream see: https://github.com/raspberrypi/firmware/issues/51 - ---- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 20 ++++++++++++++++++-- - 1 file changed, 18 insertions(+), 2 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index 05fd421..e9f4f31 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -70,6 +70,7 @@ - #include "dwc_otg_hcd_if.h" - #include "dwc_otg_dbg.h" - #include "dwc_otg_driver.h" -+#include "dwc_otg_hcd.h" - - /** - * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is -@@ -263,6 +264,7 @@ static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, - static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, - dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status) - { -+ uint64_t flags; - struct urb *urb = (struct urb *)urb_handle; - #ifdef DEBUG - if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -@@ -347,7 +349,9 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); - #else -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); - usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb); -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); - #endif - return 0; -@@ -758,6 +762,8 @@ static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb) - static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) - #endif - { -+ int rc; -+ uint64_t flags; - dwc_otg_hcd_t *dwc_otg_hcd; - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); - -@@ -779,8 +785,18 @@ static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) - usb_hcd_giveback_urb(hcd, urb); - #else -- usb_hcd_unlink_urb_from_ep(hcd, urb); -- usb_hcd_giveback_urb(hcd, urb, status); -+ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); -+ rc = usb_hcd_check_unlink_urb(hcd, urb, status); -+ if(!rc) -+ { -+ usb_hcd_unlink_urb_from_ep(hcd, urb); -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); -+ if (!rc) -+ { -+ usb_hcd_giveback_urb(hcd, urb, status); -+ } - #endif - if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { - DWC_PRINTF("Called usb_hcd_giveback_urb()\n"); --- -1.8.1.6 - - -From d1c040fe7d2f67d27f0aec67a683d975d7147b70 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 8 May 2013 11:44:40 +0100 -Subject: [PATCH 027/102] Backport of Chris Boot's i2c and spi drivers. +Date: Wed, 3 Jul 2013 00:41:10 +0100 +Subject: [PATCH 19/88] Backport of Chris Boot's i2c and spi drivers. --- arch/arm/configs/bcmrpi_cutdown_defconfig | 10 + @@ -74149,7 +85691,7 @@ index 110ce07..4d3c15d 100644 #define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device (actually the multicore sync block*/ diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index adfee98..f1b55eb 100644 +index 631736e..62ff7ac 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -343,6 +343,14 @@ config I2C_BCM2835 @@ -74582,12 +86124,12 @@ index 0000000..7cae615 +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig -index 2be0de9..4022b4e 100644 +index 92a9345..f0a2a9f 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig -@@ -75,6 +75,14 @@ config SPI_ATMEL - This selects a driver for the Atmel SPI Controller, present on - many AT32 (AVR32) and AT91 (ARM) chips. +@@ -86,6 +86,14 @@ config SPI_BCM2835 + is for the regular SPI controller. Slave mode operation is not also + not supported. +config SPI_BCM2708 + tristate "BCM2708 SPI controller driver (SPI0)" @@ -74601,11 +86143,11 @@ index 2be0de9..4022b4e 100644 tristate "SPI controller driver for ADI Blackfin5xx" depends on BLACKFIN diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile -index e53c309..0e6b719 100644 +index 33f9c09..17b4737 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile -@@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_ATH79) += spi-ath79.o - obj-$(CONFIG_SPI_AU1550) += spi-au1550.o +@@ -17,6 +17,7 @@ obj-$(CONFIG_SPI_AU1550) += spi-au1550.o + obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o +obj-$(CONFIG_SPI_BCM2708) += spi-bcm2708.o @@ -75216,10 +86758,10 @@ index 0000000..9f1580e 1.8.1.6 -From 791baf597ff57436fff6151fb1f80852a399e243 Mon Sep 17 00:00:00 2001 +From 30d5060bcf0883c2b72e362bd76d2d32ea90ba2a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 19 Jul 2012 16:00:28 +0100 -Subject: [PATCH 028/102] Add SPI_SPI_DEV module +Subject: [PATCH 20/88] Add SPI_SPI_DEV module --- arch/arm/configs/bcmrpi_defconfig | 1 + @@ -75241,12 +86783,12 @@ index 6219df3..31f5afaa 100644 1.8.1.6 -From 498d65c0773ef33dbe228bf8729301c0e72008ad Mon Sep 17 00:00:00 2001 +From 0139a2bbd4f30ba7b59a44d7f11a38c8ae15c24c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 13 Jul 2012 18:34:18 +0100 -Subject: [PATCH 029/102] Fix for quitting X hang. Interrupted mailbox reads - are not something we can reliably recover from, so down_interruptable is not - a safe call. +Subject: [PATCH 21/88] Fix for quitting X hang. Interrupted mailbox reads are + not something we can reliably recover from, so down_interruptable is not a + safe call. --- arch/arm/mach-bcm2708/vcio.c | 12 ++++-------- @@ -75279,10 +86821,10 @@ index 799a0ac..3874051 100644 1.8.1.6 -From 38a8c0ede3997cc6563acf63165153e78508518e Mon Sep 17 00:00:00 2001 +From a53fbe6aab3b6e996741b0bc12b964c5c39c5da3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 17 Jul 2012 00:48:27 +0100 -Subject: [PATCH 030/102] Add sync_after_dma module parameter +Subject: [PATCH 22/88] Add sync_after_dma module parameter --- drivers/mmc/host/sdhci-bcm2708.c | 60 +++++++++++++++++++++------------------- @@ -75399,10 +86941,10 @@ index 7bba950..3792b9f 100644 1.8.1.6 -From 48c6420d3fe58dd3abdafa9f51bbb5de8e14ee6a Mon Sep 17 00:00:00 2001 +From d55680e3f7f80bb0cfd1cff2b94e2e00874e7ade Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:25:52 +0100 -Subject: [PATCH 031/102] sdhci-bcm2708: use extension FIFO to buffer DMA +Subject: [PATCH 23/88] sdhci-bcm2708: use extension FIFO to buffer DMA transfers The additional FIFO might speed up transfers in some cases. @@ -75454,11 +86996,11 @@ index 3792b9f..326b962 100644 1.8.1.6 -From 0feba5afe3af916eb6685c1981b83537df942b52 Mon Sep 17 00:00:00 2001 +From 55cdffec9f1d501823c9899867f775b97fa38785 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Wed, 1 May 2013 20:04:12 +0100 -Subject: [PATCH 032/102] sdhci-bcm2708: use multiblock-type transfers for - single blocks +Date: Wed, 3 Jul 2013 00:42:49 +0100 +Subject: [PATCH 24/88] sdhci-bcm2708: use multiblock-type transfers for single + blocks There are issues with both single block reads (missed completion) and writes (data loss in some cases!). Just don't do single block @@ -75471,10 +87013,10 @@ adds a quirk for this and uses it. 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c -index 5bab73b..8df187c 100644 +index dd27b07..90596c5 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c -@@ -1295,7 +1295,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, +@@ -1294,7 +1294,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, brq->data.blocks = 1; } @@ -75498,14 +87040,14 @@ index 326b962..c6d6bb0 100644 ret = sdhci_add_host(host); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h -index d6f20cc..860bff9 100644 +index e326ae2..70020e3 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h -@@ -280,6 +280,7 @@ struct mmc_host { - #define MMC_CAP2_PACKED_WR (1 << 13) /* Allow packed write */ +@@ -281,6 +281,7 @@ struct mmc_host { #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR) -+#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 12) /* Always use multiblock transfers */ + #define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14) /* Don't power up before scan */ ++#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 31) /* Always use multiblock transfers */ mmc_pm_flag_t pm_caps; /* supported pm features */ @@ -75513,10 +87055,10 @@ index d6f20cc..860bff9 100644 1.8.1.6 -From e40303910281a3771fbb8108f3538d29e5193fa8 Mon Sep 17 00:00:00 2001 +From ce3c78e01628a7fd80625223a2377a6c58562b0e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 Aug 2012 19:02:14 +0100 -Subject: [PATCH 033/102] Add module parameter for missing_status quirk. +Subject: [PATCH 25/88] Add module parameter for missing_status quirk. sdhci-bcm2708.missing_status=0 may improve interrupt latency --- @@ -75572,10 +87114,10 @@ index c6d6bb0..8243593 100644 1.8.1.6 -From 4529d090b0963026040ef25ff1e549dd0260fc07 Mon Sep 17 00:00:00 2001 +From 6fa717aa060b8d60006aa6bee5f223884d5f8bcf Mon Sep 17 00:00:00 2001 From: ddv2005 Date: Sun, 5 Aug 2012 10:42:12 -0400 -Subject: [PATCH 034/102] Fix spinlock recursion in sdhci-bcm2708.c +Subject: [PATCH 26/88] Fix spinlock recursion in sdhci-bcm2708.c --- drivers/mmc/host/sdhci-bcm2708.c | 14 +++++++------- @@ -75644,35435 +87186,10 @@ index 8243593..7a703c2 100644 1.8.1.6 -From 10f41cb6c7b38a784dbc39dd8a6280bf153cefe8 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Tue, 26 Mar 2013 13:34:40 +0000 -Subject: [PATCH 035/102] Update Synopsys USB OTG driver to v2.94a and disable - CRYPTOLIB - ---- - drivers/usb/host/dwc_common_port/Makefile | 38 +- - drivers/usb/host/dwc_common_port/Makefile.fbsd | 17 + - drivers/usb/host/dwc_common_port/Makefile.linux | 39 +- - drivers/usb/host/dwc_common_port/changes.txt | 174 ++ - drivers/usb/host/dwc_common_port/dwc_cc.c | 116 +- - drivers/usb/host/dwc_common_port/dwc_cc.h | 42 +- - drivers/usb/host/dwc_common_port/dwc_common_fbsd.c | 1308 ++++++++ - .../usb/host/dwc_common_port/dwc_common_linux.c | 1343 ++++---- - drivers/usb/host/dwc_common_port/dwc_common_nbsd.c | 1275 ++++++++ - drivers/usb/host/dwc_common_port/dwc_crypto.c | 308 ++ - drivers/usb/host/dwc_common_port/dwc_crypto.h | 111 + - drivers/usb/host/dwc_common_port/dwc_dh.c | 291 ++ - drivers/usb/host/dwc_common_port/dwc_dh.h | 106 + - drivers/usb/host/dwc_common_port/dwc_list.h | 274 +- - drivers/usb/host/dwc_common_port/dwc_mem.c | 191 +- - drivers/usb/host/dwc_common_port/dwc_modpow.c | 636 ++++ - drivers/usb/host/dwc_common_port/dwc_modpow.h | 34 + - drivers/usb/host/dwc_common_port/dwc_notifier.c | 155 +- - drivers/usb/host/dwc_common_port/dwc_notifier.h | 22 +- - drivers/usb/host/dwc_common_port/dwc_os.h | 627 +++- - drivers/usb/host/dwc_common_port/usb.h | 308 +- - drivers/usb/host/dwc_otg/Makefile | 40 +- - drivers/usb/host/dwc_otg/doc/doxygen.cfg | 2 +- - drivers/usb/host/dwc_otg/dwc_otg_adp.c | 854 +++++ - drivers/usb/host/dwc_otg/dwc_otg_adp.h | 80 + - drivers/usb/host/dwc_otg/dwc_otg_attr.c | 526 ++-- - drivers/usb/host/dwc_otg/dwc_otg_attr.h | 25 +- - drivers/usb/host/dwc_otg/dwc_otg_cfi.c | 112 +- - drivers/usb/host/dwc_otg/dwc_otg_cfi.h | 29 +- - drivers/usb/host/dwc_otg/dwc_otg_cil.c | 3275 +++++++++++++++----- - drivers/usb/host/dwc_otg/dwc_otg_cil.h | 524 +++- - drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 1027 ++++-- - drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 79 +- - drivers/usb/host/dwc_otg/dwc_otg_dbg.h | 3 + - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 526 ++-- - drivers/usb/host/dwc_otg/dwc_otg_driver.h | 31 +- - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 1293 ++++---- - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 95 +- - drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 780 ++--- - drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h | 35 +- - drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 419 +-- - drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 312 +- - drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 142 +- - drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 185 ++ - drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 1157 +++++-- - drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 70 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h | 43 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 1600 +++++++--- - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 341 +- - drivers/usb/host/dwc_otg/dwc_otg_regs.h | 916 ++++-- - 50 files changed, 16416 insertions(+), 5520 deletions(-) - create mode 100644 drivers/usb/host/dwc_common_port/Makefile.fbsd - create mode 100644 drivers/usb/host/dwc_common_port/changes.txt - create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_fbsd.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_common_nbsd.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_crypto.h - create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_dh.h - create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.c - create mode 100644 drivers/usb/host/dwc_common_port/dwc_modpow.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.c - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_adp.h - create mode 100644 drivers/usb/host/dwc_otg/dwc_otg_os_dep.h - -diff --git a/drivers/usb/host/dwc_common_port/Makefile b/drivers/usb/host/dwc_common_port/Makefile -index b593b08..203c7ea 100644 ---- a/drivers/usb/host/dwc_common_port/Makefile -+++ b/drivers/usb/host/dwc_common_port/Makefile -@@ -4,21 +4,25 @@ - - ifneq ($(KERNELRELEASE),) - --#CPPFLAGS += -DDEBUG_MEMORY -+EXTRA_CFLAGS += -DDWC_LINUX -+#EXTRA_CFLAGS += -DDEBUG -+#EXTRA_CFLAGS += -DDWC_DEBUG_REGS -+#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY - --ifeq ($(CONFIG_USB_DEBUG),y) --CPPFLAGS += -DDEBUG --endif --CPPFLAGS += -DDWC_LINUX -+EXTRA_CFLAGS += -DDWC_LIBMODULE -+EXTRA_CFLAGS += -DDWC_CCLIB -+#EXTRA_CFLAGS += -DDWC_CRYPTOLIB -+EXTRA_CFLAGS += -DDWC_NOTIFYLIB -+EXTRA_CFLAGS += -DDWC_UTFLIB - - obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o --dwc_common_port_lib-objs := dwc_cc.o \ -- dwc_notifier.o \ -- dwc_common_linux.o dwc_mem.o -+dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ -+ dwc_crypto.o dwc_notifier.o \ -+ dwc_common_linux.o dwc_mem.o - - kernrelwd := $(subst ., ,$(KERNELRELEASE)) - kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) -- -+ - ifneq ($(kernrel3),2.6.20) - # grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually - EXTRA_CFLAGS += $(CPPFLAGS) -@@ -26,12 +30,21 @@ endif - - else - -+ifeq ($(KDIR),) -+$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) -+endif -+ -+ifeq ($(ARCH),) -+$(error Must give "ARCH=" on command line or in environment. Also, if \ -+ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-") -+endif -+ - ifeq ($(DOXYGEN),) --DOXYGEN := $(DOXYGEN) -+DOXYGEN := doxygen - endif - - default: -- $(MAKE) -C$(KDIR) M=$(PWD) modules -+ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules - - docs: $(wildcard *.[hc]) doc/doxygen.cfg - $(DOXYGEN) doc/doxygen.cfg -@@ -42,5 +55,4 @@ tags: $(wildcard *.[hc]) - endif - - clean: -- rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers -- -+ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ -diff --git a/drivers/usb/host/dwc_common_port/Makefile.fbsd b/drivers/usb/host/dwc_common_port/Makefile.fbsd -new file mode 100644 -index 0000000..45db991 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/Makefile.fbsd -@@ -0,0 +1,17 @@ -+CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include -+CFLAGS += -DDWC_FREEBSD -+CFLAGS += -DDEBUG -+#CFLAGS += -DDWC_DEBUG_REGS -+#CFLAGS += -DDWC_DEBUG_MEMORY -+ -+#CFLAGS += -DDWC_LIBMODULE -+#CFLAGS += -DDWC_CCLIB -+#CFLAGS += -DDWC_CRYPTOLIB -+#CFLAGS += -DDWC_NOTIFYLIB -+#CFLAGS += -DDWC_UTFLIB -+ -+KMOD = dwc_common_port_lib -+SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \ -+ dwc_common_fbsd.c dwc_mem.c -+ -+.include -diff --git a/drivers/usb/host/dwc_common_port/Makefile.linux b/drivers/usb/host/dwc_common_port/Makefile.linux -index a553a9d..961df3f 100644 ---- a/drivers/usb/host/dwc_common_port/Makefile.linux -+++ b/drivers/usb/host/dwc_common_port/Makefile.linux -@@ -3,25 +3,39 @@ - # - ifneq ($(KERNELRELEASE),) - --#CPPFLAGS += -DDEBUG_MEMORY -- --#CPPFLAGS += -DDEBUG --CPPFLAGS += -DDWC_LINUX -- --obj-m := dwc_common_port_lib.o --dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ -- dwc_crypto.o dwc_notifier.o \ -- dwc_common_linux.o dwc_mem.o -+EXTRA_CFLAGS += -DDWC_LINUX -+#EXTRA_CFLAGS += -DDEBUG -+#EXTRA_CFLAGS += -DDWC_DEBUG_REGS -+#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY -+ -+EXTRA_CFLAGS += -DDWC_LIBMODULE -+EXTRA_CFLAGS += -DDWC_CCLIB -+EXTRA_CFLAGS += -DDWC_CRYPTOLIB -+EXTRA_CFLAGS += -DDWC_NOTIFYLIB -+EXTRA_CFLAGS += -DDWC_UTFLIB -+ -+obj-m := dwc_common_port_lib.o -+dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ -+ dwc_crypto.o dwc_notifier.o \ -+ dwc_common_linux.o dwc_mem.o - - else - -+ifeq ($(KDIR),) -+$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) -+endif -+ -+ifeq ($(ARCH),) -+$(error Must give "ARCH=" on command line or in environment. Also, if \ -+ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-") -+endif - - ifeq ($(DOXYGEN),) --DOXYGEN := $(DOXYGEN) -+DOXYGEN := doxygen - endif - - default: -- $(MAKE) -C$(KDIR) M=$(PWD) modules -+ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules - - docs: $(wildcard *.[hc]) doc/doxygen.cfg - $(DOXYGEN) doc/doxygen.cfg -@@ -32,5 +46,4 @@ tags: $(wildcard *.[hc]) - endif - - clean: -- rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers -- -+ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ -diff --git a/drivers/usb/host/dwc_common_port/changes.txt b/drivers/usb/host/dwc_common_port/changes.txt -new file mode 100644 -index 0000000..f6839f9 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/changes.txt -@@ -0,0 +1,174 @@ -+ -+dwc_read_reg32() and friends now take an additional parameter, a pointer to an -+IO context struct. The IO context struct should live in an os-dependent struct -+in your driver. As an example, the dwc_usb3 driver has an os-dependent struct -+named 'os_dep' embedded in the main device struct. So there these calls look -+like this: -+ -+ dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg); -+ -+ dwc_write_reg32(&usb3_dev->os_dep.ioctx, -+ &pcd->dev_global_regs->dcfg, 0); -+ -+Note that for the existing Linux driver ports, it is not necessary to actually -+define the 'ioctx' member in the os-dependent struct. Since Linux does not -+require an IO context, its macros for dwc_read_reg32() and friends do not -+use the context pointer, so it is optimized away by the compiler. But it is -+necessary to add the pointer parameter to all of the call sites, to be ready -+for any future ports (such as FreeBSD) which do require an IO context. -+ -+ -+Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now -+take an additional parameter, a pointer to a memory context. Examples: -+ -+ addr = dwc_alloc(&usb3_dev->os_dep.memctx, size); -+ -+ dwc_free(&usb3_dev->os_dep.memctx, addr); -+ -+Again, for the Linux ports, it is not necessary to actually define the memctx -+member, but it is necessary to add the pointer parameter to all of the call -+sites. -+ -+ -+Same for dwc_dma_alloc() and dwc_dma_free(). Examples: -+ -+ virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr); -+ -+ dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr); -+ -+ -+Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples: -+ -+ mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx); -+ -+ dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex); -+ -+ -+Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples: -+ -+ lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx); -+ -+ dwc_spinlock_free(&usb3_dev->osdep.splctx, lock); -+ -+ -+Same for dwc_timer_alloc(). Example: -+ -+ timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1", -+ cb_func, cb_data); -+ -+ -+Same for dwc_waitq_alloc(). Example: -+ -+ waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx); -+ -+ -+Same for dwc_thread_run(). Example: -+ -+ thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func, -+ "dwc_usb3_thd1", data); -+ -+ -+Same for dwc_workq_alloc(). Example: -+ -+ workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1"); -+ -+ -+Same for dwc_task_alloc(). Example: -+ -+ task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1", -+ cb_func, cb_data); -+ -+ -+In addition to the context pointer additions, a few core functions have had -+other changes made to their parameters: -+ -+The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore() -+has been changed from a uint64_t to a dwc_irqflags_t. -+ -+dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the -+FreeBSD equivalent of that function requires it. -+ -+And, in addition to the context pointer, dwc_task_alloc() also adds a -+'char *name' parameter, to be consistent with dwc_thread_run() and -+dwc_workq_alloc(), and because the FreeBSD equivalent of that function -+requires a unique name. -+ -+ -+Here is a complete list of the core functions that now take a pointer to a -+context as their first parameter: -+ -+ dwc_read_reg32 -+ dwc_read_reg64 -+ dwc_write_reg32 -+ dwc_write_reg64 -+ dwc_modify_reg32 -+ dwc_modify_reg64 -+ dwc_alloc -+ dwc_alloc_atomic -+ dwc_strdup -+ dwc_free -+ dwc_dma_alloc -+ dwc_dma_free -+ dwc_mutex_alloc -+ dwc_mutex_free -+ dwc_spinlock_alloc -+ dwc_spinlock_free -+ dwc_timer_alloc -+ dwc_waitq_alloc -+ dwc_thread_run -+ dwc_workq_alloc -+ dwc_task_alloc Also adds a 'char *name' as its 2nd parameter -+ -+And here are the core functions that have other changes to their parameters: -+ -+ dwc_spinlock_irqsave 'flags' param is now a 'dwc_irqflags_t *' -+ dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t' -+ dwc_thread_should_stop Adds a 'dwc_thread_t *' parameter -+ -+ -+ -+The changes to the core functions also require some of the other library -+functions to change: -+ -+ dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx' -+ (for memory allocation) as the 1st param and a 'void *mtxctx' -+ (for mutex allocation) as the 2nd param. -+ -+ dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(), -+ dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a -+ 'void *memctx' as the 1st param. -+ -+ dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a -+ 'void *memctx' as the 1st param. -+ -+ dwc_modpow() now takes a 'void *memctx' as the 1st param. -+ -+ dwc_alloc_notification_manager() now takes a 'void *memctx' as the -+ 1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd -+ param, and also now returns an integer value that is non-zero if -+ allocation of its data structures or work queue fails. -+ -+ dwc_register_notifier() now takes a 'void *memctx' as the 1st param. -+ -+ dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first -+ param, and also now returns an integer value that is non-zero if -+ allocation of its data structures fails. -+ -+ -+ -+Other miscellaneous changes: -+ -+The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to -+DWC_DEBUG_MEMORY and DWC_DEBUG_REGS. -+ -+The following #define's have been added to allow selectively compiling library -+features: -+ -+ DWC_CCLIB -+ DWC_CRYPTOLIB -+ DWC_NOTIFYLIB -+ DWC_UTFLIB -+ -+A DWC_LIBMODULE #define has also been added. If this is not defined, then the -+module code in dwc_common_linux.c is not compiled in. This allows linking the -+library code directly into a driver module, instead of as a standalone module. -diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.c b/drivers/usb/host/dwc_common_port/dwc_cc.c -index 3a7dd71..613c901 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_cc.c -+++ b/drivers/usb/host/dwc_common_port/dwc_cc.c -@@ -1,8 +1,8 @@ - /* ========================================================================= -- * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.c $ -- * $Revision: #1 $ -- * $Date: 2008/12/21 $ -- * $Change: 1156609 $ -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $ -+ * $Revision: #4 $ -+ * $Date: 2010/11/04 $ -+ * $Change: 1621692 $ - * - * Synopsys Portability Library Software and documentation - * (hereinafter, "Software") is an Unsupported proprietary work of -@@ -33,6 +33,8 @@ - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * ========================================================================= */ -+#ifdef DWC_CCLIB -+ - #include "dwc_cc.h" - - typedef struct dwc_cc -@@ -75,9 +77,9 @@ static inline void dump_bytes(char *name, uint8_t *bytes, int len) - #define dump_bytes(x...) - #endif - --static dwc_cc_t *alloc_cc(uint8_t *name, uint32_t length) -+static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length) - { -- dwc_cc_t *cc = DWC_ALLOC(sizeof(dwc_cc_t)); -+ dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t)); - if (!cc) { - return NULL; - } -@@ -85,19 +87,24 @@ static dwc_cc_t *alloc_cc(uint8_t *name, uint32_t length) - - if (name) { - cc->length = length; -- cc->name = DWC_ALLOC(length); -+ cc->name = dwc_alloc(mem_ctx, length); -+ if (!cc->name) { -+ dwc_free(mem_ctx, cc); -+ return NULL; -+ } -+ - DWC_MEMCPY(cc->name, name, length); - } - - return cc; - } - --static void free_cc(dwc_cc_t *cc) -+static void free_cc(void *mem_ctx, dwc_cc_t *cc) - { - if (cc->name) { -- DWC_FREE(cc->name); -+ dwc_free(mem_ctx, cc->name); - } -- DWC_FREE(cc); -+ dwc_free(mem_ctx, cc); - } - - static uint32_t next_uid(dwc_cc_if_t *cc_if) -@@ -169,7 +176,8 @@ static uint32_t cc_match_cdid(dwc_cc_if_t *cc_if, uint8_t *cdid) - } - - /* Internal cc_add */ --static int32_t cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) -+static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, -+ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) - { - dwc_cc_t *cc; - uint32_t uid; -@@ -182,11 +190,11 @@ static int32_t cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t - } - - if (uid) { -- DWC_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); -+ DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); - cc = cc_find(cc_if, uid); - } - else { -- cc = alloc_cc(name, length); -+ cc = alloc_cc(mem_ctx, name, length); - cc->uid = next_uid(cc_if); - DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry); - } -@@ -195,7 +203,7 @@ static int32_t cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t - DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); - DWC_MEMCPY(&(cc->ck[0]), ck, 16); - -- DWC_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); -+ DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); - dump_bytes("CHID", cc->chid, 16); - dump_bytes("CDID", cc->cdid, 16); - dump_bytes("CK", cc->ck, 16); -@@ -203,41 +211,51 @@ static int32_t cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t - } - - /* Internal cc_clear */ --static void cc_clear(dwc_cc_if_t *cc_if) -+static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) - { - while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) { - dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list); - DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); -- free_cc(cc); -+ free_cc(mem_ctx, cc); - } - } - --dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host) -+dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, -+ dwc_notifier_t *notifier, unsigned is_host) - { - dwc_cc_if_t *cc_if = NULL; - - /* Allocate a common_cc_if structure */ -- cc_if = DWC_ALLOC(sizeof(dwc_cc_if_t)); -+ cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t)); - -- if(!cc_if) -+ if (!cc_if) - return NULL; - - #if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) - DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex); - #else -- cc_if->mutex = DWC_MUTEX_ALLOC(); -+ cc_if->mutex = dwc_mutex_alloc(mtx_ctx); - #endif -+ if (!cc_if->mutex) { -+ dwc_free(mem_ctx, cc_if); -+ return NULL; -+ } -+ - DWC_CIRCLEQ_INIT(&cc_if->list); - cc_if->is_host = is_host; - cc_if->notifier = notifier; - return cc_if; - } - --void dwc_cc_if_free(dwc_cc_if_t *cc_if) -+void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if) - { -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) - DWC_MUTEX_FREE(cc_if->mutex); -- cc_clear(cc_if); -- DWC_FREE(cc_if); -+#else -+ dwc_mutex_free(mtx_ctx, cc_if->mutex); -+#endif -+ cc_clear(mem_ctx, cc_if); -+ dwc_free(mem_ctx, cc_if); - } - - static void cc_changed(dwc_cc_if_t *cc_if) -@@ -247,37 +265,38 @@ static void cc_changed(dwc_cc_if_t *cc_if) - } - } - --void dwc_cc_clear(dwc_cc_if_t *cc_if) -+void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) - { - DWC_MUTEX_LOCK(cc_if->mutex); -- cc_clear(cc_if); -+ cc_clear(mem_ctx, cc_if); - DWC_MUTEX_UNLOCK(cc_if->mutex); - cc_changed(cc_if); - } - --int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) -+int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, -+ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) - { - uint32_t uid; - - DWC_MUTEX_LOCK(cc_if->mutex); -- uid = cc_add(cc_if, chid, cdid, ck, name, length); -+ uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length); - DWC_MUTEX_UNLOCK(cc_if->mutex); - cc_changed(cc_if); - - return uid; - } - --void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, -- uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) -+void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, -+ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) - { - dwc_cc_t* cc; - -- DWC_DEBUG("Change connection context %d", id); -+ DWC_DEBUGC("Change connection context %d", id); - - DWC_MUTEX_LOCK(cc_if->mutex); - cc = cc_find(cc_if, id); - if (!cc) { -- DWC_ERROR("Uid %d not found in cc list", id); -+ DWC_ERROR("Uid %d not found in cc list\n", id); - DWC_MUTEX_UNLOCK(cc_if->mutex); - return; - } -@@ -294,9 +313,14 @@ void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, - - if (name) { - if (cc->name) { -- DWC_FREE(cc->name); -+ dwc_free(mem_ctx, cc->name); -+ } -+ cc->name = dwc_alloc(mem_ctx, length); -+ if (!cc->name) { -+ DWC_ERROR("Out of memory in dwc_cc_change()\n"); -+ DWC_MUTEX_UNLOCK(cc_if->mutex); -+ return; - } -- cc->name = DWC_ALLOC(length); - cc->length = length; - DWC_MEMCPY(cc->name, name, length); - } -@@ -305,34 +329,34 @@ void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, - - cc_changed(cc_if); - -- DWC_DEBUG("Changed connection context id=%d\n", id); -+ DWC_DEBUGC("Changed connection context id=%d\n", id); - dump_bytes("New CHID", cc->chid, 16); - dump_bytes("New CDID", cc->cdid, 16); - dump_bytes("New CK", cc->ck, 16); - } - --void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id) -+void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id) - { - dwc_cc_t *cc; - -- DWC_DEBUG("Removing connection context %d", id); -+ DWC_DEBUGC("Removing connection context %d", id); - - DWC_MUTEX_LOCK(cc_if->mutex); - cc = cc_find(cc_if, id); - if (!cc) { -- DWC_ERROR("Uid %d not found in cc list", id); -+ DWC_ERROR("Uid %d not found in cc list\n", id); - DWC_MUTEX_UNLOCK(cc_if->mutex); - return; - } - - DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); - DWC_MUTEX_UNLOCK(cc_if->mutex); -- free_cc(cc); -+ free_cc(mem_ctx, cc); - - cc_changed(cc_if); - } - --uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length) -+uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length) - { - uint8_t *buf, *x; - uint8_t zero = 0; -@@ -345,9 +369,9 @@ uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length) - return NULL; - } - -- DWC_DEBUG("Creating data for saving (length=%d)", *length); -+ DWC_DEBUGC("Creating data for saving (length=%d)", *length); - -- buf = DWC_ALLOC(*length); -+ buf = dwc_alloc(mem_ctx, *length); - if (!buf) { - *length = 0; - DWC_MUTEX_UNLOCK(cc_if->mutex); -@@ -378,7 +402,7 @@ uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length) - return buf; - } - --void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length) -+void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length) - { - uint8_t name_length; - uint8_t *name; -@@ -388,7 +412,7 @@ void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length - uint32_t i = 0; - - DWC_MUTEX_LOCK(cc_if->mutex); -- cc_clear(cc_if); -+ cc_clear(mem_ctx, cc_if); - - while (i < length) { - chid = &data[i]; -@@ -412,11 +436,11 @@ void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length - /* check to see if we haven't overflown the buffer */ - if (i > length) { - DWC_ERROR("Data format error while attempting to load CCs " -- "(nlen=%d, iter=%d, buflen=%d).", name_length, i, length); -+ "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length); - break; - } - -- cc_add(cc_if, chid, cdid, ck, name, name_length); -+ cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length); - } - DWC_MUTEX_UNLOCK(cc_if->mutex); - -@@ -504,3 +528,5 @@ uint8_t *dwc_cc_name(dwc_cc_if_t *cc_if, int32_t id, uint8_t *length) - - return retval; - } -+ -+#endif /* DWC_CCLIB */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.h b/drivers/usb/host/dwc_common_port/dwc_cc.h -index 6b464191..6b2bbaf 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_cc.h -+++ b/drivers/usb/host/dwc_common_port/dwc_cc.h -@@ -1,8 +1,8 @@ - /* ========================================================================= -- * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.h $ -- * $Revision: #1 $ -- * $Date: 2008/12/21 $ -- * $Change: 1156609 $ -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $ -+ * $Revision: #4 $ -+ * $Date: 2010/09/28 $ -+ * $Change: 1596182 $ - * - * Synopsys Portability Library Software and documentation - * (hereinafter, "Software") is an Unsupported proprietary work of -@@ -36,6 +36,10 @@ - #ifndef _DWC_CC_H_ - #define _DWC_CC_H_ - -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - /** @file - * - * This file defines the Context Context library. -@@ -69,14 +73,15 @@ - /** This function allocates memory for a dwc_cc_if_t structure, initializes - * fields to default values, and returns a pointer to the structure or NULL on - * error. */ --extern dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host); -+extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, -+ dwc_notifier_t *notifier, unsigned is_host); - - /** Frees the memory for the specified CC structure allocated from - * dwc_cc_if_alloc(). */ --extern void dwc_cc_if_free(dwc_cc_if_t *cc_if); -+extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if); - - /** Removes all contexts from the connection context list */ --extern void dwc_cc_clear(dwc_cc_if_t *cc_if); -+extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if); - - /** Adds a connection context (CHID, CK, CDID, Name) to the connection context list. - * If a CHID already exists, the CK and name are overwritten. Statistics are -@@ -91,7 +96,9 @@ - * @param length The length othe unicode string. - * @return A unique identifier used to refer to this context that is valid for - * as long as this context is still in the list. */ --extern int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length); -+extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, -+ uint8_t *cdid, uint8_t *ck, uint8_t *name, -+ uint8_t length); - - /** Changes the CHID, CK, CDID, or Name values of a connection context in the - * list, preserving any accumulated statistics. This would typically be called -@@ -107,12 +114,14 @@ - * indicates no change. - * @param name Host friendly name UTF16-LE. NULL indicates no change. - * @param length Length of name. */ --extern void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length); -+extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, -+ uint8_t *chid, uint8_t *cdid, uint8_t *ck, -+ uint8_t *name, uint8_t length); - - /** Remove the specified connection context. - * @param cc_if The cc_if structure. - * @param id The identifier of the connection context to remove. */ --extern void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id); -+extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id); - - /** Get a binary block of data for the connection context list and attributes. - * This data can be used by the OS specific driver to save the connection -@@ -120,8 +129,10 @@ - * - * @param cc_if The cc_if structure. - * @param length Return the length of the data buffer. -- * @return A pointer to the data buffer. The memory for this buffer should be freed with DWC_FREE() after use. */ --extern uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length); -+ * @return A pointer to the data buffer. The memory for this buffer should be -+ * freed with DWC_FREE() after use. */ -+extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, -+ unsigned int *length); - - /** Restore the connection context list from the binary data that was previously - * returned from a call to dwc_cc_data_for_save. This can be used by the OS specific -@@ -130,7 +141,8 @@ - * @param cc_if The cc_if structure. - * @param data The data bytes as returned from dwc_cc_data_for_save. - * @param length The length of the data. */ --extern void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, unsigned int length); -+extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, -+ uint8_t *data, unsigned int length); - - /** Find the connection context from the specified CHID. - * -@@ -205,5 +217,9 @@ static inline int dwc_print_id_string(char *buffer, uint8_t *id) { - - /** @} */ - -+#ifdef __cplusplus -+} -+#endif -+ - #endif /* _DWC_CC_H_ */ - -diff --git a/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c -new file mode 100644 -index 0000000..6dd04b5 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c -@@ -0,0 +1,1308 @@ -+#include "dwc_os.h" -+#include "dwc_list.h" -+ -+#ifdef DWC_CCLIB -+# include "dwc_cc.h" -+#endif -+ -+#ifdef DWC_CRYPTOLIB -+# include "dwc_modpow.h" -+# include "dwc_dh.h" -+# include "dwc_crypto.h" -+#endif -+ -+#ifdef DWC_NOTIFYLIB -+# include "dwc_notifier.h" -+#endif -+ -+/* OS-Level Implementations */ -+ -+/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */ -+ -+ -+/* MISC */ -+ -+void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) -+{ -+ return memset(dest, byte, size); -+} -+ -+void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) -+{ -+ return memcpy(dest, src, size); -+} -+ -+void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) -+{ -+ bcopy(src, dest, size); -+ return dest; -+} -+ -+int DWC_MEMCMP(void *m1, void *m2, uint32_t size) -+{ -+ return memcmp(m1, m2, size); -+} -+ -+int DWC_STRNCMP(void *s1, void *s2, uint32_t size) -+{ -+ return strncmp(s1, s2, size); -+} -+ -+int DWC_STRCMP(void *s1, void *s2) -+{ -+ return strcmp(s1, s2); -+} -+ -+int DWC_STRLEN(char const *str) -+{ -+ return strlen(str); -+} -+ -+char *DWC_STRCPY(char *to, char const *from) -+{ -+ return strcpy(to, from); -+} -+ -+char *DWC_STRDUP(char const *str) -+{ -+ int len = DWC_STRLEN(str) + 1; -+ char *new = DWC_ALLOC_ATOMIC(len); -+ -+ if (!new) { -+ return NULL; -+ } -+ -+ DWC_MEMCPY(new, str, len); -+ return new; -+} -+ -+int DWC_ATOI(char *str, int32_t *value) -+{ -+ char *end = NULL; -+ -+ *value = strtol(str, &end, 0); -+ if (*end == '\0') { -+ return 0; -+ } -+ -+ return -1; -+} -+ -+int DWC_ATOUI(char *str, uint32_t *value) -+{ -+ char *end = NULL; -+ -+ *value = strtoul(str, &end, 0); -+ if (*end == '\0') { -+ return 0; -+ } -+ -+ return -1; -+} -+ -+ -+#ifdef DWC_UTFLIB -+/* From usbstring.c */ -+ -+int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) -+{ -+ int count = 0; -+ u8 c; -+ u16 uchar; -+ -+ /* this insists on correct encodings, though not minimal ones. -+ * BUT it currently rejects legit 4-byte UTF-8 code points, -+ * which need surrogate pairs. (Unicode 3.1 can use them.) -+ */ -+ while (len != 0 && (c = (u8) *s++) != 0) { -+ if (unlikely(c & 0x80)) { -+ // 2-byte sequence: -+ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx -+ if ((c & 0xe0) == 0xc0) { -+ uchar = (c & 0x1f) << 6; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c; -+ -+ // 3-byte sequence (most CJKV characters): -+ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx -+ } else if ((c & 0xf0) == 0xe0) { -+ uchar = (c & 0x0f) << 12; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c << 6; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c; -+ -+ /* no bogus surrogates */ -+ if (0xd800 <= uchar && uchar <= 0xdfff) -+ goto fail; -+ -+ // 4-byte sequence (surrogate pairs, currently rare): -+ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx -+ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx -+ // (uuuuu = wwww + 1) -+ // FIXME accept the surrogate code points (only) -+ } else -+ goto fail; -+ } else -+ uchar = c; -+ put_unaligned (cpu_to_le16 (uchar), cp++); -+ count++; -+ len--; -+ } -+ return count; -+fail: -+ return -1; -+} -+ -+#endif /* DWC_UTFLIB */ -+ -+ -+/* dwc_debug.h */ -+ -+dwc_bool_t DWC_IN_IRQ(void) -+{ -+// return in_irq(); -+ return 0; -+} -+ -+dwc_bool_t DWC_IN_BH(void) -+{ -+// return in_softirq(); -+ return 0; -+} -+ -+void DWC_VPRINTF(char *format, va_list args) -+{ -+ vprintf(format, args); -+} -+ -+int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) -+{ -+ return vsnprintf(str, size, format, args); -+} -+ -+void DWC_PRINTF(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+ -+int DWC_SPRINTF(char *buffer, char *format, ...) -+{ -+ int retval; -+ va_list args; -+ -+ va_start(args, format); -+ retval = vsprintf(buffer, format, args); -+ va_end(args); -+ return retval; -+} -+ -+int DWC_SNPRINTF(char *buffer, int size, char *format, ...) -+{ -+ int retval; -+ va_list args; -+ -+ va_start(args, format); -+ retval = vsnprintf(buffer, size, format, args); -+ va_end(args); -+ return retval; -+} -+ -+void __DWC_WARN(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+ -+void __DWC_ERROR(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+ -+void DWC_EXCEPTION(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+// BUG_ON(1); ??? -+} -+ -+#ifdef DEBUG -+void __DWC_DEBUG(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+#endif -+ -+ -+/* dwc_mem.h */ -+ -+#if 0 -+dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, -+ uint32_t align, -+ uint32_t alloc) -+{ -+ struct dma_pool *pool = dma_pool_create("Pool", NULL, -+ size, align, alloc); -+ return (dwc_pool_t *)pool; -+} -+ -+void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) -+{ -+ dma_pool_destroy((struct dma_pool *)pool); -+} -+ -+void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) -+{ -+// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); -+ return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr); -+} -+ -+void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) -+{ -+ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); -+ memset(..); -+} -+ -+void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) -+{ -+ dma_pool_free(pool, vaddr, daddr); -+} -+#endif -+ -+static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) -+{ -+ if (error) -+ return; -+ *(bus_addr_t *)arg = segs[0].ds_addr; -+} -+ -+void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) -+{ -+ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; -+ int error; -+ -+ error = bus_dma_tag_create( -+#if __FreeBSD_version >= 700000 -+ bus_get_dma_tag(dma->dev), /* parent */ -+#else -+ NULL, /* parent */ -+#endif -+ 4, 0, /* alignment, bounds */ -+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ -+ BUS_SPACE_MAXADDR, /* highaddr */ -+ NULL, NULL, /* filter, filterarg */ -+ size, /* maxsize */ -+ 1, /* nsegments */ -+ size, /* maxsegsize */ -+ 0, /* flags */ -+ NULL, /* lockfunc */ -+ NULL, /* lockarg */ -+ &dma->dma_tag); -+ if (error) { -+ device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n", -+ __func__, error); -+ goto fail_0; -+ } -+ -+ error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr, -+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); -+ if (error) { -+ device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n", -+ __func__, (uintmax_t)size, error); -+ goto fail_1; -+ } -+ -+ dma->dma_paddr = 0; -+ error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size, -+ dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT); -+ if (error || dma->dma_paddr == 0) { -+ device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n", -+ __func__, error); -+ goto fail_2; -+ } -+ -+ *dma_addr = dma->dma_paddr; -+ return dma->dma_vaddr; -+ -+fail_2: -+ bus_dmamap_unload(dma->dma_tag, dma->dma_map); -+fail_1: -+ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); -+ bus_dma_tag_destroy(dma->dma_tag); -+fail_0: -+ dma->dma_map = NULL; -+ dma->dma_tag = NULL; -+ -+ return NULL; -+} -+ -+void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) -+{ -+ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; -+ -+ if (dma->dma_tag == NULL) -+ return; -+ if (dma->dma_map != NULL) { -+ bus_dmamap_sync(dma->dma_tag, dma->dma_map, -+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); -+ bus_dmamap_unload(dma->dma_tag, dma->dma_map); -+ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); -+ dma->dma_map = NULL; -+ } -+ -+ bus_dma_tag_destroy(dma->dma_tag); -+ dma->dma_tag = NULL; -+} -+ -+void *__DWC_ALLOC(void *mem_ctx, uint32_t size) -+{ -+ return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); -+} -+ -+void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) -+{ -+ return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); -+} -+ -+void __DWC_FREE(void *mem_ctx, void *addr) -+{ -+ free(addr, M_DEVBUF); -+} -+ -+ -+#ifdef DWC_CRYPTOLIB -+/* dwc_crypto.h */ -+ -+void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) -+{ -+ get_random_bytes(buffer, length); -+} -+ -+int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) -+{ -+ struct crypto_blkcipher *tfm; -+ struct blkcipher_desc desc; -+ struct scatterlist sgd; -+ struct scatterlist sgs; -+ -+ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); -+ if (tfm == NULL) { -+ printk("failed to load transform for aes CBC\n"); -+ return -1; -+ } -+ -+ crypto_blkcipher_setkey(tfm, key, keylen); -+ crypto_blkcipher_set_iv(tfm, iv, 16); -+ -+ sg_init_one(&sgd, out, messagelen); -+ sg_init_one(&sgs, message, messagelen); -+ -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { -+ crypto_free_blkcipher(tfm); -+ DWC_ERROR("AES CBC encryption failed"); -+ return -1; -+ } -+ -+ crypto_free_blkcipher(tfm); -+ return 0; -+} -+ -+int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) -+{ -+ struct crypto_hash *tfm; -+ struct hash_desc desc; -+ struct scatterlist sg; -+ -+ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); -+ if (IS_ERR(tfm)) { -+ DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm)); -+ return 0; -+ } -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ sg_init_one(&sg, message, len); -+ crypto_hash_digest(&desc, &sg, len, out); -+ crypto_free_hash(tfm); -+ -+ return 1; -+} -+ -+int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, -+ uint8_t *key, uint32_t keylen, uint8_t *out) -+{ -+ struct crypto_hash *tfm; -+ struct hash_desc desc; -+ struct scatterlist sg; -+ -+ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); -+ if (IS_ERR(tfm)) { -+ DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm)); -+ return 0; -+ } -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ sg_init_one(&sg, message, messagelen); -+ crypto_hash_setkey(tfm, key, keylen); -+ crypto_hash_digest(&desc, &sg, messagelen, out); -+ crypto_free_hash(tfm); -+ -+ return 1; -+} -+ -+#endif /* DWC_CRYPTOLIB */ -+ -+ -+/* Byte Ordering Conversions */ -+ -+uint32_t DWC_CPU_TO_LE32(uint32_t *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+ -+uint32_t DWC_CPU_TO_BE32(uint32_t *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+ -+uint32_t DWC_LE32_TO_CPU(uint32_t *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+ -+uint32_t DWC_BE32_TO_CPU(uint32_t *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+ -+uint16_t DWC_CPU_TO_LE16(uint16_t *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+ -+uint16_t DWC_CPU_TO_BE16(uint16_t *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+ -+uint16_t DWC_LE16_TO_CPU(uint16_t *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+ -+uint16_t DWC_BE16_TO_CPU(uint16_t *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+ -+ -+/* Registers */ -+ -+uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ return bus_space_read_4(io->iot, io->ioh, ior); -+} -+ -+#if 0 -+uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ return bus_space_read_8(io->iot, io->ioh, ior); -+} -+#endif -+ -+void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ bus_space_write_4(io->iot, io->ioh, ior, value); -+} -+ -+#if 0 -+void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ bus_space_write_8(io->iot, io->ioh, ior, value); -+} -+#endif -+ -+void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, -+ uint32_t set_mask) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ bus_space_write_4(io->iot, io->ioh, ior, -+ (bus_space_read_4(io->iot, io->ioh, ior) & -+ ~clear_mask) | set_mask); -+} -+ -+#if 0 -+void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, -+ uint64_t set_mask) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ bus_space_write_8(io->iot, io->ioh, ior, -+ (bus_space_read_8(io->iot, io->ioh, ior) & -+ ~clear_mask) | set_mask); -+} -+#endif -+ -+ -+/* Locking */ -+ -+dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) -+{ -+ struct mtx *sl = DWC_ALLOC(sizeof(*sl)); -+ -+ if (!sl) { -+ DWC_ERROR("Cannot allocate memory for spinlock"); -+ return NULL; -+ } -+ -+ mtx_init(sl, "dw3spn", NULL, MTX_SPIN); -+ return (dwc_spinlock_t *)sl; -+} -+ -+void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) -+{ -+ struct mtx *sl = (struct mtx *)lock; -+ -+ mtx_destroy(sl); -+ DWC_FREE(sl); -+} -+ -+void DWC_SPINLOCK(dwc_spinlock_t *lock) -+{ -+ mtx_lock_spin((struct mtx *)lock); // ??? -+} -+ -+void DWC_SPINUNLOCK(dwc_spinlock_t *lock) -+{ -+ mtx_unlock_spin((struct mtx *)lock); // ??? -+} -+ -+void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) -+{ -+ mtx_lock_spin((struct mtx *)lock); -+} -+ -+void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) -+{ -+ mtx_unlock_spin((struct mtx *)lock); -+} -+ -+dwc_mutex_t *DWC_MUTEX_ALLOC(void) -+{ -+ struct mtx *m; -+ dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx)); -+ -+ if (!mutex) { -+ DWC_ERROR("Cannot allocate memory for mutex"); -+ return NULL; -+ } -+ -+ m = (struct mtx *)mutex; -+ mtx_init(m, "dw3mtx", NULL, MTX_DEF); -+ return mutex; -+} -+ -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+#else -+void DWC_MUTEX_FREE(dwc_mutex_t *mutex) -+{ -+ mtx_destroy((struct mtx *)mutex); -+ DWC_FREE(mutex); -+} -+#endif -+ -+void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) -+{ -+ struct mtx *m = (struct mtx *)mutex; -+ -+ mtx_lock(m); -+} -+ -+int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) -+{ -+ struct mtx *m = (struct mtx *)mutex; -+ -+ return mtx_trylock(m); -+} -+ -+void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) -+{ -+ struct mtx *m = (struct mtx *)mutex; -+ -+ mtx_unlock(m); -+} -+ -+ -+/* Timing */ -+ -+void DWC_UDELAY(uint32_t usecs) -+{ -+ DELAY(usecs); -+} -+ -+void DWC_MDELAY(uint32_t msecs) -+{ -+ do { -+ DELAY(1000); -+ } while (--msecs); -+} -+ -+void DWC_MSLEEP(uint32_t msecs) -+{ -+ struct timeval tv; -+ -+ tv.tv_sec = msecs / 1000; -+ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; -+ pause("dw3slp", tvtohz(&tv)); -+} -+ -+uint32_t DWC_TIME(void) -+{ -+ struct timeval tv; -+ -+ microuptime(&tv); // or getmicrouptime? (less precise, but faster) -+ return tv.tv_sec * 1000 + tv.tv_usec / 1000; -+} -+ -+ -+/* Timers */ -+ -+struct dwc_timer { -+ struct callout t; -+ char *name; -+ dwc_spinlock_t *lock; -+ dwc_timer_callback_t cb; -+ void *data; -+}; -+ -+dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) -+{ -+ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); -+ -+ if (!t) { -+ DWC_ERROR("Cannot allocate memory for timer"); -+ return NULL; -+ } -+ -+ callout_init(&t->t, 1); -+ -+ t->name = DWC_STRDUP(name); -+ if (!t->name) { -+ DWC_ERROR("Cannot allocate memory for timer->name"); -+ goto no_name; -+ } -+ -+ t->lock = DWC_SPINLOCK_ALLOC(); -+ if (!t->lock) { -+ DWC_ERROR("Cannot allocate memory for lock"); -+ goto no_lock; -+ } -+ -+ t->cb = cb; -+ t->data = data; -+ -+ return t; -+ -+ no_lock: -+ DWC_FREE(t->name); -+ no_name: -+ DWC_FREE(t); -+ -+ return NULL; -+} -+ -+void DWC_TIMER_FREE(dwc_timer_t *timer) -+{ -+ callout_stop(&timer->t); -+ DWC_SPINLOCK_FREE(timer->lock); -+ DWC_FREE(timer->name); -+ DWC_FREE(timer); -+} -+ -+void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) -+{ -+ struct timeval tv; -+ -+ tv.tv_sec = time / 1000; -+ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; -+ callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data); -+} -+ -+void DWC_TIMER_CANCEL(dwc_timer_t *timer) -+{ -+ callout_stop(&timer->t); -+} -+ -+ -+/* Wait Queues */ -+ -+struct dwc_waitq { -+ struct mtx lock; -+ int abort; -+}; -+ -+dwc_waitq_t *DWC_WAITQ_ALLOC(void) -+{ -+ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ -+ if (!wq) { -+ DWC_ERROR("Cannot allocate memory for waitqueue"); -+ return NULL; -+ } -+ -+ mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF); -+ wq->abort = 0; -+ -+ return wq; -+} -+ -+void DWC_WAITQ_FREE(dwc_waitq_t *wq) -+{ -+ mtx_destroy(&wq->lock); -+ DWC_FREE(wq); -+} -+ -+int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) -+{ -+// intrmask_t ipl; -+ int result = 0; -+ -+ mtx_lock(&wq->lock); -+// ipl = splbio(); -+ -+ /* Skip the sleep if already aborted or triggered */ -+ if (!wq->abort && !cond(data)) { -+// splx(ipl); -+ result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout -+// ipl = splbio(); -+ } -+ -+ if (result == ERESTART) { // signaled - restart -+ result = -DWC_E_RESTART; -+ -+ } else if (result == EINTR) { // signaled - interrupt -+ result = -DWC_E_ABORT; -+ -+ } else if (wq->abort) { -+ result = -DWC_E_ABORT; -+ -+ } else { -+ result = 0; -+ } -+ -+ wq->abort = 0; -+// splx(ipl); -+ mtx_unlock(&wq->lock); -+ return result; -+} -+ -+int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, -+ void *data, int32_t msecs) -+{ -+ struct timeval tv, tv1, tv2; -+// intrmask_t ipl; -+ int result = 0; -+ -+ tv.tv_sec = msecs / 1000; -+ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; -+ -+ mtx_lock(&wq->lock); -+// ipl = splbio(); -+ -+ /* Skip the sleep if already aborted or triggered */ -+ if (!wq->abort && !cond(data)) { -+// splx(ipl); -+ getmicrouptime(&tv1); -+ result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv)); -+ getmicrouptime(&tv2); -+// ipl = splbio(); -+ } -+ -+ if (result == 0) { // awoken -+ if (wq->abort) { -+ result = -DWC_E_ABORT; -+ } else { -+ tv2.tv_usec -= tv1.tv_usec; -+ if (tv2.tv_usec < 0) { -+ tv2.tv_usec += 1000000; -+ tv2.tv_sec--; -+ } -+ -+ tv2.tv_sec -= tv1.tv_sec; -+ result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; -+ result = msecs - result; -+ if (result <= 0) -+ result = 1; -+ } -+ } else if (result == ERESTART) { // signaled - restart -+ result = -DWC_E_RESTART; -+ -+ } else if (result == EINTR) { // signaled - interrupt -+ result = -DWC_E_ABORT; -+ -+ } else { // timed out -+ result = -DWC_E_TIMEOUT; -+ } -+ -+ wq->abort = 0; -+// splx(ipl); -+ mtx_unlock(&wq->lock); -+ return result; -+} -+ -+void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) -+{ -+ wakeup(wq); -+} -+ -+void DWC_WAITQ_ABORT(dwc_waitq_t *wq) -+{ -+// intrmask_t ipl; -+ -+ mtx_lock(&wq->lock); -+// ipl = splbio(); -+ wq->abort = 1; -+ wakeup(wq); -+// splx(ipl); -+ mtx_unlock(&wq->lock); -+} -+ -+ -+/* Threading */ -+ -+struct dwc_thread { -+ struct proc *proc; -+ int abort; -+}; -+ -+dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) -+{ -+ int retval; -+ dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread)); -+ -+ if (!thread) { -+ return NULL; -+ } -+ -+ thread->abort = 0; -+ retval = kthread_create((void (*)(void *))func, data, &thread->proc, -+ RFPROC | RFNOWAIT, 0, "%s", name); -+ if (retval) { -+ DWC_FREE(thread); -+ return NULL; -+ } -+ -+ return thread; -+} -+ -+int DWC_THREAD_STOP(dwc_thread_t *thread) -+{ -+ int retval; -+ -+ thread->abort = 1; -+ retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz); -+ -+ if (retval == 0) { -+ /* DWC_THREAD_EXIT() will free the thread struct */ -+ return 0; -+ } -+ -+ /* NOTE: We leak the thread struct if thread doesn't die */ -+ -+ if (retval == EWOULDBLOCK) { -+ return -DWC_E_TIMEOUT; -+ } -+ -+ return -DWC_E_UNKNOWN; -+} -+ -+dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread) -+{ -+ return thread->abort; -+} -+ -+void DWC_THREAD_EXIT(dwc_thread_t *thread) -+{ -+ wakeup(&thread->abort); -+ DWC_FREE(thread); -+ kthread_exit(0); -+} -+ -+ -+/* tasklets -+ - Runs in interrupt context (cannot sleep) -+ - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ] -+ - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ] -+ */ -+struct dwc_tasklet { -+ struct task t; -+ dwc_tasklet_callback_t cb; -+ void *data; -+}; -+ -+static void tasklet_callback(void *data, int pending) // what to do with pending ??? -+{ -+ dwc_tasklet_t *task = (dwc_tasklet_t *)data; -+ -+ task->cb(task->data); -+} -+ -+dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) -+{ -+ dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task)); -+ -+ if (task) { -+ task->cb = cb; -+ task->data = data; -+ TASK_INIT(&task->t, 0, tasklet_callback, task); -+ } else { -+ DWC_ERROR("Cannot allocate memory for tasklet"); -+ } -+ -+ return task; -+} -+ -+void DWC_TASK_FREE(dwc_tasklet_t *task) -+{ -+ taskqueue_drain(taskqueue_fast, &task->t); // ??? -+ DWC_FREE(task); -+} -+ -+void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) -+{ -+ /* Uses predefined system queue */ -+ taskqueue_enqueue_fast(taskqueue_fast, &task->t); -+} -+ -+ -+/* workqueues -+ - Runs in process context (can sleep) -+ */ -+typedef struct work_container { -+ dwc_work_callback_t cb; -+ void *data; -+ dwc_workq_t *wq; -+ char *name; -+ int hz; -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_ENTRY(work_container) entry; -+#endif -+ struct task task; -+} work_container_t; -+ -+#ifdef DEBUG -+DWC_CIRCLEQ_HEAD(work_container_queue, work_container); -+#endif -+ -+struct dwc_workq { -+ struct taskqueue *taskq; -+ dwc_spinlock_t *lock; -+ dwc_waitq_t *waitq; -+ int pending; -+ -+#ifdef DEBUG -+ struct work_container_queue entries; -+#endif -+}; -+ -+static void do_work(void *data, int pending) // what to do with pending ??? -+{ -+ work_container_t *container = (work_container_t *)data; -+ dwc_workq_t *wq = container->wq; -+ dwc_irqflags_t flags; -+ -+ if (container->hz) { -+ pause("dw3wrk", container->hz); -+ } -+ -+ container->cb(container->data); -+ DWC_DEBUG("Work done: %s, container=%p", container->name, container); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); -+#endif -+ if (container->name) -+ DWC_FREE(container->name); -+ DWC_FREE(container); -+ wq->pending--; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+} -+ -+static int work_done(void *data) -+{ -+ dwc_workq_t *workq = (dwc_workq_t *)data; -+ -+ return workq->pending == 0; -+} -+ -+int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) -+{ -+ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); -+} -+ -+dwc_workq_t *DWC_WORKQ_ALLOC(char *name) -+{ -+ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ -+ if (!wq) { -+ DWC_ERROR("Cannot allocate memory for workqueue"); -+ return NULL; -+ } -+ -+ wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq); -+ if (!wq->taskq) { -+ DWC_ERROR("Cannot allocate memory for taskqueue"); -+ goto no_taskq; -+ } -+ -+ wq->pending = 0; -+ -+ wq->lock = DWC_SPINLOCK_ALLOC(); -+ if (!wq->lock) { -+ DWC_ERROR("Cannot allocate memory for spinlock"); -+ goto no_lock; -+ } -+ -+ wq->waitq = DWC_WAITQ_ALLOC(); -+ if (!wq->waitq) { -+ DWC_ERROR("Cannot allocate memory for waitqueue"); -+ goto no_waitq; -+ } -+ -+ taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk"); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INIT(&wq->entries); -+#endif -+ return wq; -+ -+ no_waitq: -+ DWC_SPINLOCK_FREE(wq->lock); -+ no_lock: -+ taskqueue_free(wq->taskq); -+ no_taskq: -+ DWC_FREE(wq); -+ -+ return NULL; -+} -+ -+void DWC_WORKQ_FREE(dwc_workq_t *wq) -+{ -+#ifdef DEBUG -+ dwc_irqflags_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ -+ if (wq->pending != 0) { -+ struct work_container *container; -+ -+ DWC_ERROR("Destroying work queue with pending work"); -+ -+ DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) { -+ DWC_ERROR("Work %s still pending", container->name); -+ } -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+#endif -+ DWC_WAITQ_FREE(wq->waitq); -+ DWC_SPINLOCK_FREE(wq->lock); -+ taskqueue_free(wq->taskq); -+ DWC_FREE(wq); -+} -+ -+void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, -+ char *format, ...) -+{ -+ dwc_irqflags_t flags; -+ work_container_t *container; -+ static char name[128]; -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ if (!container) { -+ DWC_ERROR("Cannot allocate memory for container"); -+ return; -+ } -+ -+ container->name = DWC_STRDUP(name); -+ if (!container->name) { -+ DWC_ERROR("Cannot allocate memory for container->name"); -+ DWC_FREE(container); -+ return; -+ } -+ -+ container->cb = cb; -+ container->data = data; -+ container->wq = wq; -+ container->hz = 0; -+ -+ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); -+ -+ TASK_INIT(&container->task, 0, do_work, container); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); -+#endif -+ taskqueue_enqueue_fast(wq->taskq, &container->task); -+} -+ -+void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, -+ void *data, uint32_t time, char *format, ...) -+{ -+ dwc_irqflags_t flags; -+ work_container_t *container; -+ static char name[128]; -+ struct timeval tv; -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ if (!container) { -+ DWC_ERROR("Cannot allocate memory for container"); -+ return; -+ } -+ -+ container->name = DWC_STRDUP(name); -+ if (!container->name) { -+ DWC_ERROR("Cannot allocate memory for container->name"); -+ DWC_FREE(container); -+ return; -+ } -+ -+ container->cb = cb; -+ container->data = data; -+ container->wq = wq; -+ -+ tv.tv_sec = time / 1000; -+ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; -+ container->hz = tvtohz(&tv); -+ -+ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); -+ -+ TASK_INIT(&container->task, 0, do_work, container); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); -+#endif -+ taskqueue_enqueue_fast(wq->taskq, &container->task); -+} -+ -+int DWC_WORKQ_PENDING(dwc_workq_t *wq) -+{ -+ return wq->pending; -+} -diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -index fbf9dfb..f00a9ff 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c -+++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c -@@ -1,80 +1,28 @@ --#include "dwc_cc.h" --#include "dwc_notifier.h" -- - #include - #include - #include - #include - --MODULE_DESCRIPTION("DWC Common Library - Portable version"); --MODULE_AUTHOR("Synopsys Inc."); --MODULE_LICENSE ("GPL"); -- --static int dwc_common_port_init_module(void) --{ -- printk( KERN_DEBUG "Module dwc_common_port init\n" ); --#ifdef DEBUG_MEMORY -- dwc_memory_debug_start(); -+#ifdef DWC_CCLIB -+# include "dwc_cc.h" - #endif -- dwc_alloc_notification_manager(); -- return 0; --} - --static void dwc_common_port_exit_module(void) --{ -- printk( KERN_DEBUG "Module dwc_common_port exit\n" ); -- dwc_free_notification_manager(); --#ifdef DEBUG_MEMORY -- dwc_memory_debug_stop(); -+#ifdef DWC_CRYPTOLIB -+# include "dwc_modpow.h" -+# include "dwc_dh.h" -+# include "dwc_crypto.h" - #endif --} -- --module_init(dwc_common_port_init_module); --module_exit(dwc_common_port_exit_module); -- --/* CC */ --EXPORT_SYMBOL(dwc_cc_if_alloc); --EXPORT_SYMBOL(dwc_cc_if_free); --EXPORT_SYMBOL(dwc_cc_clear); --EXPORT_SYMBOL(dwc_cc_add); --EXPORT_SYMBOL(dwc_cc_remove); --EXPORT_SYMBOL(dwc_cc_change); --EXPORT_SYMBOL(dwc_cc_data_for_save); --EXPORT_SYMBOL(dwc_cc_restore_from_data); --EXPORT_SYMBOL(dwc_cc_match_chid); --EXPORT_SYMBOL(dwc_cc_match_cdid); --EXPORT_SYMBOL(dwc_cc_ck); --EXPORT_SYMBOL(dwc_cc_chid); --EXPORT_SYMBOL(dwc_cc_cdid); --EXPORT_SYMBOL(dwc_cc_name); -- --/* Notification */ --EXPORT_SYMBOL(dwc_alloc_notification_manager); --EXPORT_SYMBOL(dwc_free_notification_manager); --EXPORT_SYMBOL(dwc_register_notifier); --EXPORT_SYMBOL(dwc_unregister_notifier); --EXPORT_SYMBOL(dwc_add_observer); --EXPORT_SYMBOL(dwc_remove_observer); --EXPORT_SYMBOL(dwc_notify); - --/* Memory Debugging Routines */ --#ifdef DEBUG_MEMORY --EXPORT_SYMBOL(dwc_alloc_debug); --EXPORT_SYMBOL(dwc_alloc_atomic_debug); --EXPORT_SYMBOL(dwc_free_debug); --EXPORT_SYMBOL(dwc_dma_alloc_debug); --EXPORT_SYMBOL(dwc_dma_alloc_atomic_debug); --EXPORT_SYMBOL(dwc_dma_free_debug); -+#ifdef DWC_NOTIFYLIB -+# include "dwc_notifier.h" - #endif - - /* OS-Level Implementations */ - - /* This is the Linux kernel implementation of the DWC platform library. */ --#include --#include --#include - #include - #include -+#include - #include - #include - #include -@@ -84,24 +32,30 @@ static void dwc_common_port_exit_module(void) - #include - #include - #include -+#include -+#include - #include - #include - #include - #include --#include - #include --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --#include -+ -+#include -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -+# include - #else --#include -+# include - #endif --#include -+ - #include - #include - #include - #include --#include --#include -+ -+#include "dwc_os.h" -+#include "dwc_list.h" -+ - - /* MISC */ - -@@ -109,86 +63,83 @@ void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) - { - return memset(dest, byte, size); - } --EXPORT_SYMBOL(DWC_MEMSET); - - void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) - { - return memcpy(dest, src, size); - } --EXPORT_SYMBOL(DWC_MEMCPY); - - void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) - { - return memmove(dest, src, size); - } --EXPORT_SYMBOL(DWC_MEMMOVE); - - int DWC_MEMCMP(void *m1, void *m2, uint32_t size) - { - return memcmp(m1, m2, size); - } --EXPORT_SYMBOL(DWC_MEMCMP); - - int DWC_STRNCMP(void *s1, void *s2, uint32_t size) - { - return strncmp(s1, s2, size); - } --EXPORT_SYMBOL(DWC_STRNCMP); - - int DWC_STRCMP(void *s1, void *s2) - { - return strcmp(s1, s2); - } --EXPORT_SYMBOL(DWC_STRCMP); - - int DWC_STRLEN(char const *str) - { - return strlen(str); - } --EXPORT_SYMBOL(DWC_STRLEN); - --char *DWC_STRCPY(char *to, const char *from) -+char *DWC_STRCPY(char *to, char const *from) - { - return strcpy(to, from); - } --EXPORT_SYMBOL(DWC_STRCPY); - - char *DWC_STRDUP(char const *str) - { - int len = DWC_STRLEN(str) + 1; - char *new = DWC_ALLOC_ATOMIC(len); -+ - if (!new) { - return NULL; - } -+ - DWC_MEMCPY(new, str, len); - return new; - } --EXPORT_SYMBOL(DWC_STRDUP); - --int DWC_ATOI(char *str, int32_t *value) -+int DWC_ATOI(const char *str, int32_t *value) - { - char *end = NULL; -+ - *value = simple_strtol(str, &end, 0); - if (*end == '\0') { - return 0; - } -+ - return -1; - } --EXPORT_SYMBOL(DWC_ATOI); - --int DWC_ATOUI(char *str, uint32_t *value) -+int DWC_ATOUI(const char *str, uint32_t *value) - { - char *end = NULL; -+ - *value = simple_strtoul(str, &end, 0); - if (*end == '\0') { - return 0; - } -+ - return -1; - } --EXPORT_SYMBOL(DWC_ATOUI); - - -+#ifdef DWC_UTFLIB - /* From usbstring.c */ -+ - int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) - { - int count = 0; -@@ -238,7 +189,6 @@ int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) - // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx - // (uuuuu = wwww + 1) - // FIXME accept the surrogate code points (only) -- - } else - goto fail; - } else -@@ -251,7 +201,8 @@ int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) - fail: - return -1; - } --EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE); -+#endif /* DWC_UTFLIB */ -+ - - /* dwc_debug.h */ - -@@ -259,19 +210,16 @@ dwc_bool_t DWC_IN_IRQ(void) - { - return in_irq(); - } --EXPORT_SYMBOL(DWC_IN_IRQ); - --int DWC_IN_BH(void) -+dwc_bool_t DWC_IN_BH(void) - { - return in_softirq(); - } --EXPORT_SYMBOL(DWC_IN_BH); - - void DWC_VPRINTF(char *format, va_list args) - { - vprintk(format, args); - } --EXPORT_SYMBOL(DWC_VPRINTF); - - int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) - { -@@ -281,79 +229,78 @@ int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) - void DWC_PRINTF(char *format, ...) - { - va_list args; -+ - va_start(args, format); - DWC_VPRINTF(format, args); - va_end(args); - } --EXPORT_SYMBOL(DWC_PRINTF); - - int DWC_SPRINTF(char *buffer, char *format, ...) - { - int retval; - va_list args; -+ - va_start(args, format); - retval = vsprintf(buffer, format, args); - va_end(args); - return retval; - } --EXPORT_SYMBOL(DWC_SPRINTF); - - int DWC_SNPRINTF(char *buffer, int size, char *format, ...) - { - int retval; - va_list args; -+ - va_start(args, format); - retval = vsnprintf(buffer, size, format, args); - va_end(args); - return retval; - } --EXPORT_SYMBOL(DWC_SNPRINTF); - - void __DWC_WARN(char *format, ...) - { - va_list args; -+ - va_start(args, format); - DWC_PRINTF(KERN_WARNING); - DWC_VPRINTF(format, args); - va_end(args); - } --EXPORT_SYMBOL(__DWC_WARN); - - void __DWC_ERROR(char *format, ...) - { - va_list args; -+ - va_start(args, format); - DWC_PRINTF(KERN_ERR); - DWC_VPRINTF(format, args); - va_end(args); - } --EXPORT_SYMBOL(__DWC_ERROR); - - void DWC_EXCEPTION(char *format, ...) - { - va_list args; -+ - va_start(args, format); - DWC_PRINTF(KERN_ERR); - DWC_VPRINTF(format, args); - va_end(args); - BUG_ON(1); - } --EXPORT_SYMBOL(DWC_EXCEPTION); - - #ifdef DEBUG - void __DWC_DEBUG(char *format, ...) - { - va_list args; -+ - va_start(args, format); - DWC_PRINTF(KERN_DEBUG); - DWC_VPRINTF(format, args); - va_end(args); - } --EXPORT_SYMBOL(__DWC_DEBUG); - #endif - - -- - /* dwc_mem.h */ - - #if 0 -@@ -371,42 +318,39 @@ void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) - dma_pool_destroy((struct dma_pool *)pool); - } - --void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, U64 *dma_addr) -+void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) - { - return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); - } - --void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, U64 *dma_addr) -+void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) - { - void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); -- memset(); -+ memset(..); - } - - void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) - { - dma_pool_free(pool, vaddr, daddr); - } -- - #endif - --void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr) -+void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) - { -- void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_KERNEL); -+#ifdef xxCOSIM /* Only works for 32-bit cosim */ -+ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); -+#else -+ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); -+#endif - if (!buf) { - return NULL; - } -+ - memset(buf, 0, (size_t)size); - return buf; - } --EXPORT_SYMBOL(__DWC_DMA_ALLOC); -- --void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr) --{ -- dma_free_coherent(NULL, size, virt_addr, dma_addr); --} --EXPORT_SYMBOL(__DWC_DMA_FREE); - --void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr) -+void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) - { - void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); - if (!buf) { -@@ -415,119 +359,199 @@ void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr) - memset(buf, 0, (size_t)size); - return buf; - } --EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); - --void *__DWC_ALLOC(uint32_t size) -+void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) -+{ -+ dma_free_coherent(dma_ctx, size, virt_addr, dma_addr); -+} -+ -+void *__DWC_ALLOC(void *mem_ctx, uint32_t size) - { - return kzalloc(size, GFP_KERNEL); - } --EXPORT_SYMBOL(__DWC_ALLOC); - --void *__DWC_ALLOC_ATOMIC(uint32_t size) -+void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) - { - return kzalloc(size, GFP_ATOMIC); - } --EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC); - --void __DWC_FREE(void *addr) -+void __DWC_FREE(void *mem_ctx, void *addr) - { - kfree(addr); - } --EXPORT_SYMBOL(__DWC_FREE); - --/* Byte Ordering Conversions. */ --uint32_t DWC_CPU_TO_LE32(void *p) -+ -+#ifdef DWC_CRYPTOLIB -+/* dwc_crypto.h */ -+ -+void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) -+{ -+ get_random_bytes(buffer, length); -+} -+ -+int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) -+{ -+ struct crypto_blkcipher *tfm; -+ struct blkcipher_desc desc; -+ struct scatterlist sgd; -+ struct scatterlist sgs; -+ -+ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); -+ if (tfm == NULL) { -+ printk("failed to load transform for aes CBC\n"); -+ return -1; -+ } -+ -+ crypto_blkcipher_setkey(tfm, key, keylen); -+ crypto_blkcipher_set_iv(tfm, iv, 16); -+ -+ sg_init_one(&sgd, out, messagelen); -+ sg_init_one(&sgs, message, messagelen); -+ -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { -+ crypto_free_blkcipher(tfm); -+ DWC_ERROR("AES CBC encryption failed"); -+ return -1; -+ } -+ -+ crypto_free_blkcipher(tfm); -+ return 0; -+} -+ -+int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) -+{ -+ struct crypto_hash *tfm; -+ struct hash_desc desc; -+ struct scatterlist sg; -+ -+ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); -+ if (IS_ERR(tfm)) { -+ DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm)); -+ return 0; -+ } -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ sg_init_one(&sg, message, len); -+ crypto_hash_digest(&desc, &sg, len, out); -+ crypto_free_hash(tfm); -+ -+ return 1; -+} -+ -+int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, -+ uint8_t *key, uint32_t keylen, uint8_t *out) -+{ -+ struct crypto_hash *tfm; -+ struct hash_desc desc; -+ struct scatterlist sg; -+ -+ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); -+ if (IS_ERR(tfm)) { -+ DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm)); -+ return 0; -+ } -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ sg_init_one(&sg, message, messagelen); -+ crypto_hash_setkey(tfm, key, keylen); -+ crypto_hash_digest(&desc, &sg, messagelen, out); -+ crypto_free_hash(tfm); -+ -+ return 1; -+} -+#endif /* DWC_CRYPTOLIB */ -+ -+ -+/* Byte Ordering Conversions */ -+ -+uint32_t DWC_CPU_TO_LE32(uint32_t *p) - { - #ifdef __LITTLE_ENDIAN -- return *((uint32_t *)p); -+ return *p; - #else - uint8_t *u_p = (uint8_t *)p; - - return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); - #endif - } --EXPORT_SYMBOL(DWC_CPU_TO_LE32); - --uint32_t DWC_CPU_TO_BE32(void *p) -+uint32_t DWC_CPU_TO_BE32(uint32_t *p) - { - #ifdef __BIG_ENDIAN -- return *((uint32_t *)p); -+ return *p; - #else - uint8_t *u_p = (uint8_t *)p; - - return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); - #endif - } --EXPORT_SYMBOL(DWC_CPU_TO_BE32); - --uint32_t DWC_LE32_TO_CPU(void *p) -+uint32_t DWC_LE32_TO_CPU(uint32_t *p) - { - #ifdef __LITTLE_ENDIAN -- return *((uint32_t *)p); -+ return *p; - #else - uint8_t *u_p = (uint8_t *)p; - - return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -- - #endif - } --EXPORT_SYMBOL(DWC_LE32_TO_CPU); - --uint32_t DWC_BE32_TO_CPU(void *p) -+uint32_t DWC_BE32_TO_CPU(uint32_t *p) - { - #ifdef __BIG_ENDIAN -- return *((uint32_t *)p); -+ return *p; - #else - uint8_t *u_p = (uint8_t *)p; - - return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); - #endif - } --EXPORT_SYMBOL(DWC_BE32_TO_CPU); - --uint16_t DWC_CPU_TO_LE16(void *p) -+uint16_t DWC_CPU_TO_LE16(uint16_t *p) - { - #ifdef __LITTLE_ENDIAN -- return *((uint16_t *)p); -+ return *p; - #else - uint8_t *u_p = (uint8_t *)p; - return (u_p[1] | (u_p[0] << 8)); - #endif - } --EXPORT_SYMBOL(DWC_CPU_TO_LE16); - --uint16_t DWC_CPU_TO_BE16(void *p) -+uint16_t DWC_CPU_TO_BE16(uint16_t *p) - { - #ifdef __BIG_ENDIAN -- return *((uint16_t *)p); -+ return *p; - #else - uint8_t *u_p = (uint8_t *)p; - return (u_p[1] | (u_p[0] << 8)); - #endif - } --EXPORT_SYMBOL(DWC_CPU_TO_BE16); - --uint16_t DWC_LE16_TO_CPU(void *p) -+uint16_t DWC_LE16_TO_CPU(uint16_t *p) - { - #ifdef __LITTLE_ENDIAN -- return *((uint16_t *)p); -+ return *p; - #else - uint8_t *u_p = (uint8_t *)p; - return (u_p[1] | (u_p[0] << 8)); - #endif - } --EXPORT_SYMBOL(DWC_LE16_TO_CPU); - --uint16_t DWC_BE16_TO_CPU(void *p) -+uint16_t DWC_BE16_TO_CPU(uint16_t *p) - { - #ifdef __BIG_ENDIAN -- return *((uint16_t *p)p); -+ return *p; - #else - uint8_t *u_p = (uint8_t *)p; - return (u_p[1] | (u_p[0] << 8)); - #endif - } --EXPORT_SYMBOL(DWC_BE16_TO_CPU); - - - /* Registers */ -@@ -536,7 +560,6 @@ uint32_t DWC_READ_REG32(uint32_t volatile *reg) - { - return readl(reg); - } --EXPORT_SYMBOL(DWC_READ_REG32); - - #if 0 - uint64_t DWC_READ_REG64(uint64_t volatile *reg) -@@ -548,7 +571,6 @@ void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value) - { - writel(value, reg); - } --EXPORT_SYMBOL(DWC_WRITE_REG32); - - #if 0 - void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value) -@@ -558,330 +580,145 @@ void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value) - - void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) - { -- writel( (readl(reg) & ~clear_mask) | set_mask, reg ); -+ writel((readl(reg) & ~clear_mask) | set_mask, reg); - } --EXPORT_SYMBOL(DWC_MODIFY_REG32); - - #if 0 --void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t value) -+void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask) - { - } - #endif - - -+/* Locking */ - --/* Threading */ -- --typedef struct work_container -+dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) - { -- dwc_work_callback_t cb; -- void *data; -- dwc_workq_t *wq; -- char *name; -+ spinlock_t *sl = (spinlock_t *)1; - --#ifdef DEBUG -- DWC_CIRCLEQ_ENTRY(work_container) entry; --#endif -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ sl = DWC_ALLOC(sizeof(*sl)); -+ if (!sl) { -+ DWC_ERROR("Cannot allocate memory for spinlock\n"); -+ return NULL; -+ } - -- struct delayed_work work; --} work_container_t; -+ spin_lock_init(sl); -+#endif -+ return (dwc_spinlock_t *)sl; -+} - --#ifdef DEBUG --DWC_CIRCLEQ_HEAD(work_container_queue, work_container); -+void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) -+{ -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ DWC_FREE(lock); - #endif -+} - --struct dwc_workq -+void DWC_SPINLOCK(dwc_spinlock_t *lock) - { -- struct workqueue_struct *wq; -- int pending; -- dwc_spinlock_t *lock; -- dwc_waitq_t *waitq; -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_lock((spinlock_t *)lock); -+#endif -+} - --#ifdef DEBUG -- struct work_container_queue entries; -+void DWC_SPINUNLOCK(dwc_spinlock_t *lock) -+{ -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_unlock((spinlock_t *)lock); - #endif --}; -+} - --static void do_work(struct work_struct *work) -+void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) - { -- int64_t flags; -- struct delayed_work *dw = container_of(work, struct delayed_work, work); -- work_container_t *container = container_of(dw, struct work_container, work); -- dwc_workq_t *wq = container->wq; -+ dwc_irqflags_t f; - -- container->cb(container->data); -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_lock_irqsave((spinlock_t *)lock, f); -+#else -+ local_irq_save(f); -+#endif -+ *flags = f; -+} - --#ifdef DEBUG -- DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); -+void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) -+{ -+#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_unlock_irqrestore((spinlock_t *)lock, flags); -+#else -+ local_irq_restore(flags); - #endif -+} - -- if (container->name) { -- DWC_DEBUG("Work done: %s, container=%p", -- container->name, container); //GRAYG -- DWC_FREE(container->name); -+dwc_mutex_t *DWC_MUTEX_ALLOC(void) -+{ -+ struct mutex *m; -+ dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); -+ -+ if (!mutex) { -+ DWC_ERROR("Cannot allocate memory for mutex\n"); -+ return NULL; - } -- DWC_FREE(container); - -- DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -- wq->pending --; -- DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -- DWC_WAITQ_TRIGGER(wq->waitq); -+ m = (struct mutex *)mutex; -+ mutex_init(m); -+ return mutex; - } - --static int work_done(void *data) -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+#else -+void DWC_MUTEX_FREE(dwc_mutex_t *mutex) - { -- dwc_workq_t *workq = (dwc_workq_t *)data; -- return workq->pending == 0; -+ mutex_destroy((struct mutex *)mutex); -+ DWC_FREE(mutex); - } -+#endif - --int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) -+void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) - { -- return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); -+ struct mutex *m = (struct mutex *)mutex; -+ mutex_lock(m); - } --EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE); - --dwc_workq_t *DWC_WORKQ_ALLOC(char *name) -+int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) - { -- dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); -- wq->wq = create_singlethread_workqueue(name); -- wq->pending = 0; -- wq->lock = DWC_SPINLOCK_ALLOC(); -- wq->waitq = DWC_WAITQ_ALLOC(); --#ifdef DEBUG -- DWC_CIRCLEQ_INIT(&wq->entries); --#endif -- return wq; --} --EXPORT_SYMBOL(DWC_WORKQ_ALLOC); -- --void DWC_WORKQ_FREE(dwc_workq_t *wq) --{ --#ifdef DEBUG -- if (wq->pending != 0) { -- struct work_container *wc; -- DWC_ERROR("Destroying work queue with pending work"); -- DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { -- DWC_ERROR("Work %s still pending", wc->name); -- } -- } --#endif -- destroy_workqueue((struct workqueue_struct *)wq->wq); -- DWC_SPINLOCK_FREE(wq->lock); -- DWC_WAITQ_FREE(wq->waitq); -- DWC_FREE(wq); --} --EXPORT_SYMBOL(DWC_WORKQ_FREE); -- --void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, char *format, ...) --{ -- int64_t flags; -- work_container_t *container; -- static char name[128]; -- -- va_list args; -- va_start(args, format); -- if (format) -- DWC_VSNPRINTF(name, 128, format, args); -- va_end(args); -- -- DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -- wq->pending ++; -- DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -- DWC_WAITQ_TRIGGER(wq->waitq); -- -- container = DWC_ALLOC_ATOMIC(sizeof(*container)); -- -- container->data = data; -- container->cb = work_cb; -- container->wq = wq; -- if (format) { -- container->name = DWC_STRDUP(name); -- DWC_DEBUG("Queueing work: %s, contianer=%p", -- container->name, container); -- } else -- container->name = NULL; -- -- INIT_WORK(&container->work.work, do_work); -- --#ifdef DEBUG -- DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); --#endif -- -- queue_work(wq->wq, &container->work.work); -- --} --EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE); -- --void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...) --{ -- int64_t flags; -- work_container_t *container; -- static char name[128]; -- -- va_list args; -- va_start(args, format); -- if (format) -- DWC_VSNPRINTF(name, 128, format, args); -- va_end(args); -- -- DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -- wq->pending ++; -- DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -- DWC_WAITQ_TRIGGER(wq->waitq); -- -- container = DWC_ALLOC_ATOMIC(sizeof(*container)); -- -- container->data = data; -- container->cb = work_cb; -- container->wq = wq; -- if (format) { //GRAYG -- container->name = DWC_STRDUP(name); -- DWC_DEBUG("Queueing work: %s, contianer=%p", -- container->name, container); -- } else -- container->name = NULL; -- INIT_DELAYED_WORK(&container->work, do_work); -- --#ifdef DEBUG -- DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); --#endif -- -- queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); -- --} --EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED); -- -- --int DWC_WORKQ_PENDING(dwc_workq_t *wq) --{ -- return wq->pending; --} --EXPORT_SYMBOL(DWC_WORKQ_PENDING); -- --dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) --{ -- spinlock_t *sl = (spinlock_t *)1; --#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -- sl = DWC_ALLOC(sizeof(*sl)); -- spin_lock_init(sl); --#endif -- return (dwc_spinlock_t *)sl; --} --EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC); -- --void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) --{ --#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -- DWC_FREE(lock); --#endif --} --EXPORT_SYMBOL(DWC_SPINLOCK_FREE); -- --void DWC_SPINLOCK(dwc_spinlock_t *lock) --{ --#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -- spin_lock((spinlock_t *)lock); --#endif --} --EXPORT_SYMBOL(DWC_SPINLOCK); -- --void DWC_SPINUNLOCK(dwc_spinlock_t *lock) --{ --#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -- spin_unlock((spinlock_t *)lock); --#endif --} --EXPORT_SYMBOL(DWC_SPINUNLOCK); -- --void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags) --{ -- unsigned long f; --#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -- spin_lock_irqsave((spinlock_t *)lock, f); --#else -- local_irq_save(f); --#endif -- *flags = f; --} --EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE); -- --void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags) --{ --#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -- spin_unlock_irqrestore((spinlock_t *)lock, flags); --#else -- // in kernel 2.6.31, at least, we check for unsigned long -- local_irq_restore((unsigned long)flags); --#endif -+ struct mutex *m = (struct mutex *)mutex; -+ return mutex_trylock(m); - } --EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE); - --dwc_mutex_t *DWC_MUTEX_ALLOC(void) -+void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) - { -- dwc_mutex_t *mutex = (dwc_mutex_t*)DWC_ALLOC(sizeof(struct mutex)); - struct mutex *m = (struct mutex *)mutex; -- mutex_init(m); -- return mutex; -+ mutex_unlock(m); - } --EXPORT_SYMBOL(DWC_MUTEX_ALLOC); - --#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) --#else --void DWC_MUTEX_FREE(dwc_mutex_t *mutex) --{ -- mutex_destroy((struct mutex *)mutex); -- DWC_FREE(mutex); --} --EXPORT_SYMBOL(DWC_MUTEX_FREE); --#endif - --void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) --{ -- struct mutex *m = (struct mutex *)mutex; -- mutex_lock(m); --} --EXPORT_SYMBOL(DWC_MUTEX_LOCK); -+/* Timing */ - --int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) -+void DWC_UDELAY(uint32_t usecs) - { -- struct mutex *m = (struct mutex *)mutex; -- return mutex_trylock(m); -+ udelay(usecs); - } --EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK); - --void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) -+void DWC_MDELAY(uint32_t msecs) - { -- struct mutex *m = (struct mutex *)mutex; -- mutex_unlock(m); -+ mdelay(msecs); - } --EXPORT_SYMBOL(DWC_MUTEX_UNLOCK); - --dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data) -+void DWC_MSLEEP(uint32_t msecs) - { -- struct task_struct *thread = kthread_run(thread_function, data, name); -- if (thread == ERR_PTR(-ENOMEM)) { -- return NULL; -- } -- return (dwc_thread_t *)thread; -+ msleep(msecs); - } --EXPORT_SYMBOL(DWC_THREAD_RUN); - --int DWC_THREAD_STOP(dwc_thread_t *thread) -+uint32_t DWC_TIME(void) - { -- return kthread_stop((struct task_struct *)thread); -+ return jiffies_to_msecs(jiffies); - } --EXPORT_SYMBOL(DWC_THREAD_STOP); - --dwc_bool_t DWC_THREAD_SHOULD_STOP() --{ -- return kthread_should_stop(); --} --EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP); - - /* Timers */ - --struct dwc_timer --{ -+struct dwc_timer { - struct timer_list *t; - char *name; - dwc_timer_callback_t cb; -@@ -890,39 +727,27 @@ struct dwc_timer - dwc_spinlock_t *lock; - }; - --static void set_scheduled(dwc_timer_t *t, int s) --{ -- uint64_t flags; -- DWC_SPINLOCK_IRQSAVE(t->lock, &flags); -- t->scheduled = s; -- DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags); --} -- --static int get_scheduled(dwc_timer_t *t) --{ -- int s; -- uint64_t flags; -- DWC_SPINLOCK_IRQSAVE(t->lock, &flags); -- s = t->scheduled; -- DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags); -- return s; --} -- - static void timer_callback(unsigned long data) - { - dwc_timer_t *timer = (dwc_timer_t *)data; -- set_scheduled(timer, 0); -- DWC_DEBUG("Timer %s callback", timer->name); -+ dwc_irqflags_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); -+ timer->scheduled = 0; -+ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); -+ DWC_DEBUGC("Timer %s callback", timer->name); - timer->cb(timer->data); - } - - dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) - { - dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); -+ - if (!t) { - DWC_ERROR("Cannot allocate memory for timer"); - return NULL; - } -+ - t->t = DWC_ALLOC(sizeof(*t->t)); - if (!t->t) { - DWC_ERROR("Cannot allocate memory for timer->t"); -@@ -940,6 +765,7 @@ dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) - DWC_ERROR("Cannot allocate memory for lock"); - goto no_lock; - } -+ - t->scheduled = 0; - t->t->base = &boot_tvec_bases; - t->t->expires = jiffies; -@@ -958,181 +784,638 @@ dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) - DWC_FREE(t); - return NULL; - } --EXPORT_SYMBOL(DWC_TIMER_ALLOC); - - void DWC_TIMER_FREE(dwc_timer_t *timer) - { -- if (get_scheduled(timer)) { -+ dwc_irqflags_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); -+ -+ if (timer->scheduled) { - del_timer(timer->t); -+ timer->scheduled = 0; - } - -+ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); - DWC_SPINLOCK_FREE(timer->lock); - DWC_FREE(timer->t); - DWC_FREE(timer->name); - DWC_FREE(timer); - } --EXPORT_SYMBOL(DWC_TIMER_FREE); - - void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) - { -- if (!get_scheduled(timer)) { -- set_scheduled(timer, 1); -- //cgg: DWC_DEBUG("Scheduling timer %s to expire in +%d msec", timer->name, time); -+ dwc_irqflags_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); -+ -+ if (!timer->scheduled) { -+ timer->scheduled = 1; -+ DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time); - timer->t->expires = jiffies + msecs_to_jiffies(time); - add_timer(timer->t); -- } -- else { -- //cgg: DWC_DEBUG("Modifying timer %s to expire in +%d msec", timer->name, time); -+ } else { -+ DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time); - mod_timer(timer->t, jiffies + msecs_to_jiffies(time)); - } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); - } --EXPORT_SYMBOL(DWC_TIMER_SCHEDULE); - - void DWC_TIMER_CANCEL(dwc_timer_t *timer) - { - del_timer(timer->t); - } --EXPORT_SYMBOL(DWC_TIMER_CANCEL); - --struct dwc_tasklet --{ -- struct tasklet_struct t; -- dwc_tasklet_callback_t cb; -- void *data; -+ -+/* Wait Queues */ -+ -+struct dwc_waitq { -+ wait_queue_head_t queue; -+ int abort; - }; - --static void tasklet_callback(unsigned long data) -+dwc_waitq_t *DWC_WAITQ_ALLOC(void) - { -- dwc_tasklet_t *t = (dwc_tasklet_t *)data; -- t->cb(t->data); --} -+ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); - --dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data) --{ -- dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t)); -- -- if(t) { -- t->data = data; -- t->cb = cb; -- tasklet_init(&t->t, tasklet_callback, (unsigned long)t); -- } else { -- DWC_ERROR("Cannot allocate memory for tasklet\n"); -+ if (!wq) { -+ DWC_ERROR("Cannot allocate memory for waitqueue\n"); -+ return NULL; - } -- -- return t; --} --EXPORT_SYMBOL(DWC_TASK_ALLOC); - --void DWC_TASK_FREE(dwc_tasklet_t *t) --{ -- DWC_FREE(t); -+ init_waitqueue_head(&wq->queue); -+ wq->abort = 0; -+ return wq; - } --EXPORT_SYMBOL(DWC_TASK_FREE); - --void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) -+void DWC_WAITQ_FREE(dwc_waitq_t *wq) - { -- tasklet_schedule(&task->t); -+ DWC_FREE(wq); - } --EXPORT_SYMBOL(DWC_TASK_SCHEDULE); -- --/* Timing */ - --void DWC_UDELAY(uint32_t usecs) -+int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) - { -- udelay(usecs); --} --EXPORT_SYMBOL(DWC_UDELAY); -+ int result = wait_event_interruptible(wq->queue, -+ cond(data) || wq->abort); -+ if (result == -ERESTARTSYS) { -+ wq->abort = 0; -+ return -DWC_E_RESTART; -+ } - --void DWC_MDELAY(uint32_t msecs) --{ -- mdelay(msecs); -+ if (wq->abort == 1) { -+ wq->abort = 0; -+ return -DWC_E_ABORT; -+ } -+ -+ wq->abort = 0; -+ -+ if (result == 0) { -+ return 0; -+ } -+ -+ return -DWC_E_UNKNOWN; - } --EXPORT_SYMBOL(DWC_MDELAY); - --void DWC_MSLEEP(uint32_t msecs) -+int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, -+ void *data, int32_t msecs) - { -- msleep(msecs); -+ int32_t tmsecs; -+ int result = wait_event_interruptible_timeout(wq->queue, -+ cond(data) || wq->abort, -+ msecs_to_jiffies(msecs)); -+ if (result == -ERESTARTSYS) { -+ wq->abort = 0; -+ return -DWC_E_RESTART; -+ } -+ -+ if (wq->abort == 1) { -+ wq->abort = 0; -+ return -DWC_E_ABORT; -+ } -+ -+ wq->abort = 0; -+ -+ if (result > 0) { -+ tmsecs = jiffies_to_msecs(result); -+ if (!tmsecs) { -+ return 1; -+ } -+ -+ return tmsecs; -+ } -+ -+ if (result == 0) { -+ return -DWC_E_TIMEOUT; -+ } -+ -+ return -DWC_E_UNKNOWN; - } --EXPORT_SYMBOL(DWC_MSLEEP); - --uint32_t DWC_TIME(void) -+void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) - { -- return jiffies_to_msecs(jiffies); -+ wq->abort = 0; -+ wake_up_interruptible(&wq->queue); - } --EXPORT_SYMBOL(DWC_TIME); - -+void DWC_WAITQ_ABORT(dwc_waitq_t *wq) -+{ -+ wq->abort = 1; -+ wake_up_interruptible(&wq->queue); -+} - --/* Wait Queues */ - --struct dwc_waitq -+/* Threading */ -+ -+dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) - { -- wait_queue_head_t queue; -- int abort; -+ struct task_struct *thread = kthread_run(func, data, name); -+ -+ if (thread == ERR_PTR(-ENOMEM)) { -+ return NULL; -+ } -+ -+ return (dwc_thread_t *)thread; -+} -+ -+int DWC_THREAD_STOP(dwc_thread_t *thread) -+{ -+ return kthread_stop((struct task_struct *)thread); -+} -+ -+dwc_bool_t DWC_THREAD_SHOULD_STOP(void) -+{ -+ return kthread_should_stop(); -+} -+ -+ -+/* tasklets -+ - run in interrupt context (cannot sleep) -+ - each tasklet runs on a single CPU -+ - different tasklets can be running simultaneously on different CPUs -+ */ -+struct dwc_tasklet { -+ struct tasklet_struct t; -+ dwc_tasklet_callback_t cb; -+ void *data; - }; - --dwc_waitq_t *DWC_WAITQ_ALLOC(void) -+static void tasklet_callback(unsigned long data) - { -- dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); -- init_waitqueue_head(&wq->queue); -- wq->abort = 0; -- return wq; -+ dwc_tasklet_t *t = (dwc_tasklet_t *)data; -+ t->cb(t->data); - } --EXPORT_SYMBOL(DWC_WAITQ_ALLOC); - --void DWC_WAITQ_FREE(dwc_waitq_t *wq) -+dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) -+{ -+ dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t)); -+ -+ if (t) { -+ t->cb = cb; -+ t->data = data; -+ tasklet_init(&t->t, tasklet_callback, (unsigned long)t); -+ } else { -+ DWC_ERROR("Cannot allocate memory for tasklet\n"); -+ } -+ -+ return t; -+} -+ -+void DWC_TASK_FREE(dwc_tasklet_t *task) -+{ -+ DWC_FREE(task); -+} -+ -+void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) - { -+ tasklet_schedule(&task->t); -+} -+ -+ -+/* workqueues -+ - run in process context (can sleep) -+ */ -+typedef struct work_container { -+ dwc_work_callback_t cb; -+ void *data; -+ dwc_workq_t *wq; -+ char *name; -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_ENTRY(work_container) entry; -+#endif -+ struct delayed_work work; -+} work_container_t; -+ -+#ifdef DEBUG -+DWC_CIRCLEQ_HEAD(work_container_queue, work_container); -+#endif -+ -+struct dwc_workq { -+ struct workqueue_struct *wq; -+ dwc_spinlock_t *lock; -+ dwc_waitq_t *waitq; -+ int pending; -+ -+#ifdef DEBUG -+ struct work_container_queue entries; -+#endif -+}; -+ -+static void do_work(struct work_struct *work) -+{ -+ dwc_irqflags_t flags; -+ struct delayed_work *dw = container_of(work, struct delayed_work, work); -+ work_container_t *container = container_of(dw, struct work_container, work); -+ dwc_workq_t *wq = container->wq; -+ -+ container->cb(container->data); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); -+#endif -+ DWC_DEBUGC("Work done: %s, container=%p", container->name, container); -+ if (container->name) { -+ DWC_FREE(container->name); -+ } -+ DWC_FREE(container); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending--; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+} -+ -+static int work_done(void *data) -+{ -+ dwc_workq_t *workq = (dwc_workq_t *)data; -+ return workq->pending == 0; -+} -+ -+int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) -+{ -+ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); -+} -+ -+dwc_workq_t *DWC_WORKQ_ALLOC(char *name) -+{ -+ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ -+ if (!wq) { -+ return NULL; -+ } -+ -+ wq->wq = create_singlethread_workqueue(name); -+ if (!wq->wq) { -+ goto no_wq; -+ } -+ -+ wq->pending = 0; -+ -+ wq->lock = DWC_SPINLOCK_ALLOC(); -+ if (!wq->lock) { -+ goto no_lock; -+ } -+ -+ wq->waitq = DWC_WAITQ_ALLOC(); -+ if (!wq->waitq) { -+ goto no_waitq; -+ } -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INIT(&wq->entries); -+#endif -+ return wq; -+ -+ no_waitq: -+ DWC_SPINLOCK_FREE(wq->lock); -+ no_lock: -+ destroy_workqueue(wq->wq); -+ no_wq: - DWC_FREE(wq); -+ -+ return NULL; - } --EXPORT_SYMBOL(DWC_WAITQ_FREE); - --static int32_t check_result(dwc_waitq_t *wq, int result) --{ int32_t msecs; -- if (result > 0) { -- msecs = jiffies_to_msecs(result); -- if (!msecs) { -- return 1; -+void DWC_WORKQ_FREE(dwc_workq_t *wq) -+{ -+#ifdef DEBUG -+ if (wq->pending != 0) { -+ struct work_container *wc; -+ DWC_ERROR("Destroying work queue with pending work"); -+ DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { -+ DWC_ERROR("Work %s still pending", wc->name); - } -- return msecs; - } -+#endif -+ destroy_workqueue(wq->wq); -+ DWC_SPINLOCK_FREE(wq->lock); -+ DWC_WAITQ_FREE(wq->waitq); -+ DWC_FREE(wq); -+} - -- if (result == 0) { -- return -DWC_E_TIMEOUT; -+void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, -+ char *format, ...) -+{ -+ dwc_irqflags_t flags; -+ work_container_t *container; -+ static char name[128]; -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ if (!container) { -+ DWC_ERROR("Cannot allocate memory for container\n"); -+ return; - } - -- if ((result == -ERESTARTSYS) || (wq->abort == 1)) { -- return -DWC_E_ABORT; -+ container->name = DWC_STRDUP(name); -+ if (!container->name) { -+ DWC_ERROR("Cannot allocate memory for container->name\n"); -+ DWC_FREE(container); -+ return; - } - -- return -DWC_E_UNKNOWN; -+ container->cb = cb; -+ container->data = data; -+ container->wq = wq; -+ DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container); -+ INIT_WORK(&container->work.work, do_work); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); -+#endif -+ queue_work(wq->wq, &container->work.work); - } - --int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data) -+void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, -+ void *data, uint32_t time, char *format, ...) - { -- int result = wait_event_interruptible(wq->queue, -- condition(data) || wq->abort); -- return check_result(wq, result); -+ dwc_irqflags_t flags; -+ work_container_t *container; -+ static char name[128]; -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ if (!container) { -+ DWC_ERROR("Cannot allocate memory for container\n"); -+ return; -+ } -+ -+ container->name = DWC_STRDUP(name); -+ if (!container->name) { -+ DWC_ERROR("Cannot allocate memory for container->name\n"); -+ DWC_FREE(container); -+ return; -+ } -+ -+ container->cb = cb; -+ container->data = data; -+ container->wq = wq; -+ DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container); -+ INIT_DELAYED_WORK(&container->work, do_work); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); -+#endif -+ queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); - } --EXPORT_SYMBOL(DWC_WAITQ_WAIT); - --int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, -- void *data, int32_t msecs) -+int DWC_WORKQ_PENDING(dwc_workq_t *wq) - { -- int result = wait_event_interruptible_timeout(wq->queue, -- condition(data) || wq->abort, -- msecs_to_jiffies(msecs)); -- return check_result(wq, result); -+ return wq->pending; - } -+ -+ -+#ifdef DWC_LIBMODULE -+ -+#ifdef DWC_CCLIB -+/* CC */ -+EXPORT_SYMBOL(dwc_cc_if_alloc); -+EXPORT_SYMBOL(dwc_cc_if_free); -+EXPORT_SYMBOL(dwc_cc_clear); -+EXPORT_SYMBOL(dwc_cc_add); -+EXPORT_SYMBOL(dwc_cc_remove); -+EXPORT_SYMBOL(dwc_cc_change); -+EXPORT_SYMBOL(dwc_cc_data_for_save); -+EXPORT_SYMBOL(dwc_cc_restore_from_data); -+EXPORT_SYMBOL(dwc_cc_match_chid); -+EXPORT_SYMBOL(dwc_cc_match_cdid); -+EXPORT_SYMBOL(dwc_cc_ck); -+EXPORT_SYMBOL(dwc_cc_chid); -+EXPORT_SYMBOL(dwc_cc_cdid); -+EXPORT_SYMBOL(dwc_cc_name); -+#endif /* DWC_CCLIB */ -+ -+#ifdef DWC_CRYPTOLIB -+# ifndef CONFIG_MACH_IPMATE -+/* Modpow */ -+EXPORT_SYMBOL(dwc_modpow); -+ -+/* DH */ -+EXPORT_SYMBOL(dwc_dh_modpow); -+EXPORT_SYMBOL(dwc_dh_derive_keys); -+EXPORT_SYMBOL(dwc_dh_pk); -+# endif /* CONFIG_MACH_IPMATE */ -+ -+/* Crypto */ -+EXPORT_SYMBOL(dwc_wusb_aes_encrypt); -+EXPORT_SYMBOL(dwc_wusb_cmf); -+EXPORT_SYMBOL(dwc_wusb_prf); -+EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce); -+EXPORT_SYMBOL(dwc_wusb_gen_nonce); -+EXPORT_SYMBOL(dwc_wusb_gen_key); -+EXPORT_SYMBOL(dwc_wusb_gen_mic); -+#endif /* DWC_CRYPTOLIB */ -+ -+/* Notification */ -+#ifdef DWC_NOTIFYLIB -+EXPORT_SYMBOL(dwc_alloc_notification_manager); -+EXPORT_SYMBOL(dwc_free_notification_manager); -+EXPORT_SYMBOL(dwc_register_notifier); -+EXPORT_SYMBOL(dwc_unregister_notifier); -+EXPORT_SYMBOL(dwc_add_observer); -+EXPORT_SYMBOL(dwc_remove_observer); -+EXPORT_SYMBOL(dwc_notify); -+#endif -+ -+/* Memory Debugging Routines */ -+#ifdef DWC_DEBUG_MEMORY -+EXPORT_SYMBOL(dwc_alloc_debug); -+EXPORT_SYMBOL(dwc_alloc_atomic_debug); -+EXPORT_SYMBOL(dwc_free_debug); -+EXPORT_SYMBOL(dwc_dma_alloc_debug); -+EXPORT_SYMBOL(dwc_dma_free_debug); -+#endif -+ -+EXPORT_SYMBOL(DWC_MEMSET); -+EXPORT_SYMBOL(DWC_MEMCPY); -+EXPORT_SYMBOL(DWC_MEMMOVE); -+EXPORT_SYMBOL(DWC_MEMCMP); -+EXPORT_SYMBOL(DWC_STRNCMP); -+EXPORT_SYMBOL(DWC_STRCMP); -+EXPORT_SYMBOL(DWC_STRLEN); -+EXPORT_SYMBOL(DWC_STRCPY); -+EXPORT_SYMBOL(DWC_STRDUP); -+EXPORT_SYMBOL(DWC_ATOI); -+EXPORT_SYMBOL(DWC_ATOUI); -+ -+#ifdef DWC_UTFLIB -+EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE); -+#endif /* DWC_UTFLIB */ -+ -+EXPORT_SYMBOL(DWC_IN_IRQ); -+EXPORT_SYMBOL(DWC_IN_BH); -+EXPORT_SYMBOL(DWC_VPRINTF); -+EXPORT_SYMBOL(DWC_VSNPRINTF); -+EXPORT_SYMBOL(DWC_PRINTF); -+EXPORT_SYMBOL(DWC_SPRINTF); -+EXPORT_SYMBOL(DWC_SNPRINTF); -+EXPORT_SYMBOL(__DWC_WARN); -+EXPORT_SYMBOL(__DWC_ERROR); -+EXPORT_SYMBOL(DWC_EXCEPTION); -+ -+#ifdef DEBUG -+EXPORT_SYMBOL(__DWC_DEBUG); -+#endif -+ -+EXPORT_SYMBOL(__DWC_DMA_ALLOC); -+EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); -+EXPORT_SYMBOL(__DWC_DMA_FREE); -+EXPORT_SYMBOL(__DWC_ALLOC); -+EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC); -+EXPORT_SYMBOL(__DWC_FREE); -+ -+#ifdef DWC_CRYPTOLIB -+EXPORT_SYMBOL(DWC_RANDOM_BYTES); -+EXPORT_SYMBOL(DWC_AES_CBC); -+EXPORT_SYMBOL(DWC_SHA256); -+EXPORT_SYMBOL(DWC_HMAC_SHA256); -+#endif -+ -+EXPORT_SYMBOL(DWC_CPU_TO_LE32); -+EXPORT_SYMBOL(DWC_CPU_TO_BE32); -+EXPORT_SYMBOL(DWC_LE32_TO_CPU); -+EXPORT_SYMBOL(DWC_BE32_TO_CPU); -+EXPORT_SYMBOL(DWC_CPU_TO_LE16); -+EXPORT_SYMBOL(DWC_CPU_TO_BE16); -+EXPORT_SYMBOL(DWC_LE16_TO_CPU); -+EXPORT_SYMBOL(DWC_BE16_TO_CPU); -+EXPORT_SYMBOL(DWC_READ_REG32); -+EXPORT_SYMBOL(DWC_WRITE_REG32); -+EXPORT_SYMBOL(DWC_MODIFY_REG32); -+ -+#if 0 -+EXPORT_SYMBOL(DWC_READ_REG64); -+EXPORT_SYMBOL(DWC_WRITE_REG64); -+EXPORT_SYMBOL(DWC_MODIFY_REG64); -+#endif -+ -+EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC); -+EXPORT_SYMBOL(DWC_SPINLOCK_FREE); -+EXPORT_SYMBOL(DWC_SPINLOCK); -+EXPORT_SYMBOL(DWC_SPINUNLOCK); -+EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE); -+EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE); -+EXPORT_SYMBOL(DWC_MUTEX_ALLOC); -+ -+#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES)) -+EXPORT_SYMBOL(DWC_MUTEX_FREE); -+#endif -+ -+EXPORT_SYMBOL(DWC_MUTEX_LOCK); -+EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK); -+EXPORT_SYMBOL(DWC_MUTEX_UNLOCK); -+EXPORT_SYMBOL(DWC_UDELAY); -+EXPORT_SYMBOL(DWC_MDELAY); -+EXPORT_SYMBOL(DWC_MSLEEP); -+EXPORT_SYMBOL(DWC_TIME); -+EXPORT_SYMBOL(DWC_TIMER_ALLOC); -+EXPORT_SYMBOL(DWC_TIMER_FREE); -+EXPORT_SYMBOL(DWC_TIMER_SCHEDULE); -+EXPORT_SYMBOL(DWC_TIMER_CANCEL); -+EXPORT_SYMBOL(DWC_WAITQ_ALLOC); -+EXPORT_SYMBOL(DWC_WAITQ_FREE); -+EXPORT_SYMBOL(DWC_WAITQ_WAIT); - EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT); -+EXPORT_SYMBOL(DWC_WAITQ_TRIGGER); -+EXPORT_SYMBOL(DWC_WAITQ_ABORT); -+EXPORT_SYMBOL(DWC_THREAD_RUN); -+EXPORT_SYMBOL(DWC_THREAD_STOP); -+EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP); -+EXPORT_SYMBOL(DWC_TASK_ALLOC); -+EXPORT_SYMBOL(DWC_TASK_FREE); -+EXPORT_SYMBOL(DWC_TASK_SCHEDULE); -+EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE); -+EXPORT_SYMBOL(DWC_WORKQ_ALLOC); -+EXPORT_SYMBOL(DWC_WORKQ_FREE); -+EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE); -+EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED); -+EXPORT_SYMBOL(DWC_WORKQ_PENDING); - --void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) -+static int dwc_common_port_init_module(void) - { -- wake_up_interruptible(&wq->queue); -+ int result = 0; -+ -+ printk(KERN_DEBUG "Module dwc_common_port init\n" ); -+ -+#ifdef DWC_DEBUG_MEMORY -+ result = dwc_memory_debug_start(NULL); -+ if (result) { -+ printk(KERN_ERR -+ "dwc_memory_debug_start() failed with error %d\n", -+ result); -+ return result; -+ } -+#endif -+ -+#ifdef DWC_NOTIFYLIB -+ result = dwc_alloc_notification_manager(NULL, NULL); -+ if (result) { -+ printk(KERN_ERR -+ "dwc_alloc_notification_manager() failed with error %d\n", -+ result); -+ return result; -+ } -+#endif -+ return result; - } --EXPORT_SYMBOL(DWC_WAITQ_TRIGGER); - --void DWC_WAITQ_ABORT(dwc_waitq_t *wq) -+static void dwc_common_port_exit_module(void) - { -- wq->abort = 1; -- DWC_WAITQ_TRIGGER(wq); -+ printk(KERN_DEBUG "Module dwc_common_port exit\n" ); -+ -+#ifdef DWC_NOTIFYLIB -+ dwc_free_notification_manager(); -+#endif -+ -+#ifdef DWC_DEBUG_MEMORY -+ dwc_memory_debug_stop(); -+#endif - } --EXPORT_SYMBOL(DWC_WAITQ_ABORT); -+ -+module_init(dwc_common_port_init_module); -+module_exit(dwc_common_port_exit_module); -+ -+MODULE_DESCRIPTION("DWC Common Library - Portable version"); -+MODULE_AUTHOR("Synopsys Inc."); -+MODULE_LICENSE ("GPL"); -+ -+#endif /* DWC_LIBMODULE */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c -new file mode 100644 -index 0000000..49b07e1 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c -@@ -0,0 +1,1275 @@ -+#include "dwc_os.h" -+#include "dwc_list.h" -+ -+#ifdef DWC_CCLIB -+# include "dwc_cc.h" -+#endif -+ -+#ifdef DWC_CRYPTOLIB -+# include "dwc_modpow.h" -+# include "dwc_dh.h" -+# include "dwc_crypto.h" -+#endif -+ -+#ifdef DWC_NOTIFYLIB -+# include "dwc_notifier.h" -+#endif -+ -+/* OS-Level Implementations */ -+ -+/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */ -+ -+ -+/* MISC */ -+ -+void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) -+{ -+ return memset(dest, byte, size); -+} -+ -+void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) -+{ -+ return memcpy(dest, src, size); -+} -+ -+void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) -+{ -+ bcopy(src, dest, size); -+ return dest; -+} -+ -+int DWC_MEMCMP(void *m1, void *m2, uint32_t size) -+{ -+ return memcmp(m1, m2, size); -+} -+ -+int DWC_STRNCMP(void *s1, void *s2, uint32_t size) -+{ -+ return strncmp(s1, s2, size); -+} -+ -+int DWC_STRCMP(void *s1, void *s2) -+{ -+ return strcmp(s1, s2); -+} -+ -+int DWC_STRLEN(char const *str) -+{ -+ return strlen(str); -+} -+ -+char *DWC_STRCPY(char *to, char const *from) -+{ -+ return strcpy(to, from); -+} -+ -+char *DWC_STRDUP(char const *str) -+{ -+ int len = DWC_STRLEN(str) + 1; -+ char *new = DWC_ALLOC_ATOMIC(len); -+ -+ if (!new) { -+ return NULL; -+ } -+ -+ DWC_MEMCPY(new, str, len); -+ return new; -+} -+ -+int DWC_ATOI(char *str, int32_t *value) -+{ -+ char *end = NULL; -+ -+ /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul' -+ * should be equivalent on 2's complement machines -+ */ -+ *value = strtoul(str, &end, 0); -+ if (*end == '\0') { -+ return 0; -+ } -+ -+ return -1; -+} -+ -+int DWC_ATOUI(char *str, uint32_t *value) -+{ -+ char *end = NULL; -+ -+ *value = strtoul(str, &end, 0); -+ if (*end == '\0') { -+ return 0; -+ } -+ -+ return -1; -+} -+ -+ -+#ifdef DWC_UTFLIB -+/* From usbstring.c */ -+ -+int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) -+{ -+ int count = 0; -+ u8 c; -+ u16 uchar; -+ -+ /* this insists on correct encodings, though not minimal ones. -+ * BUT it currently rejects legit 4-byte UTF-8 code points, -+ * which need surrogate pairs. (Unicode 3.1 can use them.) -+ */ -+ while (len != 0 && (c = (u8) *s++) != 0) { -+ if (unlikely(c & 0x80)) { -+ // 2-byte sequence: -+ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx -+ if ((c & 0xe0) == 0xc0) { -+ uchar = (c & 0x1f) << 6; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c; -+ -+ // 3-byte sequence (most CJKV characters): -+ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx -+ } else if ((c & 0xf0) == 0xe0) { -+ uchar = (c & 0x0f) << 12; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c << 6; -+ -+ c = (u8) *s++; -+ if ((c & 0xc0) != 0xc0) -+ goto fail; -+ c &= 0x3f; -+ uchar |= c; -+ -+ /* no bogus surrogates */ -+ if (0xd800 <= uchar && uchar <= 0xdfff) -+ goto fail; -+ -+ // 4-byte sequence (surrogate pairs, currently rare): -+ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx -+ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx -+ // (uuuuu = wwww + 1) -+ // FIXME accept the surrogate code points (only) -+ } else -+ goto fail; -+ } else -+ uchar = c; -+ put_unaligned (cpu_to_le16 (uchar), cp++); -+ count++; -+ len--; -+ } -+ return count; -+fail: -+ return -1; -+} -+ -+#endif /* DWC_UTFLIB */ -+ -+ -+/* dwc_debug.h */ -+ -+dwc_bool_t DWC_IN_IRQ(void) -+{ -+// return in_irq(); -+ return 0; -+} -+ -+dwc_bool_t DWC_IN_BH(void) -+{ -+// return in_softirq(); -+ return 0; -+} -+ -+void DWC_VPRINTF(char *format, va_list args) -+{ -+ vprintf(format, args); -+} -+ -+int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) -+{ -+ return vsnprintf(str, size, format, args); -+} -+ -+void DWC_PRINTF(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+ -+int DWC_SPRINTF(char *buffer, char *format, ...) -+{ -+ int retval; -+ va_list args; -+ -+ va_start(args, format); -+ retval = vsprintf(buffer, format, args); -+ va_end(args); -+ return retval; -+} -+ -+int DWC_SNPRINTF(char *buffer, int size, char *format, ...) -+{ -+ int retval; -+ va_list args; -+ -+ va_start(args, format); -+ retval = vsnprintf(buffer, size, format, args); -+ va_end(args); -+ return retval; -+} -+ -+void __DWC_WARN(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+ -+void __DWC_ERROR(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+ -+void DWC_EXCEPTION(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+// BUG_ON(1); ??? -+} -+ -+#ifdef DEBUG -+void __DWC_DEBUG(char *format, ...) -+{ -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VPRINTF(format, args); -+ va_end(args); -+} -+#endif -+ -+ -+/* dwc_mem.h */ -+ -+#if 0 -+dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, -+ uint32_t align, -+ uint32_t alloc) -+{ -+ struct dma_pool *pool = dma_pool_create("Pool", NULL, -+ size, align, alloc); -+ return (dwc_pool_t *)pool; -+} -+ -+void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) -+{ -+ dma_pool_destroy((struct dma_pool *)pool); -+} -+ -+void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) -+{ -+// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); -+ return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr); -+} -+ -+void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) -+{ -+ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); -+ memset(..); -+} -+ -+void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) -+{ -+ dma_pool_free(pool, vaddr, daddr); -+} -+#endif -+ -+void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) -+{ -+ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; -+ int error; -+ -+ error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs, -+ sizeof(dma->segs) / sizeof(dma->segs[0]), -+ &dma->nsegs, BUS_DMA_NOWAIT); -+ if (error) { -+ printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__, -+ (uintmax_t)size, error); -+ goto fail_0; -+ } -+ -+ error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size, -+ (caddr_t *)&dma->dma_vaddr, -+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT); -+ if (error) { -+ printf("%s: bus_dmamem_map failed: %d\n", __func__, error); -+ goto fail_1; -+ } -+ -+ error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0, -+ BUS_DMA_NOWAIT, &dma->dma_map); -+ if (error) { -+ printf("%s: bus_dmamap_create failed: %d\n", __func__, error); -+ goto fail_2; -+ } -+ -+ error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, -+ size, NULL, BUS_DMA_NOWAIT); -+ if (error) { -+ printf("%s: bus_dmamap_load failed: %d\n", __func__, error); -+ goto fail_3; -+ } -+ -+ dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr; -+ *dma_addr = dma->dma_paddr; -+ return dma->dma_vaddr; -+ -+fail_3: -+ bus_dmamap_destroy(dma->dma_tag, dma->dma_map); -+fail_2: -+ bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size); -+fail_1: -+ bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs); -+fail_0: -+ dma->dma_map = NULL; -+ dma->dma_vaddr = NULL; -+ dma->nsegs = 0; -+ -+ return NULL; -+} -+ -+void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) -+{ -+ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; -+ -+ if (dma->dma_map != NULL) { -+ bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size, -+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); -+ bus_dmamap_unload(dma->dma_tag, dma->dma_map); -+ bus_dmamap_destroy(dma->dma_tag, dma->dma_map); -+ bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size); -+ bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs); -+ dma->dma_paddr = 0; -+ dma->dma_map = NULL; -+ dma->dma_vaddr = NULL; -+ dma->nsegs = 0; -+ } -+} -+ -+void *__DWC_ALLOC(void *mem_ctx, uint32_t size) -+{ -+ return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); -+} -+ -+void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) -+{ -+ return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); -+} -+ -+void __DWC_FREE(void *mem_ctx, void *addr) -+{ -+ free(addr, M_DEVBUF); -+} -+ -+ -+#ifdef DWC_CRYPTOLIB -+/* dwc_crypto.h */ -+ -+void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) -+{ -+ get_random_bytes(buffer, length); -+} -+ -+int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) -+{ -+ struct crypto_blkcipher *tfm; -+ struct blkcipher_desc desc; -+ struct scatterlist sgd; -+ struct scatterlist sgs; -+ -+ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); -+ if (tfm == NULL) { -+ printk("failed to load transform for aes CBC\n"); -+ return -1; -+ } -+ -+ crypto_blkcipher_setkey(tfm, key, keylen); -+ crypto_blkcipher_set_iv(tfm, iv, 16); -+ -+ sg_init_one(&sgd, out, messagelen); -+ sg_init_one(&sgs, message, messagelen); -+ -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { -+ crypto_free_blkcipher(tfm); -+ DWC_ERROR("AES CBC encryption failed"); -+ return -1; -+ } -+ -+ crypto_free_blkcipher(tfm); -+ return 0; -+} -+ -+int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) -+{ -+ struct crypto_hash *tfm; -+ struct hash_desc desc; -+ struct scatterlist sg; -+ -+ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); -+ if (IS_ERR(tfm)) { -+ DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm)); -+ return 0; -+ } -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ sg_init_one(&sg, message, len); -+ crypto_hash_digest(&desc, &sg, len, out); -+ crypto_free_hash(tfm); -+ -+ return 1; -+} -+ -+int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, -+ uint8_t *key, uint32_t keylen, uint8_t *out) -+{ -+ struct crypto_hash *tfm; -+ struct hash_desc desc; -+ struct scatterlist sg; -+ -+ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); -+ if (IS_ERR(tfm)) { -+ DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm)); -+ return 0; -+ } -+ desc.tfm = tfm; -+ desc.flags = 0; -+ -+ sg_init_one(&sg, message, messagelen); -+ crypto_hash_setkey(tfm, key, keylen); -+ crypto_hash_digest(&desc, &sg, messagelen, out); -+ crypto_free_hash(tfm); -+ -+ return 1; -+} -+ -+#endif /* DWC_CRYPTOLIB */ -+ -+ -+/* Byte Ordering Conversions */ -+ -+uint32_t DWC_CPU_TO_LE32(uint32_t *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+ -+uint32_t DWC_CPU_TO_BE32(uint32_t *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+ -+uint32_t DWC_LE32_TO_CPU(uint32_t *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+ -+uint32_t DWC_BE32_TO_CPU(uint32_t *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+#endif -+} -+ -+uint16_t DWC_CPU_TO_LE16(uint16_t *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+ -+uint16_t DWC_CPU_TO_BE16(uint16_t *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+ -+uint16_t DWC_LE16_TO_CPU(uint16_t *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+ -+uint16_t DWC_BE16_TO_CPU(uint16_t *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *p; -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+ -+ -+/* Registers */ -+ -+uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ return bus_space_read_4(io->iot, io->ioh, ior); -+} -+ -+#if 0 -+uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ return bus_space_read_8(io->iot, io->ioh, ior); -+} -+#endif -+ -+void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ bus_space_write_4(io->iot, io->ioh, ior, value); -+} -+ -+#if 0 -+void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ bus_space_write_8(io->iot, io->ioh, ior, value); -+} -+#endif -+ -+void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, -+ uint32_t set_mask) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ bus_space_write_4(io->iot, io->ioh, ior, -+ (bus_space_read_4(io->iot, io->ioh, ior) & -+ ~clear_mask) | set_mask); -+} -+ -+#if 0 -+void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, -+ uint64_t set_mask) -+{ -+ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; -+ bus_size_t ior = (bus_size_t)reg; -+ -+ bus_space_write_8(io->iot, io->ioh, ior, -+ (bus_space_read_8(io->iot, io->ioh, ior) & -+ ~clear_mask) | set_mask); -+} -+#endif -+ -+ -+/* Locking */ -+ -+dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) -+{ -+ struct simplelock *sl = DWC_ALLOC(sizeof(*sl)); -+ -+ if (!sl) { -+ DWC_ERROR("Cannot allocate memory for spinlock"); -+ return NULL; -+ } -+ -+ simple_lock_init(sl); -+ return (dwc_spinlock_t *)sl; -+} -+ -+void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) -+{ -+ struct simplelock *sl = (struct simplelock *)lock; -+ -+ DWC_FREE(sl); -+} -+ -+void DWC_SPINLOCK(dwc_spinlock_t *lock) -+{ -+ simple_lock((struct simplelock *)lock); -+} -+ -+void DWC_SPINUNLOCK(dwc_spinlock_t *lock) -+{ -+ simple_unlock((struct simplelock *)lock); -+} -+ -+void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) -+{ -+ simple_lock((struct simplelock *)lock); -+ *flags = splbio(); -+} -+ -+void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) -+{ -+ splx(flags); -+ simple_unlock((struct simplelock *)lock); -+} -+ -+dwc_mutex_t *DWC_MUTEX_ALLOC(void) -+{ -+ dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock)); -+ -+ if (!mutex) { -+ DWC_ERROR("Cannot allocate memory for mutex"); -+ return NULL; -+ } -+ -+ lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0); -+ return mutex; -+} -+ -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+#else -+void DWC_MUTEX_FREE(dwc_mutex_t *mutex) -+{ -+ DWC_FREE(mutex); -+} -+#endif -+ -+void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) -+{ -+ lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL); -+} -+ -+int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) -+{ -+ int status; -+ -+ status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL); -+ return status == 0; -+} -+ -+void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) -+{ -+ lockmgr((struct lock *)mutex, LK_RELEASE, NULL); -+} -+ -+ -+/* Timing */ -+ -+void DWC_UDELAY(uint32_t usecs) -+{ -+ DELAY(usecs); -+} -+ -+void DWC_MDELAY(uint32_t msecs) -+{ -+ do { -+ DELAY(1000); -+ } while (--msecs); -+} -+ -+void DWC_MSLEEP(uint32_t msecs) -+{ -+ struct timeval tv; -+ -+ tv.tv_sec = msecs / 1000; -+ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; -+ tsleep(&tv, 0, "dw3slp", tvtohz(&tv)); -+} -+ -+uint32_t DWC_TIME(void) -+{ -+ struct timeval tv; -+ -+ microuptime(&tv); // or getmicrouptime? (less precise, but faster) -+ return tv.tv_sec * 1000 + tv.tv_usec / 1000; -+} -+ -+ -+/* Timers */ -+ -+struct dwc_timer { -+ struct callout t; -+ char *name; -+ dwc_spinlock_t *lock; -+ dwc_timer_callback_t cb; -+ void *data; -+}; -+ -+dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) -+{ -+ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); -+ -+ if (!t) { -+ DWC_ERROR("Cannot allocate memory for timer"); -+ return NULL; -+ } -+ -+ callout_init(&t->t); -+ -+ t->name = DWC_STRDUP(name); -+ if (!t->name) { -+ DWC_ERROR("Cannot allocate memory for timer->name"); -+ goto no_name; -+ } -+ -+ t->lock = DWC_SPINLOCK_ALLOC(); -+ if (!t->lock) { -+ DWC_ERROR("Cannot allocate memory for timer->lock"); -+ goto no_lock; -+ } -+ -+ t->cb = cb; -+ t->data = data; -+ -+ return t; -+ -+ no_lock: -+ DWC_FREE(t->name); -+ no_name: -+ DWC_FREE(t); -+ -+ return NULL; -+} -+ -+void DWC_TIMER_FREE(dwc_timer_t *timer) -+{ -+ callout_stop(&timer->t); -+ DWC_SPINLOCK_FREE(timer->lock); -+ DWC_FREE(timer->name); -+ DWC_FREE(timer); -+} -+ -+void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) -+{ -+ struct timeval tv; -+ -+ tv.tv_sec = time / 1000; -+ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; -+ callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data); -+} -+ -+void DWC_TIMER_CANCEL(dwc_timer_t *timer) -+{ -+ callout_stop(&timer->t); -+} -+ -+ -+/* Wait Queues */ -+ -+struct dwc_waitq { -+ struct simplelock lock; -+ int abort; -+}; -+ -+dwc_waitq_t *DWC_WAITQ_ALLOC(void) -+{ -+ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ -+ if (!wq) { -+ DWC_ERROR("Cannot allocate memory for waitqueue"); -+ return NULL; -+ } -+ -+ simple_lock_init(&wq->lock); -+ wq->abort = 0; -+ -+ return wq; -+} -+ -+void DWC_WAITQ_FREE(dwc_waitq_t *wq) -+{ -+ DWC_FREE(wq); -+} -+ -+int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) -+{ -+ int ipl; -+ int result = 0; -+ -+ simple_lock(&wq->lock); -+ ipl = splbio(); -+ -+ /* Skip the sleep if already aborted or triggered */ -+ if (!wq->abort && !cond(data)) { -+ splx(ipl); -+ result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout -+ ipl = splbio(); -+ } -+ -+ if (result == 0) { // awoken -+ if (wq->abort) { -+ wq->abort = 0; -+ result = -DWC_E_ABORT; -+ } else { -+ result = 0; -+ } -+ -+ splx(ipl); -+ simple_unlock(&wq->lock); -+ } else { -+ wq->abort = 0; -+ splx(ipl); -+ simple_unlock(&wq->lock); -+ -+ if (result == ERESTART) { // signaled - restart -+ result = -DWC_E_RESTART; -+ } else { // signaled - must be EINTR -+ result = -DWC_E_ABORT; -+ } -+ } -+ -+ return result; -+} -+ -+int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, -+ void *data, int32_t msecs) -+{ -+ struct timeval tv, tv1, tv2; -+ int ipl; -+ int result = 0; -+ -+ tv.tv_sec = msecs / 1000; -+ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; -+ -+ simple_lock(&wq->lock); -+ ipl = splbio(); -+ -+ /* Skip the sleep if already aborted or triggered */ -+ if (!wq->abort && !cond(data)) { -+ splx(ipl); -+ getmicrouptime(&tv1); -+ result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock); -+ getmicrouptime(&tv2); -+ ipl = splbio(); -+ } -+ -+ if (result == 0) { // awoken -+ if (wq->abort) { -+ wq->abort = 0; -+ splx(ipl); -+ simple_unlock(&wq->lock); -+ result = -DWC_E_ABORT; -+ } else { -+ splx(ipl); -+ simple_unlock(&wq->lock); -+ -+ tv2.tv_usec -= tv1.tv_usec; -+ if (tv2.tv_usec < 0) { -+ tv2.tv_usec += 1000000; -+ tv2.tv_sec--; -+ } -+ -+ tv2.tv_sec -= tv1.tv_sec; -+ result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; -+ result = msecs - result; -+ if (result <= 0) -+ result = 1; -+ } -+ } else { -+ wq->abort = 0; -+ splx(ipl); -+ simple_unlock(&wq->lock); -+ -+ if (result == ERESTART) { // signaled - restart -+ result = -DWC_E_RESTART; -+ -+ } else if (result == EINTR) { // signaled - interrupt -+ result = -DWC_E_ABORT; -+ -+ } else { // timed out -+ result = -DWC_E_TIMEOUT; -+ } -+ } -+ -+ return result; -+} -+ -+void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) -+{ -+ wakeup(wq); -+} -+ -+void DWC_WAITQ_ABORT(dwc_waitq_t *wq) -+{ -+ int ipl; -+ -+ simple_lock(&wq->lock); -+ ipl = splbio(); -+ wq->abort = 1; -+ wakeup(wq); -+ splx(ipl); -+ simple_unlock(&wq->lock); -+} -+ -+ -+/* Threading */ -+ -+struct dwc_thread { -+ struct proc *proc; -+ int abort; -+}; -+ -+dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) -+{ -+ int retval; -+ dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread)); -+ -+ if (!thread) { -+ return NULL; -+ } -+ -+ thread->abort = 0; -+ retval = kthread_create1((void (*)(void *))func, data, &thread->proc, -+ "%s", name); -+ if (retval) { -+ DWC_FREE(thread); -+ return NULL; -+ } -+ -+ return thread; -+} -+ -+int DWC_THREAD_STOP(dwc_thread_t *thread) -+{ -+ int retval; -+ -+ thread->abort = 1; -+ retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz); -+ -+ if (retval == 0) { -+ /* DWC_THREAD_EXIT() will free the thread struct */ -+ return 0; -+ } -+ -+ /* NOTE: We leak the thread struct if thread doesn't die */ -+ -+ if (retval == EWOULDBLOCK) { -+ return -DWC_E_TIMEOUT; -+ } -+ -+ return -DWC_E_UNKNOWN; -+} -+ -+dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread) -+{ -+ return thread->abort; -+} -+ -+void DWC_THREAD_EXIT(dwc_thread_t *thread) -+{ -+ wakeup(&thread->abort); -+ DWC_FREE(thread); -+ kthread_exit(0); -+} -+ -+/* tasklets -+ - Runs in interrupt context (cannot sleep) -+ - Each tasklet runs on a single CPU -+ - Different tasklets can be running simultaneously on different CPUs -+ [ On NetBSD there is no corresponding mechanism, drivers don't have bottom- -+ halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ] -+ */ -+struct dwc_tasklet { -+ dwc_tasklet_callback_t cb; -+ void *data; -+}; -+ -+static void tasklet_callback(void *data) -+{ -+ dwc_tasklet_t *task = (dwc_tasklet_t *)data; -+ -+ task->cb(task->data); -+} -+ -+dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) -+{ -+ dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task)); -+ -+ if (task) { -+ task->cb = cb; -+ task->data = data; -+ } else { -+ DWC_ERROR("Cannot allocate memory for tasklet"); -+ } -+ -+ return task; -+} -+ -+void DWC_TASK_FREE(dwc_tasklet_t *task) -+{ -+ DWC_FREE(task); -+} -+ -+void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) -+{ -+ tasklet_callback(task); -+} -+ -+ -+/* workqueues -+ - Runs in process context (can sleep) -+ */ -+typedef struct work_container { -+ dwc_work_callback_t cb; -+ void *data; -+ dwc_workq_t *wq; -+ char *name; -+ int hz; -+ struct work task; -+} work_container_t; -+ -+struct dwc_workq { -+ struct workqueue *taskq; -+ dwc_spinlock_t *lock; -+ dwc_waitq_t *waitq; -+ int pending; -+ struct work_container *container; -+}; -+ -+static void do_work(struct work *task, void *data) -+{ -+ dwc_workq_t *wq = (dwc_workq_t *)data; -+ work_container_t *container = wq->container; -+ dwc_irqflags_t flags; -+ -+ if (container->hz) { -+ tsleep(container, 0, "dw3wrk", container->hz); -+ } -+ -+ container->cb(container->data); -+ DWC_DEBUG("Work done: %s, container=%p", container->name, container); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ if (container->name) -+ DWC_FREE(container->name); -+ DWC_FREE(container); -+ wq->pending--; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+} -+ -+static int work_done(void *data) -+{ -+ dwc_workq_t *workq = (dwc_workq_t *)data; -+ -+ return workq->pending == 0; -+} -+ -+int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) -+{ -+ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); -+} -+ -+dwc_workq_t *DWC_WORKQ_ALLOC(char *name) -+{ -+ int result; -+ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ -+ if (!wq) { -+ DWC_ERROR("Cannot allocate memory for workqueue"); -+ return NULL; -+ } -+ -+ result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/, -+ IPL_BIO, 0); -+ if (result) { -+ DWC_ERROR("Cannot create workqueue"); -+ goto no_taskq; -+ } -+ -+ wq->pending = 0; -+ -+ wq->lock = DWC_SPINLOCK_ALLOC(); -+ if (!wq->lock) { -+ DWC_ERROR("Cannot allocate memory for spinlock"); -+ goto no_lock; -+ } -+ -+ wq->waitq = DWC_WAITQ_ALLOC(); -+ if (!wq->waitq) { -+ DWC_ERROR("Cannot allocate memory for waitqueue"); -+ goto no_waitq; -+ } -+ -+ return wq; -+ -+ no_waitq: -+ DWC_SPINLOCK_FREE(wq->lock); -+ no_lock: -+ workqueue_destroy(wq->taskq); -+ no_taskq: -+ DWC_FREE(wq); -+ -+ return NULL; -+} -+ -+void DWC_WORKQ_FREE(dwc_workq_t *wq) -+{ -+#ifdef DEBUG -+ dwc_irqflags_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ -+ if (wq->pending != 0) { -+ struct work_container *container = wq->container; -+ -+ DWC_ERROR("Destroying work queue with pending work"); -+ -+ if (container && container->name) { -+ DWC_ERROR("Work %s still pending", container->name); -+ } -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+#endif -+ DWC_WAITQ_FREE(wq->waitq); -+ DWC_SPINLOCK_FREE(wq->lock); -+ workqueue_destroy(wq->taskq); -+ DWC_FREE(wq); -+} -+ -+void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, -+ char *format, ...) -+{ -+ dwc_irqflags_t flags; -+ work_container_t *container; -+ static char name[128]; -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ if (!container) { -+ DWC_ERROR("Cannot allocate memory for container"); -+ return; -+ } -+ -+ container->name = DWC_STRDUP(name); -+ if (!container->name) { -+ DWC_ERROR("Cannot allocate memory for container->name"); -+ DWC_FREE(container); -+ return; -+ } -+ -+ container->cb = cb; -+ container->data = data; -+ container->wq = wq; -+ container->hz = 0; -+ wq->container = container; -+ -+ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); -+ workqueue_enqueue(wq->taskq, &container->task); -+} -+ -+void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, -+ void *data, uint32_t time, char *format, ...) -+{ -+ dwc_irqflags_t flags; -+ work_container_t *container; -+ static char name[128]; -+ struct timeval tv; -+ va_list args; -+ -+ va_start(args, format); -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ if (!container) { -+ DWC_ERROR("Cannot allocate memory for container"); -+ return; -+ } -+ -+ container->name = DWC_STRDUP(name); -+ if (!container->name) { -+ DWC_ERROR("Cannot allocate memory for container->name"); -+ DWC_FREE(container); -+ return; -+ } -+ -+ container->cb = cb; -+ container->data = data; -+ container->wq = wq; -+ tv.tv_sec = time / 1000; -+ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; -+ container->hz = tvtohz(&tv); -+ wq->container = container; -+ -+ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); -+ workqueue_enqueue(wq->taskq, &container->task); -+} -+ -+int DWC_WORKQ_PENDING(dwc_workq_t *wq) -+{ -+ return wq->pending; -+} -diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.c b/drivers/usb/host/dwc_common_port/dwc_crypto.c -new file mode 100644 -index 0000000..3b03532 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c -@@ -0,0 +1,308 @@ -+/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $ -+ * $Revision: #5 $ -+ * $Date: 2010/09/28 $ -+ * $Change: 1596182 $ -+ * -+ * Synopsys Portability Library Software 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. -+ * ========================================================================= */ -+ -+/** @file -+ * This file contains the WUSB cryptographic routines. -+ */ -+ -+#ifdef DWC_CRYPTOLIB -+ -+#include "dwc_crypto.h" -+#include "usb.h" -+ -+#ifdef DEBUG -+static inline void dump_bytes(char *name, uint8_t *bytes, int len) -+{ -+ int i; -+ DWC_PRINTF("%s: ", name); -+ for (i=0; idst == src, then the bytes will be encrypted -+ * in-place. -+ * -+ * @return 0 on success, negative error code on error. -+ */ -+int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst) -+{ -+ u8 block_t[16]; -+ DWC_MEMSET(block_t, 0, 16); -+ -+ return DWC_AES_CBC(src, 16, key, 16, block_t, dst); -+} -+ -+/** -+ * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec. -+ * This function takes a data string and returns the encrypted CBC -+ * Counter-mode MIC. -+ * -+ * @param key The 128-bit symmetric key. -+ * @param nonce The CCM nonce. -+ * @param label The unique 14-byte ASCII text label. -+ * @param bytes The byte array to be encrypted. -+ * @param len Length of the byte array. -+ * @param result Byte array to receive the 8-byte encrypted MIC. -+ */ -+void dwc_wusb_cmf(u8 *key, u8 *nonce, -+ char *label, u8 *bytes, int len, u8 *result) -+{ -+ u8 block_m[16]; -+ u8 block_x[16]; -+ u8 block_t[8]; -+ int idx, blkNum; -+ u16 la = (u16)(len + 14); -+ -+ /* Set the AES-128 key */ -+ //dwc_aes_setkey(tfm, key, 16); -+ -+ /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */ -+ block_m[0] = 0x59; -+ for (idx = 0; idx < 13; idx++) -+ block_m[idx + 1] = nonce[idx]; -+ block_m[14] = 0; -+ block_m[15] = 0; -+ -+ /* Produce the CBC IV */ -+ dwc_wusb_aes_encrypt(block_m, key, block_x); -+ show_block(block_m, "CBC IV in: ", "\n", 0); -+ show_block(block_x, "CBC IV out:", "\n", 0); -+ -+ /* Fill block B1 from l(a) = Blen + 14, and A */ -+ block_x[0] ^= (u8)(la >> 8); -+ block_x[1] ^= (u8)la; -+ for (idx = 0; idx < 14; idx++) -+ block_x[idx + 2] ^= label[idx]; -+ show_block(block_x, "After xor: ", "b1\n", 16); -+ -+ dwc_wusb_aes_encrypt(block_x, key, block_x); -+ show_block(block_x, "After AES: ", "b1\n", 16); -+ -+ idx = 0; -+ blkNum = 0; -+ -+ /* Fill remaining blocks with B */ -+ while (len-- > 0) { -+ block_x[idx] ^= *bytes++; -+ if (++idx >= 16) { -+ idx = 0; -+ show_block(block_x, "After xor: ", "\n", blkNum); -+ dwc_wusb_aes_encrypt(block_x, key, block_x); -+ show_block(block_x, "After AES: ", "\n", blkNum); -+ blkNum++; -+ } -+ } -+ -+ /* Handle partial last block */ -+ if (idx > 0) { -+ show_block(block_x, "After xor: ", "\n", blkNum); -+ dwc_wusb_aes_encrypt(block_x, key, block_x); -+ show_block(block_x, "After AES: ", "\n", blkNum); -+ } -+ -+ /* Save the MIC tag */ -+ DWC_MEMCPY(block_t, block_x, 8); -+ show_block(block_t, "MIC tag : ", NULL, 8); -+ -+ /* Fill block A0 from flags = 0x01, N, and counter = 0 */ -+ block_m[0] = 0x01; -+ block_m[14] = 0; -+ block_m[15] = 0; -+ -+ /* Encrypt the counter */ -+ dwc_wusb_aes_encrypt(block_m, key, block_x); -+ show_block(block_x, "CTR[MIC] : ", NULL, 8); -+ -+ /* XOR with MIC tag */ -+ for (idx = 0; idx < 8; idx++) { -+ block_t[idx] ^= block_x[idx]; -+ } -+ -+ /* Return result to caller */ -+ DWC_MEMCPY(result, block_t, 8); -+ show_block(result, "CCM-MIC : ", NULL, 8); -+ -+} -+ -+/** -+ * The PRF function described in section 6.5 of the WUSB spec. This function -+ * concatenates MIC values returned from dwc_cmf() to create a value of -+ * the requested length. -+ * -+ * @param prf_len Length of the PRF function in bits (64, 128, or 256). -+ * @param key, nonce, label, bytes, len Same as for dwc_cmf(). -+ * @param result Byte array to receive the result. -+ */ -+void dwc_wusb_prf(int prf_len, u8 *key, -+ u8 *nonce, char *label, u8 *bytes, int len, u8 *result) -+{ -+ int i; -+ -+ nonce[0] = 0; -+ for (i = 0; i < prf_len >> 6; i++, nonce[0]++) { -+ dwc_wusb_cmf(key, nonce, label, bytes, len, result); -+ result += 8; -+ } -+} -+ -+/** -+ * Fills in CCM Nonce per the WUSB spec. -+ * -+ * @param[in] haddr Host address. -+ * @param[in] daddr Device address. -+ * @param[in] tkid Session Key(PTK) identifier. -+ * @param[out] nonce Pointer to where the CCM Nonce output is to be written. -+ */ -+void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, -+ uint8_t *nonce) -+{ -+ -+ DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr); -+ -+ DWC_MEMSET(&nonce[0], 0, 16); -+ -+ DWC_MEMCPY(&nonce[6], tkid, 3); -+ nonce[9] = daddr & 0xFF; -+ nonce[10] = (daddr >> 8) & 0xFF; -+ nonce[11] = haddr & 0xFF; -+ nonce[12] = (haddr >> 8) & 0xFF; -+ -+ dump_bytes("CCM nonce", nonce, 16); -+} -+ -+/** -+ * Generates a 16-byte cryptographic-grade random number for the Host/Device -+ * Nonce. -+ */ -+void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce) -+{ -+ uint8_t inonce[16]; -+ uint32_t temp[4]; -+ -+ /* Fill in the Nonce */ -+ DWC_MEMSET(&inonce[0], 0, sizeof(inonce)); -+ inonce[9] = addr & 0xFF; -+ inonce[10] = (addr >> 8) & 0xFF; -+ inonce[11] = inonce[9]; -+ inonce[12] = inonce[10]; -+ -+ /* Collect "randomness samples" */ -+ DWC_RANDOM_BYTES((uint8_t *)temp, 16); -+ -+ dwc_wusb_prf_128((uint8_t *)temp, nonce, -+ "Random Numbers", (uint8_t *)temp, sizeof(temp), -+ nonce); -+} -+ -+/** -+ * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the -+ * WUSB spec. -+ * -+ * @param[in] ccm_nonce Pointer to CCM Nonce. -+ * @param[in] mk Master Key to derive the session from -+ * @param[in] hnonce Pointer to Host Nonce. -+ * @param[in] dnonce Pointer to Device Nonce. -+ * @param[out] kck Pointer to where the KCK output is to be written. -+ * @param[out] ptk Pointer to where the PTK output is to be written. -+ */ -+void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce, -+ uint8_t *dnonce, uint8_t *kck, uint8_t *ptk) -+{ -+ uint8_t idata[32]; -+ uint8_t odata[32]; -+ -+ dump_bytes("ck", mk, 16); -+ dump_bytes("hnonce", hnonce, 16); -+ dump_bytes("dnonce", dnonce, 16); -+ -+ /* The data is the HNonce and DNonce concatenated */ -+ DWC_MEMCPY(&idata[0], hnonce, 16); -+ DWC_MEMCPY(&idata[16], dnonce, 16); -+ -+ dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata); -+ -+ /* Low 16 bytes of the result is the KCK, high 16 is the PTK */ -+ DWC_MEMCPY(kck, &odata[0], 16); -+ DWC_MEMCPY(ptk, &odata[16], 16); -+ -+ dump_bytes("kck", kck, 16); -+ dump_bytes("ptk", ptk, 16); -+} -+ -+/** -+ * Generates the Message Integrity Code over the Handshake data per the -+ * WUSB spec. -+ * -+ * @param ccm_nonce Pointer to CCM Nonce. -+ * @param kck Pointer to Key Confirmation Key. -+ * @param data Pointer to Handshake data to be checked. -+ * @param mic Pointer to where the MIC output is to be written. -+ */ -+void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck, -+ uint8_t *data, uint8_t *mic) -+{ -+ -+ dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC", -+ data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic); -+} -+ -+#endif /* DWC_CRYPTOLIB */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.h b/drivers/usb/host/dwc_common_port/dwc_crypto.h -new file mode 100644 -index 0000000..26fcddc ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h -@@ -0,0 +1,111 @@ -+/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $ -+ * $Revision: #3 $ -+ * $Date: 2010/09/28 $ -+ * $Change: 1596182 $ -+ * -+ * Synopsys Portability Library Software 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_CRYPTO_H_ -+#define _DWC_CRYPTO_H_ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** @file -+ * -+ * This file contains declarations for the WUSB Cryptographic routines as -+ * defined in the WUSB spec. They are only to be used internally by the DWC UWB -+ * modules. -+ */ -+ -+#include "dwc_os.h" -+ -+int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst); -+ -+void dwc_wusb_cmf(u8 *key, u8 *nonce, -+ char *label, u8 *bytes, int len, u8 *result); -+void dwc_wusb_prf(int prf_len, u8 *key, -+ u8 *nonce, char *label, u8 *bytes, int len, u8 *result); -+ -+/** -+ * The PRF-64 function described in section 6.5 of the WUSB spec. -+ * -+ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). -+ */ -+static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce, -+ char *label, u8 *bytes, int len, u8 *result) -+{ -+ dwc_wusb_prf(64, key, nonce, label, bytes, len, result); -+} -+ -+/** -+ * The PRF-128 function described in section 6.5 of the WUSB spec. -+ * -+ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). -+ */ -+static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce, -+ char *label, u8 *bytes, int len, u8 *result) -+{ -+ dwc_wusb_prf(128, key, nonce, label, bytes, len, result); -+} -+ -+/** -+ * The PRF-256 function described in section 6.5 of the WUSB spec. -+ * -+ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). -+ */ -+static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce, -+ char *label, u8 *bytes, int len, u8 *result) -+{ -+ dwc_wusb_prf(256, key, nonce, label, bytes, len, result); -+} -+ -+ -+void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, -+ uint8_t *nonce); -+void dwc_wusb_gen_nonce(uint16_t addr, -+ uint8_t *nonce); -+ -+void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, -+ uint8_t *hnonce, uint8_t *dnonce, -+ uint8_t *kck, uint8_t *ptk); -+ -+ -+void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t -+ *kck, uint8_t *data, uint8_t *mic); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _DWC_CRYPTO_H_ */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_dh.c b/drivers/usb/host/dwc_common_port/dwc_dh.c -new file mode 100644 -index 0000000..997f753 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_dh.c -@@ -0,0 +1,291 @@ -+/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $ -+ * $Revision: #3 $ -+ * $Date: 2010/09/28 $ -+ * $Change: 1596182 $ -+ * -+ * Synopsys Portability Library Software 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. -+ * ========================================================================= */ -+#ifdef DWC_CRYPTOLIB -+ -+#ifndef CONFIG_MACH_IPMATE -+ -+#include "dwc_dh.h" -+#include "dwc_modpow.h" -+ -+#ifdef DEBUG -+/* This function prints out a buffer in the format described in the Association -+ * Model specification. */ -+static void dh_dump(char *str, void *_num, int len) -+{ -+ uint8_t *num = _num; -+ int i; -+ DWC_PRINTF("%s\n", str); -+ for (i = 0; i < len; i ++) { -+ DWC_PRINTF("%02x", num[i]); -+ if (((i + 1) % 2) == 0) DWC_PRINTF(" "); -+ if (((i + 1) % 26) == 0) DWC_PRINTF("\n"); -+ } -+ -+ DWC_PRINTF("\n"); -+} -+#else -+#define dh_dump(_x...) do {; } while(0) -+#endif -+ -+/* Constant g value */ -+static __u32 dh_g[] = { -+ 0x02000000, -+}; -+ -+/* Constant p value */ -+static __u32 dh_p[] = { -+ 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A, -+ 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2, -+ 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4, -+ 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1, -+ 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520, -+ 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E, -+ 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895, -+ 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004, -+ 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6, -+ 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9, -+ 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA, -+ 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF, -+}; -+ -+static void dh_swap_bytes(void *_in, void *_out, uint32_t len) -+{ -+ uint8_t *in = _in; -+ uint8_t *out = _out; -+ int i; -+ for (i=0; inext = (link); \ - (link)->prev = (link); \ --} while(0) -+} while (0) - - #define DWC_LIST_FIRST(link) ((link)->next) - #define DWC_LIST_LAST(link) ((link)->prev) -@@ -113,42 +116,95 @@ - #define DWC_LIST_PREV(link) ((link)->prev) - #define DWC_LIST_EMPTY(link) \ - (DWC_LIST_FIRST(link) == DWC_LIST_END(link)) --#define DWC_LIST_ENTRY(link, type, field) (type *) \ -- ((uint8_t *)(link) - (size_t)(&((type *)0)->field)) -+#define DWC_LIST_ENTRY(link, type, field) \ -+ (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field)) - -+#if 0 - #define DWC_LIST_INSERT_HEAD(list, link) do { \ - (link)->next = (list)->next; \ - (link)->prev = (list); \ -- (list)->next->prev = link; \ -- (list)->next = link; \ --} while(0) -+ (list)->next->prev = (link); \ -+ (list)->next = (link); \ -+} while (0) - - #define DWC_LIST_INSERT_TAIL(list, link) do { \ -- (link)->next = list; \ -+ (link)->next = (list); \ - (link)->prev = (list)->prev; \ -- (list)->prev->next = link; \ -- (list)->prev = link; \ --} while(0) -+ (list)->prev->next = (link); \ -+ (list)->prev = (link); \ -+} while (0) -+#else -+#define DWC_LIST_INSERT_HEAD(list, link) do { \ -+ dwc_list_link_t *__next__ = (list)->next; \ -+ __next__->prev = (link); \ -+ (link)->next = __next__; \ -+ (link)->prev = (list); \ -+ (list)->next = (link); \ -+} while (0) -+ -+#define DWC_LIST_INSERT_TAIL(list, link) do { \ -+ dwc_list_link_t *__prev__ = (list)->prev; \ -+ (list)->prev = (link); \ -+ (link)->next = (list); \ -+ (link)->prev = __prev__; \ -+ __prev__->next = (link); \ -+} while (0) -+#endif -+ -+#if 0 -+static inline void __list_add(struct list_head *new, -+ struct list_head *prev, -+ struct list_head *next) -+{ -+ next->prev = new; -+ new->next = next; -+ new->prev = prev; -+ prev->next = new; -+} -+ -+static inline void list_add(struct list_head *new, struct list_head *head) -+{ -+ __list_add(new, head, head->next); -+} -+ -+static inline void list_add_tail(struct list_head *new, struct list_head *head) -+{ -+ __list_add(new, head->prev, head); -+} -+ -+static inline void __list_del(struct list_head * prev, struct list_head * next) -+{ -+ next->prev = prev; -+ prev->next = next; -+} -+ -+static inline void list_del(struct list_head *entry) -+{ -+ __list_del(entry->prev, entry->next); -+ entry->next = LIST_POISON1; -+ entry->prev = LIST_POISON2; -+} -+#endif - - #define DWC_LIST_REMOVE(link) do { \ - (link)->next->prev = (link)->prev; \ - (link)->prev->next = (link)->next; \ --} while(0) -+} while (0) - - #define DWC_LIST_REMOVE_INIT(link) do { \ - DWC_LIST_REMOVE(link); \ - DWC_LIST_INIT(link); \ --} while(0) -+} while (0) - - #define DWC_LIST_MOVE_HEAD(list, link) do { \ - DWC_LIST_REMOVE(link); \ - DWC_LIST_INSERT_HEAD(list, link); \ --} while(0) -+} while (0) - - #define DWC_LIST_MOVE_TAIL(list, link) do { \ - DWC_LIST_REMOVE(link); \ - DWC_LIST_INSERT_TAIL(list, link); \ --} while(0) -+} while (0) - - #define DWC_LIST_FOREACH(var, list) \ - for((var) = DWC_LIST_FIRST(list); \ -@@ -156,9 +212,9 @@ - (var) = DWC_LIST_NEXT(var)) - - #define DWC_LIST_FOREACH_SAFE(var, var2, list) \ -- for((var) = DWC_LIST_FIRST(list), var2 = DWC_LIST_NEXT(var); \ -+ for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var); \ - (var) != DWC_LIST_END(list); \ -- (var) = (var2), var2 = DWC_LIST_NEXT(var2)) -+ (var) = (var2), (var2) = DWC_LIST_NEXT(var2)) - - #define DWC_LIST_FOREACH_REVERSE(var, list) \ - for((var) = DWC_LIST_LAST(list); \ -@@ -172,15 +228,15 @@ - struct name { \ - struct type *slh_first; /* first element */ \ - } -- --#define DWC_SLIST_HEAD_INITIALIZER(head) \ -+ -+#define DWC_SLIST_HEAD_INITIALIZER(head) \ - { NULL } -- -+ - #define DWC_SLIST_ENTRY(type) \ - struct { \ - struct type *sle_next; /* next element */ \ - } -- -+ - /* - * Singly-linked List access methods. - */ -@@ -189,13 +245,13 @@ struct { \ - #define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) - #define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next) - --#define DWC_SLIST_FOREACH(var, head, field) \ -+#define DWC_SLIST_FOREACH(var, head, field) \ - for((var) = SLIST_FIRST(head); \ - (var) != SLIST_END(head); \ - (var) = SLIST_NEXT(var, field)) - --#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ -- for ((varp) = &SLIST_FIRST((head)); \ -+#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ -+ for((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != SLIST_END(head); \ - (varp) = &SLIST_NEXT((var), field)) - -@@ -206,7 +262,7 @@ struct { \ - SLIST_FIRST(head) = SLIST_END(head); \ - } - --#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ -+#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - (elm)->field.sle_next = (slistelm)->field.sle_next; \ - (slistelm)->field.sle_next = (elm); \ - } while (0) -@@ -237,88 +293,6 @@ struct { \ - } \ - } while (0) - --#if 0 -- --/* -- * List definitions. -- */ --#define DWC_LIST_HEAD(name, type) \ --struct name { \ -- struct type *lh_first; /* first element */ \ --} -- --#define DWC_LIST_HEAD_INITIALIZER(head) \ -- { NULL } -- --#define DWC_LIST_ENTRY(type) \ --struct { \ -- struct type *le_next; /* next element */ \ -- struct type **le_prev; /* address of previous next element */ \ --} -- --/* -- * List access methods -- */ --#define DWC_LIST_FIRST(head) ((head)->lh_first) --#define DWC_LIST_END(head) NULL --#define DWC_LIST_EMPTY(head) (DWC_LIST_FIRST(head) == DWC_LIST_END(head)) --#define DWC_LIST_NEXT(elm, field) ((elm)->field.le_next) -- --#define DWC_LIST_FOREACH(var, head, field) \ -- for((var) = DWC_LIST_FIRST(head); \ -- (var)!= DWC_LIST_END(head); \ -- (var) = DWC_LIST_NEXT(var, field)) --#define DWC_LIST_FOREACH_SAFE(var, var2, head, field) \ -- for((var) = DWC_LIST_FIRST(head), var2 = DWC_LIST_NEXT(var, field); \ -- (var) != DWC_LIST_END(head); \ -- (var) = var2, var2 = DWC_LIST_NEXT(var, field)) -- --/* -- * List functions. -- */ --#define DWC_LIST_INIT(head) do { \ -- DWC_LIST_FIRST(head) = DWC_LIST_END(head); \ --} while (0) -- --#define DWC_LIST_INSERT_AFTER(listelm, elm, field) do { \ -- if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ -- (listelm)->field.le_next->field.le_prev = \ -- &(elm)->field.le_next; \ -- (listelm)->field.le_next = (elm); \ -- (elm)->field.le_prev = &(listelm)->field.le_next; \ --} while (0) -- --#define DWC_LIST_INSERT_BEFORE(listelm, elm, field) do { \ -- (elm)->field.le_prev = (listelm)->field.le_prev; \ -- (elm)->field.le_next = (listelm); \ -- *(listelm)->field.le_prev = (elm); \ -- (listelm)->field.le_prev = &(elm)->field.le_next; \ --} while (0) -- --#define DWC_LIST_INSERT_HEAD(head, elm, field) do { \ -- if (((elm)->field.le_next = (head)->lh_first) != NULL) \ -- (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ -- (head)->lh_first = (elm); \ -- (elm)->field.le_prev = &(head)->lh_first; \ --} while (0) -- --#define DWC_LIST_REMOVE(elm, field) do { \ -- if ((elm)->field.le_next != NULL) \ -- (elm)->field.le_next->field.le_prev = \ -- (elm)->field.le_prev; \ -- *(elm)->field.le_prev = (elm)->field.le_next; \ --} while (0) -- --#define DWC_LIST_REPLACE(elm, elm2, field) do { \ -- if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ -- (elm2)->field.le_next->field.le_prev = \ -- &(elm2)->field.le_next; \ -- (elm2)->field.le_prev = (elm)->field.le_prev; \ -- *(elm2)->field.le_prev = (elm2); \ --} while (0) -- --#endif -- - /* - * Simple queue definitions. - */ -@@ -328,7 +302,7 @@ struct name { \ - struct type **sqh_last; /* addr of last next element */ \ - } - --#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ -+#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).sqh_first } - - #define DWC_SIMPLEQ_ENTRY(type) \ -@@ -352,7 +326,7 @@ struct { \ - /* - * Simple queue functions. - */ --#define DWC_SIMPLEQ_INIT(head) do { \ -+#define DWC_SIMPLEQ_INIT(head) do { \ - (head)->sqh_first = NULL; \ - (head)->sqh_last = &(head)->sqh_first; \ - } while (0) -@@ -369,7 +343,7 @@ struct { \ - (head)->sqh_last = &(elm)->field.sqe_next; \ - } while (0) - --#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ -+#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ - (head)->sqh_last = &(elm)->field.sqe_next; \ - (listelm)->field.sqe_next = (elm); \ -@@ -383,13 +357,13 @@ struct { \ - /* - * Tail queue definitions. - */ --#define DWC_TAILQ_HEAD(name, type) \ -+#define DWC_TAILQ_HEAD(name, type) \ - struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - } - --#define DWC_TAILQ_HEAD_INITIALIZER(head) \ -+#define DWC_TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - - #define DWC_TAILQ_ENTRY(type) \ -@@ -398,12 +372,12 @@ struct { \ - struct type **tqe_prev; /* address of previous next element */ \ - } - --/* -- * tail queue access methods -+/* -+ * tail queue access methods - */ - #define DWC_TAILQ_FIRST(head) ((head)->tqh_first) --#define DWC_TAILQ_END(head) NULL --#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) -+#define DWC_TAILQ_END(head) NULL -+#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - #define DWC_TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - /* XXX */ -@@ -412,7 +386,7 @@ struct { \ - #define DWC_TAILQ_EMPTY(head) \ - (TAILQ_FIRST(head) == TAILQ_END(head)) - --#define DWC_TAILQ_FOREACH(var, head, field) \ -+#define DWC_TAILQ_FOREACH(var, head, field) \ - for((var) = TAILQ_FIRST(head); \ - (var) != TAILQ_END(head); \ - (var) = TAILQ_NEXT(var, field)) -@@ -425,7 +399,7 @@ struct { \ - /* - * Tail queue functions. - */ --#define DWC_TAILQ_INIT(head) do { \ -+#define DWC_TAILQ_INIT(head) do { \ - (head)->tqh_first = NULL; \ - (head)->tqh_last = &(head)->tqh_first; \ - } while (0) -@@ -457,7 +431,7 @@ struct { \ - (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ - } while (0) - --#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ -+#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - (elm)->field.tqe_next = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ -@@ -492,7 +466,7 @@ struct name { \ - struct type *cqh_last; /* last element */ \ - } - --#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ -+#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ - { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) } - - #define DWC_CIRCLEQ_ENTRY(type) \ -@@ -502,7 +476,7 @@ struct { \ - } - - /* -- * Circular queue access methods -+ * Circular queue access methods - */ - #define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first) - #define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last) -@@ -516,33 +490,33 @@ struct { \ - - #define DWC_CIRCLEQ_FOREACH(var, head, field) \ - for((var) = DWC_CIRCLEQ_FIRST(head); \ -- (var) != DWC_CIRCLEQ_END(head); \ -+ (var) != DWC_CIRCLEQ_END(head); \ - (var) = DWC_CIRCLEQ_NEXT(var, field)) - --#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ -- for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ -+#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ -+ for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ - (var) != DWC_CIRCLEQ_END(head); \ - (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field)) - - #define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ -- for((var) = DWC_CIRCLEQ_LAST(head); \ -- (var) != DWC_CIRCLEQ_END(head); \ -+ for((var) = DWC_CIRCLEQ_LAST(head); \ -+ (var) != DWC_CIRCLEQ_END(head); \ - (var) = DWC_CIRCLEQ_PREV(var, field)) - - /* - * Circular queue functions. - */ --#define DWC_CIRCLEQ_INIT(head) do { \ -- (head)->cqh_first = DWC_CIRCLEQ_END(head); \ -- (head)->cqh_last = DWC_CIRCLEQ_END(head); \ -+#define DWC_CIRCLEQ_INIT(head) do { \ -+ (head)->cqh_first = DWC_CIRCLEQ_END(head); \ -+ (head)->cqh_last = DWC_CIRCLEQ_END(head); \ - } while (0) - --#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ -- (elm)->field.cqe_next = NULL; \ -- (elm)->field.cqe_prev = NULL; \ -+#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ -+ (elm)->field.cqe_next = NULL; \ -+ (elm)->field.cqe_prev = NULL; \ - } while (0) - --#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ -+#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm)->field.cqe_next; \ - (elm)->field.cqe_prev = (listelm); \ - if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ -@@ -552,7 +526,7 @@ struct { \ - (listelm)->field.cqe_next = (elm); \ - } while (0) - --#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ -+#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ - (elm)->field.cqe_next = (listelm); \ - (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ - if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ -@@ -582,35 +556,39 @@ struct { \ - (head)->cqh_last = (elm); \ - } while (0) - --#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ -- if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ -+#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ -+ if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ - (head)->cqh_last = (elm)->field.cqe_prev; \ - else \ - (elm)->field.cqe_next->field.cqe_prev = \ - (elm)->field.cqe_prev; \ -- if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ -+ if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ - (head)->cqh_first = (elm)->field.cqe_next; \ - else \ - (elm)->field.cqe_prev->field.cqe_next = \ - (elm)->field.cqe_next; \ - } while (0) - --#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ -- DWC_CIRCLEQ_REMOVE(head, elm, field); \ -- DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ -+#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ -+ DWC_CIRCLEQ_REMOVE(head, elm, field); \ -+ DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ - } while (0) - --#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ -+#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ - if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ -- DWC_CIRCLEQ_END(head)) \ -+ DWC_CIRCLEQ_END(head)) \ - (head).cqh_last = (elm2); \ - else \ - (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ - if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ -- DWC_CIRCLEQ_END(head)) \ -+ DWC_CIRCLEQ_END(head)) \ - (head).cqh_first = (elm2); \ - else \ - (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ - } while (0) - --#endif /* !_SYS_QUEUE_H_ */ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _DWC_LIST_H_ */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_mem.c b/drivers/usb/host/dwc_common_port/dwc_mem.c -index f2f9bc6..ad645ff 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_mem.c -+++ b/drivers/usb/host/dwc_common_port/dwc_mem.c -@@ -1,12 +1,12 @@ -+/* Memory Debugging */ -+#ifdef DWC_DEBUG_MEMORY -+ - #include "dwc_os.h" - #include "dwc_list.h" - --/* Memory Debugging */ --#ifdef DEBUG_MEMORY -- --struct allocation --{ -+struct allocation { - void *addr; -+ void *ctx; - char *func; - int line; - uint32_t size; -@@ -16,8 +16,8 @@ struct allocation - - DWC_CIRCLEQ_HEAD(allocation_queue, allocation); - --struct allocation_manager --{ -+struct allocation_manager { -+ void *mem_ctx; - struct allocation_queue allocations; - - /* statistics */ -@@ -25,148 +25,221 @@ struct allocation_manager - int num_freed; - int num_active; - uint32_t total; -- uint32_t current; -+ uint32_t cur; - uint32_t max; - }; - -- - static struct allocation_manager *manager = NULL; - --static void add_allocation(uint32_t size, char const* func, int line, void *addr, int dma) -+static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr, -+ int dma) - { -- struct allocation *a = __DWC_ALLOC_ATOMIC(sizeof(*a)); -- a->func = __DWC_ALLOC_ATOMIC(DWC_STRLEN(func)+1); -- DWC_MEMCPY(a->func, func, DWC_STRLEN(func)+1); -+ struct allocation *a; -+ -+ DWC_ASSERT(manager != NULL, "manager not allocated"); -+ -+ a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a)); -+ if (!a) { -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1); -+ if (!a->func) { -+ __DWC_FREE(manager->mem_ctx, a); -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1); -+ a->addr = addr; -+ a->ctx = ctx; - a->line = line; - a->size = size; -- a->addr = addr; - a->dma = dma; - DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry); - - /* Update stats */ -- manager->num ++; -- manager->num_active ++; -+ manager->num++; -+ manager->num_active++; - manager->total += size; -- manager->current += size; -- if (manager->max < manager->current) { -- manager->max = manager->current; -+ manager->cur += size; -+ -+ if (manager->max < manager->cur) { -+ manager->max = manager->cur; - } -+ -+ return 0; - } - --static struct allocation *find_allocation(void *addr) -+static struct allocation *find_allocation(void *ctx, void *addr) - { - struct allocation *a; -+ - DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { -- if (a->addr == addr) { -+ if (a->ctx == ctx && a->addr == addr) { - return a; - } - } -+ - return NULL; - } - --static void free_allocation(void *addr, char const* func, int line) -+static void free_allocation(void *ctx, void *addr, char const *func, int line) - { -- struct allocation *a = find_allocation(addr); -- if (!a && func && (line >= 0)) { -- DWC_ASSERT(0, "Free of address %p that was never allocated or already freed %s:%d", addr, func, line); -+ struct allocation *a = find_allocation(ctx, addr); -+ -+ if (!a) { -+ DWC_ASSERT(0, -+ "Free of address %p that was never allocated or already freed %s:%d", -+ addr, func, line); - return; - } -+ - DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry); - -- manager->num_active --; -- manager->num_freed ++; -- manager->current -= a->size; -- __DWC_FREE(a->func); -- __DWC_FREE(a); -+ manager->num_active--; -+ manager->num_freed++; -+ manager->cur -= a->size; -+ __DWC_FREE(manager->mem_ctx, a->func); -+ __DWC_FREE(manager->mem_ctx, a); - } - --void dwc_memory_debug_start(void) -+int dwc_memory_debug_start(void *mem_ctx) - { - DWC_ASSERT(manager == NULL, "Memory debugging has already started\n"); -- if (manager == NULL) { -- manager = __DWC_ALLOC(sizeof(*manager)); -+ -+ if (manager) { -+ return -DWC_E_BUSY; -+ } -+ -+ manager = __DWC_ALLOC(mem_ctx, sizeof(*manager)); -+ if (!manager) { -+ return -DWC_E_NO_MEMORY; - } - - DWC_CIRCLEQ_INIT(&manager->allocations); -+ manager->mem_ctx = mem_ctx; - manager->num = 0; - manager->num_freed = 0; - manager->num_active = 0; - manager->total = 0; -- manager->current = 0; -+ manager->cur = 0; - manager->max = 0; -+ -+ return 0; - } - - void dwc_memory_debug_stop(void) - { - struct allocation *a; -+ - dwc_memory_debug_report(); - - DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { - DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line); -- free_allocation(a->addr, NULL, -1); -+ free_allocation(a->ctx, a->addr, NULL, -1); - } - -- __DWC_FREE(manager); -+ __DWC_FREE(manager->mem_ctx, manager); - } - - void dwc_memory_debug_report(void) - { - struct allocation *a; -+ - DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n"); - DWC_PRINTF("Num Allocations = %d\n", manager->num); - DWC_PRINTF("Freed = %d\n", manager->num_freed); - DWC_PRINTF("Active = %d\n", manager->num_active); -- DWC_PRINTF("Current Memory Used = %d\n", manager->current); -+ DWC_PRINTF("Current Memory Used = %d\n", manager->cur); - DWC_PRINTF("Total Memory Used = %d\n", manager->total); - DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max); - DWC_PRINTF("Unfreed allocations:\n"); - - DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { -- DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", a->addr, a->size, a->func, a->line, a->dma); -+ DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", -+ a->addr, a->size, a->func, a->line, a->dma); - } - } - -- -- - /* The replacement functions */ --void *dwc_alloc_debug(uint32_t size, char const* func, int line) -+void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line) - { -- void *addr = __DWC_ALLOC(size); -- add_allocation(size, func, line, addr, 0); -+ void *addr = __DWC_ALLOC(mem_ctx, size); -+ -+ if (!addr) { -+ return NULL; -+ } -+ -+ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { -+ __DWC_FREE(mem_ctx, addr); -+ return NULL; -+ } -+ - return addr; - } - --void *dwc_alloc_atomic_debug(uint32_t size, char const* func, int line) -+void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, -+ int line) - { -- void *addr = __DWC_ALLOC_ATOMIC(size); -- add_allocation(size, func, line, addr, 0); -+ void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size); -+ -+ if (!addr) { -+ return NULL; -+ } -+ -+ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { -+ __DWC_FREE(mem_ctx, addr); -+ return NULL; -+ } -+ - return addr; - } - --void dwc_free_debug(void *addr, char const* func, int line) -+void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line) - { -- free_allocation(addr, func, line); -- __DWC_FREE(addr); -+ free_allocation(mem_ctx, addr, func, line); -+ __DWC_FREE(mem_ctx, addr); - } - --void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line) -+void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, -+ char const *func, int line) - { -- void *addr = __DWC_DMA_ALLOC(size, dma_addr); -- add_allocation(size, func, line, addr, 1); -+ void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr); -+ -+ if (!addr) { -+ return NULL; -+ } -+ -+ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { -+ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); -+ return NULL; -+ } -+ - return addr; - } - --void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line) -+void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, -+ dwc_dma_t *dma_addr, char const *func, int line) - { -- void *addr = __DWC_DMA_ALLOC_ATOMIC(size, dma_addr); -- add_allocation(size, func, line, addr, 1); -+ void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr); -+ -+ if (!addr) { -+ return NULL; -+ } -+ -+ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { -+ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); -+ return NULL; -+ } -+ - return addr; - } - --void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line) -+void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, -+ dwc_dma_t dma_addr, char const *func, int line) - { -- free_allocation(virt_addr, func, line); -- __DWC_DMA_FREE(size, virt_addr, dma_addr); -+ free_allocation(dma_ctx, virt_addr, func, line); -+ __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr); - } - --#endif /* DEBUG_MEMORY */ -+#endif /* DWC_DEBUG_MEMORY */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.c b/drivers/usb/host/dwc_common_port/dwc_modpow.c -new file mode 100644 -index 0000000..b7c456b ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c -@@ -0,0 +1,636 @@ -+/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows. -+ * -+ * PuTTY is copyright 1997-2007 Simon Tatham. -+ * -+ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian -+ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, -+ * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus -+ * Kuhn, and CORE SDI S.A. -+ * -+ * Permission is hereby granted, free of charge, to any person -+ * obtaining a copy of this software and associated documentation files -+ * (the "Software"), to deal in the Software without restriction, -+ * including without limitation the rights to use, copy, modify, merge, -+ * publish, distribute, sublicense, and/or sell copies of the Software, -+ * and to permit persons to whom the Software is furnished to do so, -+ * subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be -+ * included in all copies or substantial portions of the Software. -+ -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -+ * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE -+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -+ * -+ */ -+#ifdef DWC_CRYPTOLIB -+ -+#ifndef CONFIG_MACH_IPMATE -+ -+#include "dwc_modpow.h" -+ -+#define BIGNUM_INT_MASK 0xFFFFFFFFUL -+#define BIGNUM_TOP_BIT 0x80000000UL -+#define BIGNUM_INT_BITS 32 -+ -+ -+static void *snmalloc(void *mem_ctx, size_t n, size_t size) -+{ -+ void *p; -+ size *= n; -+ if (size == 0) size = 1; -+ p = dwc_alloc(mem_ctx, size); -+ return p; -+} -+ -+#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type))) -+#define sfree dwc_free -+ -+/* -+ * Usage notes: -+ * * Do not call the DIVMOD_WORD macro with expressions such as array -+ * subscripts, as some implementations object to this (see below). -+ * * Note that none of the division methods below will cope if the -+ * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful -+ * to avoid this case. -+ * If this condition occurs, in the case of the x86 DIV instruction, -+ * an overflow exception will occur, which (according to a correspondent) -+ * will manifest on Windows as something like -+ * 0xC0000095: Integer overflow -+ * The C variant won't give the right answer, either. -+ */ -+ -+#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) -+ -+#if defined __GNUC__ && defined __i386__ -+#define DIVMOD_WORD(q, r, hi, lo, w) \ -+ __asm__("div %2" : \ -+ "=d" (r), "=a" (q) : \ -+ "r" (w), "d" (hi), "a" (lo)) -+#else -+#define DIVMOD_WORD(q, r, hi, lo, w) do { \ -+ BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ -+ q = n / w; \ -+ r = n % w; \ -+} while (0) -+#endif -+ -+// q = n / w; -+// r = n % w; -+ -+#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8) -+ -+#define BIGNUM_INTERNAL -+ -+static Bignum newbn(void *mem_ctx, int length) -+{ -+ Bignum b = snewn(mem_ctx, length + 1, BignumInt); -+ //if (!b) -+ //abort(); /* FIXME */ -+ DWC_MEMSET(b, 0, (length + 1) * sizeof(*b)); -+ b[0] = length; -+ return b; -+} -+ -+void freebn(void *mem_ctx, Bignum b) -+{ -+ /* -+ * Burn the evidence, just in case. -+ */ -+ DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1)); -+ sfree(mem_ctx, b); -+} -+ -+/* -+ * Compute c = a * b. -+ * Input is in the first len words of a and b. -+ * Result is returned in the first 2*len words of c. -+ */ -+static void internal_mul(BignumInt *a, BignumInt *b, -+ BignumInt *c, int len) -+{ -+ int i, j; -+ BignumDblInt t; -+ -+ for (j = 0; j < 2 * len; j++) -+ c[j] = 0; -+ -+ for (i = len - 1; i >= 0; i--) { -+ t = 0; -+ for (j = len - 1; j >= 0; j--) { -+ t += MUL_WORD(a[i], (BignumDblInt) b[j]); -+ t += (BignumDblInt) c[i + j + 1]; -+ c[i + j + 1] = (BignumInt) t; -+ t = t >> BIGNUM_INT_BITS; -+ } -+ c[i] = (BignumInt) t; -+ } -+} -+ -+static void internal_add_shifted(BignumInt *number, -+ unsigned n, int shift) -+{ -+ int word = 1 + (shift / BIGNUM_INT_BITS); -+ int bshift = shift % BIGNUM_INT_BITS; -+ BignumDblInt addend; -+ -+ addend = (BignumDblInt)n << bshift; -+ -+ while (addend) { -+ addend += number[word]; -+ number[word] = (BignumInt) addend & BIGNUM_INT_MASK; -+ addend >>= BIGNUM_INT_BITS; -+ word++; -+ } -+} -+ -+/* -+ * Compute a = a % m. -+ * Input in first alen words of a and first mlen words of m. -+ * Output in first alen words of a -+ * (of which first alen-mlen words will be zero). -+ * The MSW of m MUST have its high bit set. -+ * Quotient is accumulated in the `quotient' array, which is a Bignum -+ * rather than the internal bigendian format. Quotient parts are shifted -+ * left by `qshift' before adding into quot. -+ */ -+static void internal_mod(BignumInt *a, int alen, -+ BignumInt *m, int mlen, -+ BignumInt *quot, int qshift) -+{ -+ BignumInt m0, m1; -+ unsigned int h; -+ int i, k; -+ -+ m0 = m[0]; -+ if (mlen > 1) -+ m1 = m[1]; -+ else -+ m1 = 0; -+ -+ for (i = 0; i <= alen - mlen; i++) { -+ BignumDblInt t; -+ unsigned int q, r, c, ai1; -+ -+ if (i == 0) { -+ h = 0; -+ } else { -+ h = a[i - 1]; -+ a[i - 1] = 0; -+ } -+ -+ if (i == alen - 1) -+ ai1 = 0; -+ else -+ ai1 = a[i + 1]; -+ -+ /* Find q = h:a[i] / m0 */ -+ if (h >= m0) { -+ /* -+ * Special case. -+ * -+ * To illustrate it, suppose a BignumInt is 8 bits, and -+ * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then -+ * our initial division will be 0xA123 / 0xA1, which -+ * will give a quotient of 0x100 and a divide overflow. -+ * However, the invariants in this division algorithm -+ * are not violated, since the full number A1:23:... is -+ * _less_ than the quotient prefix A1:B2:... and so the -+ * following correction loop would have sorted it out. -+ * -+ * In this situation we set q to be the largest -+ * quotient we _can_ stomach (0xFF, of course). -+ */ -+ q = BIGNUM_INT_MASK; -+ } else { -+ /* Macro doesn't want an array subscript expression passed -+ * into it (see definition), so use a temporary. */ -+ BignumInt tmplo = a[i]; -+ DIVMOD_WORD(q, r, h, tmplo, m0); -+ -+ /* Refine our estimate of q by looking at -+ h:a[i]:a[i+1] / m0:m1 */ -+ t = MUL_WORD(m1, q); -+ if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) { -+ q--; -+ t -= m1; -+ r = (r + m0) & BIGNUM_INT_MASK; /* overflow? */ -+ if (r >= (BignumDblInt) m0 && -+ t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--; -+ } -+ } -+ -+ /* Subtract q * m from a[i...] */ -+ c = 0; -+ for (k = mlen - 1; k >= 0; k--) { -+ t = MUL_WORD(q, m[k]); -+ t += c; -+ c = (unsigned)(t >> BIGNUM_INT_BITS); -+ if ((BignumInt) t > a[i + k]) -+ c++; -+ a[i + k] -= (BignumInt) t; -+ } -+ -+ /* Add back m in case of borrow */ -+ if (c != h) { -+ t = 0; -+ for (k = mlen - 1; k >= 0; k--) { -+ t += m[k]; -+ t += a[i + k]; -+ a[i + k] = (BignumInt) t; -+ t = t >> BIGNUM_INT_BITS; -+ } -+ q--; -+ } -+ if (quot) -+ internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i)); -+ } -+} -+ -+/* -+ * Compute p % mod. -+ * The most significant word of mod MUST be non-zero. -+ * We assume that the result array is the same size as the mod array. -+ * We optionally write out a quotient if `quotient' is non-NULL. -+ * We can avoid writing out the result if `result' is NULL. -+ */ -+void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient) -+{ -+ BignumInt *n, *m; -+ int mshift; -+ int plen, mlen, i, j; -+ -+ /* Allocate m of size mlen, copy mod to m */ -+ /* We use big endian internally */ -+ mlen = mod[0]; -+ m = snewn(mem_ctx, mlen, BignumInt); -+ //if (!m) -+ //abort(); /* FIXME */ -+ for (j = 0; j < mlen; j++) -+ m[j] = mod[mod[0] - j]; -+ -+ /* Shift m left to make msb bit set */ -+ for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++) -+ if ((m[0] << mshift) & BIGNUM_TOP_BIT) -+ break; -+ if (mshift) { -+ for (i = 0; i < mlen - 1; i++) -+ m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift)); -+ m[mlen - 1] = m[mlen - 1] << mshift; -+ } -+ -+ plen = p[0]; -+ /* Ensure plen > mlen */ -+ if (plen <= mlen) -+ plen = mlen + 1; -+ -+ /* Allocate n of size plen, copy p to n */ -+ n = snewn(mem_ctx, plen, BignumInt); -+ //if (!n) -+ //abort(); /* FIXME */ -+ for (j = 0; j < plen; j++) -+ n[j] = 0; -+ for (j = 1; j <= (int)p[0]; j++) -+ n[plen - j] = p[j]; -+ -+ /* Main computation */ -+ internal_mod(n, plen, m, mlen, quotient, mshift); -+ -+ /* Fixup result in case the modulus was shifted */ -+ if (mshift) { -+ for (i = plen - mlen - 1; i < plen - 1; i++) -+ n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift)); -+ n[plen - 1] = n[plen - 1] << mshift; -+ internal_mod(n, plen, m, mlen, quotient, 0); -+ for (i = plen - 1; i >= plen - mlen; i--) -+ n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift)); -+ } -+ -+ /* Copy result to buffer */ -+ if (result) { -+ for (i = 1; i <= (int)result[0]; i++) { -+ int j = plen - i; -+ result[i] = j >= 0 ? n[j] : 0; -+ } -+ } -+ -+ /* Free temporary arrays */ -+ for (i = 0; i < mlen; i++) -+ m[i] = 0; -+ sfree(mem_ctx, m); -+ for (i = 0; i < plen; i++) -+ n[i] = 0; -+ sfree(mem_ctx, n); -+} -+ -+/* -+ * Simple remainder. -+ */ -+Bignum bigmod(void *mem_ctx, Bignum a, Bignum b) -+{ -+ Bignum r = newbn(mem_ctx, b[0]); -+ bigdivmod(mem_ctx, a, b, r, NULL); -+ return r; -+} -+ -+/* -+ * Compute (base ^ exp) % mod. -+ */ -+Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod) -+{ -+ BignumInt *a, *b, *n, *m; -+ int mshift; -+ int mlen, i, j; -+ Bignum base, result; -+ -+ /* -+ * The most significant word of mod needs to be non-zero. It -+ * should already be, but let's make sure. -+ */ -+ //assert(mod[mod[0]] != 0); -+ -+ /* -+ * Make sure the base is smaller than the modulus, by reducing -+ * it modulo the modulus if not. -+ */ -+ base = bigmod(mem_ctx, base_in, mod); -+ -+ /* Allocate m of size mlen, copy mod to m */ -+ /* We use big endian internally */ -+ mlen = mod[0]; -+ m = snewn(mem_ctx, mlen, BignumInt); -+ //if (!m) -+ //abort(); /* FIXME */ -+ for (j = 0; j < mlen; j++) -+ m[j] = mod[mod[0] - j]; -+ -+ /* Shift m left to make msb bit set */ -+ for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++) -+ if ((m[0] << mshift) & BIGNUM_TOP_BIT) -+ break; -+ if (mshift) { -+ for (i = 0; i < mlen - 1; i++) -+ m[i] = -+ (m[i] << mshift) | (m[i + 1] >> -+ (BIGNUM_INT_BITS - mshift)); -+ m[mlen - 1] = m[mlen - 1] << mshift; -+ } -+ -+ /* Allocate n of size mlen, copy base to n */ -+ n = snewn(mem_ctx, mlen, BignumInt); -+ //if (!n) -+ //abort(); /* FIXME */ -+ i = mlen - base[0]; -+ for (j = 0; j < i; j++) -+ n[j] = 0; -+ for (j = 0; j < base[0]; j++) -+ n[i + j] = base[base[0] - j]; -+ -+ /* Allocate a and b of size 2*mlen. Set a = 1 */ -+ a = snewn(mem_ctx, 2 * mlen, BignumInt); -+ //if (!a) -+ //abort(); /* FIXME */ -+ b = snewn(mem_ctx, 2 * mlen, BignumInt); -+ //if (!b) -+ //abort(); /* FIXME */ -+ for (i = 0; i < 2 * mlen; i++) -+ a[i] = 0; -+ a[2 * mlen - 1] = 1; -+ -+ /* Skip leading zero bits of exp. */ -+ i = 0; -+ j = BIGNUM_INT_BITS - 1; -+ while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) { -+ j--; -+ if (j < 0) { -+ i++; -+ j = BIGNUM_INT_BITS - 1; -+ } -+ } -+ -+ /* Main computation */ -+ while (i < exp[0]) { -+ while (j >= 0) { -+ internal_mul(a + mlen, a + mlen, b, mlen); -+ internal_mod(b, mlen * 2, m, mlen, NULL, 0); -+ if ((exp[exp[0] - i] & (1 << j)) != 0) { -+ internal_mul(b + mlen, n, a, mlen); -+ internal_mod(a, mlen * 2, m, mlen, NULL, 0); -+ } else { -+ BignumInt *t; -+ t = a; -+ a = b; -+ b = t; -+ } -+ j--; -+ } -+ i++; -+ j = BIGNUM_INT_BITS - 1; -+ } -+ -+ /* Fixup result in case the modulus was shifted */ -+ if (mshift) { -+ for (i = mlen - 1; i < 2 * mlen - 1; i++) -+ a[i] = -+ (a[i] << mshift) | (a[i + 1] >> -+ (BIGNUM_INT_BITS - mshift)); -+ a[2 * mlen - 1] = a[2 * mlen - 1] << mshift; -+ internal_mod(a, mlen * 2, m, mlen, NULL, 0); -+ for (i = 2 * mlen - 1; i >= mlen; i--) -+ a[i] = -+ (a[i] >> mshift) | (a[i - 1] << -+ (BIGNUM_INT_BITS - mshift)); -+ } -+ -+ /* Copy result to buffer */ -+ result = newbn(mem_ctx, mod[0]); -+ for (i = 0; i < mlen; i++) -+ result[result[0] - i] = a[i + mlen]; -+ while (result[0] > 1 && result[result[0]] == 0) -+ result[0]--; -+ -+ /* Free temporary arrays */ -+ for (i = 0; i < 2 * mlen; i++) -+ a[i] = 0; -+ sfree(mem_ctx, a); -+ for (i = 0; i < 2 * mlen; i++) -+ b[i] = 0; -+ sfree(mem_ctx, b); -+ for (i = 0; i < mlen; i++) -+ m[i] = 0; -+ sfree(mem_ctx, m); -+ for (i = 0; i < mlen; i++) -+ n[i] = 0; -+ sfree(mem_ctx, n); -+ -+ freebn(mem_ctx, base); -+ -+ return result; -+} -+ -+ -+#ifdef UNITTEST -+ -+static __u32 dh_p[] = { -+ 96, -+ 0xFFFFFFFF, -+ 0xFFFFFFFF, -+ 0xA93AD2CA, -+ 0x4B82D120, -+ 0xE0FD108E, -+ 0x43DB5BFC, -+ 0x74E5AB31, -+ 0x08E24FA0, -+ 0xBAD946E2, -+ 0x770988C0, -+ 0x7A615D6C, -+ 0xBBE11757, -+ 0x177B200C, -+ 0x521F2B18, -+ 0x3EC86A64, -+ 0xD8760273, -+ 0xD98A0864, -+ 0xF12FFA06, -+ 0x1AD2EE6B, -+ 0xCEE3D226, -+ 0x4A25619D, -+ 0x1E8C94E0, -+ 0xDB0933D7, -+ 0xABF5AE8C, -+ 0xA6E1E4C7, -+ 0xB3970F85, -+ 0x5D060C7D, -+ 0x8AEA7157, -+ 0x58DBEF0A, -+ 0xECFB8504, -+ 0xDF1CBA64, -+ 0xA85521AB, -+ 0x04507A33, -+ 0xAD33170D, -+ 0x8AAAC42D, -+ 0x15728E5A, -+ 0x98FA0510, -+ 0x15D22618, -+ 0xEA956AE5, -+ 0x3995497C, -+ 0x95581718, -+ 0xDE2BCBF6, -+ 0x6F4C52C9, -+ 0xB5C55DF0, -+ 0xEC07A28F, -+ 0x9B2783A2, -+ 0x180E8603, -+ 0xE39E772C, -+ 0x2E36CE3B, -+ 0x32905E46, -+ 0xCA18217C, -+ 0xF1746C08, -+ 0x4ABC9804, -+ 0x670C354E, -+ 0x7096966D, -+ 0x9ED52907, -+ 0x208552BB, -+ 0x1C62F356, -+ 0xDCA3AD96, -+ 0x83655D23, -+ 0xFD24CF5F, -+ 0x69163FA8, -+ 0x1C55D39A, -+ 0x98DA4836, -+ 0xA163BF05, -+ 0xC2007CB8, -+ 0xECE45B3D, -+ 0x49286651, -+ 0x7C4B1FE6, -+ 0xAE9F2411, -+ 0x5A899FA5, -+ 0xEE386BFB, -+ 0xF406B7ED, -+ 0x0BFF5CB6, -+ 0xA637ED6B, -+ 0xF44C42E9, -+ 0x625E7EC6, -+ 0xE485B576, -+ 0x6D51C245, -+ 0x4FE1356D, -+ 0xF25F1437, -+ 0x302B0A6D, -+ 0xCD3A431B, -+ 0xEF9519B3, -+ 0x8E3404DD, -+ 0x514A0879, -+ 0x3B139B22, -+ 0x020BBEA6, -+ 0x8A67CC74, -+ 0x29024E08, -+ 0x80DC1CD1, -+ 0xC4C6628B, -+ 0x2168C234, -+ 0xC90FDAA2, -+ 0xFFFFFFFF, -+ 0xFFFFFFFF, -+}; -+ -+static __u32 dh_a[] = { -+ 8, -+ 0xdf367516, -+ 0x86459caa, -+ 0xe2d459a4, -+ 0xd910dae0, -+ 0x8a8b5e37, -+ 0x67ab31c6, -+ 0xf0b55ea9, -+ 0x440051d6, -+}; -+ -+static __u32 dh_b[] = { -+ 8, -+ 0xded92656, -+ 0xe07a048a, -+ 0x6fa452cd, -+ 0x2df89d30, -+ 0xc75f1b0f, -+ 0x8ce3578f, -+ 0x7980a324, -+ 0x5daec786, -+}; -+ -+static __u32 dh_g[] = { -+ 1, -+ 2, -+}; -+ -+int main(void) -+{ -+ int i; -+ __u32 *k; -+ k = dwc_modpow(NULL, dh_g, dh_a, dh_p); -+ -+ printf("\n\n"); -+ for (i=0; i> 16; -+ printf("%04x %04x ", m, l); -+ if (!((i + 1)%13)) printf("\n"); -+ } -+ printf("\n\n"); -+ -+ if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) { -+ printf("PASS\n\n"); -+ } -+ else { -+ printf("FAIL\n\n"); -+ } -+ -+} -+ -+#endif /* UNITTEST */ -+ -+#endif /* CONFIG_MACH_IPMATE */ -+ -+#endif /*DWC_CRYPTOLIB */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.h b/drivers/usb/host/dwc_common_port/dwc_modpow.h -new file mode 100644 -index 0000000..64f00c2 ---- /dev/null -+++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h -@@ -0,0 +1,34 @@ -+/* -+ * dwc_modpow.h -+ * See dwc_modpow.c for license and changes -+ */ -+#ifndef _DWC_MODPOW_H -+#define _DWC_MODPOW_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include "dwc_os.h" -+ -+/** @file -+ * -+ * This file defines the module exponentiation function which is only used -+ * internally by the DWC UWB modules for calculation of PKs during numeric -+ * association. The routine is taken from the PUTTY, an open source terminal -+ * emulator. The PUTTY License is preserved in the dwc_modpow.c file. -+ * -+ */ -+ -+typedef uint32_t BignumInt; -+typedef uint64_t BignumDblInt; -+typedef BignumInt *Bignum; -+ -+/* Compute modular exponentiaion */ -+extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _LINUX_BIGNUM_H */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.c b/drivers/usb/host/dwc_common_port/dwc_notifier.c -index e44bb81..8b3772a 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_notifier.c -+++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c -@@ -1,8 +1,9 @@ -+#ifdef DWC_NOTIFYLIB -+ - #include "dwc_notifier.h" - #include "dwc_list.h" - --typedef struct dwc_observer --{ -+typedef struct dwc_observer { - void *observer; - dwc_notifier_callback_t callback; - void *data; -@@ -12,8 +13,8 @@ - - DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer); - --typedef struct dwc_notifier --{ -+typedef struct dwc_notifier { -+ void *mem_ctx; - void *object; - struct observer_queue observers; - DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry; -@@ -21,30 +22,43 @@ - - DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier); - --typedef struct manager --{ -+typedef struct manager { -+ void *mem_ctx; -+ void *wkq_ctx; - dwc_workq_t *wq; -- dwc_mutex_t *mutex; -+// dwc_mutex_t *mutex; - struct notifier_queue notifiers; - } manager_t; - - static manager_t *manager = NULL; - --static void create_manager(void) -+static int create_manager(void *mem_ctx, void *wkq_ctx) - { -- manager = DWC_ALLOC(sizeof(manager_t)); -+ manager = dwc_alloc(mem_ctx, sizeof(manager_t)); -+ if (!manager) { -+ return -DWC_E_NO_MEMORY; -+ } -+ - DWC_CIRCLEQ_INIT(&manager->notifiers); -- manager->wq = DWC_WORKQ_ALLOC("DWC Notification WorkQ"); -+ -+ manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ"); -+ if (!manager->wq) { -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ return 0; - } - - static void free_manager(void) - { -- DWC_WORKQ_FREE(manager->wq); -+ dwc_workq_free(manager->wq); -+ - /* All notifiers must have unregistered themselves before this module - * can be removed. Hitting this assertion indicates a programmer - * error. */ -- DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), "Notification manager being freed before all notifiers have been removed"); -- DWC_FREE(manager); -+ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), -+ "Notification manager being freed before all notifiers have been removed"); -+ dwc_free(manager->mem_ctx, manager); - } - - #ifdef DEBUG -@@ -52,12 +66,14 @@ static void dump_manager(void) - { - notifier_t *n; - observer_t *o; -+ - DWC_ASSERT(manager, "Notification manager not found"); -- DWC_DEBUG("List of all notifiers and observers:"); -+ -+ DWC_DEBUG("List of all notifiers and observers:\n"); - DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { -- DWC_DEBUG("Notifier %p has observers:", n->object); -+ DWC_DEBUG("Notifier %p has observers:\n", n->object); - DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) { -- DWC_DEBUG(" %p watching %s", o->observer, o->notification); -+ DWC_DEBUG(" %p watching %s\n", o->observer, o->notification); - } - } - } -@@ -65,9 +81,15 @@ static void dump_manager(void) - #define dump_manager(...) - #endif - --static observer_t *alloc_observer(void *observer, char *notification, dwc_notifier_callback_t callback, void *data) -+static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification, -+ dwc_notifier_callback_t callback, void *data) - { -- observer_t *new_observer = DWC_ALLOC(sizeof(observer_t)); -+ observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t)); -+ -+ if (!new_observer) { -+ return NULL; -+ } -+ - DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry); - new_observer->observer = observer; - new_observer->notification = notification; -@@ -76,12 +98,12 @@ static observer_t *alloc_observer(void *observer, char *notification, dwc_notifi - return new_observer; - } - --static void free_observer(observer_t *observer) -+static void free_observer(void *mem_ctx, observer_t *observer) - { -- DWC_FREE(observer); -+ dwc_free(mem_ctx, observer); - } - --static notifier_t *alloc_notifier(void *object) -+static notifier_t *alloc_notifier(void *mem_ctx, void *object) - { - notifier_t *notifier; - -@@ -89,10 +111,15 @@ static notifier_t *alloc_notifier(void *object) - return NULL; - } - -- notifier = DWC_ALLOC(sizeof(notifier_t)); -+ notifier = dwc_alloc(mem_ctx, sizeof(notifier_t)); -+ if (!notifier) { -+ return NULL; -+ } -+ - DWC_CIRCLEQ_INIT(¬ifier->observers); - DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry); - -+ notifier->mem_ctx = mem_ctx; - notifier->object = object; - return notifier; - } -@@ -100,30 +127,36 @@ static notifier_t *alloc_notifier(void *object) - static void free_notifier(notifier_t *notifier) - { - observer_t *observer; -+ - DWC_CIRCLEQ_FOREACH(observer, ¬ifier->observers, list_entry) { -- free_observer(observer); -+ free_observer(notifier->mem_ctx, observer); - } -- DWC_FREE(notifier); -+ -+ dwc_free(notifier->mem_ctx, notifier); - } - - static notifier_t *find_notifier(void *object) - { - notifier_t *notifier; -+ -+ DWC_ASSERT(manager, "Notification manager not found"); -+ - if (!object) { - return NULL; - } -- DWC_ASSERT(manager, "Notification manager not found"); -+ - DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) { - if (notifier->object == object) { - return notifier; - } - } -+ - return NULL; - } - --void dwc_alloc_notification_manager(void) -+int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx) - { -- create_manager(); -+ return create_manager(mem_ctx, wkq_ctx); - } - - void dwc_free_notification_manager(void) -@@ -131,18 +164,24 @@ void dwc_free_notification_manager(void) - free_manager(); - } - --dwc_notifier_t *dwc_register_notifier(void *object) -+dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object) - { -- notifier_t *notifier = find_notifier(object); -+ notifier_t *notifier; -+ - DWC_ASSERT(manager, "Notification manager not found"); -+ -+ notifier = find_notifier(object); - if (notifier) { -- DWC_ERROR("Notifier %p is already registered", object); -+ DWC_ERROR("Notifier %p is already registered\n", object); - return NULL; - } - -- notifier = alloc_notifier(object); -- DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); -+ notifier = alloc_notifier(mem_ctx, object); -+ if (!notifier) { -+ return NULL; -+ } - -+ DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); - - DWC_INFO("Notifier %p registered", object); - dump_manager(); -@@ -153,13 +192,17 @@ dwc_notifier_t *dwc_register_notifier(void *object) - void dwc_unregister_notifier(dwc_notifier_t *notifier) - { - DWC_ASSERT(manager, "Notification manager not found"); -+ - if (!DWC_CIRCLEQ_EMPTY(¬ifier->observers)) { - observer_t *o; -- DWC_ERROR("Notifier %p has active observers when removing", notifier->object); -+ -+ DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object); - DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { -- DWC_DEBUG(" %p watching %s", o->observer, o->notification); -+ DWC_DEBUGC(" %p watching %s\n", o->observer, o->notification); - } -- DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers), "Notifier %p has active observers when removing", notifier); -+ -+ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers), -+ "Notifier %p has active observers when removing", notifier); - } - - DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry); -@@ -170,16 +213,21 @@ void dwc_unregister_notifier(dwc_notifier_t *notifier) - } - - /* Add an observer to observe the notifier for a particular state, event, or notification. */ --int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *data) -+int dwc_add_observer(void *observer, void *object, char *notification, -+ dwc_notifier_callback_t callback, void *data) - { - notifier_t *notifier = find_notifier(object); - observer_t *new_observer; -+ - if (!notifier) { -- DWC_ERROR("Notifier %p is not found when adding observer", object); -- return -1; -+ DWC_ERROR("Notifier %p is not found when adding observer\n", object); -+ return -DWC_E_INVALID; - } - -- new_observer = alloc_observer(observer, notification, callback, data); -+ new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data); -+ if (!new_observer) { -+ return -DWC_E_NO_MEMORY; -+ } - - DWC_CIRCLEQ_INSERT_TAIL(¬ifier->observers, new_observer, list_entry); - -@@ -193,16 +241,19 @@ int dwc_add_observer(void *observer, void *object, char *notification, dwc_notif - int dwc_remove_observer(void *observer) - { - notifier_t *n; -+ - DWC_ASSERT(manager, "Notification manager not found"); -+ - DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { - observer_t *o; - observer_t *o2; -+ - DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) { - if (o->observer == observer) { - DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry); - DWC_INFO("Removing observer %p from notifier %p watching notification %s:", - o->observer, n->object, o->notification); -- free_observer(o); -+ free_observer(n->mem_ctx, o); - } - } - } -@@ -211,42 +262,53 @@ int dwc_remove_observer(void *observer) - return 0; - } - --typedef struct callback_data --{ -+typedef struct callback_data { -+ void *mem_ctx; - dwc_notifier_callback_t cb; - void *observer; - void *data; - void *object; -- void *notification; -+ char *notification; - void *notification_data; - } cb_data_t; - - static void cb_task(void *data) - { - cb_data_t *cb = (cb_data_t *)data; -+ - cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data); -- DWC_FREE(cb); -+ dwc_free(cb->mem_ctx, cb); - } - - void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data) - { - observer_t *o; -+ - DWC_ASSERT(manager, "Notification manager not found"); -+ - DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { - int len = DWC_STRLEN(notification); -+ - if (DWC_STRLEN(o->notification) != len) { - continue; - } - - if (DWC_STRNCMP(o->notification, notification, len) == 0) { -- cb_data_t *cb_data = DWC_ALLOC(sizeof(cb_data_t)); -+ cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t)); -+ -+ if (!cb_data) { -+ DWC_ERROR("Failed to allocate callback data\n"); -+ return; -+ } -+ -+ cb_data->mem_ctx = notifier->mem_ctx; - cb_data->cb = o->callback; - cb_data->observer = o->observer; - cb_data->data = o->data; - cb_data->object = notifier->object; - cb_data->notification = notification; - cb_data->notification_data = notification_data; -- DWC_DEBUG("Observer found %p for notification %s", o->observer, notification); -+ DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification); - DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data, - "Notify callback from %p for Notification %s, to observer %p", - cb_data->object, notification, cb_data->observer); -@@ -254,3 +316,4 @@ void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification - } - } - -+#endif /* DWC_NOTIFYLIB */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.h b/drivers/usb/host/dwc_common_port/dwc_notifier.h -index a1388d1..4a8cdfe 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_notifier.h -+++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h -@@ -2,6 +2,10 @@ - #ifndef __DWC_NOTIFIER_H__ - #define __DWC_NOTIFIER_H__ - -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - #include "dwc_os.h" - - /** @file -@@ -66,21 +70,22 @@ - * the documentation of the observable module with the notifications. - * @param user_data This is any custom data that the observer provided when - * adding itself as an observer to the notification. */ --typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, void *notification_data, void *user_data); -+typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, -+ void *notification_data, void *user_data); - - /** Brings up the notification manager. */ --extern void dwc_alloc_notification_manager(void); -+extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx); - /** Brings down the notification manager. */ - extern void dwc_free_notification_manager(void); - --/** This function register an observable module. A dwc_notifier_t object is -+/** This function registers an observable module. A dwc_notifier_t object is - * returned to the observable module. This is an opaque object that is used by - * the observable module to trigger notifications. This object should only be - * accessible to functions that are authorized to trigger notifications for this - * module. Observers do not need this object. */ --extern dwc_notifier_t *dwc_register_notifier(void *object); -+extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object); - --/** This function unregister an observable module. All observers have to be -+/** This function unregisters an observable module. All observers have to be - * removed prior to unregistration. */ - extern void dwc_unregister_notifier(dwc_notifier_t *notifier); - -@@ -92,7 +97,8 @@ - * @param notification The notification to observe - * @param callback The callback function to call - * @param user_data Any additional user data to pass into the callback function */ --extern int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *user_data); -+extern int dwc_add_observer(void *observer, void *object, char *notification, -+ dwc_notifier_callback_t callback, void *user_data); - - /** Removes the specified observer from all notifications that it is currently - * observing. */ -@@ -109,4 +115,8 @@ - */ - void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data); - -+#ifdef __cplusplus -+} -+#endif -+ - #endif /* __DWC_NOTIFIER_H__ */ -diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h -index 453966a..308ddd5 100644 ---- a/drivers/usb/host/dwc_common_port/dwc_os.h -+++ b/drivers/usb/host/dwc_common_port/dwc_os.h -@@ -1,8 +1,8 @@ - /* ========================================================================= -- * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_os.h $ -- * $Revision: #2 $ -- * $Date: 2009/04/02 $ -- * $Change: 1224130 $ -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $ -+ * $Revision: #14 $ -+ * $Date: 2010/11/04 $ -+ * $Change: 1621695 $ - * - * Synopsys Portability Library Software and documentation - * (hereinafter, "Software") is an Unsupported proprietary work of -@@ -36,6 +36,10 @@ - #ifndef _DWC_OS_H_ - #define _DWC_OS_H_ - -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - /** @file - * - * DWC portability library, low level os-wrapper functions -@@ -51,12 +55,16 @@ - */ - - #ifdef DWC_LINUX --# include --# ifdef CONFIG_DEBUG_MUTEXES --# include --# endif --#else --# include -+# include -+# ifdef CONFIG_DEBUG_MUTEXES -+# include -+# endif -+# include -+# include -+#endif -+ -+#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -+# include - #endif - - -@@ -67,29 +75,58 @@ - #define YES 1 - #define NO 0 - --/** @todo make them positive and return the negative error code */ -+#ifdef DWC_LINUX -+ -+/** @name Error Codes */ -+#define DWC_E_INVALID EINVAL -+#define DWC_E_NO_MEMORY ENOMEM -+#define DWC_E_NO_DEVICE ENODEV -+#define DWC_E_NOT_SUPPORTED EOPNOTSUPP -+#define DWC_E_TIMEOUT ETIMEDOUT -+#define DWC_E_BUSY EBUSY -+#define DWC_E_AGAIN EAGAIN -+#define DWC_E_RESTART ERESTART -+#define DWC_E_ABORT ECONNABORTED -+#define DWC_E_SHUTDOWN ESHUTDOWN -+#define DWC_E_NO_DATA ENODATA -+#define DWC_E_DISCONNECT ECONNRESET -+#define DWC_E_UNKNOWN EINVAL -+#define DWC_E_NO_STREAM_RES ENOSR -+#define DWC_E_COMMUNICATION ECOMM -+#define DWC_E_OVERFLOW EOVERFLOW -+#define DWC_E_PROTOCOL EPROTO -+#define DWC_E_IN_PROGRESS EINPROGRESS -+#define DWC_E_PIPE EPIPE -+#define DWC_E_IO EIO -+#define DWC_E_NO_SPACE ENOSPC -+ -+#else -+ - /** @name Error Codes */ --#define DWC_E_INVALID 1001 --#define DWC_E_NO_MEMORY 1002 --#define DWC_E_NO_DEVICE 1003 --#define DWC_E_NOT_SUPPORTED 1004 --#define DWC_E_TIMEOUT 1005 --#define DWC_E_BUSY 1006 --#define DWC_E_AGAIN 1007 --#define DWC_E_RESTART 1008 --#define DWC_E_ABORT 1009 --#define DWC_E_SHUTDOWN 1010 --#define DWC_E_NO_DATA 1011 --#define DWC_E_DISCONNECT 2000 --#define DWC_E_UNKNOWN 3000 --#define DWC_E_NO_STREAM_RES 4001 --#define DWC_E_COMMUNICATION 4002 --#define DWC_E_OVERFLOW 4003 --#define DWC_E_PROTOCOL 4004 --#define DWC_E_IN_PROGRESS 4005 --#define DWC_E_PIPE 4006 --#define DWC_E_IO 4007 --#define DWC_E_NO_SPACE 4008 -+#define DWC_E_INVALID 1001 -+#define DWC_E_NO_MEMORY 1002 -+#define DWC_E_NO_DEVICE 1003 -+#define DWC_E_NOT_SUPPORTED 1004 -+#define DWC_E_TIMEOUT 1005 -+#define DWC_E_BUSY 1006 -+#define DWC_E_AGAIN 1007 -+#define DWC_E_RESTART 1008 -+#define DWC_E_ABORT 1009 -+#define DWC_E_SHUTDOWN 1010 -+#define DWC_E_NO_DATA 1011 -+#define DWC_E_DISCONNECT 2000 -+#define DWC_E_UNKNOWN 3000 -+#define DWC_E_NO_STREAM_RES 4001 -+#define DWC_E_COMMUNICATION 4002 -+#define DWC_E_OVERFLOW 4003 -+#define DWC_E_PROTOCOL 4004 -+#define DWC_E_IN_PROGRESS 4005 -+#define DWC_E_PIPE 4006 -+#define DWC_E_IO 4007 -+#define DWC_E_NO_SPACE 4008 -+ -+#endif -+ - - /** @name Tracing/Logging Functions - * -@@ -100,8 +137,6 @@ - * expensive on your system. By default undefining the DEBUG macro already - * no-ops some of these functions. */ - --#include -- - /** Returns non-zero if in interrupt context. */ - extern dwc_bool_t DWC_IN_IRQ(void); - #define dwc_in_irq DWC_IN_IRQ -@@ -111,6 +146,15 @@ static inline char *dwc_irq(void) { - return DWC_IN_IRQ() ? "IRQ" : ""; - } - -+/** Returns non-zero if in bottom-half context. */ -+extern dwc_bool_t DWC_IN_BH(void); -+#define dwc_in_bh DWC_IN_BH -+ -+/** Returns "BH" if DWC_IN_BH is true. */ -+static inline char *dwc_bh(void) { -+ return DWC_IN_BH() ? "BH" : ""; -+} -+ - /** - * A vprintf() clone. Just call vprintf if you've got it. - */ -@@ -132,7 +176,7 @@ extern void DWC_PRINTF(char *format, ...) - #ifdef __GNUC__ - __attribute__ ((format(printf, 1, 2))); - #else -- ; -+ ; - #endif - #define dwc_printf DWC_PRINTF - -@@ -141,9 +185,9 @@ extern void DWC_PRINTF(char *format, ...) - */ - extern int DWC_SPRINTF(char *string, char *format, ...) - #ifdef __GNUC__ -- __attribute__ ((format(printf, 2, 3))); -+ __attribute__ ((format(printf, 2, 3))); - #else -- ; -+ ; - #endif - #define dwc_sprintf DWC_SPRINTF - -@@ -152,9 +196,9 @@ extern int DWC_SPRINTF(char *string, char *format, ...) - */ - extern int DWC_SNPRINTF(char *string, int size, char *format, ...) - #ifdef __GNUC__ -- __attribute__ ((format(printf, 3, 4))); -+ __attribute__ ((format(printf, 3, 4))); - #else -- ; -+ ; - #endif - #define dwc_snprintf DWC_SNPRINTF - -@@ -167,23 +211,23 @@ extern int DWC_SNPRINTF(char *string, int size, char *format, ...) - */ - extern void __DWC_WARN(char *format, ...) - #ifdef __GNUC__ -- __attribute__ ((format(printf, 1, 2))); -+ __attribute__ ((format(printf, 1, 2))); - #else -- ; -+ ; - #endif - - /** - * Prints an error message. On systems that don't differentiate between errors - * and regular log messages, just print it. Indicates that something went wrong -- * with the driver, but it can be recovered from. Works like printf(). -+ * with the driver. Works like printf(). - * - * Use the DWC_ERROR macro to call this function. - */ - extern void __DWC_ERROR(char *format, ...) - #ifdef __GNUC__ -- __attribute__ ((format(printf, 1, 2))); -+ __attribute__ ((format(printf, 1, 2))); - #else -- ; -+ ; - #endif - - /** -@@ -196,12 +240,16 @@ extern void __DWC_ERROR(char *format, ...) - */ - extern void DWC_EXCEPTION(char *format, ...) - #ifdef __GNUC__ -- __attribute__ ((format(printf, 1, 2))); -+ __attribute__ ((format(printf, 1, 2))); - #else -- ; -+ ; - #endif - #define dwc_exception DWC_EXCEPTION - -+#ifndef DWC_OTG_DEBUG_LEV -+#define DWC_OTG_DEBUG_LEV 0 -+#endif -+ - #ifdef DEBUG - /** - * Prints out a debug message. Used for logging/trace messages. -@@ -210,120 +258,203 @@ extern void DWC_EXCEPTION(char *format, ...) - */ - extern void __DWC_DEBUG(char *format, ...) - #ifdef __GNUC__ -- __attribute__ ((format(printf, 1, 2))); -+ __attribute__ ((format(printf, 1, 2))); - #else -- ; -+ ; - #endif - #else - #define __DWC_DEBUG printk --#include - #endif - - /** - * Prints out a Debug message. - */ --#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", __func__, dwc_irq(), ## _args) -+#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \ -+ __func__, dwc_irq(), ## _args) - #define dwc_debug DWC_DEBUG - /** -+ * Prints out a Debug message if enabled at compile time. -+ */ -+#if DWC_OTG_DEBUG_LEV > 0 -+#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args ) -+#else -+#define DWC_DEBUGC(_format, _args...) -+#endif -+#define dwc_debugc DWC_DEBUGC -+/** - * Prints out an informative message. - */ --#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", dwc_irq(), ## _args) -+#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \ -+ dwc_irq(), ## _args) - #define dwc_info DWC_INFO - /** -+ * Prints out an informative message if enabled at compile time. -+ */ -+#if DWC_OTG_DEBUG_LEV > 1 -+#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args ) -+#else -+#define DWC_INFOC(_format, _args...) -+#endif -+#define dwc_infoc DWC_INFOC -+/** - * Prints out a warning message. - */ --#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) -+#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \ -+ dwc_irq(), __func__, __LINE__, ## _args) - #define dwc_warn DWC_WARN - /** - * Prints out an error message. - */ --#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) -+#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \ -+ dwc_irq(), __func__, __LINE__, ## _args) - #define dwc_error DWC_ERROR - --#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) -+#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \ -+ dwc_irq(), __func__, __LINE__, ## _args) - #define dwc_proto_error DWC_PROTO_ERROR - - #ifdef DEBUG - /** Prints out a exception error message if the _expr expression fails. Disabled - * if DEBUG is not enabled. */ --#define DWC_ASSERT(_expr, _format, _args...) if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), __FILE__, __LINE__, ## _args); } -+#define DWC_ASSERT(_expr, _format, _args...) do { \ -+ if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \ -+ __FILE__, __LINE__, ## _args); } \ -+ } while (0) - #else - #define DWC_ASSERT(_x...) - #endif - #define dwc_assert DWC_ASSERT - --/** @name Byter Ordering -+ -+/** @name Byte Ordering - * The following functions are for conversions between processor's byte ordering - * and specific ordering you want. - */ - - /** Converts 32 bit data in CPU byte ordering to little endian. */ --extern uint32_t DWC_CPU_TO_LE32(void *p); -+extern uint32_t DWC_CPU_TO_LE32(uint32_t *p); - #define dwc_cpu_to_le32 DWC_CPU_TO_LE32 -+ - /** Converts 32 bit data in CPU byte orderint to big endian. */ --extern uint32_t DWC_CPU_TO_BE32(void *p); -+extern uint32_t DWC_CPU_TO_BE32(uint32_t *p); - #define dwc_cpu_to_be32 DWC_CPU_TO_BE32 - - /** Converts 32 bit little endian data to CPU byte ordering. */ --extern uint32_t DWC_LE32_TO_CPU(void *p); -+extern uint32_t DWC_LE32_TO_CPU(uint32_t *p); - #define dwc_le32_to_cpu DWC_LE32_TO_CPU -+ - /** Converts 32 bit big endian data to CPU byte ordering. */ --extern uint32_t DWC_BE32_TO_CPU(void *p); -+extern uint32_t DWC_BE32_TO_CPU(uint32_t *p); - #define dwc_be32_to_cpu DWC_BE32_TO_CPU - - /** Converts 16 bit data in CPU byte ordering to little endian. */ --extern uint16_t DWC_CPU_TO_LE16(void *p); -+extern uint16_t DWC_CPU_TO_LE16(uint16_t *p); - #define dwc_cpu_to_le16 DWC_CPU_TO_LE16 -+ - /** Converts 16 bit data in CPU byte orderint to big endian. */ --extern uint16_t DWC_CPU_TO_BE16(void *p); -+extern uint16_t DWC_CPU_TO_BE16(uint16_t *p); - #define dwc_cpu_to_be16 DWC_CPU_TO_BE16 - - /** Converts 16 bit little endian data to CPU byte ordering. */ --extern uint16_t DWC_LE16_TO_CPU(void *p); -+extern uint16_t DWC_LE16_TO_CPU(uint16_t *p); - #define dwc_le16_to_cpu DWC_LE16_TO_CPU -+ - /** Converts 16 bit bi endian data to CPU byte ordering. */ --extern uint16_t DWC_BE16_TO_CPU(void *p); -+extern uint16_t DWC_BE16_TO_CPU(uint16_t *p); - #define dwc_be16_to_cpu DWC_BE16_TO_CPU - -+ - /** @name Register Read/Write - * -- * The following five functions should be implemented to read/write registers of -+ * The following six functions should be implemented to read/write registers of - * 32-bit and 64-bit sizes. All modules use this to read/write register values. - * The reg value is a pointer to the register calculated from the void *base - * variable passed into the driver when it is started. */ - -+#ifdef DWC_LINUX -+/* Linux doesn't need any extra parameters for register read/write, so we -+ * just throw away the IO context parameter. -+ */ - /** Reads the content of a 32-bit register. */ - extern uint32_t DWC_READ_REG32(uint32_t volatile *reg); --#define dwc_read_reg32 DWC_READ_REG32 -+#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_) -+ - /** Reads the content of a 64-bit register. */ - extern uint64_t DWC_READ_REG64(uint64_t volatile *reg); --#define dwc_read_reg64 DWC_READ_REG64 -+#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_) -+ - /** Writes to a 32-bit register. */ - extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value); --#define dwc_write_reg32 DWC_WRITE_REG32 -+#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_) -+ - /** Writes to a 64-bit register. */ - extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value); --#define dwc_write_reg64 DWC_WRITE_REG64 --/** -+#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_) -+ -+/** - * Modify bit values in a register. Using the - * algorithm: (reg_contents & ~clear_mask) | set_mask. - */ - extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); -+#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_) -+extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); -+#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_) -+ -+#endif /* DWC_LINUX */ -+ -+#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -+typedef struct dwc_ioctx { -+ struct device *dev; -+ bus_space_tag_t iot; -+ bus_space_handle_t ioh; -+} dwc_ioctx_t; -+ -+/** BSD needs two extra parameters for register read/write, so we pass -+ * them in using the IO context parameter. -+ */ -+/** Reads the content of a 32-bit register. */ -+extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg); -+#define dwc_read_reg32 DWC_READ_REG32 -+ -+/** Reads the content of a 64-bit register. */ -+extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg); -+#define dwc_read_reg64 DWC_READ_REG64 -+ -+/** Writes to a 32-bit register. */ -+extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value); -+#define dwc_write_reg32 DWC_WRITE_REG32 -+ -+/** Writes to a 64-bit register. */ -+extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value); -+#define dwc_write_reg64 DWC_WRITE_REG64 -+ -+/** -+ * Modify bit values in a register. Using the -+ * algorithm: (reg_contents & ~clear_mask) | set_mask. -+ */ -+extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); - #define dwc_modify_reg32 DWC_MODIFY_REG32 -+extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); -+#define dwc_modify_reg64 DWC_MODIFY_REG64 -+ -+#endif /* DWC_FREEBSD || DWC_NETBSD */ - - /** @cond */ - --/** @name Some convenience MACROS used internally. Define DEBUG_REGS to log the -+/** @name Some convenience MACROS used internally. Define DWC_DEBUG_REGS to log the - * register writes. */ - --#ifdef DEBUG_REGS -+#ifdef DWC_LINUX -+ -+# ifdef DWC_DEBUG_REGS - - #define dwc_define_read_write_reg_n(_reg,_container_type) \ - static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ - return DWC_READ_REG32(&container->regs->_reg[num]); \ - } \ - static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ -- DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, &(((uint32_t*)container->regs->_reg)[num]), data); \ -+ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ -+ &(((uint32_t*)container->regs->_reg)[num]), data); \ - DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ - } - -@@ -332,11 +463,11 @@ extern void __DWC_DEBUG(char *format, ...) - return DWC_READ_REG32(&container->regs->_reg); \ - } \ - static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ -- DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ -+ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ - DWC_WRITE_REG32(&container->regs->_reg, data); \ - } - --#else -+# else /* DWC_DEBUG_REGS */ - - #define dwc_define_read_write_reg_n(_reg,_container_type) \ - static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ -@@ -354,11 +485,59 @@ extern void __DWC_DEBUG(char *format, ...) - DWC_WRITE_REG32(&container->regs->_reg, data); \ - } - --#endif -+# endif /* DWC_DEBUG_REGS */ -+ -+#endif /* DWC_LINUX */ -+ -+#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -+ -+# ifdef DWC_DEBUG_REGS -+ -+#define dwc_define_read_write_reg_n(_reg,_container_type) \ -+static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ -+ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ -+} \ -+static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ -+ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ -+ &(((uint32_t*)container->regs->_reg)[num]), data); \ -+ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ -+} -+ -+#define dwc_define_read_write_reg(_reg,_container_type) \ -+static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ -+ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ -+} \ -+static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ -+ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ -+ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ -+} -+ -+# else /* DWC_DEBUG_REGS */ -+ -+#define dwc_define_read_write_reg_n(_reg,_container_type) \ -+static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ -+ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ -+} \ -+static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ -+ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ -+} -+ -+#define dwc_define_read_write_reg(_reg,_container_type) \ -+static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ -+ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ -+} \ -+static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ -+ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ -+} -+ -+# endif /* DWC_DEBUG_REGS */ -+ -+#endif /* DWC_FREEBSD || DWC_NETBSD */ - - /** @endcond */ - - -+#ifdef DWC_CRYPTOLIB - /** @name Crypto Functions - * - * These are the low-level cryptographic functions used by the driver. */ -@@ -366,16 +545,21 @@ extern void __DWC_DEBUG(char *format, ...) - /** Perform AES CBC */ - extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out); - #define dwc_aes_cbc DWC_AES_CBC -+ - /** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */ - extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length); - #define dwc_random_bytes DWC_RANDOM_BYTES -+ - /** Perform the SHA-256 hash function */ - extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out); - #define dwc_sha256 DWC_SHA256 -+ - /** Calculated the HMAC-SHA256 */ - extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out); - #define dwc_hmac_sha256 DWC_HMAC_SHA256 - -+#endif /* DWC_CRYPTOLIB */ -+ - - /** @name Memory Allocation - * -@@ -384,7 +568,7 @@ extern void __DWC_DEBUG(char *format, ...) - * of the memory debugging routines need to be implemented. The allocation - * routines all ZERO the contents of the memory. - * -- * Defining DEBUG_MEMORY turns on memory debugging and statistic gathering. -+ * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering. - * This checks for memory leaks, keeping track of alloc/free pairs. It also - * keeps track of how much memory the driver is using at any given time. */ - -@@ -394,9 +578,38 @@ extern void __DWC_DEBUG(char *format, ...) - - #define DWC_INVALID_DMA_ADDR 0x0 - --typedef uint32_t dwc_dma_t; -+#ifdef DWC_LINUX -+/** Type for a DMA address */ -+typedef dma_addr_t dwc_dma_t; -+#endif -+ -+#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -+typedef bus_addr_t dwc_dma_t; -+#endif - --/** @todo these functions will be added in the future */ -+#ifdef DWC_FREEBSD -+typedef struct dwc_dmactx { -+ struct device *dev; -+ bus_dma_tag_t dma_tag; -+ bus_dmamap_t dma_map; -+ bus_addr_t dma_paddr; -+ void *dma_vaddr; -+} dwc_dmactx_t; -+#endif -+ -+#ifdef DWC_NETBSD -+typedef struct dwc_dmactx { -+ struct device *dev; -+ bus_dma_tag_t dma_tag; -+ bus_dmamap_t dma_map; -+ bus_dma_segment_t segs[1]; -+ int nsegs; -+ bus_addr_t dma_paddr; -+ void *dma_vaddr; -+} dwc_dmactx_t; -+#endif -+ -+/* @todo these functions will be added in the future */ - #if 0 - /** - * Creates a DMA pool from which you can allocate DMA buffers. Buffers -@@ -416,79 +629,121 @@ extern void __DWC_DEBUG(char *format, ...) - * when you are done with it. - */ - extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary); -+ - /** - * Destroy a DMA pool. All buffers allocated from that pool must be freed first. - */ - extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool); -+ - /** - * Allocate a buffer from the specified DMA pool and zeros its contents. - */ - extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr); -+ - /** - * Free a previously allocated buffer from the DMA pool. - */ - extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr); - #endif - -- - /** Allocates a DMA capable buffer and zeroes its contents. */ --extern void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr); -+extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); - - /** Allocates a DMA capable buffer and zeroes its contents in atomic contest */ --extern void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr); -+extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); - --/** Frees a previosly allocated buffer. */ --extern void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr); -+/** Frees a previously allocated buffer. */ -+extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr); - - /** Allocates a block of memory and zeroes its contents. */ --extern void *__DWC_ALLOC(uint32_t size); -+extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size); - - /** Allocates a block of memory and zeroes its contents, in an atomic manner - * which can be used inside interrupt context. The size should be sufficiently - * small, a few KB at most, such that failures are not likely to occur. Can just call - * __DWC_ALLOC if it is atomic. */ --extern void *__DWC_ALLOC_ATOMIC(uint32_t size); -+extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size); - - /** Frees a previously allocated buffer. */ --extern void __DWC_FREE(void *addr); -+extern void __DWC_FREE(void *mem_ctx, void *addr); - --#ifndef DEBUG_MEMORY -+#ifndef DWC_DEBUG_MEMORY - --#define DWC_ALLOC(_size_) __DWC_ALLOC(_size_) --#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(_size_) --#define DWC_FREE(_addr_) __DWC_FREE(_addr_) --#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(_size_,_dma_) --#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) --#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(_size_,_virt_,_dma_) -+#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_) -+#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_) -+#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) - --#else -+# ifdef DWC_LINUX -+#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) -+# endif - --extern void *dwc_alloc_debug(uint32_t size, char const *func, int line); --extern void *dwc_alloc_atomic_debug(uint32_t size, char const *func, int line); --extern void dwc_free_debug(void *addr, char const *func, int line); --extern void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line); -+# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -+#define DWC_DMA_ALLOC __DWC_DMA_ALLOC -+#define DWC_DMA_FREE __DWC_DMA_FREE -+# endif - extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line); --extern void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line); - --extern void dwc_memory_debug_start(void); -+#else /* DWC_DEBUG_MEMORY */ -+ -+extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line); -+extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line); -+extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line); -+extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, -+ char const *func, int line); -+extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, -+ char const *func, int line); -+extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, -+ dwc_dma_t dma_addr, char const *func, int line); -+ -+extern int dwc_memory_debug_start(void *mem_ctx); - extern void dwc_memory_debug_stop(void); - extern void dwc_memory_debug_report(void); - --#define DWC_ALLOC(_size_) (dwc_alloc_debug(_size_, __func__, __LINE__)) --#define DWC_ALLOC_ATOMIC(_size_) (dwc_alloc_atomic_debug(_size_, __func__, __LINE__)) --#define DWC_FREE(_addr_) (dwc_free_debug(_addr_, __func__, __LINE__)) --#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(_size_, _dma_, __func__, __LINE__) --#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(_size_, _dma_, __func__, __LINE__) --#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(_size_, _virt_, _dma_, __func__, __LINE__) -+#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__) -+#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \ -+ __func__, __LINE__) -+#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) -+ -+# ifdef DWC_LINUX -+#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ -+ _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ -+ _dma_, __func__, __LINE__) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ -+ _virt_, _dma_, __func__, __LINE__) -+# endif -+ -+# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -+#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \ -+ _dma_, __func__, __LINE__) -+#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \ -+ _virt_, _dma_, __func__, __LINE__) -+# endif -+ -+#endif /* DWC_DEBUG_MEMORY */ -+ -+#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_) -+#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_) -+#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_) - --#endif /* DEBUG_MEMORY */ -+#ifdef DWC_LINUX -+/* Linux doesn't need any extra parameters for DMA buffer allocation, so we -+ * just throw away the DMA context parameter. -+ */ -+#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_) -+#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_) -+#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_) -+#endif - --#define dwc_alloc DWC_ALLOC --#define dwc_alloc_atomic DWC_ALLOC_ATOMIC --#define dwc_free DWC_FREE -+#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -+/** BSD needs several extra parameters for DMA buffer allocation, so we pass -+ * them in using the DMA context parameter. -+ */ - #define dwc_dma_alloc DWC_DMA_ALLOC --#define dwc_dma_alloc_atomic DWC_DMA_ALLOC_ATOMIC - #define dwc_dma_free DWC_DMA_FREE -+#endif - - - /** @name Memory and String Processing */ -@@ -496,24 +751,31 @@ extern void __DWC_DEBUG(char *format, ...) - /** memset() clone */ - extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size); - #define dwc_memset DWC_MEMSET -+ - /** memcpy() clone */ - extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size); - #define dwc_memcpy DWC_MEMCPY -+ - /** memmove() clone */ - extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size); - #define dwc_memmove DWC_MEMMOVE -+ - /** memcmp() clone */ - extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size); - #define dwc_memcmp DWC_MEMCMP -+ - /** strcmp() clone */ - extern int DWC_STRCMP(void *s1, void *s2); - #define dwc_strcmp DWC_STRCMP -+ - /** strncmp() clone */ - extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size); - #define dwc_strncmp DWC_STRNCMP -+ - /** strlen() clone, for NULL terminated ASCII strings */ - extern int DWC_STRLEN(char const *str); - #define dwc_strlen DWC_STRLEN -+ - /** strcpy() clone, for NULL terminated ASCII strings */ - extern char *DWC_STRCPY(char *to, const char *from); - #define dwc_strcpy DWC_STRCPY -@@ -523,7 +785,7 @@ extern void __DWC_DEBUG(char *format, ...) - * calling a predefined strdup. Otherwise the memory allocated by this routine - * will not be seen by the debugging routines. */ - extern char *DWC_STRDUP(char const *str); --#define dwc_strdup DWC_STRDUP -+#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_) - - /** NOT an atoi() clone. Read the description carefully. Returns an integer - * converted from the string str in base 10 unless the string begins with a "0x" -@@ -535,14 +797,19 @@ extern void __DWC_DEBUG(char *format, ...) - * conversion are undefined. On sucess it returns 0. Overflow conditions are - * undefined. An example implementation using atoi() can be referenced from the - * Linux implementation. */ --extern int DWC_ATOI(char *str, int32_t *value); -+extern int DWC_ATOI(const char *str, int32_t *value); - #define dwc_atoi DWC_ATOI -+ - /** Same as above but for unsigned. */ --extern int DWC_ATOUI(char *str, uint32_t *value); -+extern int DWC_ATOUI(const char *str, uint32_t *value); - #define dwc_atoui DWC_ATOUI -+ -+#ifdef DWC_UTFLIB - /** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */ - extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len); - #define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE -+#endif -+ - - /** @name Wait queues - * -@@ -552,6 +819,8 @@ extern void __DWC_DEBUG(char *format, ...) - * unblocked and the condition will be check again. Waitqs should be triggered - * every time a condition can potentially change.*/ - struct dwc_waitq; -+ -+/** Type for a waitq */ - typedef struct dwc_waitq dwc_waitq_t; - - /** The type of waitq condition callback function. This is called every time -@@ -560,7 +829,8 @@ extern void __DWC_DEBUG(char *format, ...) - - /** Allocate a waitq */ - extern dwc_waitq_t *DWC_WAITQ_ALLOC(void); --#define dwc_waitq_alloc DWC_WAITQ_ALLOC -+#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC() -+ - /** Free a waitq */ - extern void DWC_WAITQ_FREE(dwc_waitq_t *wq); - #define dwc_waitq_free DWC_WAITQ_FREE -@@ -568,23 +838,28 @@ extern void __DWC_DEBUG(char *format, ...) - /** Check the condition and if it is false, block on the waitq. When unblocked, check the - * condition again. The function returns when the condition becomes true. The return value - * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */ --extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data); --#define dwc_waitq_wait DWC_WAITQ_WAIT; -+extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data); -+#define dwc_waitq_wait DWC_WAITQ_WAIT -+ - /** Check the condition and if it is false, block on the waitq. When unblocked, - * check the condition again. The function returns when the condition become - * true or the timeout has passed. The return value is 0 on condition true or - * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on - * error. */ --extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data, int32_t msecs); -+extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, -+ void *data, int32_t msecs); - #define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT -+ - /** Trigger a waitq, unblocking all processes. This should be called whenever a condition - * has potentially changed. */ - extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq); - #define dwc_waitq_trigger DWC_WAITQ_TRIGGER -+ - /** Unblock all processes waiting on the waitq with an ABORTED result. */ - extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq); - #define dwc_waitq_abort DWC_WAITQ_ABORT - -+ - /** @name Threads - * - * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP -@@ -593,6 +868,8 @@ extern void __DWC_DEBUG(char *format, ...) - */ - - struct dwc_thread; -+ -+/** Type for a thread */ - typedef struct dwc_thread dwc_thread_t; - - /** The thread function */ -@@ -600,21 +877,42 @@ extern void __DWC_DEBUG(char *format, ...) - - /** Create a thread and start it running the thread_function. Returns a handle - * to the thread */ --extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data); --#define dwc_thread_run DWC_THREAD_RUN -+extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data); -+#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_) -+ - /** Stops a thread. Return the value returned by the thread. Or will return - * DWC_ABORT if the thread never started. */ - extern int DWC_THREAD_STOP(dwc_thread_t *thread); - #define dwc_thread_stop DWC_THREAD_STOP -+ - /** Signifies to the thread that it must stop. */ -+#ifdef DWC_LINUX -+/* Linux doesn't need any parameters for kthread_should_stop() */ - extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void); -+#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP() -+ -+/* No thread_exit function in Linux */ -+#define dwc_thread_exit(_thrd_) -+#endif -+ -+#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) -+/** BSD needs the thread pointer for kthread_suspend_check() */ -+extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread); - #define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP - -+/** The thread must call this to exit. */ -+extern void DWC_THREAD_EXIT(dwc_thread_t *thread); -+#define dwc_thread_exit DWC_THREAD_EXIT -+#endif -+ -+ - /** @name Work queues - * - * Workqs are used to queue a callback function to be called at some later time, - * in another thread. */ - struct dwc_workq; -+ -+/** Type for a workq */ - typedef struct dwc_workq dwc_workq_t; - - /** The type of the callback function to be called. */ -@@ -622,33 +920,38 @@ extern void __DWC_DEBUG(char *format, ...) - - /** Allocate a workq */ - extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name); --#define dwc_workq_alloc DWC_WORKQ_ALLOC -+#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_) -+ - /** Free a workq. All work must be completed before being freed. */ - extern void DWC_WORKQ_FREE(dwc_workq_t *workq); - #define dwc_workq_free DWC_WORKQ_FREE -+ - /** Schedule a callback on the workq, passing in data. The function will be - * scheduled at some later time. */ --extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, char *format, ...) -+extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb, -+ void *data, char *format, ...) - #ifdef __GNUC__ - __attribute__ ((format(printf, 4, 5))); - #else -- ; -+ ; - #endif - #define dwc_workq_schedule DWC_WORKQ_SCHEDULE - --/** Schedule a callback on the workq, that will be called until at least -+/** Schedule a callback on the workq, that will be called until at least - * given number miliseconds have passed. */ --extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...) -+extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb, -+ void *data, uint32_t time, char *format, ...) - #ifdef __GNUC__ - __attribute__ ((format(printf, 5, 6))); - #else -- ; -+ ; - #endif - #define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED - - /** The number of processes in the workq */ - extern int DWC_WORKQ_PENDING(dwc_workq_t *workq); - #define dwc_workq_pending DWC_WORKQ_PENDING -+ - /** Blocks until all the work in the workq is complete or timed out. Returns < - * 0 on timeout. */ - extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout); -@@ -659,14 +962,22 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - * - */ - struct dwc_tasklet; -+ -+/** Type for a tasklet */ - typedef struct dwc_tasklet dwc_tasklet_t; - -+/** The type of the callback function to be called */ - typedef void (*dwc_tasklet_callback_t)(void *data); - --extern dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data); --#define dwc_task_alloc DWC_TASK_ALLOC --extern void DWC_TASK_FREE(dwc_tasklet_t *t); -+/** Allocates a tasklet */ -+extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data); -+#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_) -+ -+/** Frees a tasklet */ -+extern void DWC_TASK_FREE(dwc_tasklet_t *task); - #define dwc_task_free DWC_TASK_FREE -+ -+/** Schedules a tasklet to run */ - extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task); - #define dwc_task_schedule DWC_TASK_SCHEDULE - -@@ -676,12 +987,18 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - * Callbacks must be small and atomic. - */ - struct dwc_timer; -+ -+/** Type for a timer */ - typedef struct dwc_timer dwc_timer_t; - -+/** The type of the callback function to be called */ - typedef void (*dwc_timer_callback_t)(void *data); - -+/** Allocates a timer */ - extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data); --#define dwc_timer_alloc DWC_TIMER_ALLOC -+#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_) -+ -+/** Frees a timer */ - extern void DWC_TIMER_FREE(dwc_timer_t *timer); - #define dwc_timer_free DWC_TIMER_FREE - -@@ -698,7 +1015,6 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - #define dwc_timer_cancel DWC_TIMER_CANCEL - - -- - /** @name Spinlocks - * - * These locks are used when the work between the lock/unlock is atomic and -@@ -711,25 +1027,30 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - * change, and so you never have to lock between processes. */ - - struct dwc_spinlock; -+ -+/** Type for a spinlock */ - typedef struct dwc_spinlock dwc_spinlock_t; - -+/** Type for the 'flags' argument to spinlock funtions */ -+typedef unsigned long dwc_irqflags_t; -+ - /** Returns an initialized lock variable. This function should allocate and - * initialize the OS-specific data structure used for locking. This data - * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should - * be freed by the DWC_FREE_LOCK when it is no longer used. */ - extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void); --#define dwc_spinlock_alloc DWC_SPINLOCK_ALLOC -+#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC() - - /** Frees an initialized lock variable. */ - extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock); --#define dwc_spinlock_free DWC_SPINLOCK_FREE -+#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_) - - /** Disables interrupts and blocks until it acquires the lock. - * - * @param lock Pointer to the spinlock. - * @param flags Unsigned long for irq flags storage. - */ --extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags); -+extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags); - #define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE - - /** Re-enables the interrupt and releases the lock. -@@ -738,7 +1059,7 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - * @param flags Unsigned long for irq flags storage. Must be the same as was - * passed into DWC_LOCK. - */ --extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags); -+extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags); - #define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE - - /** Blocks until it acquires the lock. -@@ -755,6 +1076,7 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock); - #define dwc_spinunlock DWC_SPINUNLOCK - -+ - /** @name Mutexes - * - * Unlike spinlocks Mutexes lock only between processes and the work between the -@@ -762,43 +1084,49 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - */ - - struct dwc_mutex; --typedef struct dwc_mutex dwc_mutex_t; - -+/** Type for a mutex */ -+typedef struct dwc_mutex dwc_mutex_t; - - /* For Linux Mutex Debugging make it inline because the debugging routines use - * the symbol to determine recursive locking. This makes it falsely think - * recursive locking occurs. */ --#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) - #define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \ - __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \ - mutex_init((struct mutex *)__mutexp); \ - }) - #endif -+ -+/** Allocate a mutex */ - extern dwc_mutex_t *DWC_MUTEX_ALLOC(void); --#define dwc_mutex_alloc DWC_MUTEX_ALLOC -+#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC() - - /* For memory leak debugging when using Linux Mutex Debugging */ --#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) -+#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) - #define DWC_MUTEX_FREE(__mutexp) do { \ - mutex_destroy((struct mutex *)__mutexp); \ - DWC_FREE(__mutexp); \ - } while(0) - #else -+/** Free a mutex */ - extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex); --#define dwc_mutex_free DWC_MUTEX_FREE -+#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_) - #endif - -+/** Lock a mutex */ - extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex); - #define dwc_mutex_lock DWC_MUTEX_LOCK -+ - /** Non-blocking lock returns 1 on successful lock. */ - extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex); - #define dwc_mutex_trylock DWC_MUTEX_TRYLOCK -+ -+/** Unlock a mutex */ - extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex); - #define dwc_mutex_unlock DWC_MUTEX_UNLOCK - - -- -- - /** @name Time */ - - /** Microsecond delay. -@@ -823,15 +1151,16 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - extern void DWC_MSLEEP(uint32_t msecs); - #define dwc_msleep DWC_MSLEEP - -+/** -+ * Returns number of milliseconds since boot. -+ */ - extern uint32_t DWC_TIME(void); - #define dwc_time DWC_TIME - --#endif // _DWC_OS_H_ - - - -- --/** @mainpage DWC Portability and Common Library -+/* @mainpage DWC Portability and Common Library - * - * This is the documentation for the DWC Portability and Common Library. - * -@@ -923,3 +1252,9 @@ extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t w - * threading should be able to be implemented with the defined behavior. - * - */ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _DWC_OS_H_ */ -diff --git a/drivers/usb/host/dwc_common_port/usb.h b/drivers/usb/host/dwc_common_port/usb.h -index 2ee4252..27bda82 100644 ---- a/drivers/usb/host/dwc_common_port/usb.h -+++ b/drivers/usb/host/dwc_common_port/usb.h -@@ -41,7 +41,9 @@ - #ifndef _USB_H_ - #define _USB_H_ - --#include "dwc_os.h" -+#ifdef __cplusplus -+extern "C" { -+#endif - - /* - * The USB records contain some unaligned little-endian word -@@ -54,6 +56,9 @@ - typedef u_int8_t uDWord[4]; - - #define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) -+#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff } -+#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \ -+ ((x) >> 16) & 0xff, ((x) >> 24) & 0xff } - - #if 1 - #define UGETW(w) ((w)[0] | ((w)[1] << 8)) -@@ -74,6 +79,21 @@ - #define USETDW(w,v) (*(u_int32_t *)(w) = (v)) - #endif - -+/* -+ * Macros for accessing UAS IU fields, which are big-endian -+ */ -+#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l)) -+#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff } -+#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ -+ ((x) >> 8) & 0xff, (x) & 0xff } -+#define IUGETW(w) (((w)[0] << 8) | (w)[1]) -+#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v)) -+#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) -+#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \ -+ (w)[1] = (u_int8_t)((v) >> 16), \ -+ (w)[2] = (u_int8_t)((v) >> 8), \ -+ (w)[3] = (u_int8_t)(v)) -+ - #define UPACKED __attribute__((__packed__)) - - typedef struct { -@@ -140,6 +160,7 @@ - #define UDESC_STRING 0x03 - #define UDESC_INTERFACE 0x04 - #define UDESC_ENDPOINT 0x05 -+#define UDESC_SS_USB_COMPANION 0x30 - #define UDESC_DEVICE_QUALIFIER 0x06 - #define UDESC_OTHER_SPEED_CONFIGURATION 0x07 - #define UDESC_INTERFACE_POWER 0x08 -@@ -157,6 +178,8 @@ - #define WUDESC_BOS 0x0f - #define WUDESC_DEVICE_CAPABILITY 0x10 - #define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11 -+#define UDESC_BOS 0x0f -+#define UDESC_DEVICE_CAPABILITY 0x10 - #define UDESC_CS_DEVICE 0x21 /* class specific */ - #define UDESC_CS_CONFIG 0x22 - #define UDESC_CS_STRING 0x23 -@@ -177,11 +200,11 @@ - #define WUR_SET_SECURITY_DATA 0x12 - #define WUR_GET_SECURITY_DATA 0x13 - #define WUR_SET_WUSB_DATA 0x14 --#define WUDATA_DRPIE_INFO 0x01 --#define WUDATA_TRANSMIT_DATA 0x02 --#define WUDATA_TRANSMIT_PARAMS 0x03 --#define WUDATA_RECEIVE_PARAMS 0x04 --#define WUDATA_TRANSMIT_POWER 0x05 -+#define WUDATA_DRPIE_INFO 0x01 -+#define WUDATA_TRANSMIT_DATA 0x02 -+#define WUDATA_TRANSMIT_PARAMS 0x03 -+#define WUDATA_RECEIVE_PARAMS 0x04 -+#define WUDATA_TRANSMIT_POWER 0x05 - #define WUR_LOOPBACK_DATA_WRITE 0x15 - #define WUR_LOOPBACK_DATA_READ 0x16 - #define WUR_SET_INTERFACE_DS 0x17 -@@ -193,11 +216,15 @@ - #define UF_DEVICE_B_HNP_ENABLE 3 - #define UF_DEVICE_A_HNP_SUPPORT 4 - #define UF_DEVICE_A_ALT_HNP_SUPPORT 5 --#define WUF_WUSB 3 --#define WUF_TX_DRPIE 0x0 --#define WUF_DEV_XMIT_PACKET 0x1 --#define WUF_COUNT_PACKETS 0x2 --#define WUF_CAPTURE_PACKETS 0x3 -+#define WUF_WUSB 3 -+#define WUF_TX_DRPIE 0x0 -+#define WUF_DEV_XMIT_PACKET 0x1 -+#define WUF_COUNT_PACKETS 0x2 -+#define WUF_CAPTURE_PACKETS 0x3 -+#define UF_FUNCTION_SUSPEND 0 -+#define UF_U1_ENABLE 48 -+#define UF_U2_ENABLE 49 -+#define UF_LTM_ENABLE 50 - - /* Class requests from the USB 2.0 hub spec, table 11-15 */ - #define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE) -@@ -209,6 +236,10 @@ - #define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE) - #define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE) - -+#ifdef _MSC_VER -+#include -+#endif -+ - typedef struct { - uByte bLength; - uByte bDescriptorType; -@@ -218,6 +249,11 @@ - typedef struct { - uByte bLength; - uByte bDescriptorType; -+} UPACKED usb_descriptor_header_t; -+ -+typedef struct { -+ uByte bLength; -+ uByte bDescriptorType; - uWord bcdUSB; - #define UD_USB_2_0 0x0200 - #define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) -@@ -243,6 +279,10 @@ - uByte bNumInterface; - uByte bConfigurationValue; - uByte iConfiguration; -+#define UC_ATT_ONE (1 << 7) /* must be set */ -+#define UC_ATT_SELFPOWER (1 << 6) /* self powered */ -+#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */ -+#define UC_ATT_BATTERY (1 << 4) /* battery powered */ - uByte bmAttributes; - #define UC_BUS_POWERED 0x80 - #define UC_SELF_POWERED 0x40 -@@ -292,6 +332,19 @@ - } UPACKED usb_endpoint_descriptor_t; - #define USB_ENDPOINT_DESCRIPTOR_SIZE 7 - -+typedef struct ss_endpoint_companion_descriptor { -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bMaxBurst; -+#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f) -+#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f)) -+#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03) -+#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03)) -+ uByte bmAttributes; -+ uWord wBytesPerInterval; -+} UPACKED ss_endpoint_companion_descriptor_t; -+#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6 -+ - typedef struct { - uByte bLength; - uByte bDescriptorType; -@@ -420,6 +473,10 @@ - #define UPS_C_PORT_RESET 0x0010 - } UPACKED usb_port_status_t; - -+#ifdef _MSC_VER -+#include -+#endif -+ - /* Device class codes */ - #define UDCLASS_IN_INTERFACE 0x00 - #define UDCLASS_COMM 0x02 -@@ -443,13 +500,13 @@ - #define UISUBCLASS_MIDISTREAM 3 - - #define UICLASS_CDC 0x02 /* communication */ --#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 -+#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 - #define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 --#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 --#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 --#define UISUBCLASS_CAPI_CONTROLMODEL 5 --#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 --#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 -+#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 -+#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 -+#define UISUBCLASS_CAPI_CONTROLMODEL 5 -+#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 -+#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 - #define UIPROTO_CDC_AT 1 - - #define UICLASS_HID 0x03 -@@ -519,7 +576,6 @@ - - #define UICLASS_VENDOR 0xff - -- - #define USB_HUB_MAX_DEPTH 5 - - /* -@@ -558,7 +614,6 @@ - - #define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ - -- - #define USB_UNCONFIG_NO 0 - #define USB_UNCONFIG_INDEX (-1) - -@@ -638,9 +693,12 @@ struct usb_device_info { - u_int8_t udi_protocol; - u_int8_t udi_config; - u_int8_t udi_speed; --#define USB_SPEED_LOW 1 --#define USB_SPEED_FULL 2 --#define USB_SPEED_HIGH 3 -+#define USB_SPEED_UNKNOWN 0 -+#define USB_SPEED_LOW 1 -+#define USB_SPEED_FULL 2 -+#define USB_SPEED_HIGH 3 -+#define USB_SPEED_VARIABLE 4 -+#define USB_SPEED_SUPER 5 - int udi_power; /* power consumption in mA, 0 if selfpowered */ - int udi_nports; - char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; -@@ -660,17 +718,14 @@ struct usb_device_stats { - u_long uds_requests[4]; /* indexed by transfer type UE_* */ - }; - -- -- -- - #define WUSB_MIN_IE 0x80 - #define WUSB_WCTA_IE 0x80 - #define WUSB_WCONNECTACK_IE 0x81 - #define WUSB_WHOSTINFO_IE 0x82 - #define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3) --#define WUHI_CA_RECONN 0x00 --#define WUHI_CA_LIMITED 0x01 --#define WUHI_CA_ALL 0x03 -+#define WUHI_CA_RECONN 0x00 -+#define WUHI_CA_LIMITED 0x01 -+#define WUHI_CA_ALL 0x03 - #define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3) - #define WUSB_WCHCHANGEANNOUNCE_IE 0x83 - #define WUSB_WDEV_DISCONNECT_IE 0x84 -@@ -701,150 +756,191 @@ struct usb_device_stats { - #define WUSB_DN_ALIVE 0x07 - #define WUSB_DN_MAX 0x07 - -+#ifdef _MSC_VER -+#include -+#endif - - /* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */ - typedef struct wusb_hndshk_data { -- uint8_t bMessageNumber; -- uint8_t bStatus; -- uint8_t tTKID[3]; -- uint8_t bReserved; -- uint8_t CDID[16]; -- uint8_t Nonce[16]; -- uint8_t MIC[8]; -+ uByte bMessageNumber; -+ uByte bStatus; -+ uByte tTKID[3]; -+ uByte bReserved; -+ uByte CDID[16]; -+ uByte Nonce[16]; -+ uByte MIC[8]; - } UPACKED wusb_hndshk_data_t; - #define WUSB_HANDSHAKE_LEN_FOR_MIC 38 - - /* WUSB Connection Context */ - typedef struct wusb_conn_context { -- uint8_t CHID [16]; -- uint8_t CDID [16]; -- uint8_t CK [16]; -+ uByte CHID [16]; -+ uByte CDID [16]; -+ uByte CK [16]; - } UPACKED wusb_conn_context_t; - - /* WUSB Security Descriptor */ - typedef struct wusb_security_desc { -- uint8_t bLength; -- uint8_t bDescriptorType; -- uint16_t wTotalLength; -- uint8_t bNumEncryptionTypes; -+ uByte bLength; -+ uByte bDescriptorType; -+ uWord wTotalLength; -+ uByte bNumEncryptionTypes; - } UPACKED wusb_security_desc_t; - - /* WUSB Encryption Type Descriptor */ - typedef struct wusb_encrypt_type_desc { -- uint8_t bLength; -- uint8_t bDescriptorType; -+ uByte bLength; -+ uByte bDescriptorType; - -- uint8_t bEncryptionType; --#define WUETD_UNSECURE 0 -+ uByte bEncryptionType; -+#define WUETD_UNSECURE 0 - #define WUETD_WIRED 1 - #define WUETD_CCM_1 2 - #define WUETD_RSA_1 3 - -- uint8_t bEncryptionValue; -- uint8_t bAuthKeyIndex; -+ uByte bEncryptionValue; -+ uByte bAuthKeyIndex; - } UPACKED wusb_encrypt_type_desc_t; - - /* WUSB Key Descriptor */ - typedef struct wusb_key_desc { -- uint8_t bLength; -- uint8_t bDescriptorType; -- uint8_t tTKID[3]; -- uint8_t bReserved; -- uint8_t KeyData[1]; /* variable length */ -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte tTKID[3]; -+ uByte bReserved; -+ uByte KeyData[1]; /* variable length */ - } UPACKED wusb_key_desc_t; - - /* WUSB BOS Descriptor (Binary device Object Store) */ - typedef struct wusb_bos_desc { -- uint8_t bLength; -- uint8_t bDescriptorType; -- uint16_t wTotalLength; -- uint8_t bNumDeviceCaps; -+ uByte bLength; -+ uByte bDescriptorType; -+ uWord wTotalLength; -+ uByte bNumDeviceCaps; - } UPACKED wusb_bos_desc_t; - -+#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 -+typedef struct usb_dev_cap_20_ext_desc { -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bDevCapabilityType; -+#define USB_20_EXT_LPM 0x02 -+ uDWord bmAttributes; -+} UPACKED usb_dev_cap_20_ext_desc_t; -+ -+#define USB_DEVICE_CAPABILITY_SS_USB 0x03 -+typedef struct usb_dev_cap_ss_usb { -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bDevCapabilityType; -+#define USB_DC_SS_USB_LTM_CAPABLE 0x02 -+ uByte bmAttributes; -+#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 -+#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 -+#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 -+#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 -+ uWord wSpeedsSupported; -+ uByte bFunctionalitySupport; -+ uByte bU1DevExitLat; -+ uWord wU2DevExitLat; -+} UPACKED usb_dev_cap_ss_usb_t; -+ -+#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 -+typedef struct usb_dev_cap_container_id { -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bDevCapabilityType; -+ uByte bReserved; -+ uByte containerID[16]; -+} UPACKED usb_dev_cap_container_id_t; - - /* Device Capability Type Codes */ - #define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01 - - /* Device Capability Descriptor */ - typedef struct wusb_dev_cap_desc { -- uint8_t bLength; -- uint8_t bDescriptorType; -- uint8_t bDevCapabilityType; -- uint8_t caps[1]; /* Variable length */ -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bDevCapabilityType; -+ uByte caps[1]; /* Variable length */ - } UPACKED wusb_dev_cap_desc_t; - - /* Device Capability Descriptor */ - typedef struct wusb_dev_cap_uwb_desc { -- uint8_t bLength; -- uint8_t bDescriptorType; -- uint8_t bDevCapabilityType; -- uint8_t bmAttributes; -- uint16_t wPHYRates; /* Bitmap */ -- uint8_t bmTFITXPowerInfo; -- uint8_t bmFFITXPowerInfo; -- uint16_t bmBandGroup; -- uint8_t bReserved; -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bDevCapabilityType; -+ uByte bmAttributes; -+ uWord wPHYRates; /* Bitmap */ -+ uByte bmTFITXPowerInfo; -+ uByte bmFFITXPowerInfo; -+ uWord bmBandGroup; -+ uByte bReserved; - } UPACKED wusb_dev_cap_uwb_desc_t; - - /* Wireless USB Endpoint Companion Descriptor */ - typedef struct wusb_endpoint_companion_desc { -- uint8_t bLength; -- uint8_t bDescriptorType; -- uint8_t bMaxBurst; -- uint8_t bMaxSequence; -- uint16_t wMaxStreamDelay; -- uint16_t wOverTheAirPacketSize; -- uint8_t bOverTheAirInterval; -- uint8_t bmCompAttributes; -+ uByte bLength; -+ uByte bDescriptorType; -+ uByte bMaxBurst; -+ uByte bMaxSequence; -+ uWord wMaxStreamDelay; -+ uWord wOverTheAirPacketSize; -+ uByte bOverTheAirInterval; -+ uByte bmCompAttributes; - } UPACKED wusb_endpoint_companion_desc_t; - -- - /* Wireless USB Numeric Association M1 Data Structure */ - typedef struct wusb_m1_data { -- uint8_t version; -- uint16_t langId; -- uint8_t deviceFriendlyNameLength; -- uint8_t sha_256_m3[32]; -- uint8_t deviceFriendlyName[256]; -+ uByte version; -+ uWord langId; -+ uByte deviceFriendlyNameLength; -+ uByte sha_256_m3[32]; -+ uByte deviceFriendlyName[256]; - } UPACKED wusb_m1_data_t; - - typedef struct wusb_m2_data { -- uint8_t version; -- uint16_t langId; -- uint8_t hostFriendlyNameLength; -- uint8_t pkh[384]; -- uint8_t hostFriendlyName[256]; -+ uByte version; -+ uWord langId; -+ uByte hostFriendlyNameLength; -+ uByte pkh[384]; -+ uByte hostFriendlyName[256]; - } UPACKED wusb_m2_data_t; - - typedef struct wusb_m3_data { -- uint8_t pkd[384]; -- uint8_t nd; -+ uByte pkd[384]; -+ uByte nd; - } UPACKED wusb_m3_data_t; - - typedef struct wusb_m4_data { -- uint32_t _attributeTypeIdAndLength_1; -- uint16_t associationTypeId; -+ uDWord _attributeTypeIdAndLength_1; -+ uWord associationTypeId; - -- uint32_t _attributeTypeIdAndLength_2; -- uint16_t associationSubTypeId; -+ uDWord _attributeTypeIdAndLength_2; -+ uWord associationSubTypeId; - -- uint32_t _attributeTypeIdAndLength_3; -- uint32_t length; -+ uDWord _attributeTypeIdAndLength_3; -+ uDWord length; - -- uint32_t _attributeTypeIdAndLength_4; -- uint32_t associationStatus; -+ uDWord _attributeTypeIdAndLength_4; -+ uDWord associationStatus; - -- uint32_t _attributeTypeIdAndLength_5; -- uint8_t chid[16]; -+ uDWord _attributeTypeIdAndLength_5; -+ uByte chid[16]; - -- uint32_t _attributeTypeIdAndLength_6; -- uint8_t cdid[16]; -+ uDWord _attributeTypeIdAndLength_6; -+ uByte cdid[16]; - -- uint32_t _attributeTypeIdAndLength_7; -- uint8_t bandGroups[2]; -+ uDWord _attributeTypeIdAndLength_7; -+ uByte bandGroups[2]; - } UPACKED wusb_m4_data_t; - -+#ifdef _MSC_VER -+#include -+#endif - -- -+#ifdef __cplusplus -+} -+#endif - - #endif /* _USB_H_ */ -diff --git a/drivers/usb/host/dwc_otg/Makefile b/drivers/usb/host/dwc_otg/Makefile -index fed13f4..c4c6e4e 100644 ---- a/drivers/usb/host/dwc_otg/Makefile -+++ b/drivers/usb/host/dwc_otg/Makefile -@@ -4,27 +4,30 @@ - - ifneq ($(KERNELRELEASE),) - -+# Use the BUS_INTERFACE variable to compile the software for either -+# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus. - ifeq ($(BUS_INTERFACE),) -- # BUS_INTERFACE = -DLM_INTERFACE -- BUS_INTERFACE = -DPLATFORM_INTERFACE=1 -+# BUS_INTERFACE = -DPCI_INTERFACE -+# BUS_INTERFACE = -DLM_INTERFACE -+ BUS_INTERFACE = -DPLATFORM_INTERFACE - endif - --ifeq ($(CONFIG_USB_DEBUG),y) --CPPFLAGS += -DDEBUG --endif -+#EXTRA_CFLAGS += -DDEBUG -+#EXTRA_CFLAGS += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs - - # Use one of the following flags to compile the software in host-only or - # device-only mode. --#CPPFLAGS += -DDWC_HOST_ONLY --#CPPFLAGS += -DDWC_DEVICE_ONLY -- --CPPFLAGS += -Dlinux -DDWC_HS_ELECT_TST --#CGG: CPPFLAGS += -DDWC_EN_ISOC --CPPFLAGS += -I$(obj)/../dwc_common_port --#CPPFLAGS += -I$(PORTLIB) --CPPFLAGS += -DDWC_LINUX --CPPFLAGS += $(CFI) --CPPFLAGS += $(BUS_INTERFACE) -+#EXTRA_CFLAGS += -DDWC_HOST_ONLY -+#EXTRA_CFLAGS += -DDWC_DEVICE_ONLY -+ -+EXTRA_CFLAGS += -Dlinux -DDWC_HS_ELECT_TST -+#EXTRA_CFLAGS += -DDWC_EN_ISOC -+EXTRA_CFLAGS += -I$(obj)/../dwc_common_port -+#EXTRA_CFLAGS += -I$(PORTLIB) -+EXTRA_CFLAGS += -DDWC_LINUX -+EXTRA_CFLAGS += $(CFI) -+EXTRA_CFLAGS += $(BUS_INTERFACE) -+#EXTRA_CFLAGS += -DDWC_DEV_SRPCAP - - obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o - -@@ -32,6 +35,7 @@ dwc_otg-objs := dwc_otg_driver.o dwc_otg_attr.o - dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o - dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o - dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o -+dwc_otg-objs += dwc_otg_adp.o - ifneq ($(CFI),) - dwc_otg-objs += dwc_otg_cfi.o - endif -@@ -56,12 +60,8 @@ default: portlib - $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules - - install: default --ifneq ($(INSTALL_MOD_PATH),) - $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install - $(MAKE) -C$(KDIR) M=$(PWD) modules_install --else -- @echo "No install path defined" --endif - - portlib: - $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules -@@ -75,6 +75,6 @@ tags: $(wildcard *.[hc]) - - - clean: -- rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions -+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers - - endif -diff --git a/drivers/usb/host/dwc_otg/doc/doxygen.cfg b/drivers/usb/host/dwc_otg/doc/doxygen.cfg -index ddd0a10..2646c88 100644 ---- a/drivers/usb/host/dwc_otg/doc/doxygen.cfg -+++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg -@@ -4,7 +4,7 @@ - # Project related configuration options - #--------------------------------------------------------------------------- - PROJECT_NAME = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver" --PROJECT_NUMBER = v2.90a -+PROJECT_NUMBER = v2.94a - OUTPUT_DIRECTORY = ./doc/ - CREATE_SUBDIRS = NO - OUTPUT_LANGUAGE = English -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.c b/drivers/usb/host/dwc_otg/dwc_otg_adp.c -new file mode 100644 -index 0000000..0877472 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.c -@@ -0,0 +1,854 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $ -+ * $Revision: #12 $ -+ * $Date: 2011/10/26 $ -+ * $Change: 1873028 $ -+ * -+ * 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. -+ * ========================================================================== */ -+ -+#include "dwc_os.h" -+#include "dwc_otg_regs.h" -+#include "dwc_otg_cil.h" -+#include "dwc_otg_adp.h" -+ -+/** @file -+ * -+ * This file contains the most of the Attach Detect Protocol implementation for -+ * the driver to support OTG Rev2.0. -+ * -+ */ -+ -+void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value) -+{ -+ adpctl_data_t adpctl; -+ -+ adpctl.d32 = value; -+ adpctl.b.ar = 0x2; -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); -+ -+ while (adpctl.b.ar) { -+ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); -+ } -+ -+} -+ -+/** -+ * Function is called to read ADP registers -+ */ -+uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if) -+{ -+ adpctl_data_t adpctl; -+ -+ adpctl.d32 = 0; -+ adpctl.b.ar = 0x1; -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); -+ -+ while (adpctl.b.ar) { -+ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); -+ } -+ -+ return adpctl.d32; -+} -+ -+/** -+ * Function is called to read ADPCTL register and filter Write-clear bits -+ */ -+uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if) -+{ -+ adpctl_data_t adpctl; -+ -+ adpctl.d32 = dwc_otg_adp_read_reg(core_if); -+ adpctl.b.adp_tmout_int = 0; -+ adpctl.b.adp_prb_int = 0; -+ adpctl.b.adp_tmout_int = 0; -+ -+ return adpctl.d32; -+} -+ -+/** -+ * Function is called to write ADP registers -+ */ -+void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr, -+ uint32_t set) -+{ -+ dwc_otg_adp_write_reg(core_if, -+ (dwc_otg_adp_read_reg(core_if) & (~clr)) | set); -+} -+ -+static void adp_sense_timeout(void *ptr) -+{ -+ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; -+ core_if->adp.sense_timer_started = 0; -+ DWC_PRINTF("ADP SENSE TIMEOUT\n"); -+ if (core_if->adp_enable) { -+ dwc_otg_adp_sense_stop(core_if); -+ dwc_otg_adp_probe_start(core_if); -+ } -+} -+ -+/** -+ * This function is called when the ADP vbus timer expires. Timeout is 1.1s. -+ */ -+static void adp_vbuson_timeout(void *ptr) -+{ -+ gpwrdn_data_t gpwrdn; -+ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; -+ hprt0_data_t hprt0 = {.d32 = 0 }; -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__); -+ if (core_if) { -+ core_if->adp.vbuson_timer_started = 0; -+ /* Turn off vbus */ -+ hprt0.b.prtpwr = 1; -+ DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0); -+ gpwrdn.d32 = 0; -+ -+ /* Power off the core */ -+ if (core_if->power_down == 2) { -+ /* Enable Wakeup Logic */ -+// gpwrdn.b.wkupactiv = 1; -+ gpwrdn.b.pmuactv = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, -+ gpwrdn.d32); -+ -+ /* Suspend the Phy Clock */ -+ pcgcctl.b.stoppclk = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); -+ -+ /* Switch on VDD */ -+// gpwrdn.b.wkupactiv = 1; -+ gpwrdn.b.pmuactv = 1; -+ gpwrdn.b.pwrdnrstn = 1; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, -+ gpwrdn.d32); -+ } else { -+ /* Enable Power Down Logic */ -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ } -+ -+ /* Power off the core */ -+ if (core_if->power_down == 2) { -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, -+ gpwrdn.d32, 0); -+ } -+ -+ /* Unmask SRP detected interrupt from Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.srp_det_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ -+ dwc_otg_adp_probe_start(core_if); -+ dwc_otg_dump_global_registers(core_if); -+ dwc_otg_dump_host_registers(core_if); -+ } -+ -+} -+ -+/** -+ * Start the ADP Initial Probe timer to detect if Port Connected interrupt is -+ * not asserted within 1.1 seconds. -+ * -+ * @param core_if the pointer to core_if strucure. -+ */ -+void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if) -+{ -+ core_if->adp.vbuson_timer_started = 1; -+ if (core_if->adp.vbuson_timer) -+ { -+ DWC_PRINTF("SCHEDULING VBUSON TIMER\n"); -+ /* 1.1 secs + 60ms necessary for cil_hcd_start*/ -+ DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160); -+ } else { -+ DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer); -+ } -+} -+ -+#if 0 -+/** -+ * Masks all DWC OTG core interrupts -+ * -+ */ -+static void mask_all_interrupts(dwc_otg_core_if_t * core_if) -+{ -+ int i; -+ gahbcfg_data_t ahbcfg = {.d32 = 0 }; -+ -+ /* Mask Host Interrupts */ -+ -+ /* Clear and disable HCINTs */ -+ for (i = 0; i < core_if->core_params->host_channels; i++) { -+ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0); -+ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF); -+ -+ } -+ -+ /* Clear and disable HAINT */ -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000); -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF); -+ -+ /* Mask Device Interrupts */ -+ if (!core_if->multiproc_int_enable) { -+ /* Clear and disable IN Endpoint interrupts */ -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0); -+ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> -+ diepint, 0xFFFFFFFF); -+ } -+ -+ /* Clear and disable OUT Endpoint interrupts */ -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0); -+ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> -+ doepint, 0xFFFFFFFF); -+ } -+ -+ /* Clear and disable DAINT */ -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint, -+ 0xFFFFFFFF); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0); -+ } else { -+ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> -+ diepeachintmsk[i], 0); -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> -+ diepint, 0xFFFFFFFF); -+ } -+ -+ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> -+ doepeachintmsk[i], 0); -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> -+ doepint, 0xFFFFFFFF); -+ } -+ -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, -+ 0); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint, -+ 0xFFFFFFFF); -+ -+ } -+ -+ /* Disable interrupts */ -+ ahbcfg.b.glblintrmsk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); -+ -+ /* Disable all interrupts. */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); -+ -+ /* Clear any pending interrupts */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* Clear any pending OTG Interrupts */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF); -+} -+ -+/** -+ * Unmask Port Connection Detected interrupt -+ * -+ */ -+static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if) -+{ -+ gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 }; -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); -+} -+#endif -+ -+/** -+ * Starts the ADP Probing -+ * -+ * @param core_if the pointer to core_if structure. -+ */ -+uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if) -+{ -+ -+ adpctl_data_t adpctl = {.d32 = 0}; -+ gpwrdn_data_t gpwrdn; -+#if 0 -+ adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1, -+ .b.adp_sns_int = 1, b.adp_tmout_int}; -+#endif -+ dwc_otg_disable_global_interrupts(core_if); -+ DWC_PRINTF("ADP Probe Start\n"); -+ core_if->adp.probe_enabled = 1; -+ -+ adpctl.b.adpres = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ -+ while (adpctl.b.adpres) { -+ adpctl.d32 = dwc_otg_adp_read_reg(core_if); -+ } -+ -+ adpctl.d32 = 0; -+ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ -+ /* In Host mode unmask SRP detected interrupt */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.sts_chngint_msk = 1; -+ if (!gpwrdn.b.idsts) { -+ gpwrdn.b.srp_det_msk = 1; -+ } -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ -+ adpctl.b.adp_tmout_int_msk = 1; -+ adpctl.b.adp_prb_int_msk = 1; -+ adpctl.b.prb_dschg = 1; -+ adpctl.b.prb_delta = 1; -+ adpctl.b.prb_per = 1; -+ adpctl.b.adpen = 1; -+ adpctl.b.enaprb = 1; -+ -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ DWC_PRINTF("ADP Probe Finish\n"); -+ return 0; -+} -+ -+/** -+ * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted -+ * within 3 seconds. -+ * -+ * @param core_if the pointer to core_if strucure. -+ */ -+void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if) -+{ -+ core_if->adp.sense_timer_started = 1; -+ DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ ); -+} -+ -+/** -+ * Starts the ADP Sense -+ * -+ * @param core_if the pointer to core_if strucure. -+ */ -+uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if) -+{ -+ adpctl_data_t adpctl; -+ -+ DWC_PRINTF("ADP Sense Start\n"); -+ -+ /* Unmask ADP sense interrupt and mask all other from the core */ -+ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); -+ adpctl.b.adp_sns_int_msk = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ dwc_otg_disable_global_interrupts(core_if); // vahrama -+ -+ /* Set ADP reset bit*/ -+ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); -+ adpctl.b.adpres = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ -+ while (adpctl.b.adpres) { -+ adpctl.d32 = dwc_otg_adp_read_reg(core_if); -+ } -+ -+ adpctl.b.adpres = 0; -+ adpctl.b.adpen = 1; -+ adpctl.b.enasns = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ -+ dwc_otg_adp_sense_timer_start(core_if); -+ -+ return 0; -+} -+ -+/** -+ * Stops the ADP Probing -+ * -+ * @param core_if the pointer to core_if strucure. -+ */ -+uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if) -+{ -+ -+ adpctl_data_t adpctl; -+ DWC_PRINTF("Stop ADP probe\n"); -+ core_if->adp.probe_enabled = 0; -+ core_if->adp.probe_counter = 0; -+ adpctl.d32 = dwc_otg_adp_read_reg(core_if); -+ -+ adpctl.b.adpen = 0; -+ adpctl.b.adp_prb_int = 1; -+ adpctl.b.adp_tmout_int = 1; -+ adpctl.b.adp_sns_int = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ -+ return 0; -+} -+ -+/** -+ * Stops the ADP Sensing -+ * -+ * @param core_if the pointer to core_if strucure. -+ */ -+uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if) -+{ -+ adpctl_data_t adpctl; -+ -+ core_if->adp.sense_enabled = 0; -+ -+ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); -+ adpctl.b.enasns = 0; -+ adpctl.b.adp_sns_int = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ -+ return 0; -+} -+ -+/** -+ * Called to turn on the VBUS after initial ADP probe in host mode. -+ * If port power was already enabled in cil_hcd_start function then -+ * only schedule a timer. -+ * -+ * @param core_if the pointer to core_if structure. -+ */ -+void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if) -+{ -+ hprt0_data_t hprt0 = {.d32 = 0 }; -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr); -+ -+ if (hprt0.b.prtpwr == 0) { -+ hprt0.b.prtpwr = 1; -+ //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ } -+ -+ dwc_otg_adp_vbuson_timer_start(core_if); -+} -+ -+/** -+ * Called right after driver is loaded -+ * to perform initial actions for ADP -+ * -+ * @param core_if the pointer to core_if structure. -+ * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN -+ */ -+void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host) -+{ -+ gpwrdn_data_t gpwrdn; -+ -+ DWC_PRINTF("ADP Initial Start\n"); -+ core_if->adp.adp_started = 1; -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ dwc_otg_disable_global_interrupts(core_if); -+ if (is_host) { -+ DWC_PRINTF("HOST MODE\n"); -+ /* Enable Power Down Logic Interrupt*/ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ /* Initialize first ADP probe to obtain Ramp Time value */ -+ core_if->adp.initial_probe = 1; -+ dwc_otg_adp_probe_start(core_if); -+ } else { -+ gotgctl_data_t gotgctl; -+ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); -+ DWC_PRINTF("DEVICE MODE\n"); -+ if (gotgctl.b.bsesvld == 0) { -+ /* Enable Power Down Logic Interrupt*/ -+ gpwrdn.d32 = 0; -+ DWC_PRINTF("VBUS is not valid - start ADP probe\n"); -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ core_if->adp.initial_probe = 1; -+ dwc_otg_adp_probe_start(core_if); -+ } else { -+ DWC_PRINTF("VBUS is valid - initialize core as a Device\n"); -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ dwc_otg_dump_global_registers(core_if); -+ dwc_otg_dump_dev_registers(core_if); -+ } -+ } -+} -+ -+void dwc_otg_adp_init(dwc_otg_core_if_t * core_if) -+{ -+ core_if->adp.adp_started = 0; -+ core_if->adp.initial_probe = 0; -+ core_if->adp.probe_timer_values[0] = -1; -+ core_if->adp.probe_timer_values[1] = -1; -+ core_if->adp.probe_enabled = 0; -+ core_if->adp.sense_enabled = 0; -+ core_if->adp.sense_timer_started = 0; -+ core_if->adp.vbuson_timer_started = 0; -+ core_if->adp.probe_counter = 0; -+ core_if->adp.gpwrdn = 0; -+ core_if->adp.attached = DWC_OTG_ADP_UNKOWN; -+ /* Initialize timers */ -+ core_if->adp.sense_timer = -+ DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if); -+ core_if->adp.vbuson_timer = -+ DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if); -+ if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer) -+ { -+ DWC_ERROR("Could not allocate memory for ADP timers\n"); -+ } -+} -+ -+void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if) -+{ -+ gpwrdn_data_t gpwrdn = { .d32 = 0 }; -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ if (core_if->adp.probe_enabled) -+ dwc_otg_adp_probe_stop(core_if); -+ if (core_if->adp.sense_enabled) -+ dwc_otg_adp_sense_stop(core_if); -+ if (core_if->adp.sense_timer_started) -+ DWC_TIMER_CANCEL(core_if->adp.sense_timer); -+ if (core_if->adp.vbuson_timer_started) -+ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); -+ DWC_TIMER_FREE(core_if->adp.sense_timer); -+ DWC_TIMER_FREE(core_if->adp.vbuson_timer); -+} -+ -+///////////////////////////////////////////////////////////////////// -+////////////// ADP Interrupt Handlers /////////////////////////////// -+///////////////////////////////////////////////////////////////////// -+/** -+ * This function sets Ramp Timer values -+ */ -+static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val) -+{ -+ if (core_if->adp.probe_timer_values[0] == -1) { -+ core_if->adp.probe_timer_values[0] = val; -+ core_if->adp.probe_timer_values[1] = -1; -+ return 1; -+ } else { -+ core_if->adp.probe_timer_values[1] = -+ core_if->adp.probe_timer_values[0]; -+ core_if->adp.probe_timer_values[0] = val; -+ return 0; -+ } -+} -+ -+/** -+ * This function compares Ramp Timer values -+ */ -+static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if) -+{ -+ uint32_t diff; -+ if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1]) -+ diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1]; -+ else -+ diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0]; -+ if(diff < 2) { -+ return 0; -+ } else { -+ return 1; -+ } -+} -+ -+/** -+ * This function handles ADP Probe Interrupts -+ */ -+static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if, -+ uint32_t val) -+{ -+ adpctl_data_t adpctl = {.d32 = 0 }; -+ gpwrdn_data_t gpwrdn, temp; -+ adpctl.d32 = val; -+ -+ temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ core_if->adp.probe_counter++; -+ core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ if (adpctl.b.rtim == 0 && !temp.b.idsts){ -+ DWC_PRINTF("RTIM value is 0\n"); -+ goto exit; -+ } -+ if (set_timer_value(core_if, adpctl.b.rtim) && -+ core_if->adp.initial_probe) { -+ core_if->adp.initial_probe = 0; -+ dwc_otg_adp_probe_stop(core_if); -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* check which value is for device mode and which for Host mode */ -+ if (!temp.b.idsts) { /* considered host mode value is 0 */ -+ /* -+ * Turn on VBUS after initial ADP probe. -+ */ -+ core_if->op_state = A_HOST; -+ dwc_otg_enable_global_interrupts(core_if); -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_hcd_start(core_if); -+ dwc_otg_adp_turnon_vbus(core_if); -+ DWC_SPINLOCK(core_if->lock); -+ } else { -+ /* -+ * Initiate SRP after initial ADP probe. -+ */ -+ dwc_otg_enable_global_interrupts(core_if); -+ dwc_otg_initiate_srp(core_if); -+ } -+ } else if (core_if->adp.probe_counter > 2){ -+ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ if (compare_timer_values(core_if)) { -+ DWC_PRINTF("Difference in timer values !!! \n"); -+// core_if->adp.attached = DWC_OTG_ADP_ATTACHED; -+ dwc_otg_adp_probe_stop(core_if); -+ -+ /* Power on the core */ -+ if (core_if->power_down == 2) { -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ } -+ -+ /* check which value is for device mode and which for Host mode */ -+ if (!temp.b.idsts) { /* considered host mode value is 0 */ -+ /* Disable Interrupt from Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, gpwrdn.d32, 0); -+ -+ /* -+ * Initialize the Core for Host mode. -+ */ -+ core_if->op_state = A_HOST; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_hcd_start(core_if); -+ } else { -+ gotgctl_data_t gotgctl; -+ /* Mask SRP detected interrupt from Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.srp_det_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, gpwrdn.d32, 0); -+ -+ /* Disable Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, gpwrdn.d32, 0); -+ -+ /* -+ * Initialize the Core for Device mode. -+ */ -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ -+ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); -+ if (!gotgctl.b.bsesvld) { -+ dwc_otg_initiate_srp(core_if); -+ } -+ } -+ } -+ if (core_if->power_down == 2) { -+ if (gpwrdn.b.bsessvld) { -+ /* Mask SRP detected interrupt from Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.srp_det_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Disable Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* -+ * Initialize the Core for Device mode. -+ */ -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ } -+ } -+ } -+exit: -+ /* Clear interrupt */ -+ adpctl.d32 = dwc_otg_adp_read_reg(core_if); -+ adpctl.b.adp_prb_int = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ -+ return 0; -+} -+ -+/** -+ * This function hadles ADP Sense Interrupt -+ */ -+static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if) -+{ -+ adpctl_data_t adpctl; -+ /* Stop ADP Sense timer */ -+ DWC_TIMER_CANCEL(core_if->adp.sense_timer); -+ -+ /* Restart ADP Sense timer */ -+ dwc_otg_adp_sense_timer_start(core_if); -+ -+ /* Clear interrupt */ -+ adpctl.d32 = dwc_otg_adp_read_reg(core_if); -+ adpctl.b.adp_sns_int = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ -+ return 0; -+} -+ -+/** -+ * This function handles ADP Probe Interrupts -+ */ -+static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if, -+ uint32_t val) -+{ -+ adpctl_data_t adpctl = {.d32 = 0 }; -+ adpctl.d32 = val; -+ set_timer_value(core_if, adpctl.b.rtim); -+ -+ /* Clear interrupt */ -+ adpctl.d32 = dwc_otg_adp_read_reg(core_if); -+ adpctl.b.adp_tmout_int = 1; -+ dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ -+ return 0; -+} -+ -+/** -+ * ADP Interrupt handler. -+ * -+ */ -+int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if) -+{ -+ int retval = 0; -+ adpctl_data_t adpctl = {.d32 = 0}; -+ -+ adpctl.d32 = dwc_otg_adp_read_reg(core_if); -+ DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32); -+ -+ if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) { -+ DWC_PRINTF("ADP Sense interrupt\n"); -+ retval |= dwc_otg_adp_handle_sns_intr(core_if); -+ } -+ if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) { -+ DWC_PRINTF("ADP timeout interrupt\n"); -+ retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32); -+ } -+ if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) { -+ DWC_PRINTF("ADP Probe interrupt\n"); -+ adpctl.b.adp_prb_int = 1; -+ retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32); -+ } -+ -+// dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0); -+ //dwc_otg_adp_write_reg(core_if, adpctl.d32); -+ DWC_PRINTF("RETURN FROM ADP ISR\n"); -+ -+ return retval; -+} -+ -+/** -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if) -+{ -+ -+#ifndef DWC_HOST_ONLY -+ hprt0_data_t hprt0; -+ gpwrdn_data_t gpwrdn; -+ DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n"); -+ -+ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ /* check which value is for device mode and which for Host mode */ -+ if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */ -+ DWC_PRINTF("SRP: Host mode\n"); -+ -+ if (core_if->adp_enable) { -+ dwc_otg_adp_probe_stop(core_if); -+ -+ /* Power on the core */ -+ if (core_if->power_down == 2) { -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ } -+ -+ core_if->op_state = A_HOST; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_hcd_start(core_if); -+ } -+ -+ /* Turn on the port power bit. */ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtpwr = 1; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ -+ /* Start the Connection timer. So a message can be displayed -+ * if connect does not occur within 10 seconds. */ -+ cil_hcd_session_start(core_if); -+ } else { -+ DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__); -+ if (core_if->adp_enable) { -+ dwc_otg_adp_probe_stop(core_if); -+ -+ /* Power on the core */ -+ if (core_if->power_down == 2) { -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ } -+ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 0; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, -+ gpwrdn.d32); -+ -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ } -+ } -+#endif -+ return 1; -+} -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.h b/drivers/usb/host/dwc_otg/dwc_otg_adp.h -new file mode 100644 -index 0000000..d8c3f85 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.h -@@ -0,0 +1,80 @@ -+/* ========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $ -+ * $Revision: #7 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871159 $ -+ * -+ * 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_ADP_H__ -+#define __DWC_OTG_ADP_H__ -+ -+/** -+ * @file -+ * -+ * This file contains the Attach Detect Protocol interfaces and defines -+ * (functions) and structures for Linux. -+ * -+ */ -+ -+#define DWC_OTG_ADP_UNATTACHED 0 -+#define DWC_OTG_ADP_ATTACHED 1 -+#define DWC_OTG_ADP_UNKOWN 2 -+ -+typedef struct dwc_otg_adp { -+ uint32_t adp_started; -+ uint32_t initial_probe; -+ int32_t probe_timer_values[2]; -+ uint32_t probe_enabled; -+ uint32_t sense_enabled; -+ dwc_timer_t *sense_timer; -+ uint32_t sense_timer_started; -+ dwc_timer_t *vbuson_timer; -+ uint32_t vbuson_timer_started; -+ uint32_t attached; -+ uint32_t probe_counter; -+ uint32_t gpwrdn; -+} dwc_otg_adp_t; -+ -+/** -+ * Attach Detect Protocol functions -+ */ -+ -+extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value); -+extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if); -+extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if); -+extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if); -+extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if); -+extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if); -+extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); -+extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if); -+extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if); -+extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if); -+extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if); -+ -+#endif //__DWC_OTG_ADP_H__ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -index 26ff76f..95eb7f8 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_attr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $ -- * $Revision: #35 $ -- * $Date: 2009/04/03 $ -- * $Change: 1225160 $ -+ * $Revision: #44 $ -+ * $Date: 2010/11/29 $ -+ * $Change: 1636033 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -213,6 +213,37 @@ - - - -+ rem_wakeup_pwrdn -+ On read, shows the status core - hibernated or not. On write, initiates -+ a remote wakeup of the device from Hibernation. -+ Read/Write -+ -+ -+ -+ mode_ch_tim_en -+ This bit is used to enable or disable the host core to wait for 200 PHY -+ clock cycles at the end of Resume to change the opmode signal to the PHY to 00 -+ after Suspend or LPM. -+ Read/Write -+ -+ -+ -+ fr_interval -+ On read, shows the value of HFIR Frame Interval. On write, dynamically -+ reload HFIR register during runtime. The application can write a value to this -+ register only after the Port Enable bit of the Host Port Control and Status -+ register (HPRT.PrtEnaPort) has been set -+ Read/Write -+ -+ -+ -+ disconnect_us -+ On read, shows the status of disconnect_device_us. On write, sets disconnect_us -+ which causes soft disconnect for 100us. Applicable only for device mode of operation. -+ Read/Write -+ -+ -+ - regdump - Dumps the contents of core registers. - Read -@@ -262,12 +293,6 @@ - - - -- sleep_local_dev -- Generetates sleep signaling. Applicable only in host mode. -- Write -- -- -- - sleep_status - Shows sleep status of device. - Read -@@ -283,36 +308,7 @@ - echo 0 > /sys/devices/lm0/buspower - */ - --#include --#include --#include --#include --#include --#include --#include --#include /* permission constants */ --#include --#include --#include --#include -- -- --#ifdef LM_INTERFACE --#include --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --#include --#else --/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - -- here we use definitions stolen from arm-integrator headers --*/ --#include --#endif --#elif defined(PLATFORM_INTERFACE) --#include --#endif -- --#include -- -+#include "dwc_otg_os_dep.h" - #include "dwc_os.h" - #include "dwc_otg_driver.h" - #include "dwc_otg_attr.h" -@@ -481,24 +477,24 @@ - /**@{*/ - - /** -+ * Helper function returning the otg_device structure of the given device -+ */ -+static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev) -+{ -+ dwc_otg_device_t *otg_dev; -+ DWC_OTG_GETDRVDEV(otg_dev, _dev); -+ return otg_dev; -+} -+ -+/** - * Show the register offset of the Register Access. - */ - static ssize_t regoffset_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = container_of(_dev, -- struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", -- otg_dev->reg_offset); -+ otg_dev->os_dep.reg_offset); - } - - /** -@@ -508,20 +504,14 @@ static ssize_t regoffset_store(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = container_of(_dev, -- struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - uint32_t offset = simple_strtoul(buf, NULL, 16); -- if (offset < SZ_256K) { -- otg_dev->reg_offset = offset; -+#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE) -+ if (offset < SZ_256K) { -+#elif defined(PCI_INTERFACE) -+ if (offset < 0x00040000) { -+#endif -+ otg_dev->os_dep.reg_offset = offset; - } else { - dev_err(_dev, "invalid offset\n"); - } -@@ -538,31 +528,21 @@ static ssize_t regoffset_store(struct device *_dev, - static ssize_t regvalue_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - uint32_t val; - volatile uint32_t *addr; - -- if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { -+ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { - /* Calculate the address */ -- addr = (uint32_t *) (otg_dev->reg_offset + -- (uint8_t *) otg_dev->base); -- val = dwc_read_reg32(addr); -+ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + -+ (uint8_t *) otg_dev->os_dep.base); -+ val = DWC_READ_REG32(addr); - return snprintf(buf, - sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, -- "Reg@0x%06x = 0x%08x\n", otg_dev->reg_offset, -+ "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset, - val); - } else { -- dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->reg_offset); -+ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset); - return sprintf(buf, "invalid offset\n"); - } - } -@@ -576,28 +556,18 @@ static ssize_t regvalue_store(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - volatile uint32_t *addr; - uint32_t val = simple_strtoul(buf, NULL, 16); - //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val); -- if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { -+ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { - /* Calculate the address */ -- addr = (uint32_t *) (otg_dev->reg_offset + -- (uint8_t *) otg_dev->base); -- dwc_write_reg32(addr, val); -+ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + -+ (uint8_t *) otg_dev->os_dep.base); -+ DWC_WRITE_REG32(addr, val); - } else { - dev_err(_dev, "Invalid Register Offset (0x%08x)\n", -- otg_dev->reg_offset); -+ otg_dev->os_dep.reg_offset); - } - return count; - } -@@ -609,7 +579,7 @@ static ssize_t regvalue_store(struct device *_dev, - */ - DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode"); - DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable"); --DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "Mode"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable"); - DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect"); - DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC"); - -@@ -655,16 +625,7 @@ static ssize_t regvalue_store(struct device *_dev, - static ssize_t hnp_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - return sprintf(buf, "HstNegScs = 0x%x\n", - dwc_otg_get_hnpstatus(otg_dev->core_if)); - } -@@ -676,16 +637,7 @@ static ssize_t hnp_store(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - uint32_t in = simple_strtoul(buf, NULL, 16); - dwc_otg_set_hnpreq(otg_dev->core_if, in); - return count; -@@ -703,16 +655,7 @@ static ssize_t srp_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { - #ifndef DWC_HOST_ONLY --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - return sprintf(buf, "SesReqScs = 0x%x\n", - dwc_otg_get_srpstatus(otg_dev->core_if)); - #else -@@ -728,16 +671,7 @@ static ssize_t srp_store(struct device *_dev, - const char *buf, size_t count) - { - #ifndef DWC_HOST_ONLY --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - dwc_otg_pcd_initiate_srp(otg_dev->pcd); - #endif - return count; -@@ -754,16 +688,7 @@ static ssize_t srp_store(struct device *_dev, - static ssize_t buspower_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - return sprintf(buf, "Bus Power = 0x%x\n", - dwc_otg_get_prtpower(otg_dev->core_if)); - } -@@ -775,16 +700,7 @@ static ssize_t buspower_store(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - uint32_t on = simple_strtoul(buf, NULL, 16); - dwc_otg_set_prtpower(otg_dev->core_if, on); - return count; -@@ -801,17 +717,7 @@ static ssize_t buspower_store(struct device *_dev, - static ssize_t bussuspend_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - return sprintf(buf, "Bus Suspend = 0x%x\n", - dwc_otg_get_prtsuspend(otg_dev->core_if)); - } -@@ -823,17 +729,7 @@ static ssize_t bussuspend_store(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - uint32_t in = simple_strtoul(buf, NULL, 16); - dwc_otg_set_prtsuspend(otg_dev->core_if, in); - return count; -@@ -842,22 +738,65 @@ static ssize_t bussuspend_store(struct device *_dev, - DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); - - /** -+ * Show the Mode Change Ready Timer status -+ */ -+static ssize_t mode_ch_tim_en_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n", -+ dwc_otg_get_mode_ch_tim(otg_dev->core_if)); -+} -+ -+/** -+ * Set the Mode Change Ready Timer status -+ */ -+static ssize_t mode_ch_tim_en_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ uint32_t in = simple_strtoul(buf, NULL, 16); -+ dwc_otg_set_mode_ch_tim(otg_dev->core_if, in); -+ return count; -+} -+ -+DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store); -+ -+/** -+ * Show the value of HFIR Frame Interval bitfield -+ */ -+static ssize_t fr_interval_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ return sprintf(buf, "Frame Interval = 0x%x\n", -+ dwc_otg_get_fr_interval(otg_dev->core_if)); -+} -+ -+/** -+ * Set the HFIR Frame Interval value -+ */ -+static ssize_t fr_interval_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ uint32_t in = simple_strtoul(buf, NULL, 10); -+ dwc_otg_set_fr_interval(otg_dev->core_if, in); -+ return count; -+} -+ -+DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store); -+ -+/** - * Show the status of Remote Wakeup. - */ - static ssize_t remote_wakeup_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { - #ifndef DWC_HOST_ONLY --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - - return sprintf(buf, - "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n", -@@ -880,17 +819,7 @@ static ssize_t remote_wakeup_store(struct device *_dev, - const char *buf, size_t count) - { - #ifndef DWC_HOST_ONLY --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - uint32_t val = simple_strtoul(buf, NULL, 16); - - if (val & 1) { -@@ -906,22 +835,69 @@ static ssize_t remote_wakeup_store(struct device *_dev, - remote_wakeup_store); - - /** -+ * Show the whether core is hibernated or not. -+ */ -+static ssize_t rem_wakeup_pwrdn_show(struct device *_dev, -+ struct device_attribute *attr, char *buf) -+{ -+#ifndef DWC_HOST_ONLY -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ -+ if (dwc_otg_get_core_state(otg_dev->core_if)) { -+ DWC_PRINTF("Core is in hibernation\n"); -+ } else { -+ DWC_PRINTF("Core is not in hibernation\n"); -+ } -+#endif /* DWC_HOST_ONLY */ -+ return 0; -+} -+ -+extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, -+ int rem_wakeup, int reset); -+ -+/** -+ * Initiate a remote wakeup of the device to exit from hibernation. -+ */ -+static ssize_t rem_wakeup_pwrdn_store(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+#ifndef DWC_HOST_ONLY -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0); -+#endif -+ return count; -+} -+ -+DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show, -+ rem_wakeup_pwrdn_store); -+ -+static ssize_t disconnect_us(struct device *_dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ -+#ifndef DWC_HOST_ONLY -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); -+ uint32_t val = simple_strtoul(buf, NULL, 16); -+ DWC_PRINTF("The Passed value is %04x\n", val); -+ -+ dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50); -+ -+#endif /* DWC_HOST_ONLY */ -+ return count; -+} -+ -+DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us); -+ -+/** - * Dump global registers and either host or device registers (depending on the - * current mode of the core). - */ - static ssize_t regdump_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - - dwc_otg_dump_global_registers(otg_dev->core_if); - if (dwc_otg_is_host_mode(otg_dev->core_if)) { -@@ -942,16 +918,7 @@ static ssize_t regdump_show(struct device *_dev, - static ssize_t spramdump_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - - dwc_otg_dump_spram(otg_dev->core_if); - -@@ -967,17 +934,7 @@ static ssize_t hcddump_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { - #ifndef DWC_DEVICE_ONLY --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - dwc_otg_hcd_dump_state(otg_dev->hcd); - #endif /* DWC_DEVICE_ONLY */ - return sprintf(buf, "HCD Dump\n"); -@@ -994,16 +951,7 @@ static ssize_t hcd_frrem_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { - #ifndef DWC_DEVICE_ONLY --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - - dwc_otg_hcd_dump_frrem(otg_dev->hcd); - #endif /* DWC_DEVICE_ONLY */ -@@ -1021,17 +969,7 @@ static ssize_t hcd_frrem_show(struct device *_dev, - static ssize_t rd_reg_test_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - int i; - int time; - int start_jiffies; -@@ -1057,17 +995,7 @@ static ssize_t rd_reg_test_show(struct device *_dev, - static ssize_t wr_reg_test_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - uint32_t reg_val; - int i; - int time; -@@ -1096,16 +1024,7 @@ static ssize_t wr_reg_test_show(struct device *_dev, - static ssize_t lpmresp_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - - if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) - return sprintf(buf, "** LPM is DISABLED **\n"); -@@ -1124,17 +1043,7 @@ static ssize_t lpmresp_store(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - uint32_t val = simple_strtoul(buf, NULL, 16); - - if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { -@@ -1157,18 +1066,7 @@ static ssize_t lpmresp_store(struct device *_dev, - static ssize_t sleepstatus_show(struct device *_dev, - struct device_attribute *attr, char *buf) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - return sprintf(buf, "Sleep Status = %d\n", - dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)); - } -@@ -1180,17 +1078,7 @@ static ssize_t sleepstatus_store(struct device *_dev, - struct device_attribute *attr, - const char *buf, size_t count) - { --#ifdef LM_INTERFACE -- struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -- dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platform_dev = -- container_of(_dev, struct platform_device, dev); -- dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); - dwc_otg_core_if_t *core_if = otg_dev->core_if; - - if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) { -@@ -1207,23 +1095,22 @@ static ssize_t sleepstatus_store(struct device *_dev, - DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show, - sleepstatus_store); - --#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */ -+#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */ - - /**@}*/ - - /** - * Create the device files - */ --void dwc_otg_attr_create ( -+void dwc_otg_attr_create( - #ifdef LM_INTERFACE - struct lm_device *dev - #elif defined(PCI_INTERFACE) - struct pci_dev *dev - #elif defined(PLATFORM_INTERFACE) -- struct platform_device *dev -+ struct platform_device *dev - #endif -- ) -- -+ ) - { - int error; - -@@ -1238,6 +1125,8 @@ void dwc_otg_attr_create ( - error = device_create_file(&dev->dev, &dev_attr_srp); - error = device_create_file(&dev->dev, &dev_attr_buspower); - error = device_create_file(&dev->dev, &dev_attr_bussuspend); -+ error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en); -+ error = device_create_file(&dev->dev, &dev_attr_fr_interval); - error = device_create_file(&dev->dev, &dev_attr_busconnected); - error = device_create_file(&dev->dev, &dev_attr_gotgctl); - error = device_create_file(&dev->dev, &dev_attr_gusbcfg); -@@ -1252,6 +1141,8 @@ void dwc_otg_attr_create ( - error = device_create_file(&dev->dev, &dev_attr_hptxfsiz); - error = device_create_file(&dev->dev, &dev_attr_hprt0); - error = device_create_file(&dev->dev, &dev_attr_remote_wakeup); -+ error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); -+ error = device_create_file(&dev->dev, &dev_attr_disconnect_us); - error = device_create_file(&dev->dev, &dev_attr_regdump); - error = device_create_file(&dev->dev, &dev_attr_spramdump); - error = device_create_file(&dev->dev, &dev_attr_hcddump); -@@ -1267,7 +1158,7 @@ void dwc_otg_attr_create ( - /** - * Remove the device files - */ --void dwc_otg_attr_remove ( -+void dwc_otg_attr_remove( - #ifdef LM_INTERFACE - struct lm_device *dev - #elif defined(PCI_INTERFACE) -@@ -1275,8 +1166,7 @@ void dwc_otg_attr_remove ( - #elif defined(PLATFORM_INTERFACE) - struct platform_device *dev - #endif -- ) -- -+ ) - { - device_remove_file(&dev->dev, &dev_attr_regoffset); - device_remove_file(&dev->dev, &dev_attr_regvalue); -@@ -1289,6 +1179,8 @@ void dwc_otg_attr_remove ( - device_remove_file(&dev->dev, &dev_attr_srp); - device_remove_file(&dev->dev, &dev_attr_buspower); - device_remove_file(&dev->dev, &dev_attr_bussuspend); -+ device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en); -+ device_remove_file(&dev->dev, &dev_attr_fr_interval); - device_remove_file(&dev->dev, &dev_attr_busconnected); - device_remove_file(&dev->dev, &dev_attr_gotgctl); - device_remove_file(&dev->dev, &dev_attr_gusbcfg); -@@ -1303,6 +1195,8 @@ void dwc_otg_attr_remove ( - device_remove_file(&dev->dev, &dev_attr_hptxfsiz); - device_remove_file(&dev->dev, &dev_attr_hprt0); - device_remove_file(&dev->dev, &dev_attr_remote_wakeup); -+ device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); -+ device_remove_file(&dev->dev, &dev_attr_disconnect_us); - device_remove_file(&dev->dev, &dev_attr_regdump); - device_remove_file(&dev->dev, &dev_attr_spramdump); - device_remove_file(&dev->dev, &dev_attr_hcddump); -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -index b59651d..fc14d94 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_attr.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $ -- * $Revision: #11 $ -- * $Date: 2009/04/03 $ -- * $Change: 1225160 $ -+ * $Revision: #13 $ -+ * $Date: 2010/06/21 $ -+ * $Change: 1532021 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -47,6 +47,8 @@ - extern struct device_attribute dev_attr_srp; - extern struct device_attribute dev_attr_buspower; - extern struct device_attribute dev_attr_bussuspend; -+extern struct device_attribute dev_attr_mode_ch_tim_en; -+extern struct device_attribute dev_attr_fr_interval; - extern struct device_attribute dev_attr_busconnected; - extern struct device_attribute dev_attr_gotgctl; - extern struct device_attribute dev_attr_gusbcfg; -@@ -62,27 +64,26 @@ - extern struct device_attribute dev_attr_hprt0; - #ifdef CONFIG_USB_DWC_OTG_LPM - extern struct device_attribute dev_attr_lpm_response; --extern struct device_attribute dev_attr_sleep_local_dev; - extern struct device_attribute devi_attr_sleep_status; - #endif - --void dwc_otg_attr_create ( -+void dwc_otg_attr_create( - #ifdef LM_INTERFACE -- struct lm_device *dev -+ struct lm_device *dev - #elif defined(PCI_INTERFACE) -- struct pci_dev *dev -+ struct pci_dev *dev - #elif defined(PLATFORM_INTERFACE) - struct platform_device *dev - #endif -- ); -+ ); - --void dwc_otg_attr_remove ( -+void dwc_otg_attr_remove( - #ifdef LM_INTERFACE -- struct lm_device *dev -+ struct lm_device *dev - #elif defined(PCI_INTERFACE) -- struct pci_dev *dev -+ struct pci_dev *dev - #elif defined(PLATFORM_INTERFACE) - struct platform_device *dev - #endif -- ); -+ ); - #endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.c b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c -index 7fe7255..a9878d6 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cfi.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c -@@ -28,7 +28,8 @@ - - /** @file - * -- * This file contains the most of the CFI implementation for the OTG. -+ * This file contains the most of the CFI(Core Feature Interface) -+ * implementation for the OTG. - */ - - #ifdef DWC_UTE_CFI -@@ -285,7 +286,7 @@ int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl) - if (wValue == 0) { - /* @TODO - MAS - fix the access to the base field */ - regaddr = 0; -- //regaddr = (uint32_t) pcd->otg_dev->base; -+ //regaddr = (uint32_t) pcd->otg_dev->os_dep.base; - //GET_CORE_IF(pcd)->co - regaddr |= wIndex; - } else { -@@ -293,7 +294,7 @@ int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl) - } - - /* Read a 32-bit value of the memory at the regaddr */ -- regval = dwc_read_reg32((uint32_t *) regaddr); -+ regval = DWC_READ_REG32((uint32_t *) regaddr); - - ep = &pcd->ep0; - dwc_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t)); -@@ -406,13 +407,13 @@ static void cfi_release(cfiobject_t * cfiobj) - CFI_INFO("%s\n", __func__); - - if (cfiobj->buf_in.buf) { -- dwc_dma_free(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, -+ DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, - cfiobj->buf_in.addr); - cfiobj->buf_in.buf = NULL; - } - - if (cfiobj->buf_out.buf) { -- dwc_dma_free(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, -+ DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, - cfiobj->buf_out.addr); - cfiobj->buf_out.buf = NULL; - } -@@ -431,21 +432,21 @@ static void cfi_release(cfiobject_t * cfiobj) - static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep) - { - if (cfiep->bm_sg) { -- dwc_free(cfiep->bm_sg); -+ DWC_FREE(cfiep->bm_sg); - cfiep->bm_sg = NULL; - } - - if (cfiep->bm_align) { -- dwc_free(cfiep->bm_align); -+ DWC_FREE(cfiep->bm_align); - cfiep->bm_align = NULL; - } - - if (cfiep->bm_concat) { - if (NULL != cfiep->bm_concat->wTxBytes) { -- dwc_free(cfiep->bm_concat->wTxBytes); -+ DWC_FREE(cfiep->bm_concat->wTxBytes); - cfiep->bm_concat->wTxBytes = NULL; - } -- dwc_free(cfiep->bm_concat); -+ DWC_FREE(cfiep->bm_concat); - cfiep->bm_concat = NULL; - } - } -@@ -459,7 +460,7 @@ static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep) - { - int retval = 0; - -- cfiep->bm_sg = dwc_alloc(sizeof(ddma_sg_buffer_setup_t)); -+ cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t)); - if (NULL == cfiep->bm_sg) { - CFI_INFO("Failed to allocate memory for SG feature value\n"); - return -DWC_E_NO_MEMORY; -@@ -470,21 +471,21 @@ static int cfi_ep_init_defaults(struct dwc_otg_pcd *pcd, cfi_ep_t * cfiep) - * memory for the wTxBytes field - it will be done in the set_feature_value - * request handler. - */ -- cfiep->bm_concat = dwc_alloc(sizeof(ddma_concat_buffer_setup_t)); -+ cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t)); - if (NULL == cfiep->bm_concat) { - CFI_INFO - ("Failed to allocate memory for CONCATENATION feature value\n"); -- dwc_free(cfiep->bm_sg); -+ DWC_FREE(cfiep->bm_sg); - return -DWC_E_NO_MEMORY; - } - dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); - -- cfiep->bm_align = dwc_alloc(sizeof(ddma_align_buffer_setup_t)); -+ cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t)); - if (NULL == cfiep->bm_align) { - CFI_INFO - ("Failed to allocate memory for Alignment feature value\n"); -- dwc_free(cfiep->bm_sg); -- dwc_free(cfiep->bm_concat); -+ DWC_FREE(cfiep->bm_sg); -+ DWC_FREE(cfiep->bm_concat); - return -DWC_E_NO_MEMORY; - } - dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t)); -@@ -516,7 +517,7 @@ static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, - - if (NULL == cfiep) { - /* Allocate a cfi_ep_t object */ -- cfiep = dwc_alloc(sizeof(cfi_ep_t)); -+ cfiep = DWC_ALLOC(sizeof(cfi_ep_t)); - if (NULL == cfiep) { - CFI_INFO - ("Unable to allocate memory for in function %s\n", -@@ -530,12 +531,12 @@ static int cfi_ep_enable(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, - - /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */ - ep->dwc_ep.descs = -- dwc_dma_alloc(MAX_DMA_DESCS_PER_EP * -+ DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP * - sizeof(dwc_otg_dma_desc_t), - &ep->dwc_ep.descs_dma_addr); - - if (NULL == ep->dwc_ep.descs) { -- dwc_free(cfiep); -+ DWC_FREE(cfiep); - return -DWC_E_NO_MEMORY; - } - -@@ -596,7 +597,7 @@ static int cfi_ctrl_write_complete(struct cfiobject *cfi, - reg_value = *((uint32_t *) buf); - if (wValue == 0) { - addr = 0; -- //addr = (uint32_t) pcd->otg_dev->base; -+ //addr = (uint32_t) pcd->otg_dev->os_dep.base; - addr += wIndex; - } else { - addr = (wValue << 16) | wIndex; -@@ -791,7 +792,7 @@ static void *cfi_ep_alloc_buf(struct cfiobject *cfi, struct dwc_otg_pcd *pcd, - struct dwc_otg_pcd_ep *ep, dma_addr_t * dma, - unsigned size, gfp_t flags) - { -- return dwc_dma_alloc(size, dma); -+ return DWC_DMA_ALLOC(size, dma); - } - - /** -@@ -803,7 +804,7 @@ int init_cfi(cfiobject_t * cfiobj) - - /* Allocate a buffer for IN XFERs */ - cfiobj->buf_in.buf = -- dwc_dma_alloc(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); -+ DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); - if (NULL == cfiobj->buf_in.buf) { - CFI_INFO("Unable to allocate buffer for INs\n"); - return -DWC_E_NO_MEMORY; -@@ -811,7 +812,7 @@ int init_cfi(cfiobject_t * cfiobj) - - /* Allocate a buffer for OUT XFERs */ - cfiobj->buf_out.buf = -- dwc_dma_alloc(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); -+ DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); - if (NULL == cfiobj->buf_out.buf) { - CFI_INFO("Unable to allocate buffer for OUT\n"); - return -DWC_E_NO_MEMORY; -@@ -925,7 +926,7 @@ static int cfi_reset_concat_val(cfi_ep_t * cfiep) - { - /* First we need to free the wTxBytes field */ - if (cfiep->bm_concat->wTxBytes) { -- dwc_free(cfiep->bm_concat->wTxBytes); -+ DWC_FREE(cfiep->bm_concat->wTxBytes); - cfiep->bm_concat->wTxBytes = NULL; - } - -@@ -984,8 +985,9 @@ static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr, - params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - - 1]; - params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = -- GET_CORE_IF(pcd)->init_txfsiz[ep->dwc_ep. -- tx_fifo_num - 1]; -+ GET_CORE_IF(pcd)->init_txfsiz[ep-> -+ dwc_ep.tx_fifo_num - -+ 1]; - } - } - -@@ -1004,13 +1006,14 @@ static int cfi_handle_reset_fifo_val(struct dwc_otg_pcd *pcd, uint8_t ep_addr, - int i; - for (i = 0; i < core_if->hwcfg4.b.num_in_eps; - i++) { -- core_if->core_params-> -- dev_tx_fifo_size[i] = tx_siz[i]; -+ core_if-> -+ core_params->dev_tx_fifo_size[i] = -+ tx_siz[i]; - } - } else { -- params->dev_tx_fifo_size[ep->dwc_ep. -- tx_fifo_num - 1] = -- tx_siz[0]; -+ params->dev_tx_fifo_size[ep-> -+ dwc_ep.tx_fifo_num - -+ 1] = tx_siz[0]; - } - } - retval = -DWC_E_INVALID; -@@ -1349,12 +1352,12 @@ static int cfi_ep_set_concat_val(uint8_t * buf, struct dwc_otg_pcd *pcd) - - /* Free the previously allocated storage for the wTxBytes */ - if (ep->bm_concat->wTxBytes) { -- dwc_free(ep->bm_concat->wTxBytes); -+ DWC_FREE(ep->bm_concat->wTxBytes); - } - - /* Allocate a new storage for the wTxBytes field */ - ep->bm_concat->wTxBytes = -- dwc_alloc(sizeof(uint16_t) * pConcatValHdr->bDescCount); -+ DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount); - if (NULL == ep->bm_concat->wTxBytes) { - CFI_INFO("%s: Unable to allocate memory\n", __func__); - return -DWC_E_NO_MEMORY; -@@ -1446,16 +1449,15 @@ static int32_t get_txfifo_size(struct dwc_otg_pcd *pcd, uint16_t wValue) - - switch (wValue >> 8) { - case 0: -- return (GET_CORE_IF(pcd)-> -- pwron_txfsiz[ep->dwc_ep.tx_fifo_num - 1] < -- 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->dwc_ep. -- tx_fifo_num - -- 1] : 32768; -+ return (GET_CORE_IF(pcd)->pwron_txfsiz -+ [ep->dwc_ep.tx_fifo_num - 1] < -+ 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep-> -+ dwc_ep.tx_fifo_num -+ - 1] : 32768; - break; - case 1: -- return GET_CORE_IF(pcd)->core_params->dev_tx_fifo_size[ep-> -- dwc_ep. -- num - 1]; -+ return GET_CORE_IF(pcd)->core_params-> -+ dev_tx_fifo_size[ep->dwc_ep.num - 1]; - break; - default: - return -DWC_E_INVALID; -@@ -1552,65 +1554,63 @@ static uint8_t resize_fifos(dwc_otg_core_if_t * core_if) - - /* Configure data FIFO sizes */ - if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { -- rx_fsz_bak = dwc_read_reg32(&global_regs->grxfsiz); -+ rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz); - rx_fifo_size = params->dev_rx_fifo_size; -- dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size); -+ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); - - /* - * Tx FIFOs These FIFOs are numbered from 1 to 15. - * Indexes of the FIFO size module parameters in the - * dev_tx_fifo_size array and the FIFO size registers in -- * the dptxfsiz_dieptxf array run from 0 to 14. -+ * the dtxfsiz array run from 0 to 14. - */ - - /* Non-periodic Tx FIFO */ -- nptxfsz_bak = dwc_read_reg32(&global_regs->gnptxfsiz); -+ nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz); - nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; - start_address = params->dev_rx_fifo_size; - nptxfifosize.b.startaddr = start_address; - -- dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32); -+ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); - - start_address += nptxfifosize.b.depth; - - for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -- txfsz_bak[i] = -- dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]); -+ txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]); - - txfifosize[i].b.depth = params->dev_tx_fifo_size[i]; - txfifosize[i].b.startaddr = start_address; -- dwc_write_reg32(&global_regs->dptxfsiz_dieptxf[i], -+ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], - txfifosize[i].d32); - - start_address += txfifosize[i].b.depth; - } - - /** Check if register values are set correctly */ -- if (rx_fifo_size != dwc_read_reg32(&global_regs->grxfsiz)) { -+ if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) { - retval = 0; - } - -- if (nptxfifosize.d32 != dwc_read_reg32(&global_regs->gnptxfsiz)) { -+ if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) { - retval = 0; - } - - for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { - if (txfifosize[i].d32 != -- dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i])) { -+ DWC_READ_REG32(&global_regs->dtxfsiz[i])) { - retval = 0; - } - } - - /** If register values are not set correctly, reset old values */ - if (retval == 0) { -- dwc_write_reg32(&global_regs->grxfsiz, rx_fsz_bak); -+ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak); - - /* Non-periodic Tx FIFO */ -- dwc_write_reg32(&global_regs->gnptxfsiz, nptxfsz_bak); -+ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak); - - for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -- dwc_write_reg32(&global_regs-> -- dptxfsiz_dieptxf[i], -+ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], - txfsz_bak[i]); - } - } -@@ -1873,4 +1873,4 @@ static int cfi_set_feature_value(struct dwc_otg_pcd *pcd) - return retval; - } - --#endif //DWC_UTE_CFI -+#endif //DWC_UTE_CFI -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.h b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h -index 0215224..cbccdab 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cfi.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h -@@ -2,7 +2,7 @@ - * 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 -@@ -12,7 +12,7 @@ - * 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 -@@ -33,10 +33,11 @@ - #include "dwc_cfi_common.h" - - /** -- * @file -- * -- * This file contains the CFI related OTG PCD specific common constants, interfaces -- * (functions and macros) and data structures. -+ * @file -+ * This file contains the CFI related OTG PCD specific common constants, -+ * interfaces(functions and macros) and data structures.The CFI Protocol is an -+ * optional interface for internal testing purposes that a DUT may implement to -+ * support testing of configurable features. - * - */ - -@@ -70,7 +71,7 @@ - #define max(x,y) ({ \ - x > y ? x : y; }) - --/** -+/** - * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is - * also used for setting up a buffer for Circular DDMA. - */ -@@ -134,7 +135,7 @@ struct _rx_fifo_size_setup { - - /** - * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest -- * This structure encapsulates the standard usb_ctrlrequest and adds a pointer -+ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer - * to the data returned in the data stage of a 3-stage Control Write requests. - */ - struct cfi_usb_ctrlrequest { -@@ -150,7 +151,7 @@ struct cfi_usb_ctrlrequest { - - /** - * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures. -- * This structure is used to store the buffer setup data for any -+ * This structure is used to store the buffer setup data for any - * enabled endpoint in the PCD. - */ - struct cfi_ep { -@@ -170,7 +171,7 @@ struct cfi_ep { - ddma_align_buffer_setup_t *bm_align; - /* XFER length */ - uint32_t xfer_len; -- /* -+ /* - * Count of DMA descriptors currently used. - * The total should not exceed the MAX_DMA_DESCS_PER_EP value - * defined in the dwc_otg_cil.h -@@ -190,7 +191,7 @@ struct cfi_ep { - - /** - * This is the interface for the CFI operations. -- * -+ * - * @param ep_enable Called when any endpoint is enabled and activated. - * @param release Called when the CFI object is released and it needs to correctly - * deallocate the dynamic memory -@@ -229,12 +230,12 @@ struct cfiobject { - /* This flag shall control the propagation of a specific request - * to the gadget's processing routines. - * 0 - no gadget handling -- * 1 - the gadget needs to know about this request (w/o completing a status -+ * 1 - the gadget needs to know about this request (w/o completing a status - * phase - just return a 0 to the _setup callback) - */ - uint8_t need_gadget_att; - -- /* Flag indicating whether the status IN phase needs to be -+ /* Flag indicating whether the status IN phase needs to be - * completed by the PCD - */ - uint8_t need_status_in_complete; -@@ -316,4 +317,4 @@ static inline struct cfi_ep *get_cfi_ep_by_pcd_ep(struct cfiobject *cfi, - - int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); - --#endif /* (__DWC_OTG_CFI_H__) */ -+#endif /* (__DWC_OTG_CFI_H__) */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -index ccfe6b5..1b33b66 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cil.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -@@ -1,13 +1,13 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $ -- * $Revision: #159 $ -- * $Date: 2009/04/21 $ -- * $Change: 1237465 $ -+ * $Revision: #189 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871160 $ - * - * 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 -@@ -17,7 +17,7 @@ - * 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 -@@ -31,7 +31,7 @@ - * DAMAGE. - * ========================================================================== */ - --/** @file -+/** @file - * - * The Core Interface Layer provides basic services for accessing and - * managing the DWC_otg hardware. These services are used by both the -@@ -51,7 +51,7 @@ - * - * The Core Interface Layer has the following requirements: - * - Provides basic controller operations. -- * - Minimal use of OS services. -+ * - Minimal use of OS services. - * - The OS services used will be abstracted by using inline functions - * or macros. - * -@@ -63,12 +63,12 @@ - - static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if); - --/** -+/** - * This function is called to initialize the DWC_otg CSR data -- * structures. The register addresses in the device and host -+ * structures. The register addresses in the device and host - * structures are initialized from the base address supplied by the -- * caller. The calling function must make the OS calls to get the -- * base address of the DWC_otg controller registers. The core_params -+ * caller. The calling function must make the OS calls to get the -+ * base address of the DWC_otg controller registers. The core_params - * argument holds the parameters that specify how the core should be - * configured. - * -@@ -85,9 +85,9 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - - DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr); - -- core_if = dwc_alloc(sizeof(dwc_otg_core_if_t)); -+ core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t)); - -- if (core_if == 0) { -+ if (core_if == NULL) { - DWC_DEBUGPL(DBG_CIL, - "Allocation of dwc_otg_core_if_t failed\n"); - return 0; -@@ -97,11 +97,11 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - /* - * Allocate the Device Mode structures. - */ -- dev_if = dwc_alloc(sizeof(dwc_otg_dev_if_t)); -+ dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t)); - -- if (dev_if == 0) { -+ if (dev_if == NULL) { - DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n"); -- dwc_free(core_if); -+ DWC_FREE(core_if); - return 0; - } - -@@ -130,13 +130,13 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - /* - * Allocate the Host Mode structures. - */ -- host_if = dwc_alloc(sizeof(dwc_otg_host_if_t)); -+ host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t)); - -- if (host_if == 0) { -+ if (host_if == NULL) { - DWC_DEBUGPL(DBG_CIL, - "Allocation of dwc_otg_host_if_t failed\n"); -- dwc_free(dev_if); -- dwc_free(core_if); -+ DWC_FREE(dev_if); -+ DWC_FREE(core_if); - return 0; - } - -@@ -161,8 +161,8 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - core_if->data_fifo[i] = - (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET + - (i * DWC_OTG_DATA_FIFO_SIZE)); -- DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08x\n", -- i, (unsigned)core_if->data_fifo[i]); -+ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n", -+ i, (unsigned long)core_if->data_fifo[i]); - } - - core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET); -@@ -174,13 +174,28 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - * easy access later. - */ - core_if->hwcfg1.d32 = -- dwc_read_reg32(&core_if->core_global_regs->ghwcfg1); -+ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1); - core_if->hwcfg2.d32 = -- dwc_read_reg32(&core_if->core_global_regs->ghwcfg2); -+ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); - core_if->hwcfg3.d32 = -- dwc_read_reg32(&core_if->core_global_regs->ghwcfg3); -+ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3); - core_if->hwcfg4.d32 = -- dwc_read_reg32(&core_if->core_global_regs->ghwcfg4); -+ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); -+ -+ /* Force host mode to get HPTXFSIZ exact power on value */ -+ { -+ gusbcfg_data_t gusbcfg = {.d32 = 0 }; -+ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); -+ gusbcfg.b.force_host_mode = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); -+ dwc_mdelay(100); -+ core_if->hptxfsiz.d32 = -+ DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); -+ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); -+ gusbcfg.b.force_host_mode = 0; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); -+ dwc_mdelay(100); -+ } - - DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); - DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); -@@ -188,9 +203,9 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); - - core_if->hcfg.d32 = -- dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg); -+ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); - core_if->dcfg.d32 = -- dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); - - DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32); - DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32); -@@ -224,13 +239,13 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg"); - if (core_if->wq_otg == 0) { - DWC_WARN("DWC_WORKQ_ALLOC failed\n"); -- dwc_free(host_if); -- dwc_free(dev_if); -- dwc_free(core_if); -+ DWC_FREE(host_if); -+ DWC_FREE(dev_if); -+ DWC_FREE(core_if); - return 0; - } - -- core_if->snpsid = dwc_read_reg32(&core_if->core_global_regs->gsnpsid); -+ core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid); - - DWC_PRINTF("Core Release: %x.%x%x%x\n", - (core_if->snpsid >> 12 & 0xF), -@@ -241,10 +256,10 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - w_wakeup_detected, core_if); - if (core_if->wkp_timer == 0) { - DWC_WARN("DWC_TIMER_ALLOC failed\n"); -- dwc_free(host_if); -- dwc_free(dev_if); -+ DWC_FREE(host_if); -+ DWC_FREE(dev_if); - DWC_WORKQ_FREE(core_if->wq_otg); -- dwc_free(core_if); -+ DWC_FREE(core_if); - return 0; - } - -@@ -252,12 +267,17 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - DWC_WARN("Error while setting core params\n"); - } - -+ core_if->hibernation_suspend = 0; -+ -+ /** ADP initialization */ -+ dwc_otg_adp_init(core_if); -+ - return core_if; - } - - /** - * This function frees the structures allocated by dwc_otg_cil_init(). -- * -+ * - * @param core_if The core interface pointer returned from - * dwc_otg_cil_init(). - * -@@ -267,22 +287,32 @@ void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if) - DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); - - /* Disable all interrupts */ -- dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 1, 0); -- dwc_write_reg32(&core_if->core_global_regs->gintmsk, 0); -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); - - if (core_if->wq_otg) { - DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500); - DWC_WORKQ_FREE(core_if->wq_otg); - } - if (core_if->dev_if) { -- dwc_free(core_if->dev_if); -+ DWC_FREE(core_if->dev_if); - } - if (core_if->host_if) { -- dwc_free(core_if->host_if); -+ DWC_FREE(core_if->host_if); -+ } -+ -+ /** Remove ADP Stuff */ -+ dwc_otg_adp_remove(core_if); -+ if (core_if->core_params) { -+ DWC_FREE(core_if->core_params); -+ } -+ if (core_if->wkp_timer) { -+ DWC_TIMER_FREE(core_if->wkp_timer); - } -- dwc_free(core_if); -- DWC_TIMER_FREE(core_if->wkp_timer); -- DWC_FREE(core_if->core_params); -+ if (core_if->srp_timer) { -+ DWC_TIMER_FREE(core_if->srp_timer); -+ } -+ DWC_FREE(core_if); - } - - /** -@@ -295,7 +325,7 @@ void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if) - { - gahbcfg_data_t ahbcfg = {.d32 = 0 }; - ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ -- dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); - } - - /** -@@ -307,9 +337,8 @@ void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t * core_if) - void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if) - { - gahbcfg_data_t ahbcfg = {.d32 = 0 }; -- ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ -- DWC_PRINTF("%x -> %x\n", (unsigned int)&core_if->core_global_regs->gahbcfg, ahbcfg.d32); -- dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); -+ ahbcfg.b.glblintrmsk = 1; /* Disable interrupts */ -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); - } - - /** -@@ -325,13 +354,13 @@ static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if) - gintmsk_data_t intr_mask = {.d32 = 0 }; - - /* Clear any pending OTG Interrupts */ -- dwc_write_reg32(&global_regs->gotgint, 0xFFFFFFFF); -+ DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF); - - /* Clear any pending interrupts */ -- dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); - -- /* -- * Enable the interrupts in the GINTMSK. -+ /* -+ * Enable the interrupts in the GINTMSK. - */ - intr_mask.b.modemismatch = 1; - intr_mask.b.otgintr = 1; -@@ -342,7 +371,7 @@ static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if) - - intr_mask.b.conidstschng = 1; - intr_mask.b.wkupintr = 1; -- intr_mask.b.disconnect = 1; -+ intr_mask.b.disconnect = 0; - intr_mask.b.usbsuspend = 1; - intr_mask.b.sessreqintr = 1; - #ifdef CONFIG_USB_DWC_OTG_LPM -@@ -350,7 +379,709 @@ static void dwc_otg_enable_common_interrupts(dwc_otg_core_if_t * core_if) - intr_mask.b.lpmtranrcvd = 1; - } - #endif -- dwc_write_reg32(&global_regs->gintmsk, intr_mask.d32); -+ DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32); -+} -+ -+/* -+ * The restore operation is modified to support Synopsys Emulated Powerdown and -+ * Hibernation. This function is for exiting from Device mode hibernation by -+ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. -+ * @param core_if Programming view of DWC_otg controller. -+ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. -+ * @param reset - indicates whether resume is initiated by Reset. -+ */ -+int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, -+ int rem_wakeup, int reset) -+{ -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ dctl_data_t dctl = {.d32 = 0 }; -+ -+ int timeout = 2000; -+ -+ if (!core_if->hibernation_suspend) { -+ DWC_PRINTF("Already exited from Hibernation\n"); -+ return 1; -+ } -+ -+ DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__); -+ /* Switch-on voltage to the core */ -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Reset core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Assert Restore signal */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.restore = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable power clamps */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ if (rem_wakeup) { -+ dwc_udelay(70); -+ } -+ -+ /* Deassert Reset core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable PMU interrupt */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Mask interrupts from gpwrdn */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.connect_det_msk = 1; -+ gpwrdn.b.srp_det_msk = 1; -+ gpwrdn.b.disconn_det_msk = 1; -+ gpwrdn.b.rst_det_msk = 1; -+ gpwrdn.b.lnstchng_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Indicates that we are going out from hibernation */ -+ core_if->hibernation_suspend = 0; -+ -+ /* -+ * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1 -+ * indicates restore from remote_wakeup -+ */ -+ restore_essential_regs(core_if, rem_wakeup, 0); -+ -+ /* -+ * Wait a little for seeing new value of variable hibernation_suspend if -+ * Restore done interrupt received before polling -+ */ -+ dwc_udelay(10); -+ -+ if (core_if->hibernation_suspend == 0) { -+ /* -+ * Wait For Restore_done Interrupt. This mechanism of polling the -+ * interrupt is introduced to avoid any possible race conditions -+ */ -+ do { -+ gintsts_data_t gintsts; -+ gintsts.d32 = -+ DWC_READ_REG32(&core_if->core_global_regs->gintsts); -+ if (gintsts.b.restoredone) { -+ gintsts.d32 = 0; -+ gintsts.b.restoredone = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs-> -+ gintsts, gintsts.d32); -+ DWC_PRINTF("Restore Done Interrupt seen\n"); -+ break; -+ } -+ dwc_udelay(10); -+ } while (--timeout); -+ if (!timeout) { -+ DWC_PRINTF("Restore Done interrupt wasn't generated here\n"); -+ } -+ } -+ /* Clear all pending interupts */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* De-assert Restore */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.restore = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ if (!rem_wakeup) { -+ pcgcctl.d32 = 0; -+ pcgcctl.b.rstpdwnmodule = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); -+ } -+ -+ /* Restore GUSBCFG and DCFG */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, -+ core_if->gr_backup->gusbcfg_local); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, -+ core_if->dr_backup->dcfg); -+ -+ /* De-assert Wakeup Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ if (!rem_wakeup) { -+ /* Set Device programming done bit */ -+ dctl.b.pwronprgdone = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ } else { -+ /* Start Remote Wakeup Signaling */ -+ dctl.d32 = core_if->dr_backup->dctl; -+ dctl.b.rmtwkupsig = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); -+ } -+ -+ dwc_mdelay(2); -+ /* Clear all pending interupts */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* Restore global registers */ -+ dwc_otg_restore_global_regs(core_if); -+ /* Restore device global registers */ -+ dwc_otg_restore_dev_regs(core_if, rem_wakeup); -+ -+ if (rem_wakeup) { -+ dwc_mdelay(7); -+ dctl.d32 = 0; -+ dctl.b.rmtwkupsig = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); -+ } -+ -+ core_if->hibernation_suspend = 0; -+ /* The core will be in ON STATE */ -+ core_if->lx_state = DWC_OTG_L0; -+ DWC_PRINTF("Hibernation recovery completes here\n"); -+ -+ return 1; -+} -+ -+/* -+ * The restore operation is modified to support Synopsys Emulated Powerdown and -+ * Hibernation. This function is for exiting from Host mode hibernation by -+ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. -+ * @param core_if Programming view of DWC_otg controller. -+ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. -+ * @param reset - indicates whether resume is initiated by Reset. -+ */ -+int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, -+ int rem_wakeup, int reset) -+{ -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ hprt0_data_t hprt0 = {.d32 = 0 }; -+ -+ int timeout = 2000; -+ -+ DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__); -+ /* Switch-on voltage to the core */ -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Reset core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Assert Restore signal */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.restore = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable power clamps */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ if (!rem_wakeup) { -+ dwc_udelay(50); -+ } -+ -+ /* Deassert Reset core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable PMU interrupt */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.connect_det_msk = 1; -+ gpwrdn.b.srp_det_msk = 1; -+ gpwrdn.b.disconn_det_msk = 1; -+ gpwrdn.b.rst_det_msk = 1; -+ gpwrdn.b.lnstchng_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Indicates that we are going out from hibernation */ -+ core_if->hibernation_suspend = 0; -+ -+ /* Set Restore Essential Regs bit in PCGCCTL register */ -+ restore_essential_regs(core_if, rem_wakeup, 1); -+ -+ /* Wait a little for seeing new value of variable hibernation_suspend if -+ * Restore done interrupt received before polling */ -+ dwc_udelay(10); -+ -+ if (core_if->hibernation_suspend == 0) { -+ /* Wait For Restore_done Interrupt. This mechanism of polling the -+ * interrupt is introduced to avoid any possible race conditions -+ */ -+ do { -+ gintsts_data_t gintsts; -+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); -+ if (gintsts.b.restoredone) { -+ gintsts.d32 = 0; -+ gintsts.b.restoredone = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n"); -+ break; -+ } -+ dwc_udelay(10); -+ } while (--timeout); -+ if (!timeout) { -+ DWC_WARN("Restore Done interrupt wasn't generated\n"); -+ } -+ } -+ -+ /* Set the flag's value to 0 again after receiving restore done interrupt */ -+ core_if->hibernation_suspend = 0; -+ -+ /* This step is not described in functional spec but if not wait for this -+ * delay, mismatch interrupts occurred because just after restore core is -+ * in Device mode(gintsts.curmode == 0) */ -+ dwc_mdelay(100); -+ -+ /* Clear all pending interrupts */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* De-assert Restore */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.restore = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Restore GUSBCFG and HCFG */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, -+ core_if->gr_backup->gusbcfg_local); -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, -+ core_if->hr_backup->hcfg_local); -+ -+ /* De-assert Wakeup Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Start the Resume operation by programming HPRT0 */ -+ hprt0.d32 = core_if->hr_backup->hprt0_local; -+ hprt0.b.prtpwr = 1; -+ hprt0.b.prtena = 0; -+ hprt0.b.prtsusp = 0; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ -+ DWC_PRINTF("Resume Starts Now\n"); -+ if (!reset) { // Indicates it is Resume Operation -+ hprt0.d32 = core_if->hr_backup->hprt0_local; -+ hprt0.b.prtres = 1; -+ hprt0.b.prtpwr = 1; -+ hprt0.b.prtena = 0; -+ hprt0.b.prtsusp = 0; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ -+ if (!rem_wakeup) -+ hprt0.b.prtres = 0; -+ /* Wait for Resume time and then program HPRT again */ -+ dwc_mdelay(100); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ -+ } else { // Indicates it is Reset Operation -+ hprt0.d32 = core_if->hr_backup->hprt0_local; -+ hprt0.b.prtrst = 1; -+ hprt0.b.prtpwr = 1; -+ hprt0.b.prtena = 0; -+ hprt0.b.prtsusp = 0; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ /* Wait for Reset time and then program HPRT again */ -+ dwc_mdelay(60); -+ hprt0.b.prtrst = 0; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ } -+ /* Clear all interrupt status */ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtconndet = 1; -+ hprt0.b.prtenchng = 1; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ -+ /* Clear all pending interupts */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* Restore global registers */ -+ dwc_otg_restore_global_regs(core_if); -+ /* Restore host global registers */ -+ dwc_otg_restore_host_regs(core_if, reset); -+ -+ /* The core will be in ON STATE */ -+ core_if->lx_state = DWC_OTG_L0; -+ DWC_PRINTF("Hibernation recovery is complete here\n"); -+ return 0; -+} -+ -+/** Saves some register values into system memory. */ -+int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if) -+{ -+ struct dwc_otg_global_regs_backup *gr; -+ int i; -+ -+ gr = core_if->gr_backup; -+ if (!gr) { -+ gr = DWC_ALLOC(sizeof(*gr)); -+ if (!gr) { -+ return -DWC_E_NO_MEMORY; -+ } -+ core_if->gr_backup = gr; -+ } -+ -+ gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); -+ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); -+ gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); -+ gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); -+ gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); -+ gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz); -+ gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); -+#endif -+ gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl); -+ gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl); -+ gr->gdfifocfg_local = -+ DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg); -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ gr->dtxfsiz_local[i] = -+ DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i])); -+ } -+ -+ DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n"); -+ DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl = %08x\n", gr->gotgctl_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg = %08x\n", gr->gahbcfg_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg = %08x\n", gr->gusbcfg_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz = %08x\n", gr->grxfsiz_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n", -+ gr->gnptxfsiz_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz = %08x\n", -+ gr->hptxfsiz_local); -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg = %08x\n", gr->glpmcfg_local); -+#endif -+ DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl = %08x\n", gr->gi2cctl_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl = %08x\n", gr->pcgcctl_local); -+ DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg = %08x\n",gr->gdfifocfg_local); -+ -+ return 0; -+} -+ -+/** Saves GINTMSK register before setting the msk bits. */ -+int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if) -+{ -+ struct dwc_otg_global_regs_backup *gr; -+ -+ gr = core_if->gr_backup; -+ if (!gr) { -+ gr = DWC_ALLOC(sizeof(*gr)); -+ if (!gr) { -+ return -DWC_E_NO_MEMORY; -+ } -+ core_if->gr_backup = gr; -+ } -+ -+ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); -+ -+ DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n"); -+ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); -+ -+ return 0; -+} -+ -+int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if) -+{ -+ struct dwc_otg_dev_regs_backup *dr; -+ int i; -+ -+ dr = core_if->dr_backup; -+ if (!dr) { -+ dr = DWC_ALLOC(sizeof(*dr)); -+ if (!dr) { -+ return -DWC_E_NO_MEMORY; -+ } -+ core_if->dr_backup = dr; -+ } -+ -+ dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); -+ dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); -+ dr->daintmsk = -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); -+ dr->diepmsk = -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk); -+ dr->doepmsk = -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk); -+ -+ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -+ dr->diepctl[i] = -+ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); -+ dr->dieptsiz[i] = -+ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz); -+ dr->diepdma[i] = -+ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma); -+ } -+ -+ DWC_DEBUGPL(DBG_ANY, -+ "=============Backing Host registers==============\n"); -+ DWC_DEBUGPL(DBG_ANY, "Backed up dcfg = %08x\n", dr->dcfg); -+ DWC_DEBUGPL(DBG_ANY, "Backed up dctl = %08x\n", dr->dctl); -+ DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk = %08x\n", -+ dr->daintmsk); -+ DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk = %08x\n", dr->diepmsk); -+ DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk = %08x\n", dr->doepmsk); -+ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -+ DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d] = %08x\n", i, -+ dr->diepctl[i]); -+ DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d] = %08x\n", -+ i, dr->dieptsiz[i]); -+ DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d] = %08x\n", i, -+ dr->diepdma[i]); -+ } -+ -+ return 0; -+} -+ -+int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if) -+{ -+ struct dwc_otg_host_regs_backup *hr; -+ int i; -+ -+ hr = core_if->hr_backup; -+ if (!hr) { -+ hr = DWC_ALLOC(sizeof(*hr)); -+ if (!hr) { -+ return -DWC_E_NO_MEMORY; -+ } -+ core_if->hr_backup = hr; -+ } -+ -+ hr->hcfg_local = -+ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); -+ hr->haintmsk_local = -+ DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk); -+ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { -+ hr->hcintmsk_local[i] = -+ DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk); -+ } -+ hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0); -+ hr->hfir_local = -+ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); -+ -+ DWC_DEBUGPL(DBG_ANY, -+ "=============Backing Host registers===============\n"); -+ DWC_DEBUGPL(DBG_ANY, "Backed up hcfg = %08x\n", -+ hr->hcfg_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local); -+ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { -+ DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i, -+ hr->hcintmsk_local[i]); -+ } -+ DWC_DEBUGPL(DBG_ANY, "Backed up hprt0 = %08x\n", -+ hr->hprt0_local); -+ DWC_DEBUGPL(DBG_ANY, "Backed up hfir = %08x\n", -+ hr->hfir_local); -+ -+ return 0; -+} -+ -+int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if) -+{ -+ struct dwc_otg_global_regs_backup *gr; -+ int i; -+ -+ gr = core_if->gr_backup; -+ if (!gr) { -+ return -DWC_E_INVALID; -+ } -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local); -+ DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, -+ gr->gnptxfsiz_local); -+ DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz, -+ gr->hptxfsiz_local); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg, -+ gr->gdfifocfg_local); -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i], -+ gr->dtxfsiz_local[i]); -+ } -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, -+ (gr->gahbcfg_local)); -+ return 0; -+} -+ -+int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup) -+{ -+ struct dwc_otg_dev_regs_backup *dr; -+ int i; -+ -+ dr = core_if->dr_backup; -+ -+ if (!dr) { -+ return -DWC_E_INVALID; -+ } -+ -+ if (!rem_wakeup) -+ { -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dr->dctl); -+ } -+ -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk); -+ -+ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]); -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]); -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]); -+ } -+ -+ return 0; -+} -+ -+int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset) -+{ -+ struct dwc_otg_host_regs_backup *hr; -+ int i; -+ hr = core_if->hr_backup; -+ -+ if (!hr) { -+ return -DWC_E_INVALID; -+ } -+ -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local); -+ //if (!reset) -+ //{ -+ // DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local); -+ //} -+ -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, -+ hr->haintmsk_local); -+ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { -+ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, -+ hr->hcintmsk_local[i]); -+ } -+ -+ return 0; -+} -+ -+int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if) -+{ -+ struct dwc_otg_global_regs_backup *gr; -+ -+ gr = core_if->gr_backup; -+ -+ /* Restore values for LPM and I2C */ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local); -+#endif -+ DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local); -+ -+ return 0; -+} -+ -+int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host) -+{ -+ struct dwc_otg_global_regs_backup *gr; -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ gahbcfg_data_t gahbcfg = {.d32 = 0 }; -+ gusbcfg_data_t gusbcfg = {.d32 = 0 }; -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ -+ /* Restore LPM and I2C registers */ -+ restore_lpm_i2c_regs(core_if); -+ -+ /* Set PCGCCTL to 0 */ -+ DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000); -+ -+ gr = core_if->gr_backup; -+ /* Load restore values for [31:14] bits */ -+ DWC_WRITE_REG32(core_if->pcgcctl, -+ ((gr->pcgcctl_local & 0xffffc000) | 0x00020000)); -+ -+ /* Umnask global Interrupt in GAHBCFG and restore it */ -+ gahbcfg.d32 = gr->gahbcfg_local; -+ gahbcfg.b.glblintrmsk = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); -+ -+ /* Clear all pending interupts */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ -+ /* Unmask restore done interrupt */ -+ gintmsk.b.restoredone = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); -+ -+ /* Restore GUSBCFG and HCFG/DCFG */ -+ gusbcfg.d32 = core_if->gr_backup->gusbcfg_local; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); -+ -+ if (is_host) { -+ hcfg_data_t hcfg = {.d32 = 0 }; -+ hcfg.d32 = core_if->hr_backup->hcfg_local; -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, -+ hcfg.d32); -+ -+ /* Load restore values for [31:14] bits */ -+ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; -+ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; -+ -+ if (rmode) -+ pcgcctl.b.restoremode = 1; -+ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); -+ dwc_udelay(10); -+ -+ /* Load restore values for [31:14] bits and set EssRegRestored bit */ -+ pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000; -+ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; -+ pcgcctl.b.ess_reg_restored = 1; -+ if (rmode) -+ pcgcctl.b.restoremode = 1; -+ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); -+ } else { -+ dcfg_data_t dcfg = {.d32 = 0 }; -+ dcfg.d32 = core_if->dr_backup->dcfg; -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); -+ -+ /* Load restore values for [31:14] bits */ -+ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; -+ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; -+ if (!rmode) { -+ pcgcctl.d32 |= 0x208; -+ } -+ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); -+ dwc_udelay(10); -+ -+ /* Load restore values for [31:14] bits */ -+ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; -+ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; -+ pcgcctl.b.ess_reg_restored = 1; -+ if (!rmode) -+ pcgcctl.d32 |= 0x208; -+ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); -+ } -+ -+ return 0; - } - - /** -@@ -374,9 +1105,9 @@ static void init_fslspclksel(dwc_otg_core_if_t * core_if) - } - - DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val); -- hcfg.d32 = dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg); -+ 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); -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); - } - - /** -@@ -404,14 +1135,14 @@ static void init_devspd(dwc_otg_core_if_t * core_if) - - DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); - -- dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); - dcfg.b.devspd = val; -- dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); - } - - /** - * This function calculates the number of IN EPS -- * using GHWCFG1 and GHWCFG2 registers values -+ * using GHWCFG1 and GHWCFG2 registers values - * - * @param core_if Programming view of the DWC_otg controller - */ -@@ -440,7 +1171,7 @@ static uint32_t calc_num_in_eps(dwc_otg_core_if_t * core_if) - - /** - * This function calculates the number of OUT EPS -- * using GHWCFG1 and GHWCFG2 registers values -+ * using GHWCFG1 and GHWCFG2 registers values - * - * @param core_if Programming view of the DWC_otg controller - */ -@@ -480,8 +1211,7 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - core_if, global_regs); - - /* Common Initialization */ -- -- usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); - - /* Program the ULPI External VBUS bit if needed */ - usbcfg.b.ulpi_ext_vbus_drv = -@@ -491,11 +1221,15 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - /* 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); -+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); - - /* Reset the Controller */ - dwc_otg_core_reset(core_if); - -+ core_if->adp_enable = core_if->core_params->adp_supp_enable; -+ core_if->power_down = core_if->core_params->power_down; -+ core_if->otg_sts = 0; -+ - /* Initialize parameters from Hardware configuration registers. */ - dev_if->num_in_eps = calc_num_in_eps(core_if); - dev_if->num_out_eps = calc_num_out_eps(core_if); -@@ -505,22 +1239,22 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - - for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { - dev_if->perio_tx_fifo_size[i] = -- dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16; -+ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; - DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", - i, dev_if->perio_tx_fifo_size[i]); - } - - for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { - dev_if->tx_fifo_size[i] = -- dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16; -+ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; - DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", -- i, dev_if->perio_tx_fifo_size[i]); -+ i, dev_if->tx_fifo_size[i]); - } - - core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth; -- core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz); -+ core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz); - core_if->nperio_tx_fifo_size = -- dwc_read_reg32(&global_regs->gnptxfsiz) >> 16; -+ DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16; - - DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); - DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); -@@ -538,9 +1272,9 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - if (!core_if->phy_init_done) { - core_if->phy_init_done = 1; - DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n"); -- usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); - usbcfg.b.physel = 1; -- dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); - - /* Reset after a PHY select */ - dwc_otg_core_reset(core_if); -@@ -558,17 +1292,17 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - if (core_if->core_params->i2c_enable) { - DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n"); - /* Program GUSBCFG.OtgUtmifsSel to I2C */ -- usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); - usbcfg.b.otgutmifssel = 1; -- dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); - - /* Program GI2CCTL.I2CEn */ -- i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl); -+ i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl); - i2cctl.b.i2cdevaddr = 1; - i2cctl.b.i2cen = 0; -- dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32); -+ DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); - i2cctl.b.i2cen = 1; -- dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32); -+ DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); - } - - } /* endif speed == DWC_SPEED_PARAM_FULL */ -@@ -579,24 +1313,26 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - /* 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) { -+ -+ if (core_if->core_params->phy_type == 2) { - /* ULPI interface */ -+ usbcfg.b.ulpi_utmi_sel = 1; - usbcfg.b.phyif = 0; - usbcfg.b.ddrsel = - core_if->core_params->phy_ulpi_ddr; -- } else { -+ } else if (core_if->core_params->phy_type == 1) { - /* UTMI+ interface */ -+ usbcfg.b.ulpi_utmi_sel = 0; - if (core_if->core_params->phy_utmi_width == 16) { - usbcfg.b.phyif = 1; - - } else { - usbcfg.b.phyif = 0; - } -- -+ } else { -+ DWC_ERROR("FS PHY TYPE\n"); - } -- -- dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); - /* Reset after setting the PHY parameters */ - dwc_otg_core_reset(core_if); - } -@@ -606,15 +1342,15 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - (core_if->hwcfg2.b.fs_phy_type == 1) && - (core_if->core_params->ulpi_fs_ls)) { - DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n"); -- usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ 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); -+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); - } else { -- usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ 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); -+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); - } - - /* Program the GAHBCFG Register. */ -@@ -646,8 +1382,10 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - - case DWC_INT_DMA_ARCH: - DWC_DEBUGPL(DBG_CIL, "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 */ -+ /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for -+ Host mode ISOC in issue fix - vahrama */ -+ /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */ -+ ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4; - core_if->dma_enable = (core_if->core_params->dma_enable != 0); - core_if->dma_desc_enable = - (core_if->core_params->dma_desc_enable != 0); -@@ -665,9 +1403,13 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - DWC_PRINTF("Using Slave mode\n"); - core_if->dma_desc_enable = 0; - } -+ -+ if (core_if->core_params->ahb_single) { -+ ahbcfg.b.ahbsingle = 1; -+ } - - ahbcfg.b.dmaenable = core_if->dma_enable; -- dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32); -+ DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32); - - core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en; - -@@ -678,10 +1420,10 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n", - ((core_if->multiproc_int_enable) ? "enabled" : "disabled")); - -- /* -- * Program the GUSBCFG register. -+ /* -+ * Program the GUSBCFG register. - */ -- usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); - - switch (core_if->hwcfg2.b.op_mode) { - case DWC_MODE_HNP_SRP_CAPABLE: -@@ -725,7 +1467,7 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - break; - } - -- dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); -+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); - - #ifdef CONFIG_USB_DWC_OTG_LPM - if (core_if->core_params->lpm_enable) { -@@ -740,7 +1482,7 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - /* Retry 3 times */ - lpmcfg.b.retry_count = 3; - -- dwc_modify_reg32(&core_if->core_global_regs->glpmcfg, -+ DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg, - 0, lpmcfg.d32); - - } -@@ -748,9 +1490,20 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - 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, -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg, - 0, gusbcfg.d32); - } -+ { -+ gotgctl_data_t gotgctl = {.d32 = 0 }; -+ gotgctl.b.otgver = core_if->core_params->otg_ver; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, -+ gotgctl.d32); -+ /* Set OTG version supported */ -+ core_if->otg_ver = core_if->core_params->otg_ver; -+ DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n", -+ core_if->core_params->otg_ver, core_if->otg_ver); -+ } -+ - - /* Enable common interrupts */ - dwc_otg_enable_common_interrupts(core_if); -@@ -769,7 +1522,7 @@ void dwc_otg_core_init(dwc_otg_core_if_t * core_if) - } - } - --/** -+/** - * This function enables the Device mode interrupts. - * - * @param core_if Programming view of DWC_otg controller -@@ -782,10 +1535,10 @@ void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) - DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); - - /* Disable all interrupts. */ -- dwc_write_reg32(&global_regs->gintmsk, 0); -+ DWC_WRITE_REG32(&global_regs->gintmsk, 0); - - /* Clear any pending interrupts */ -- dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); - - /* Enable the common interrupts */ - dwc_otg_enable_common_interrupts(core_if); -@@ -793,6 +1546,8 @@ void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) - /* Enable interrupts */ - intr_mask.b.usbreset = 1; - intr_mask.b.enumdone = 1; -+ /* Disable Disconnect interrupt in Device mode */ -+ intr_mask.b.disconnect = 0; - - if (!core_if->multiproc_int_enable) { - intr_mask.b.inepintr = 1; -@@ -804,15 +1559,36 @@ void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) - if (core_if->en_multiple_tx_fifo == 0) { - intr_mask.b.epmismatch = 1; - } -+ -+ //intr_mask.b.incomplisoout = 1; -+ intr_mask.b.incomplisoin = 1; -+ -+/* Enable the ignore frame number for ISOC xfers - MAS */ -+/* Disable to support high bandwith ISOC transfers - manukz */ -+#if 0 -+#ifdef DWC_UTE_PER_IO -+ if (core_if->dma_enable) { -+ if (core_if->dma_desc_enable) { -+ dctl_data_t dctl1 = {.d32 = 0 }; -+ dctl1.b.ifrmnum = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> -+ dctl, 0, dctl1.d32); -+ DWC_DEBUG("----Enabled Ignore frame number (0x%08x)", -+ DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->dctl)); -+ } -+ } -+#endif -+#endif - #ifdef DWC_EN_ISOC - if (core_if->dma_enable) { - if (core_if->dma_desc_enable == 0) { - if (core_if->pti_enh_enable) { - dctl_data_t dctl = {.d32 = 0 }; - dctl.b.ifrmnum = 1; -- dwc_modify_reg32(&core_if->dev_if-> -- dev_global_regs->dctl, 0, -- dctl.d32); -+ DWC_MODIFY_REG32(&core_if-> -+ dev_if->dev_global_regs->dctl, -+ 0, dctl.d32); - } else { - intr_mask.b.incomplisoin = 1; - intr_mask.b.incomplisoout = 1; -@@ -822,7 +1598,7 @@ void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) - intr_mask.b.incomplisoin = 1; - intr_mask.b.incomplisoout = 1; - } --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ - - /** @todo NGS: Should this be a module parameter? */ - #ifdef USE_PERIODIC_EP -@@ -832,16 +1608,16 @@ void dwc_otg_enable_device_interrupts(dwc_otg_core_if_t * core_if) - intr_mask.b.incomplisoout = 1; - #endif - -- dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); -+ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); - - DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, -- dwc_read_reg32(&global_regs->gintmsk)); -+ DWC_READ_REG32(&global_regs->gintmsk)); - } - - /** - * This function initializes the DWC_otg controller registers for - * device mode. -- * -+ * - * @param core_if Programming view of DWC_otg controller - * - */ -@@ -852,23 +1628,38 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - dwc_otg_dev_if_t *dev_if = core_if->dev_if; - dwc_otg_core_params_t *params = core_if->core_params; - dcfg_data_t dcfg = {.d32 = 0 }; -+ depctl_data_t diepctl = {.d32 = 0 }; - grstctl_t resetctl = {.d32 = 0 }; - uint32_t rx_fifo_size; - fifosize_data_t nptxfifosize; - fifosize_data_t txfifosize; - dthrctl_data_t dthrctl; - fifosize_data_t ptxfifosize; -+ uint16_t rxfsiz, nptxfsiz; -+ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; -+ hwcfg3_data_t hwcfg3 = {.d32 = 0 }; - - /* Restart the Phy Clock */ -- dwc_write_reg32(core_if->pcgcctl, 0); -+ DWC_WRITE_REG32(core_if->pcgcctl, 0); - - /* Device configuration register */ - init_devspd(core_if); -- dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg); -+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); - dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0; - dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80; -+ /* Enable Device OUT NAK in case of DDMA mode*/ -+ if (core_if->core_params->dev_out_nak) { -+ dcfg.b.endevoutnak = 1; -+ } - -- dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ if (core_if->core_params->cont_on_bna) { -+ dctl_data_t dctl = {.d32 = 0 }; -+ dctl.b.encontonbna = 1; -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ } -+ -+ -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); - - /* Configure data FIFO sizes */ - if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { -@@ -881,17 +1672,17 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - - /* Rx FIFO */ - DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->grxfsiz)); -+ DWC_READ_REG32(&global_regs->grxfsiz)); - - #ifdef DWC_UTE_CFI -- core_if->pwron_rxfsiz = dwc_read_reg32(&global_regs->grxfsiz); -+ core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz); - core_if->init_rxfsiz = params->dev_rx_fifo_size; - #endif - rx_fifo_size = params->dev_rx_fifo_size; -- dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size); -+ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); - - DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->grxfsiz)); -+ DWC_READ_REG32(&global_regs->grxfsiz)); - - /** Set Periodic Tx FIFO Mask all bits 0 */ - core_if->p_tx_msk = 0; -@@ -902,16 +1693,16 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - if (core_if->en_multiple_tx_fifo == 0) { - /* Non-periodic Tx FIFO */ - DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->gnptxfsiz)); -+ DWC_READ_REG32(&global_regs->gnptxfsiz)); - - nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; - nptxfifosize.b.startaddr = params->dev_rx_fifo_size; - -- dwc_write_reg32(&global_regs->gnptxfsiz, -+ DWC_WRITE_REG32(&global_regs->gnptxfsiz, - nptxfifosize.d32); - - DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->gnptxfsiz)); -+ DWC_READ_REG32(&global_regs->gnptxfsiz)); - - /**@todo NGS: Fix Periodic FIFO Sizing! */ - /* -@@ -923,24 +1714,18 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - /** @todo Finish debug of this */ - ptxfifosize.b.startaddr = - nptxfifosize.b.startaddr + nptxfifosize.b.depth; -- for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; -- i++) { -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { - ptxfifosize.b.depth = - params->dev_perio_tx_fifo_size[i]; - DWC_DEBUGPL(DBG_CIL, -- "initial dptxfsiz_dieptxf[%d]=%08x\n", -- i, -- dwc_read_reg32(&global_regs-> -- dptxfsiz_dieptxf -+ "initial dtxfsiz[%d]=%08x\n", i, -+ DWC_READ_REG32(&global_regs->dtxfsiz - [i])); -- dwc_write_reg32(&global_regs-> -- dptxfsiz_dieptxf[i], -+ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], - ptxfifosize.d32); -- DWC_DEBUGPL(DBG_CIL, -- "new dptxfsiz_dieptxf[%d]=%08x\n", -+ DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n", - i, -- dwc_read_reg32(&global_regs-> -- dptxfsiz_dieptxf -+ DWC_READ_REG32(&global_regs->dtxfsiz - [i])); - ptxfifosize.b.startaddr += ptxfifosize.b.depth; - } -@@ -949,27 +1734,27 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - * Tx FIFOs These FIFOs are numbered from 1 to 15. - * Indexes of the FIFO size module parameters in the - * dev_tx_fifo_size array and the FIFO size registers in -- * the dptxfsiz_dieptxf array run from 0 to 14. -+ * the dtxfsiz array run from 0 to 14. - */ - - /* Non-periodic Tx FIFO */ - DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->gnptxfsiz)); -+ DWC_READ_REG32(&global_regs->gnptxfsiz)); - - #ifdef DWC_UTE_CFI - core_if->pwron_gnptxfsiz = -- (dwc_read_reg32(&global_regs->gnptxfsiz) >> 16); -+ (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); - core_if->init_gnptxfsiz = - params->dev_nperio_tx_fifo_size; - #endif - nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; - nptxfifosize.b.startaddr = params->dev_rx_fifo_size; - -- dwc_write_reg32(&global_regs->gnptxfsiz, -+ DWC_WRITE_REG32(&global_regs->gnptxfsiz, - nptxfifosize.d32); - - DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->gnptxfsiz)); -+ DWC_READ_REG32(&global_regs->gnptxfsiz)); - - txfifosize.b.startaddr = - nptxfifosize.b.startaddr + nptxfifosize.b.depth; -@@ -980,69 +1765,100 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - params->dev_tx_fifo_size[i]; - - DWC_DEBUGPL(DBG_CIL, -- "initial dptxfsiz_dieptxf[%d]=%08x\n", -+ "initial dtxfsiz[%d]=%08x\n", - i, -- dwc_read_reg32(&global_regs-> -- dptxfsiz_dieptxf -+ DWC_READ_REG32(&global_regs->dtxfsiz - [i])); - - #ifdef DWC_UTE_CFI - core_if->pwron_txfsiz[i] = -- (dwc_read_reg32 -- (&global_regs->dptxfsiz_dieptxf[i]) >> 16); -+ (DWC_READ_REG32 -+ (&global_regs->dtxfsiz[i]) >> 16); - core_if->init_txfsiz[i] = - params->dev_tx_fifo_size[i]; - #endif -- dwc_write_reg32(&global_regs-> -- dptxfsiz_dieptxf[i], -+ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], - txfifosize.d32); - - DWC_DEBUGPL(DBG_CIL, -- "new dptxfsiz_dieptxf[%d]=%08x\n", -+ "new dtxfsiz[%d]=%08x\n", - i, -- dwc_read_reg32(&global_regs-> -- dptxfsiz_dieptxf -+ DWC_READ_REG32(&global_regs->dtxfsiz - [i])); - - txfifosize.b.startaddr += txfifosize.b.depth; - } -+ /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */ -+ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); -+ hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3); -+ gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16); -+ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); -+ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); -+ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); -+ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz; -+ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); - } - } -+ - /* Flush the FIFOs */ - dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ - dwc_otg_flush_rx_fifo(core_if); - - /* Flush the Learning Queue. */ - resetctl.b.intknqflsh = 1; -- dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); - -+ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { -+ core_if->start_predict = 0; -+ for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) { -+ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active -+ } -+ core_if->nextep_seq[0] = 0; -+ core_if->first_in_nextep_seq = 0; -+ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); -+ diepctl.b.nextep = 0; -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); -+ -+ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ -+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); -+ dcfg.b.epmscnt = 2; -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ -+ DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ __func__, core_if->first_in_nextep_seq); -+ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -+ DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]); -+ } -+ DWC_DEBUGPL(DBG_CILV,"\n"); -+ } -+ - /* Clear all pending Device Interrupts */ -- /** @todo - if the condition needed to be checked -- * or in any case all pending interrutps should be cleared? -- */ -+ /** @todo - if the condition needed to be checked -+ * or in any case all pending interrutps should be cleared? -+ */ - if (core_if->multiproc_int_enable) { - for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -- dwc_write_reg32(&dev_if->dev_global_regs-> -- diepeachintmsk[i], 0); -+ DWC_WRITE_REG32(&dev_if-> -+ dev_global_regs->diepeachintmsk[i], 0); - } - - for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { -- dwc_write_reg32(&dev_if->dev_global_regs-> -- doepeachintmsk[i], 0); -+ DWC_WRITE_REG32(&dev_if-> -+ dev_global_regs->doepeachintmsk[i], 0); - } - -- dwc_write_reg32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); -- dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk, 0); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0); - } else { -- dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, 0); -- dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, 0); -- dwc_write_reg32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); -- dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, 0); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0); - } - - for (i = 0; i <= dev_if->num_in_eps; i++) { - depctl_data_t depctl; -- depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); -+ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); - if (depctl.b.epena) { - depctl.d32 = 0; - depctl.b.epdis = 1; -@@ -1051,16 +1867,16 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - depctl.d32 = 0; - } - -- dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); - -- dwc_write_reg32(&dev_if->in_ep_regs[i]->dieptsiz, 0); -- dwc_write_reg32(&dev_if->in_ep_regs[i]->diepdma, 0); -- dwc_write_reg32(&dev_if->in_ep_regs[i]->diepint, 0xFF); -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0); -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0); -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF); - } - - for (i = 0; i <= dev_if->num_out_eps; i++) { - depctl_data_t depctl; -- depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); -+ depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); - if (depctl.b.epena) { - depctl.d32 = 0; - depctl.b.epdis = 1; -@@ -1069,11 +1885,11 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - depctl.d32 = 0; - } - -- dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); - -- dwc_write_reg32(&dev_if->out_ep_regs[i]->doeptsiz, 0); -- dwc_write_reg32(&dev_if->out_ep_regs[i]->doepdma, 0); -- dwc_write_reg32(&dev_if->out_ep_regs[i]->doepint, 0xFF); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF); - } - - if (core_if->en_multiple_tx_fifo && core_if->dma_enable) { -@@ -1094,7 +1910,7 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - dthrctl.b.rx_thr_len = dev_if->rx_thr_length; - dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio; - -- dwc_write_reg32(&dev_if->dev_global_regs->dtknqr3_dthrctl, -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl, - dthrctl.d32); - - DWC_DEBUGPL(DBG_CIL, -@@ -1111,10 +1927,11 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - diepmsk_data_t msk = {.d32 = 0 }; - msk.b.txfifoundrn = 1; - if (core_if->multiproc_int_enable) { -- dwc_modify_reg32(&dev_if->dev_global_regs-> -- diepeachintmsk[0], msk.d32, msk.d32); -+ DWC_MODIFY_REG32(&dev_if-> -+ dev_global_regs->diepeachintmsk[0], -+ msk.d32, msk.d32); - } else { -- dwc_modify_reg32(&dev_if->dev_global_regs->diepmsk, -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, - msk.d32, msk.d32); - } - } -@@ -1123,11 +1940,18 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - /* Set NAK on Babble */ - dctl_data_t dctl = {.d32 = 0 }; - dctl.b.nakonbble = 1; -- dwc_modify_reg32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ } -+ -+ if (core_if->snpsid >= OTG_CORE_REV_2_94a) { -+ dctl_data_t dctl = {.d32 = 0 }; -+ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl); -+ dctl.b.sftdiscon = 0; -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32); - } - } - --/** -+/** - * This function enables the Host mode interrupts. - * - * @param core_if Programming view of DWC_otg controller -@@ -1140,10 +1964,10 @@ void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if) - DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if); - - /* Disable all interrupts. */ -- dwc_write_reg32(&global_regs->gintmsk, 0); -+ DWC_WRITE_REG32(&global_regs->gintmsk, 0); - - /* Clear any pending interrupts. */ -- dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); -+ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); - - /* Enable the common interrupts */ - dwc_otg_enable_common_interrupts(core_if); -@@ -1152,17 +1976,15 @@ void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * core_if) - * Enable host mode interrupts without disturbing common - * interrupts. - */ -- -- /* Do not need sof interrupt for Descriptor DMA*/ -- if (!core_if->dma_desc_enable) -- intr_mask.b.sofintr = 1; -+ -+ intr_mask.b.disconnect = 1; - intr_mask.b.portintr = 1; - intr_mask.b.hcintr = 1; - -- dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); -+ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); - } - --/** -+/** - * This function disables the Host Mode interrupts. - * - * @param core_if Programming view of DWC_otg controller -@@ -1184,7 +2006,7 @@ void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * core_if) - intr_mask.b.ptxfempty = 1; - intr_mask.b.nptxfempty = 1; - -- dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 0); -+ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0); - } - - /** -@@ -1206,9 +2028,12 @@ void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if) - hprt0_data_t hprt0 = {.d32 = 0 }; - fifosize_data_t nptxfifosize; - fifosize_data_t ptxfifosize; -+ uint16_t rxfsiz, nptxfsiz, hptxfsiz; -+ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; - int i; - hcchar_data_t hcchar; - hcfg_data_t hcfg; -+ hfir_data_t hfir; - dwc_otg_hc_regs_t *hc_regs; - int num_channels; - gotgctl_data_t gotgctl = {.d32 = 0 }; -@@ -1216,38 +2041,52 @@ void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if) - DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); - - /* Restart the Phy Clock */ -- dwc_write_reg32(core_if->pcgcctl, 0); -+ 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.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); -- -+ DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); -+ -+ } -+ -+ /* This bit allows dynamic reloading of the HFIR register -+ * during runtime. This bit needs to be programmed during -+ * initial configuration and its value must not be changed -+ * during runtime.*/ -+ if (core_if->core_params->reload_ctl == 1) { -+ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); -+ hfir.b.hfirrldctrl = 1; -+ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.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)))) { -- -- DWC_ERROR("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); -+ 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)))) { -+ -+ DWC_ERROR("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); -+ 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) { - DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", -@@ -1261,65 +2100,79 @@ void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if) - - /* Rx FIFO */ - DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->grxfsiz)); -- dwc_write_reg32(&global_regs->grxfsiz, -+ DWC_READ_REG32(&global_regs->grxfsiz)); -+ DWC_WRITE_REG32(&global_regs->grxfsiz, - params->host_rx_fifo_size); - DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->grxfsiz)); -+ DWC_READ_REG32(&global_regs->grxfsiz)); - - /* Non-periodic Tx FIFO */ - DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->gnptxfsiz)); -+ 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); -+ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); - DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->gnptxfsiz)); -+ DWC_READ_REG32(&global_regs->gnptxfsiz)); - - /* Periodic Tx FIFO */ - DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->hptxfsiz)); -+ 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); -+ DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32); - DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", -- dwc_read_reg32(&global_regs->hptxfsiz)); -+ DWC_READ_REG32(&global_regs->hptxfsiz)); -+ -+ if (core_if->en_multiple_tx_fifo) { -+ /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */ -+ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); -+ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); -+ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); -+ hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16); -+ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz; -+ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); -+ } - } - -+ /* TODO - check this */ - /* Clear Host Set HNP Enable in the OTG Control Register */ - gotgctl.b.hstsethnpen = 1; -- dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); -- -+ 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_tx_fifo(core_if, 0x10 /* all TX FIFOs */ ); - dwc_otg_flush_rx_fifo(core_if); - -- if(!core_if->core_params->dma_desc_enable) { -+ /* Clear Host Set HNP Enable in the OTG Control Register */ -+ gotgctl.b.hstsethnpen = 1; -+ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); -+ -+ 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.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); -+ 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.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); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs); - do { -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - if (++count > 1000) { - DWC_ERROR - ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n", -@@ -1330,7 +2183,7 @@ void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if) - } while (hcchar.b.chen); - } - } -- -+ - /* Turn on the vbus power. */ - DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state); - if (core_if->op_state == A_HOST) { -@@ -1338,7 +2191,7 @@ void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if) - DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); - if (hprt0.b.prtpwr == 0) { - hprt0.b.prtpwr = 1; -- dwc_write_reg32(host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(host_if->hprt0, hprt0.d32); - } - } - -@@ -1369,7 +2222,7 @@ void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - /* 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); -+ DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32); - - /* Enable channel interrupts required for this transfer. */ - hc_intr_mask.d32 = 0; -@@ -1379,10 +2232,10 @@ void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - if (!core_if->dma_desc_enable) - hc_intr_mask.b.ahberr = 1; - else { -- if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) - hc_intr_mask.b.xfercompl = 1; - } -- -+ - if (hc->error_state && !hc->do_split && - hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { - hc_intr_mask.b.ack = 1; -@@ -1458,15 +2311,15 @@ void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - break; - } - } -- dwc_write_reg32(&hc_regs->hcintmsk, hc_intr_mask.d32); -+ DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32); - - /* Enable the top level host channel interrupt. */ - intr_enable = (1 << hc_num); -- dwc_modify_reg32(&host_if->host_global_regs->haintmsk, 0, intr_enable); -+ DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable); - - /* Make sure host channel interrupts are enabled. */ - gintmsk.b.hcintr = 1; -- dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); - - /* - * Program the HCCHARn register with the endpoint characteristics for -@@ -1480,16 +2333,14 @@ void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - hcchar.b.eptype = hc->ep_type; - hcchar.b.mps = hc->max_packet; - -- dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); - -- DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -- DWC_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr); -- DWC_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum); -- DWC_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir); -- DWC_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev); -- DWC_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype); -- DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); -- DWC_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt); -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n", -+ __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum); -+ DWC_DEBUGPL(DBG_HCDV, " Is In %d, Is Low Speed %d, EP Type %d, " -+ "Max Pkt %d, Multi Cnt %d\n", -+ hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype, -+ hcchar.b.mps, hcchar.b.multicnt); - - /* - * Program the HCSPLIT register for SPLITs -@@ -1503,15 +2354,15 @@ void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - hcsplt.b.xactpos = hc->xact_pos; - hcsplt.b.hubaddr = hc->hub_addr; - hcsplt.b.prtaddr = hc->port_addr; -- DWC_DEBUGPL(DBG_HCDV, " comp split %d\n", hc->complete_split); -- DWC_DEBUGPL(DBG_HCDV, " xact pos %d\n", hc->xact_pos); -- DWC_DEBUGPL(DBG_HCDV, " hub addr %d\n", hc->hub_addr); -- DWC_DEBUGPL(DBG_HCDV, " port addr %d\n", hc->port_addr); -- DWC_DEBUGPL(DBG_HCDV, " is_in %d\n", hc->ep_is_in); -- DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); -- DWC_DEBUGPL(DBG_HCDV, " xferlen: %d\n", hc->xfer_len); -+ DWC_DEBUGPL(DBG_HCDV, "\t comp split %d\n", hc->complete_split); -+ DWC_DEBUGPL(DBG_HCDV, "\t xact pos %d\n", hc->xact_pos); -+ DWC_DEBUGPL(DBG_HCDV, "\t hub addr %d\n", hc->hub_addr); -+ DWC_DEBUGPL(DBG_HCDV, "\t port addr %d\n", hc->port_addr); -+ DWC_DEBUGPL(DBG_HCDV, "\t is_in %d\n", hc->ep_is_in); -+ DWC_DEBUGPL(DBG_HCDV, "\t Max Pkt: %d\n", hcchar.b.mps); -+ DWC_DEBUGPL(DBG_HCDV, "\t xferlen: %d\n", hc->xfer_len); - } -- dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); -+ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); - - } - -@@ -1571,14 +2422,14 @@ void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if, - hcintmsk_data_t hcintmsk; - hcintmsk.d32 = 0; - hcintmsk.b.chhltd = 1; -- dwc_write_reg32(&hc_regs->hcintmsk, hcintmsk.d32); -+ DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32); - - /* - * Make sure no other interrupts besides halt are currently - * pending. Handling another interrupt could cause a crash due - * to the QTD and QH state. - */ -- dwc_write_reg32(&hc_regs->hcint, ~hcintmsk.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32); - - /* - * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR -@@ -1587,7 +2438,7 @@ void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if, - */ - hc->halt_status = halt_status; - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - if (hcchar.b.chen == 0) { - /* - * The channel is either already halted or it hasn't -@@ -1618,32 +2469,32 @@ void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if, - return; - } - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -- -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); -+ - /* No need to set the bit in DDMA for disabling the channel */ -- //TODO check it everywhere channel is disabled -- if(!core_if->core_params->dma_desc_enable) -+ //TODO check it everywhere channel is disabled -+ if (!core_if->core_params->dma_desc_enable) - hcchar.b.chen = 1; - hcchar.b.chdis = 1; -- -+ - if (!core_if->dma_enable) { - /* Check for space in the request queue to issue the halt. */ - if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || - hc->ep_type == DWC_OTG_EP_TYPE_BULK) { -- nptxsts.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts); - if (nptxsts.b.nptxqspcavail == 0) { - hcchar.b.chen = 0; - } - } else { - hptxsts.d32 = -- dwc_read_reg32(&host_global_regs->hptxsts); -+ DWC_READ_REG32(&host_global_regs->hptxsts); - if ((hptxsts.b.ptxqspcavail == 0) - || (core_if->queuing_high_bandwidth)) { - hcchar.b.chen = 0; - } - } - } -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - - hc->halt_status = halt_status; - -@@ -1681,8 +2532,8 @@ void dwc_otg_hc_cleanup(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - * conditions. - */ - hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -- dwc_write_reg32(&hc_regs->hcintmsk, 0); -- dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF); -+ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0); -+ DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF); - #ifdef DEBUG - DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]); - #endif -@@ -1705,7 +2556,7 @@ static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if, - hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { - hfnum_data_t hfnum; - hfnum.d32 = -- dwc_read_reg32(&core_if->host_if->host_global_regs->hfnum); -+ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum); - - /* 1 if _next_ frame is odd, 0 if it's even */ - hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; -@@ -1735,36 +2586,85 @@ static inline void hc_set_even_odd_frame(dwc_otg_core_if_t * core_if, - #ifdef DEBUG - void hc_xfer_timeout(void *ptr) - { -- hc_xfer_info_t *xfer_info = (hc_xfer_info_t *) ptr; -- int hc_num = xfer_info->hc->hc_num; -+ hc_xfer_info_t *xfer_info = NULL; -+ int hc_num = 0; -+ -+ if (ptr) -+ xfer_info = (hc_xfer_info_t *) ptr; -+ -+ if (!xfer_info->hc) { -+ DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc); -+ return; -+ } -+ -+ hc_num = xfer_info->hc->hc_num; - DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num); - DWC_WARN(" start_hcchar_val 0x%08x\n", - xfer_info->core_if->start_hcchar_val[hc_num]); - } - #endif - -+void ep_xfer_timeout(void *ptr) -+{ -+ ep_xfer_info_t *xfer_info = NULL; -+ int ep_num = 0; -+ dctl_data_t dctl = {.d32 = 0 }; -+ gintsts_data_t gintsts = {.d32 = 0 }; -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ -+ if (ptr) -+ xfer_info = (ep_xfer_info_t *) ptr; -+ -+ if (!xfer_info->ep) { -+ DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep); -+ return; -+ } -+ -+ ep_num = xfer_info->ep->num; -+ DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num); -+ /* Put the sate to 2 as it was time outed */ -+ xfer_info->state = 2; -+ -+ dctl.d32 = DWC_READ_REG32(&xfer_info->core_if-> -+ dev_if->dev_global_regs->dctl); -+ gintsts.d32 = DWC_READ_REG32(&xfer_info->core_if-> -+ core_global_regs->gintsts); -+ gintmsk.d32 = DWC_READ_REG32(&xfer_info->core_if-> -+ core_global_regs->gintmsk); -+ -+ if (!gintmsk.b.goutnakeff) { -+ /* Unmask it */ -+ gintmsk.b.goutnakeff = 1; -+ DWC_WRITE_REG32(&xfer_info->core_if-> -+ core_global_regs->gintmsk, gintmsk.d32); -+ -+ } -+ -+ if (!gintsts.b.goutnakeff) { -+ dctl.b.sgoutnak = 1; -+ } -+ DWC_WRITE_REG32(&xfer_info->core_if->dev_if-> -+ dev_global_regs->dctl, dctl.d32); -+ -+} -+ - void set_pid_isoc(dwc_hc_t * hc) - { - /* Set up the initial PID for the transfer. */ - if (hc->speed == DWC_OTG_EP_SPEED_HIGH) { - if (hc->ep_is_in) { - if (hc->multi_count == 1) { -- hc->data_pid_start = -- DWC_OTG_HC_PID_DATA0; -+ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; - } else if (hc->multi_count == 2) { -- hc->data_pid_start = -- DWC_OTG_HC_PID_DATA1; -+ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; - } else { -- hc->data_pid_start = -- DWC_OTG_HC_PID_DATA2; -+ hc->data_pid_start = DWC_OTG_HC_PID_DATA2; - } - } else { - if (hc->multi_count == 1) { -- hc->data_pid_start = -- DWC_OTG_HC_PID_DATA0; -+ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; - } else { -- hc->data_pid_start = -- DWC_OTG_HC_PID_MDATA; -+ hc->data_pid_start = DWC_OTG_HC_PID_MDATA; - } - } - } else { -@@ -1899,7 +2799,7 @@ void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - hc->start_pkt_count = num_packets; - hctsiz.b.pktcnt = num_packets; - hctsiz.b.pid = hc->data_pid_start; -- dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); - - DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); - DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); -@@ -1911,20 +2811,20 @@ void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - if (hc->align_buff) { - dma_addr = hc->align_buff; - } else { -- dma_addr = (uint32_t)hc->xfer_buff; -+ dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff); - } -- dwc_write_reg32(&hc_regs->hcdma, dma_addr); -+ DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr); - } - - /* Start the split */ - if (hc->do_split) { - hcsplt_data_t hcsplt; -- hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); - hcsplt.b.spltena = 1; -- dwc_write_reg32(&hc_regs->hcsplt, hcsplt.d32); -+ DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32); - } - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - hcchar.b.multicnt = hc->multi_count; - hc_set_even_odd_frame(core_if, hc, &hcchar); - #ifdef DEBUG -@@ -1938,7 +2838,7 @@ void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - /* 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); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - - hc->xfer_started = 1; - hc->requests++; -@@ -1953,6 +2853,7 @@ void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - hc->hc_num, core_if);//GRAYG - core_if->hc_xfer_info[hc->hc_num].core_if = core_if; - core_if->hc_xfer_info[hc->hc_num].hc = hc; -+ - /* Start a timer for this transfer. */ - DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); - } -@@ -1960,7 +2861,7 @@ void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - } - - /** -- * This function does the setup for a data transfer for a host channel -+ * This function does the setup for a data transfer for a host channel - * and starts the transfer in Descriptor DMA mode. - * - * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. -@@ -1975,40 +2876,40 @@ void dwc_otg_hc_start_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - */ - void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - { -- dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; - hcchar_data_t hcchar; - hctsiz_data_t hctsiz; -- hcdma_data_t hcdma; -- -+ hcdma_data_t hcdma; -+ - hctsiz.d32 = 0; - -- if (hc->do_ping && !hc->ep_is_in) -+ if (hc->do_ping) - hctsiz.b_ddma.dopng = 1; - - if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) - set_pid_isoc(hc); -- -+ - /* Packet Count and Xfer Size are not used in Descriptor DMA mode */ - hctsiz.b_ddma.pid = hc->data_pid_start; -- hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ -- hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ -- -+ hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ -+ hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ -+ - DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); - DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); -- DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); -+ DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); - -- dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); - - hcdma.d32 = 0; -- hcdma.b.dma_addr = ((uint32_t)hc->desc_list_addr) >> 11; -- -+ hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11; -+ - /* Always start from first descriptor. */ - hcdma.b.ctd = 0; -- dwc_write_reg32(&hc_regs->hcdma, hcdma.d32); -+ DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32); - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - hcchar.b.multicnt = hc->multi_count; -- -+ - #ifdef DEBUG - core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; - if (hcchar.b.chdis) { -@@ -2020,14 +2921,15 @@ void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - /* 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); -+ -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - - hc->xfer_started = 1; - hc->requests++; -- -+ - #ifdef DEBUG -- if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) { -+ if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) -+ && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) { - DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n", - hc->hc_num, core_if);//GRAYG - core_if->hc_xfer_info[hc->hc_num].core_if = core_if; -@@ -2035,11 +2937,10 @@ void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - /* Start a timer for this transfer. */ - DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); - } -- - #endif -- -+ - } -- -+ - /** - * This function continues a data transfer that was started by previous call - * to dwc_otg_hc_start_transfer. The caller must ensure there is -@@ -2082,13 +2983,13 @@ int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - dwc_otg_hc_regs_t *hc_regs = - core_if->host_if->hc_regs[hc->hc_num]; - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - hc_set_even_odd_frame(core_if, hc, &hcchar); - hcchar.b.chen = 1; - hcchar.b.chdis = 0; - DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", - hcchar.d32); -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - hc->requests++; - return 1; - } else { -@@ -2099,7 +3000,7 @@ int dwc_otg_hc_continue_transfer(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - hcchar_data_t hcchar; - dwc_otg_hc_regs_t *hc_regs; - hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - hc_set_even_odd_frame(core_if, hc, &hcchar); - } - -@@ -2128,12 +3029,12 @@ void dwc_otg_hc_do_ping(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - hctsiz.d32 = 0; - hctsiz.b.dopng = 1; - hctsiz.b.pktcnt = 1; -- dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); -+ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - hcchar.b.chen = 1; - hcchar.b.chdis = 0; -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - } - - /* -@@ -2168,7 +3069,7 @@ void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - if ((((unsigned long)data_buff) & 0x3) == 0) { - /* xfer_buff is DWORD aligned. */ - for (i = 0; i < dword_count; i++, data_buff++) { -- dwc_write_reg32(data_fifo, *data_buff); -+ DWC_WRITE_REG32(data_fifo, *data_buff); - } - } else { - /* xfer_buff is not DWORD aligned. */ -@@ -2177,7 +3078,7 @@ void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - data = - (data_buff[0] | data_buff[1] << 8 | data_buff[2] << - 16 | data_buff[3] << 24); -- dwc_write_reg32(data_fifo, data); -+ DWC_WRITE_REG32(data_fifo, data); - } - } - -@@ -2186,21 +3087,62 @@ void dwc_otg_hc_write_packet(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) - } - - /** -- * Gets the current USB frame number. This is the frame number from the last -- * SOF packet. -+ * Gets the current USB frame number. This is the frame number from the last -+ * SOF packet. - */ - uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if) - { - dsts_data_t dsts; -- dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - - /* read current frame/microframe number from DSTS register */ - return dsts.b.soffn; - } - - /** -- * This function reads a setup packet from the Rx FIFO into the destination -- * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) -+ * Calculates and gets the frame Interval value of HFIR register according PHY -+ * type and speed.The application can modify a value of HFIR register only after -+ * the Port Enable bit of the Host Port Control and Status register -+ * (HPRT.PrtEnaPort) has been set. -+*/ -+ -+uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if) -+{ -+ gusbcfg_data_t usbcfg; -+ hwcfg2_data_t hwcfg2; -+ hprt0_data_t hprt0; -+ int clock = 60; // default value -+ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); -+ hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); -+ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); -+ if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) -+ clock = 60; -+ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3) -+ clock = 48; -+ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && -+ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) -+ clock = 30; -+ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && -+ !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) -+ clock = 60; -+ if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel && -+ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) -+ clock = 48; -+ if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2) -+ clock = 48; -+ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1) -+ clock = 48; -+ if (hprt0.b.prtspd == 0) -+ /* High speed case */ -+ return 125 * clock; -+ else -+ /* FS/LS case */ -+ return 1000 * clock; -+} -+ -+/** -+ * This function reads a setup packet from the Rx FIFO into the destination -+ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) - * Interrupt routine when a SETUP packet has been received in Slave mode. - * - * @param core_if Programming view of DWC_otg controller. -@@ -2211,13 +3153,13 @@ void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest) - /* Get the 8 bytes of a setup transaction data */ - - /* Pop 2 DWORDS off the receive data FIFO into memory */ -- dest[0] = dwc_read_reg32(core_if->data_fifo[0]); -- dest[1] = dwc_read_reg32(core_if->data_fifo[0]); -+ dest[0] = DWC_READ_REG32(core_if->data_fifo[0]); -+ dest[1] = DWC_READ_REG32(core_if->data_fifo[0]); - } - - /** -- * This function enables EP0 OUT to receive SETUP packets and configures EP0 -- * IN for transmitting packets. It is normally called when the -+ * This function enables EP0 OUT to receive SETUP packets and configures EP0 -+ * IN for transmitting packets. It is normally called when the - * "Enumeration Done" interrupt occurs. - * - * @param core_if Programming view of DWC_otg controller. -@@ -2232,9 +3174,9 @@ void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - dctl_data_t dctl = {.d32 = 0 }; - - /* Read the Device Status and Endpoint 0 Control registers */ -- dsts.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dsts); -- diepctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl); -- doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl); -+ dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts); -+ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); -+ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); - - /* Set the MPS of the IN EP based on the enumeration speed */ - switch (dsts.b.enumspd) { -@@ -2248,28 +3190,29 @@ void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - break; - } - -- dwc_write_reg32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); - - /* Enable OUT EP for receive */ - doepctl.b.epena = 1; -- dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); - - #ifdef VERBOSE - DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", -- dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); -+ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); - DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", -- dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl)); -+ DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); - #endif - dctl.b.cgnpinnak = 1; - -- dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); - DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n", -- dwc_read_reg32(&dev_if->dev_global_regs->dctl)); -+ DWC_READ_REG32(&dev_if->dev_global_regs->dctl)); -+ - } - - /** - * This function activates an EP. The Device EP control register for -- * the EP is configured as defined in the ep structure. Note: This -+ * the EP is configured as defined in the ep structure. Note: This - * function is not used for EP0. - * - * @param core_if Programming view of DWC_otg controller. -@@ -2281,10 +3224,17 @@ void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - depctl_data_t depctl; - volatile uint32_t *addr; - daint_data_t daintmsk = {.d32 = 0 }; -+ dcfg_data_t dcfg; -+ uint8_t i; - - DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, - (ep->is_in ? "IN" : "OUT")); - -+#ifdef DWC_UTE_PER_IO -+ ep->xiso_frame_num = 0xFFFFFFFF; -+ ep->xiso_active_xfers = 0; -+ ep->xiso_queued_xfers = 0; -+#endif - /* Read DEPCTLn register */ - if (ep->is_in == 1) { - addr = &dev_if->in_ep_regs[ep->num]->diepctl; -@@ -2296,21 +3246,43 @@ void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - /* If the EP is already active don't change the EP Control - * register. */ -- depctl.d32 = dwc_read_reg32(addr); -+ depctl.d32 = DWC_READ_REG32(addr); - if (!depctl.b.usbactep) { - depctl.b.mps = ep->maxpacket; - depctl.b.eptype = ep->type; - depctl.b.txfnum = ep->tx_fifo_num; - - if (ep->type == DWC_OTG_EP_TYPE_ISOC) { -- depctl.b.setd0pid = 1; // ??? -+ depctl.b.setd0pid = 1; // ??? - } else { - depctl.b.setd0pid = 1; - } - depctl.b.usbactep = 1; - -- dwc_write_reg32(addr, depctl.d32); -- DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", dwc_read_reg32(addr)); -+ /* Update nextep_seq array and EPMSCNT in DCFG*/ -+ if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) { // NP IN EP -+ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { -+ if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq) -+ break; -+ } -+ core_if->nextep_seq[i] = ep->num; -+ core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq; -+ depctl.b.nextep = core_if->nextep_seq[ep->num]; -+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); -+ dcfg.b.epmscnt++; -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ -+ DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ __func__, core_if->first_in_nextep_seq); -+ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -+ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); -+ } -+ -+ } -+ -+ -+ DWC_WRITE_REG32(addr, depctl.d32); -+ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr)); - } - - /* Enable the Interrupt for this EP */ -@@ -2322,17 +3294,26 @@ void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - diepmsk.b.epdisabled = 1; - diepmsk.b.ahberr = 1; - diepmsk.b.intknepmis = 1; -+ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) -+ diepmsk.b.intknepmis = 0; - diepmsk.b.txfifoundrn = 1; //????? -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ diepmsk.b.nak = 1; -+ } - -+ -+ -+/* - if (core_if->dma_desc_enable) { - diepmsk.b.bna = 1; - } -+*/ - /* -- if(core_if->dma_enable) { -+ if (core_if->dma_enable) { - doepmsk.b.nak = 1; - } - */ -- dwc_write_reg32(&dev_if->dev_global_regs-> -+ DWC_WRITE_REG32(&dev_if->dev_global_regs-> - diepeachintmsk[ep->num], diepmsk.d32); - - } else { -@@ -2340,35 +3321,53 @@ void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - doepmsk.b.xfercompl = 1; - doepmsk.b.ahberr = 1; - doepmsk.b.epdisabled = 1; -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) -+ doepmsk.b.outtknepdis = 1; -+ -+/* - - if (core_if->dma_desc_enable) { - doepmsk.b.bna = 1; - } -+*/ - /* - doepmsk.b.babble = 1; - doepmsk.b.nyet = 1; - doepmsk.b.nak = 1; - */ -- dwc_write_reg32(&dev_if->dev_global_regs-> -+ DWC_WRITE_REG32(&dev_if->dev_global_regs-> - doepeachintmsk[ep->num], doepmsk.d32); - } -- dwc_modify_reg32(&dev_if->dev_global_regs->deachintmsk, -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk, - 0, daintmsk.d32); - } else { -- dwc_modify_reg32(&dev_if->dev_global_regs->daintmsk, -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ if (ep->is_in) -+ { -+ diepmsk_data_t diepmsk = {.d32 = 0 }; -+ diepmsk.b.nak = 1; -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32); -+ } else { -+ doepmsk_data_t doepmsk = {.d32 = 0 }; -+ doepmsk.b.outtknepdis = 1; -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32); -+ } -+ } -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk, - 0, daintmsk.d32); - } - - DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", -- dwc_read_reg32(&dev_if->dev_global_regs->daintmsk)); -+ DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk)); - - ep->stall_clear_flag = 0; -+ - return; - } - - /** -- * This function deactivates an EP. This is done by clearing the USB Active -- * EP bit in the Device EP control register. Note: This function is not used -+ * This function deactivates an EP. This is done by clearing the USB Active -+ * EP bit in the Device EP control register. Note: This function is not used - * for EP0. EP0 cannot be deactivated. - * - * @param core_if Programming view of DWC_otg controller. -@@ -2379,6 +3378,14 @@ void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - depctl_data_t depctl = {.d32 = 0 }; - volatile uint32_t *addr; - daint_data_t daintmsk = {.d32 = 0 }; -+ dcfg_data_t dcfg; -+ uint8_t i = 0; -+ -+#ifdef DWC_UTE_PER_IO -+ ep->xiso_frame_num = 0xFFFFFFFF; -+ ep->xiso_active_xfers = 0; -+ ep->xiso_queued_xfers = 0; -+#endif - - /* Read DEPCTLn register */ - if (ep->is_in == 1) { -@@ -2389,31 +3396,121 @@ void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - daintmsk.ep.out = 1 << ep->num; - } - -- depctl.d32 = dwc_read_reg32(addr); -+ depctl.d32 = DWC_READ_REG32(addr); - - depctl.b.usbactep = 0; -+ -+ /* Update nextep_seq array and EPMSCNT in DCFG*/ -+ if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN -+ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { -+ if (core_if->nextep_seq[i] == ep->num) -+ break; -+ } -+ core_if->nextep_seq[i] = core_if->nextep_seq[ep->num]; -+ if (core_if->first_in_nextep_seq == ep->num) -+ core_if->first_in_nextep_seq = i; -+ core_if->nextep_seq[ep->num] = 0xff; -+ depctl.b.nextep = 0; -+ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.b.epmscnt--; -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); -+ -+ DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ __func__, core_if->first_in_nextep_seq); -+ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -+ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); -+ } -+ } -+ -+ if (ep->is_in == 1) -+ depctl.b.txfnum = 0; - - if (core_if->dma_desc_enable) - depctl.b.epdis = 1; - -- dwc_write_reg32(addr, depctl.d32); -+ DWC_WRITE_REG32(addr, depctl.d32); -+ depctl.d32 = DWC_READ_REG32(addr); -+ if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC && depctl.b.epena) -+ { -+ depctl_data_t depctl = {.d32 = 0}; -+ if (ep->is_in) -+ { -+ diepint_data_t diepint = {.d32 = 0}; -+ -+ depctl.b.snak = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepctl, depctl.d32); -+ do -+ { -+ dwc_udelay(10); -+ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[ep->num]->diepint); -+ } while (!diepint.b.inepnakeff); -+ diepint.b.inepnakeff = 1; -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ in_ep_regs[ep->num]->diepint, diepint.d32); -+ depctl.d32 = 0; -+ depctl.b.epdis = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepctl, depctl.d32); -+ do -+ { -+ dwc_udelay(10); -+ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[ep->num]->diepint); -+ } while (!diepint.b.epdisabled); -+ diepint.b.epdisabled = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepint, diepint.d32); -+ } else { -+ dctl_data_t dctl = {.d32 = 0}; -+ gintmsk_data_t gintsts = {.d32 = 0}; -+ doepint_data_t doepint = {.d32 = 0}; -+ dctl.b.sgoutnak = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ do -+ { -+ dwc_udelay(10); -+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); -+ } while (!gintsts.b.goutnakeff); -+ gintsts.d32 = 0; -+ gintsts.b.goutnakeff = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ depctl.d32 = 0; -+ depctl.b.epdis = 1; -+ depctl.b.snak = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32); -+ do -+ { -+ dwc_udelay(10); -+ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[ep->num]->doepint); -+ } while (!doepint.b.epdisabled); -+ -+ doepint.b.epdisabled = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32); -+ -+ dctl.d32 = 0; -+ dctl.b.cgoutnak = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ } -+ } - - /* Disable the Interrupt for this EP */ - if (core_if->multiproc_int_enable) { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs->deachintmsk, -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, - daintmsk.d32, 0); - - if (ep->is_in == 1) { -- dwc_write_reg32(&core_if->dev_if->dev_global_regs-> -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> - diepeachintmsk[ep->num], 0); - } else { -- dwc_write_reg32(&core_if->dev_if->dev_global_regs-> -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> - doepeachintmsk[ep->num], 0); - } - } else { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs->daintmsk, -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk, - daintmsk.d32, 0); - } -+ - } - - /** -@@ -2428,28 +3525,52 @@ static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - uint32_t offset; - uint32_t xfer_est; - int i; -+ unsigned maxxfer_local, total_len; -+ -+ if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR && -+ (ep->maxpacket%4)) { -+ maxxfer_local = ep->maxpacket; -+ total_len = ep->xfer_len; -+ } else { -+ maxxfer_local = ep->maxxfer; -+ total_len = ep->total_len; -+ } -+ -+ ep->desc_cnt = (total_len / maxxfer_local) + -+ ((total_len % maxxfer_local) ? 1 : 0); - -- ep->desc_cnt = (ep->total_len / ep->maxxfer) + -- ((ep->total_len % ep->maxxfer) ? 1 : 0); - if (!ep->desc_cnt) - ep->desc_cnt = 1; - -+ if (ep->desc_cnt > MAX_DMA_DESC_CNT) -+ ep->desc_cnt = MAX_DMA_DESC_CNT; -+ - dma_desc = ep->desc_addr; -- xfer_est = ep->total_len; -+ if (maxxfer_local == ep->maxpacket) { -+ if ((total_len % maxxfer_local) && -+ (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) { -+ xfer_est = (ep->desc_cnt - 1) * maxxfer_local + -+ (total_len % maxxfer_local); -+ } else -+ xfer_est = ep->desc_cnt * maxxfer_local; -+ } -+ else -+ xfer_est = total_len; - offset = 0; - for (i = 0; i < ep->desc_cnt; ++i) { - /** DMA Descriptor Setup */ -- if (xfer_est > ep->maxxfer) { -+ if (xfer_est > maxxfer_local) { - dma_desc->status.b.bs = BS_HOST_BUSY; - dma_desc->status.b.l = 0; - dma_desc->status.b.ioc = 0; - dma_desc->status.b.sp = 0; -- dma_desc->status.b.bytes = ep->maxxfer; -+ dma_desc->status.b.bytes = maxxfer_local; - dma_desc->buf = ep->dma_addr + offset; -+ dma_desc->status.b.sts = 0; - dma_desc->status.b.bs = BS_HOST_READY; - -- xfer_est -= ep->maxxfer; -- offset += ep->maxxfer; -+ xfer_est -= maxxfer_local; -+ offset += maxxfer_local; - } else { - dma_desc->status.b.bs = BS_HOST_BUSY; - dma_desc->status.b.l = 1; -@@ -2461,20 +3582,76 @@ static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - sent_zlp) ? 1 : 0); - dma_desc->status.b.bytes = xfer_est; - } else { -- dma_desc->status.b.bytes = -- xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); -+ if (maxxfer_local == ep->maxpacket) -+ dma_desc->status.b.bytes = xfer_est; -+ else -+ dma_desc->status.b.bytes = -+ xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); - } - - dma_desc->buf = ep->dma_addr + offset; -+ dma_desc->status.b.sts = 0; - dma_desc->status.b.bs = BS_HOST_READY; - } - dma_desc++; - } - } -+/** -+ * This function is called when to write ISOC data into appropriate dedicated -+ * periodic FIFO. -+ */ -+static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) -+{ -+ dwc_otg_dev_if_t *dev_if = core_if->dev_if; -+ dwc_otg_dev_in_ep_regs_t *ep_regs; -+ dtxfsts_data_t txstatus = {.d32 = 0 }; -+ uint32_t len = 0; -+ int epnum = dwc_ep->num; -+ int dwords; -+ -+ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); -+ -+ ep_regs = core_if->dev_if->in_ep_regs[epnum]; -+ -+ len = dwc_ep->xfer_len - dwc_ep->xfer_count; -+ -+ if (len > dwc_ep->maxpacket) { -+ len = dwc_ep->maxpacket; -+ } -+ -+ dwords = (len + 3) / 4; -+ -+ /* While there is space in the queue and space in the FIFO and -+ * More data to tranfer, Write packets to the Tx FIFO */ -+ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); -+ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); -+ -+ while (txstatus.b.txfspcavail > dwords && -+ dwc_ep->xfer_count < dwc_ep->xfer_len && -+ dwc_ep->xfer_len != 0) { -+ /* Write the FIFO */ -+ dwc_otg_ep_write_packet(core_if, dwc_ep, 0); -+ -+ len = dwc_ep->xfer_len - dwc_ep->xfer_count; -+ if (len > dwc_ep->maxpacket) { -+ len = dwc_ep->maxpacket; -+ } - -+ dwords = (len + 3) / 4; -+ txstatus.d32 = -+ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); -+ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, -+ txstatus.d32); -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, -+ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); -+ -+ return 1; -+} - /** - * This function does the setup for a data transfer for an EP and -- * starts the transfer. For an IN transfer, the packets will be -+ * starts the transfer. For an IN transfer, the packets will be - * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, - * the packets are unloaded from the Rx FIFO in the ISR. the ISR. - * -@@ -2502,21 +3679,27 @@ void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - gnptxsts_data_t gtxstatus; - - gtxstatus.d32 = -- dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); - - if (core_if->en_multiple_tx_fifo == 0 -- && gtxstatus.b.nptxqspcavail == 0) { -+ && gtxstatus.b.nptxqspcavail == 0 -+ && !core_if->dma_enable) { - #ifdef DEBUG - DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32); - #endif - return; - } - -- depctl.d32 = dwc_read_reg32(&(in_regs->diepctl)); -- deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz)); -+ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); -+ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); -+ -+ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) -+ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? -+ ep->maxxfer : (ep->total_len - ep->xfer_len); -+ else -+ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? -+ MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); - -- ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? -- ep->maxxfer : (ep->total_len - ep->xfer_len); - - /* Zero Length Packet? */ - if ((ep->xfer_len - ep->xfer_count) == 0) { -@@ -2526,93 +3709,121 @@ void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - /* Program the transfer size and packet count - * as follows: xfersize = N * maxpacket + - * short_packet pktcnt = N + (short_packet -- * exist ? 1 : 0) -+ * exist ? 1 : 0) - */ - deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; - deptsiz.b.pktcnt = - (ep->xfer_len - ep->xfer_count - 1 + - ep->maxpacket) / ep->maxpacket; -+ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { -+ deptsiz.b.pktcnt = MAX_PKT_CNT; -+ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; -+ } -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) -+ deptsiz.b.mc = deptsiz.b.pktcnt; - } - - /* Write the DMA register */ - if (core_if->dma_enable) { - if (core_if->dma_desc_enable == 0) { -- dwc_write_reg32(&in_regs->dieptsiz, -+ if (ep->type != DWC_OTG_EP_TYPE_ISOC) -+ deptsiz.b.mc = 1; -+ DWC_WRITE_REG32(&in_regs->dieptsiz, - deptsiz.d32); -- dwc_write_reg32(&(in_regs->diepdma), -+ DWC_WRITE_REG32(&(in_regs->diepdma), - (uint32_t) ep->dma_addr); - } else { - #ifdef DWC_UTE_CFI - /* The descriptor chain should be already initialized by now */ - if (ep->buff_mode != BM_STANDARD) { -- dwc_write_reg32(&in_regs->diepdma, -+ DWC_WRITE_REG32(&in_regs->diepdma, - ep->descs_dma_addr); - } else { - #endif -- init_dma_desc_chain(core_if, ep); -+ init_dma_desc_chain(core_if, ep); - /** DIEPDMAn Register write */ -- dwc_write_reg32(&in_regs->diepdma, -- ep->dma_desc_addr); -+ DWC_WRITE_REG32(&in_regs->diepdma, -+ ep->dma_desc_addr); - #ifdef DWC_UTE_CFI -- } -+ } - #endif - } - } else { -- dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); - if (ep->type != DWC_OTG_EP_TYPE_ISOC) { -- /** -+ /** - * Enable the Non-Periodic Tx FIFO empty interrupt, - * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, - * the data will be written into the fifo by the ISR. - */ - if (core_if->en_multiple_tx_fifo == 0) { - intr_mask.b.nptxfempty = 1; -- dwc_modify_reg32(&core_if-> -- core_global_regs-> -- gintmsk, intr_mask.d32, -- intr_mask.d32); -+ DWC_MODIFY_REG32 -+ (&core_if->core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); - } else { - /* Enable the Tx FIFO Empty Interrupt for this EP */ - if (ep->xfer_len > 0) { - uint32_t fifoemptymsk = 0; - fifoemptymsk = 1 << ep->num; -- dwc_modify_reg32(&core_if-> -- dev_if-> -- dev_global_regs-> -- dtknqr4_fifoemptymsk, -- 0, -- fifoemptymsk); -+ DWC_MODIFY_REG32 -+ (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk, -+ 0, fifoemptymsk); - - } - } -+ } else { -+ write_isoc_tx_fifo(core_if, ep); -+ } -+ } -+ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) -+ depctl.b.nextep = core_if->nextep_seq[ep->num]; -+ -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) -+ { -+ dsts_data_t dsts = {.d32 = 0}; -+ if (ep->bInterval == 1) { -+ dsts.d32 = -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); -+ ep->frame_num = dsts.b.soffn + ep->bInterval; -+ if (ep->frame_num > 0x3FFF) -+ { -+ ep->frm_overrun = 1; -+ ep->frame_num &= 0x3FFF; -+ } else -+ ep->frm_overrun = 0; -+ if (ep->frame_num & 0x1) { -+ depctl.b.setd1pid = 1; -+ } else { -+ depctl.b.setd0pid = 1; -+ } - } - } -- - /* EP enable, IN data in FIFO */ - depctl.b.cnak = 1; - depctl.b.epena = 1; -- dwc_write_reg32(&in_regs->diepctl, depctl.d32); -- -- depctl.d32 = -- dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -- depctl.b.nextep = ep->num; -- dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl, -- depctl.d32); -+ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); - - } else { - /* OUT endpoint */ - dwc_otg_dev_out_ep_regs_t *out_regs = - core_if->dev_if->out_ep_regs[ep->num]; - -- depctl.d32 = dwc_read_reg32(&(out_regs->doepctl)); -- deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz)); -+ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); -+ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); - -- ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? -- ep->maxxfer : (ep->total_len - ep->xfer_len); -+ if (!core_if->dma_desc_enable) { -+ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) -+ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? -+ ep->maxxfer : (ep->total_len - ep->xfer_len); -+ else -+ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len -+ - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); -+ } - - /* Program the transfer size and packet count as follows: -- * -- * pktcnt = N -+ * -+ * pktcnt = N - * xfersize = N * maxpacket - */ - if ((ep->xfer_len - ep->xfer_count) == 0) { -@@ -2623,8 +3834,13 @@ void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - deptsiz.b.pktcnt = - (ep->xfer_len - ep->xfer_count + - (ep->maxpacket - 1)) / ep->maxpacket; -- ep->xfer_len = -- deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; -+ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { -+ deptsiz.b.pktcnt = MAX_PKT_CNT; -+ } -+ if (!core_if->dma_desc_enable) { -+ ep->xfer_len = -+ deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; -+ } - deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; - } - -@@ -2633,47 +3849,98 @@ void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - if (core_if->dma_enable) { - if (!core_if->dma_desc_enable) { -- dwc_write_reg32(&out_regs->doeptsiz, -+ DWC_WRITE_REG32(&out_regs->doeptsiz, - deptsiz.d32); - -- dwc_write_reg32(&(out_regs->doepdma), -+ DWC_WRITE_REG32(&(out_regs->doepdma), - (uint32_t) ep->dma_addr); - } else { - #ifdef DWC_UTE_CFI - /* The descriptor chain should be already initialized by now */ - if (ep->buff_mode != BM_STANDARD) { -- dwc_write_reg32(&out_regs->doepdma, -+ DWC_WRITE_REG32(&out_regs->doepdma, - ep->descs_dma_addr); - } else { - #endif -- -- init_dma_desc_chain(core_if, ep); -- -+ /** This is used for interrupt out transfers*/ -+ if (!ep->xfer_len) -+ ep->xfer_len = ep->total_len; -+ init_dma_desc_chain(core_if, ep); -+ -+ if (core_if->core_params->dev_out_nak) { -+ if (ep->type == DWC_OTG_EP_TYPE_BULK) { -+ deptsiz.b.pktcnt = (ep->total_len + -+ (ep->maxpacket - 1)) / ep->maxpacket; -+ deptsiz.b.xfersize = ep->total_len; -+ /* Remember initial value of doeptsiz */ -+ core_if->start_doeptsiz_val[ep->num] = deptsiz.d32; -+ DWC_WRITE_REG32(&out_regs->doeptsiz, -+ deptsiz.d32); -+ } -+ } - /** DOEPDMAn Register write */ -- dwc_write_reg32(&out_regs->doepdma, -- ep->dma_desc_addr); -+ DWC_WRITE_REG32(&out_regs->doepdma, -+ ep->dma_desc_addr); - #ifdef DWC_UTE_CFI - } - #endif - } - } else { -- dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); -+ } -+ -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) -+ { -+ dsts_data_t dsts = {.d32 = 0}; -+ if (ep->bInterval == 1) { -+ dsts.d32 = -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); -+ ep->frame_num = dsts.b.soffn + ep->bInterval; -+ if (ep->frame_num > 0x3FFF) -+ { -+ ep->frm_overrun = 1; -+ ep->frame_num &= 0x3FFF; -+ } else -+ ep->frm_overrun = 0; -+ -+ if (ep->frame_num & 0x1) { -+ depctl.b.setd1pid = 1; -+ } else { -+ depctl.b.setd0pid = 1; -+ } -+ } - } - - /* EP enable */ - depctl.b.cnak = 1; - depctl.b.epena = 1; - -- dwc_write_reg32(&out_regs->doepctl, depctl.d32); -+ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); - - DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", -- dwc_read_reg32(&out_regs->doepctl), -- dwc_read_reg32(&out_regs->doeptsiz)); -+ DWC_READ_REG32(&out_regs->doepctl), -+ DWC_READ_REG32(&out_regs->doeptsiz)); - DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", -- dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -- daintmsk), -- dwc_read_reg32(&core_if->core_global_regs-> -- gintmsk)); -+ DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->daintmsk), -+ DWC_READ_REG32(&core_if-> -+ core_global_regs->gintmsk)); -+ -+ -+ /* Timer is scheduling only for out bulk transfers for -+ * "Device DDMA OUT NAK Enhancement" feature to inform user -+ * about received data payload in case of timeout -+ */ -+ if (core_if->core_params->dev_out_nak) { -+ if (ep->type == DWC_OTG_EP_TYPE_BULK) { -+ core_if->ep_xfer_info[ep->num].core_if = core_if; -+ core_if->ep_xfer_info[ep->num].ep = ep; -+ core_if->ep_xfer_info[ep->num].state = 1; -+ -+ /* Start a timer for this transfer. */ -+ DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000); -+ } -+ } - } - } - -@@ -2700,8 +3967,8 @@ void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - dwc_otg_dev_in_ep_regs_t *in_regs = - core_if->dev_if->in_ep_regs[ep->num]; - -- depctl.d32 = dwc_read_reg32(&(in_regs->diepctl)); -- deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz)); -+ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); -+ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); - - deptsiz.b.xfersize = 0; - deptsiz.b.pktcnt = 1; -@@ -2709,54 +3976,50 @@ void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - /* Write the DMA register */ - if (core_if->dma_enable) { - if (core_if->dma_desc_enable == 0) { -- dwc_write_reg32(&in_regs->dieptsiz, -+ deptsiz.b.mc = 1; -+ DWC_WRITE_REG32(&in_regs->dieptsiz, - deptsiz.d32); -- dwc_write_reg32(&(in_regs->diepdma), -+ DWC_WRITE_REG32(&(in_regs->diepdma), - (uint32_t) ep->dma_addr); - } - } else { -- dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -- /** -+ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); -+ /** - * Enable the Non-Periodic Tx FIFO empty interrupt, - * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, - * the data will be written into the fifo by the ISR. - */ - if (core_if->en_multiple_tx_fifo == 0) { - intr_mask.b.nptxfempty = 1; -- dwc_modify_reg32(&core_if->core_global_regs-> -- gintmsk, intr_mask.d32, -- intr_mask.d32); -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); - } else { - /* Enable the Tx FIFO Empty Interrupt for this EP */ - if (ep->xfer_len > 0) { - uint32_t fifoemptymsk = 0; - fifoemptymsk = 1 << ep->num; -- dwc_modify_reg32(&core_if->dev_if-> -- dev_global_regs-> -- dtknqr4_fifoemptymsk, -+ DWC_MODIFY_REG32(&core_if-> -+ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, - 0, fifoemptymsk); - } - } - } - -+ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) -+ depctl.b.nextep = core_if->nextep_seq[ep->num]; - /* EP enable, IN data in FIFO */ - depctl.b.cnak = 1; - depctl.b.epena = 1; -- dwc_write_reg32(&in_regs->diepctl, depctl.d32); -- -- depctl.d32 = -- dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -- depctl.b.nextep = ep->num; -- dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl, -- depctl.d32); -+ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); - - } else { - /* OUT endpoint */ - dwc_otg_dev_out_ep_regs_t *out_regs = - core_if->dev_if->out_ep_regs[ep->num]; - -- depctl.d32 = dwc_read_reg32(&(out_regs->doepctl)); -- deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz)); -+ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); -+ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); - - /* Zero Length Packet */ - deptsiz.b.xfersize = ep->maxpacket; -@@ -2764,21 +4027,21 @@ void dwc_otg_ep_start_zl_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - if (core_if->dma_enable) { - if (!core_if->dma_desc_enable) { -- dwc_write_reg32(&out_regs->doeptsiz, -+ DWC_WRITE_REG32(&out_regs->doeptsiz, - deptsiz.d32); - -- dwc_write_reg32(&(out_regs->doepdma), -+ DWC_WRITE_REG32(&(out_regs->doepdma), - (uint32_t) ep->dma_addr); - } - } else { -- dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); - } - - /* EP enable */ - depctl.b.cnak = 1; - depctl.b.epena = 1; - -- dwc_write_reg32(&out_regs->doepctl, depctl.d32); -+ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); - - } - } -@@ -2814,14 +4077,15 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - gnptxsts_data_t gtxstatus; - - gtxstatus.d32 = -- dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); - - if (core_if->en_multiple_tx_fifo == 0 -- && gtxstatus.b.nptxqspcavail == 0) { -+ && gtxstatus.b.nptxqspcavail == 0 -+ && !core_if->dma_enable) { - #ifdef DEBUG -- deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); - DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", -- dwc_read_reg32(&in_regs->diepctl)); -+ DWC_READ_REG32(&in_regs->diepctl)); - DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", - deptsiz.d32, - deptsiz.b.xfersize, deptsiz.b.pktcnt); -@@ -2831,8 +4095,8 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - return; - } - -- depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -- deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); -+ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); - - /* Zero Length Packet? */ - if (ep->xfer_len == 0) { -@@ -2842,7 +4106,7 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - /* Program the transfer size and packet count - * as follows: xfersize = N * maxpacket + - * short_packet pktcnt = N + (short_packet -- * exist ? 1 : 0) -+ * exist ? 1 : 0) - */ - if (ep->xfer_len > ep->maxpacket) { - ep->xfer_len = ep->maxpacket; -@@ -2861,10 +4125,10 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - /* Write the DMA register */ - if (core_if->dma_enable) { - if (core_if->dma_desc_enable == 0) { -- dwc_write_reg32(&in_regs->dieptsiz, -+ DWC_WRITE_REG32(&in_regs->dieptsiz, - deptsiz.d32); - -- dwc_write_reg32(&(in_regs->diepdma), -+ DWC_WRITE_REG32(&(in_regs->diepdma), - (uint32_t) ep->dma_addr); - } else { - dma_desc = core_if->dev_if->in_desc_addr; -@@ -2877,40 +4141,42 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - (ep->xfer_len == ep->maxpacket) ? 0 : 1; - dma_desc->status.b.bytes = ep->xfer_len; - dma_desc->buf = ep->dma_addr; -+ dma_desc->status.b.sts = 0; - dma_desc->status.b.bs = BS_HOST_READY; - - /** DIEPDMA0 Register write */ -- dwc_write_reg32(&in_regs->diepdma, -- core_if->dev_if-> -- dma_in_desc_addr); -+ DWC_WRITE_REG32(&in_regs->diepdma, -+ core_if-> -+ dev_if->dma_in_desc_addr); - } - } else { -- dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); - } - -+ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) -+ depctl.b.nextep = core_if->nextep_seq[ep->num]; - /* EP enable, IN data in FIFO */ - depctl.b.cnak = 1; - depctl.b.epena = 1; -- dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); - -- /** -+ /** - * Enable the Non-Periodic Tx FIFO empty interrupt, the - * data will be written into the fifo by the ISR. - */ - if (!core_if->dma_enable) { - if (core_if->en_multiple_tx_fifo == 0) { - intr_mask.b.nptxfempty = 1; -- dwc_modify_reg32(&core_if->core_global_regs-> -- gintmsk, intr_mask.d32, -- intr_mask.d32); -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); - } else { - /* Enable the Tx FIFO Empty Interrupt for this EP */ - if (ep->xfer_len > 0) { - uint32_t fifoemptymsk = 0; - fifoemptymsk |= 1 << ep->num; -- dwc_modify_reg32(&core_if->dev_if-> -- dev_global_regs-> -- dtknqr4_fifoemptymsk, -+ DWC_MODIFY_REG32(&core_if-> -+ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, - 0, fifoemptymsk); - } - } -@@ -2920,8 +4186,8 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - dwc_otg_dev_out_ep_regs_t *out_regs = - core_if->dev_if->out_ep_regs[0]; - -- depctl.d32 = dwc_read_reg32(&out_regs->doepctl); -- deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz); -+ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); -+ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); - - /* Program the transfer size and packet count as follows: - * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) -@@ -2935,10 +4201,10 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - if (core_if->dma_enable) { - if (!core_if->dma_desc_enable) { -- dwc_write_reg32(&out_regs->doeptsiz, -+ DWC_WRITE_REG32(&out_regs->doeptsiz, - deptsiz.d32); - -- dwc_write_reg32(&(out_regs->doepdma), -+ DWC_WRITE_REG32(&(out_regs->doepdma), - (uint32_t) ep->dma_addr); - } else { - dma_desc = core_if->dev_if->out_desc_addr; -@@ -2949,21 +4215,22 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - dma_desc->status.b.ioc = 1; - dma_desc->status.b.bytes = ep->maxpacket; - dma_desc->buf = ep->dma_addr; -+ dma_desc->status.b.sts = 0; - dma_desc->status.b.bs = BS_HOST_READY; - - /** DOEPDMA0 Register write */ -- dwc_write_reg32(&out_regs->doepdma, -- core_if->dev_if-> -- dma_out_desc_addr); -+ DWC_WRITE_REG32(&out_regs->doepdma, -+ core_if-> -+ dev_if->dma_out_desc_addr); - } - } else { -- dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); - } - - /* EP enable */ - depctl.b.cnak = 1; - depctl.b.epena = 1; -- dwc_write_reg32(&(out_regs->doepctl), depctl.d32); -+ DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32); - } - } - -@@ -2989,17 +4256,17 @@ void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - gnptxsts_data_t tx_status = {.d32 = 0 }; - - tx_status.d32 = -- dwc_read_reg32(&core_if->core_global_regs->gnptxsts); -+ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); - /** @todo Should there be check for room in the Tx - * Status Queue. If not remove the code above this comment. */ - -- depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -- deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); -+ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); -+ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); - - /* Program the transfer size and packet count - * as follows: xfersize = N * maxpacket + - * short_packet pktcnt = N + (short_packet -- * exist ? 1 : 0) -+ * exist ? 1 : 0) - */ - - if (core_if->dma_desc_enable == 0) { -@@ -3013,7 +4280,7 @@ void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - } else { - ep->xfer_len = deptsiz.b.xfersize; - } -- dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); - } else { - ep->xfer_len = - (ep->total_len - ep->xfer_count) > -@@ -3030,10 +4297,11 @@ void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - (ep->xfer_len == ep->maxpacket) ? 0 : 1; - dma_desc->status.b.bytes = ep->xfer_len; - dma_desc->buf = ep->dma_addr; -+ dma_desc->status.b.sts = 0; - dma_desc->status.b.bs = BS_HOST_READY; - - /** DIEPDMA0 Register write */ -- dwc_write_reg32(&in_regs->diepdma, -+ DWC_WRITE_REG32(&in_regs->diepdma, - core_if->dev_if->dma_in_desc_addr); - } - -@@ -3045,16 +4313,17 @@ void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - /* Write the DMA register */ - if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { - if (core_if->dma_desc_enable == 0) -- dwc_write_reg32(&(in_regs->diepdma), -+ DWC_WRITE_REG32(&(in_regs->diepdma), - (uint32_t) ep->dma_addr); - } -- -+ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) -+ depctl.b.nextep = core_if->nextep_seq[ep->num]; - /* EP enable, IN data in FIFO */ - depctl.b.cnak = 1; - depctl.b.epena = 1; -- dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); - -- /** -+ /** - * Enable the Non-Periodic Tx FIFO empty interrupt, the - * data will be written into the fifo by the ISR. - */ -@@ -3062,18 +4331,17 @@ void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - if (core_if->en_multiple_tx_fifo == 0) { - /* First clear it from GINTSTS */ - intr_mask.b.nptxfempty = 1; -- dwc_modify_reg32(&core_if->core_global_regs-> -- gintmsk, intr_mask.d32, -- intr_mask.d32); -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); - - } else { - /* Enable the Tx FIFO Empty Interrupt for this EP */ - if (ep->xfer_len > 0) { - uint32_t fifoemptymsk = 0; - fifoemptymsk |= 1 << ep->num; -- dwc_modify_reg32(&core_if->dev_if-> -- dev_global_regs-> -- dtknqr4_fifoemptymsk, -+ DWC_MODIFY_REG32(&core_if-> -+ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, - 0, fifoemptymsk); - } - } -@@ -3082,19 +4350,19 @@ void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - dwc_otg_dev_out_ep_regs_t *out_regs = - core_if->dev_if->out_ep_regs[0]; - -- depctl.d32 = dwc_read_reg32(&out_regs->doepctl); -- deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz); -+ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); -+ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); - - /* Program the transfer size and packet count - * as follows: xfersize = N * maxpacket + - * short_packet pktcnt = N + (short_packet -- * exist ? 1 : 0) -+ * exist ? 1 : 0) - */ - deptsiz.b.xfersize = ep->maxpacket; - deptsiz.b.pktcnt = 1; - - if (core_if->dma_desc_enable == 0) { -- dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); - } else { - dma_desc = core_if->dev_if->out_desc_addr; - -@@ -3104,10 +4372,11 @@ void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - dma_desc->status.b.ioc = 1; - dma_desc->status.b.bytes = ep->maxpacket; - dma_desc->buf = ep->dma_addr; -+ dma_desc->status.b.sts = 0; - dma_desc->status.b.bs = BS_HOST_READY; - - /** DOEPDMA0 Register write */ -- dwc_write_reg32(&out_regs->doepdma, -+ DWC_WRITE_REG32(&out_regs->doepdma, - core_if->dev_if->dma_out_desc_addr); - } - -@@ -3119,14 +4388,15 @@ void dwc_otg_ep0_continue_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - /* Write the DMA register */ - if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { - if (core_if->dma_desc_enable == 0) -- dwc_write_reg32(&(out_regs->doepdma), -+ DWC_WRITE_REG32(&(out_regs->doepdma), - (uint32_t) ep->dma_addr); -+ - } - - /* EP enable, IN data in FIFO */ - depctl.b.cnak = 1; - depctl.b.epena = 1; -- dwc_write_reg32(&out_regs->doepctl, depctl.d32); -+ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); - - } - } -@@ -3164,7 +4434,7 @@ static inline void dump_msg(const u8 * buf, unsigned int length) - - /** - * This function writes a packet into the Tx FIFO associated with the -- * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For -+ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For - * periodic EPs the periodic Tx FIFO associated with the EP is written - * with all packets for the next micro-frame. - * -@@ -3177,15 +4447,15 @@ void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep, - { - /** - * The buffer is padded to DWORD on a per packet basis in -- * slave/dma mode if the MPS is not DWORD aligned. The last -+ * slave/dma mode if the MPS is not DWORD aligned. The last - * packet, if short, is also padded to a multiple of DWORD. - * -- * ep->xfer_buff always starts DWORD aligned in memory and is a -+ * ep->xfer_buff always starts DWORD aligned in memory and is a - * multiple of DWORD in length - * - * ep->xfer_len can be any number of bytes - * -- * ep->xfer_count is a multiple of ep->maxpacket until the last -+ * ep->xfer_count is a multiple of ep->maxpacket until the last - * packet - * - * FIFO access is DWORD */ -@@ -3228,7 +4498,7 @@ void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep, - - if (!dma) { - for (i = 0; i < dword_count; i++, data_buff++) { -- dwc_write_reg32(fifo, *data_buff); -+ DWC_WRITE_REG32(fifo, *data_buff); - } - } - -@@ -3237,7 +4507,7 @@ void dwc_otg_ep_write_packet(dwc_otg_core_if_t * core_if, dwc_ep_t * ep, - ep->dma_addr += byte_count; - } - --/** -+/** - * Set the EP STALL. - * - * @param core_if Programming view of DWC_otg controller. -@@ -3253,29 +4523,29 @@ void dwc_otg_ep_set_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - if (ep->is_in == 1) { - depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); -- depctl.d32 = dwc_read_reg32(depctl_addr); -+ depctl.d32 = DWC_READ_REG32(depctl_addr); - - /* set the disable and stall bits */ - if (depctl.b.epena) { - depctl.b.epdis = 1; - } - depctl.b.stall = 1; -- dwc_write_reg32(depctl_addr, depctl.d32); -+ DWC_WRITE_REG32(depctl_addr, depctl.d32); - } else { - depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); -- depctl.d32 = dwc_read_reg32(depctl_addr); -+ depctl.d32 = DWC_READ_REG32(depctl_addr); - - /* set the stall bit */ - depctl.b.stall = 1; -- dwc_write_reg32(depctl_addr, depctl.d32); -+ DWC_WRITE_REG32(depctl_addr, depctl.d32); - } - -- DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); -+ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); - - return; - } - --/** -+/** - * Clear the EP STALL. - * - * @param core_if Programming view of DWC_otg controller. -@@ -3295,12 +4565,12 @@ void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); - } - -- depctl.d32 = dwc_read_reg32(depctl_addr); -+ depctl.d32 = DWC_READ_REG32(depctl_addr); - - /* clear the stall bits */ - depctl.b.stall = 0; - -- /* -+ /* - * USB Spec 9.4.5: For endpoints using data toggle, regardless - * of whether an endpoint has the Halt feature set, a - * ClearFeature(ENDPOINT_HALT) request always results in the -@@ -3311,14 +4581,14 @@ void dwc_otg_ep_clear_stall(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - depctl.b.setd0pid = 1; /* DATA0 */ - } - -- dwc_write_reg32(depctl_addr, depctl.d32); -- DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); -+ DWC_WRITE_REG32(depctl_addr, depctl.d32); -+ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); - return; - } - --/** -+/** - * This function reads a packet from the Rx FIFO into the destination -- * buffer. To read SETUP data use dwc_otg_read_setup_packet. -+ * buffer. To read SETUP data use dwc_otg_read_setup_packet. - * - * @param core_if Programming view of DWC_otg controller. - * @param dest Destination buffer for the packet. -@@ -3343,7 +4613,7 @@ void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, - core_if, dest, bytes); - - for (i = 0; i < word_count; i++, data_buff++) { -- *data_buff = dwc_read_reg32(fifo); -+ *data_buff = DWC_READ_REG32(fifo); - } - - return; -@@ -3361,119 +4631,125 @@ void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if) - - DWC_PRINTF("Device Global Registers\n"); - addr = &core_if->dev_if->dev_global_regs->dcfg; -- DWC_PRINTF("DCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n", (unsigned long) addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->dctl; -- DWC_PRINTF("DCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n", (unsigned long) addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->dsts; -- DWC_PRINTF("DSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n", (unsigned long) addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->diepmsk; -- DWC_PRINTF("DIEPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->doepmsk; -- DWC_PRINTF("DOEPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DOEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->daint; -- DWC_PRINTF("DAINT @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->daintmsk; -- DWC_PRINTF("DAINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->dtknqr1; -- DWC_PRINTF("DTKNQR1 @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DTKNQR1 @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - if (core_if->hwcfg2.b.dev_token_q_depth > 6) { - addr = &core_if->dev_if->dev_global_regs->dtknqr2; -- DWC_PRINTF("DTKNQR2 @0x%08X : 0x%08X\n", -- (uint32_t) addr, dwc_read_reg32(addr)); -+ DWC_PRINTF("DTKNQR2 @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - } - - addr = &core_if->dev_if->dev_global_regs->dvbusdis; -- DWC_PRINTF("DVBUSID @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DVBUSID @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - - addr = &core_if->dev_if->dev_global_regs->dvbuspulse; -- DWC_PRINTF("DVBUSPULSE @0x%08X : 0x%08X\n", -- (uint32_t) addr, dwc_read_reg32(addr)); -+ DWC_PRINTF("DVBUSPULSE @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - -- addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; -- DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08X : 0x%08X\n", -- (uint32_t) addr, dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; -+ DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - - if (core_if->hwcfg2.b.dev_token_q_depth > 22) { - addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; -- DWC_PRINTF("DTKNQR4 @0x%08X : 0x%08X\n", -- (uint32_t) addr, dwc_read_reg32(addr)); -+ DWC_PRINTF("DTKNQR4 @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - } - - addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; -- DWC_PRINTF("FIFOEMPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -- -- addr = &core_if->dev_if->dev_global_regs->deachint; -- DWC_PRINTF("DEACHINT @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -- addr = &core_if->dev_if->dev_global_regs->deachintmsk; -- DWC_PRINTF("DEACHINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -- -- for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { -- addr = &core_if->dev_if->dev_global_regs->diepeachintmsk[i]; -- DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08X : 0x%08X\n", i, -- (uint32_t) addr, dwc_read_reg32(addr)); -- } -+ DWC_PRINTF("FIFOEMPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); -+ -+ if (core_if->hwcfg2.b.multi_proc_int) { -+ -+ addr = &core_if->dev_if->dev_global_regs->deachint; -+ DWC_PRINTF("DEACHINT @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->deachintmsk; -+ DWC_PRINTF("DEACHINTMSK @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); -+ -+ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { -+ addr = -+ &core_if->dev_if->dev_global_regs-> -+ diepeachintmsk[i]; -+ DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", -+ i, (unsigned long)addr, -+ DWC_READ_REG32(addr)); -+ } - -- for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { -- addr = &core_if->dev_if->dev_global_regs->doepeachintmsk[i]; -- DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08X : 0x%08X\n", i, -- (uint32_t) addr, dwc_read_reg32(addr)); -+ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { -+ addr = -+ &core_if->dev_if->dev_global_regs-> -+ doepeachintmsk[i]; -+ DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", -+ i, (unsigned long)addr, -+ DWC_READ_REG32(addr)); -+ } - } - - for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { - DWC_PRINTF("Device IN EP %d Registers\n", i); - addr = &core_if->dev_if->in_ep_regs[i]->diepctl; -- DWC_PRINTF("DIEPCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DIEPCTL @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->in_ep_regs[i]->diepint; -- DWC_PRINTF("DIEPINT @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DIEPINT @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; -- DWC_PRINTF("DIETSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DIETSIZ @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->in_ep_regs[i]->diepdma; -- DWC_PRINTF("DIEPDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DIEPDMA @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts; -- DWC_PRINTF("DTXFSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DTXFSTS @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->in_ep_regs[i]->diepdmab; -- DWC_PRINTF("DIEPDMAB @0x%08X : 0x%08X\n", (uint32_t) addr, -- 0 /*dwc_read_reg32(addr) */ ); -+ DWC_PRINTF("DIEPDMAB @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ ); - } - - for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { - DWC_PRINTF("Device OUT EP %d Registers\n", i); - addr = &core_if->dev_if->out_ep_regs[i]->doepctl; -- DWC_PRINTF("DOEPCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -- addr = &core_if->dev_if->out_ep_regs[i]->doepfn; -- DWC_PRINTF("DOEPFN @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DOEPCTL @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->out_ep_regs[i]->doepint; -- DWC_PRINTF("DOEPINT @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DOEPINT @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; -- DWC_PRINTF("DOETSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DOETSIZ @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->out_ep_regs[i]->doepdma; -- DWC_PRINTF("DOEPDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("DOEPDMA @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */ - addr = &core_if->dev_if->out_ep_regs[i]->doepdmab; -- DWC_PRINTF("DOEPDMAB @0x%08X : 0x%08X\n", -- (uint32_t) addr, dwc_read_reg32(addr)); -+ DWC_PRINTF("DOEPDMAB @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - } - - } -@@ -3490,15 +4766,15 @@ void dwc_otg_dump_spram(dwc_otg_core_if_t * core_if) - - DWC_PRINTF("SPRAM Data:\n"); - start_addr = (void *)core_if->core_global_regs; -- DWC_PRINTF("Base Address: 0x%8X\n", (uint32_t) start_addr); -+ DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr); - start_addr += 0x00028000; - end_addr = (void *)core_if->core_global_regs; - end_addr += 0x000280e0; - - for (addr = start_addr; addr < end_addr; addr += 16) { - DWC_PRINTF -- ("0x%8X:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", -- (uint32_t) addr, addr[0], addr[1], addr[2], addr[3], -+ ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", -+ (unsigned long)addr, addr[0], addr[1], addr[2], addr[3], - addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], - addr[10], addr[11], addr[12], addr[13], addr[14], addr[15] - ); -@@ -3519,57 +4795,58 @@ void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if) - - DWC_PRINTF("Host Global Registers\n"); - addr = &core_if->host_if->host_global_regs->hcfg; -- DWC_PRINTF("HCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HCFG @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->host_if->host_global_regs->hfir; -- DWC_PRINTF("HFIR @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HFIR @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->host_if->host_global_regs->hfnum; -- DWC_PRINTF("HFNUM @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HFNUM @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->host_if->host_global_regs->hptxsts; -- DWC_PRINTF("HPTXSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->host_if->host_global_regs->haint; -- DWC_PRINTF("HAINT @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->host_if->host_global_regs->haintmsk; -- DWC_PRINTF("HAINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - if (core_if->dma_desc_enable) { - addr = &core_if->host_if->host_global_regs->hflbaddr; -- DWC_PRINTF("HFLBADDR @0x%08X : 0x%08X\n",(uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HFLBADDR @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - } -- -+ - addr = core_if->host_if->hprt0; -- DWC_PRINTF("HPRT0 @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HPRT0 @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - - for (i = 0; i < core_if->core_params->host_channels; i++) { - DWC_PRINTF("Host Channel %d Specific Registers\n", i); - addr = &core_if->host_if->hc_regs[i]->hcchar; -- DWC_PRINTF("HCCHAR @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HCCHAR @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->host_if->hc_regs[i]->hcsplt; -- DWC_PRINTF("HCSPLT @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HCSPLT @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->host_if->hc_regs[i]->hcint; -- DWC_PRINTF("HCINT @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HCINT @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->host_if->hc_regs[i]->hcintmsk; -- DWC_PRINTF("HCINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HCINTMSK @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->host_if->hc_regs[i]->hctsiz; -- DWC_PRINTF("HCTSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HCTSIZ @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->host_if->hc_regs[i]->hcdma; -- DWC_PRINTF("HCDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HCDMA @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - if (core_if->dma_desc_enable) { -- addr=&core_if->host_if->hc_regs[i]->hcdmab; -- DWC_PRINTF("HCDMAB @0x%08X : 0x%08X\n",(uint32_t) addr, dwc_read_reg32(addr)); -- } -+ addr = &core_if->host_if->hc_regs[i]->hcdmab; -+ DWC_PRINTF("HCDMAB @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); -+ } - - } - return; -@@ -3582,85 +4859,102 @@ void dwc_otg_dump_host_registers(dwc_otg_core_if_t * core_if) - */ - void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if) - { -- int i; -+ int i, ep_num; - volatile uint32_t *addr; -+ char *txfsiz; - - DWC_PRINTF("Core Global Registers\n"); - addr = &core_if->core_global_regs->gotgctl; -- DWC_PRINTF("GOTGCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GOTGCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gotgint; -- DWC_PRINTF("GOTGINT @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GOTGINT @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gahbcfg; -- DWC_PRINTF("GAHBCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GAHBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gusbcfg; -- DWC_PRINTF("GUSBCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GUSBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->grstctl; -- DWC_PRINTF("GRSTCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GRSTCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gintsts; -- DWC_PRINTF("GINTSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GINTSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gintmsk; -- DWC_PRINTF("GINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->grxstsr; -- DWC_PRINTF("GRXSTSR @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GRXSTSR @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->grxfsiz; -- DWC_PRINTF("GRXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GRXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gnptxfsiz; -- DWC_PRINTF("GNPTXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gnptxsts; -- DWC_PRINTF("GNPTXSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GNPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gi2cctl; -- DWC_PRINTF("GI2CCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GI2CCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gpvndctl; -- DWC_PRINTF("GPVNDCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GPVNDCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->ggpio; -- DWC_PRINTF("GGPIO @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GGPIO @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->guid; -- DWC_PRINTF("GUID @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GUID @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->gsnpsid; -- DWC_PRINTF("GSNPSID @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GSNPSID @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->ghwcfg1; -- DWC_PRINTF("GHWCFG1 @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GHWCFG1 @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->ghwcfg2; -- DWC_PRINTF("GHWCFG2 @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GHWCFG2 @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->ghwcfg3; -- DWC_PRINTF("GHWCFG3 @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GHWCFG3 @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->ghwcfg4; -- DWC_PRINTF("GHWCFG4 @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GHWCFG4 @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - addr = &core_if->core_global_regs->glpmcfg; -- DWC_PRINTF("GLPMCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("GLPMCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); -+ addr = &core_if->core_global_regs->gpwrdn; -+ DWC_PRINTF("GPWRDN @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); -+ addr = &core_if->core_global_regs->gdfifocfg; -+ DWC_PRINTF("GDFIFOCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); -+ addr = &core_if->core_global_regs->adpctl; -+ DWC_PRINTF("ADPCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ dwc_otg_adp_read_reg(core_if)); - addr = &core_if->core_global_regs->hptxfsiz; -- DWC_PRINTF("HPTXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("HPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - -- for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { -- addr = &core_if->core_global_regs->dptxfsiz_dieptxf[i]; -- DWC_PRINTF("DPTXFSIZ[%d] @0x%08X : 0x%08X\n", i, -- (uint32_t) addr, dwc_read_reg32(addr)); -+ if (core_if->en_multiple_tx_fifo == 0) { -+ ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep; -+ txfsiz = "DPTXFSIZ"; -+ } else { -+ ep_num = core_if->hwcfg4.b.num_in_eps; -+ txfsiz = "DIENPTXF"; -+ } -+ for (i = 0; i < ep_num; i++) { -+ addr = &core_if->core_global_regs->dtxfsiz[i]; -+ DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1, -+ (unsigned long)addr, DWC_READ_REG32(addr)); - } - addr = core_if->pcgcctl; -- DWC_PRINTF("PCGCCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -- dwc_read_reg32(addr)); -+ DWC_PRINTF("PCGCCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, -+ DWC_READ_REG32(addr)); - } - - /** -@@ -3679,14 +4973,14 @@ void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num) - - greset.b.txfflsh = 1; - greset.b.txfnum = num; -- dwc_write_reg32(&global_regs->grstctl, greset.d32); -+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); - - do { -- greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); - if (++count > 10000) { - DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", - __func__, greset.d32, -- dwc_read_reg32(&global_regs->gnptxsts)); -+ DWC_READ_REG32(&global_regs->gnptxsts)); - break; - } - dwc_udelay(1); -@@ -3709,13 +5003,13 @@ void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t * core_if) - - DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__); - /* -- * -+ * - */ - greset.b.rxfflsh = 1; -- dwc_write_reg32(&global_regs->grstctl, greset.d32); -+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); - - do { -- greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); - if (++count > 10000) { - DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, - greset.d32); -@@ -3742,7 +5036,7 @@ void dwc_otg_core_reset(dwc_otg_core_if_t * core_if) - /* Wait for AHB master IDLE state. */ - do { - dwc_udelay(10); -- greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); - if (++count > 100000) { - DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__, - greset.d32); -@@ -3754,9 +5048,9 @@ void dwc_otg_core_reset(dwc_otg_core_if_t * core_if) - /* Core Soft Reset */ - count = 0; - greset.b.csftrst = 1; -- dwc_write_reg32(&global_regs->grstctl, greset.d32); -+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); - do { -- greset.d32 = dwc_read_reg32(&global_regs->grstctl); -+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); - if (++count > 10000) { - DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", - __func__, greset.d32); -@@ -3781,7 +5075,7 @@ uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t * _core_if) - } - - /** -- * Register HCD callbacks. The callbacks are used to start and stop -+ * Register HCD callbacks. The callbacks are used to start and stop - * the HCD for interrupt processing. - * - * @param core_if Programming view of DWC_otg controller. -@@ -3796,7 +5090,7 @@ void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * core_if, - } - - /** -- * Register PCD callbacks. The callbacks are used to start and stop -+ * Register PCD callbacks. The callbacks are used to start and stop - * the PCD for interrupt processing. - * - * @param core_if Programming view of DWC_otg controller. -@@ -3842,7 +5136,7 @@ void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - /* While there is space in the queue and space in the FIFO and - * More data to tranfer, Write packets to the Tx FIFO */ - txstatus.d32 = -- dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); -+ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); - DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32); - - while (txstatus.b.txfspcavail > dwords && -@@ -3857,8 +5151,8 @@ void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - dwords = (len + 3) / 4; - txstatus.d32 = -- dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -- dtxfsts); -+ DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[ep->num]->dtxfsts); - DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num, - txstatus.d32); - } -@@ -3894,18 +5188,18 @@ void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, - /* Program the transfer size and packet count - * as follows: xfersize = N * maxpacket + - * short_packet pktcnt = N + (short_packet -- * exist ? 1 : 0) -+ * exist ? 1 : 0) - */ - deptsiz.b.xfersize = ep->xfer_len; - deptsiz.b.pktcnt = - (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; - deptsiz.b.mc = deptsiz.b.pktcnt; -- dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, - deptsiz.d32); - - /* Write the DMA register */ - if (core_if->dma_enable) { -- dwc_write_reg32(& -+ DWC_WRITE_REG32(& - (core_if->dev_if->in_ep_regs[ep->num]-> - diepdma), (uint32_t) ep->dma_addr); - } -@@ -3914,11 +5208,11 @@ void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, - (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; - deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; - -- dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> - doeptsiz, deptsiz.d32); - - if (core_if->dma_enable) { -- dwc_write_reg32(& -+ DWC_WRITE_REG32(& - (core_if->dev_if->out_ep_regs[ep->num]-> - doepdma), (uint32_t) ep->dma_addr); - } -@@ -3929,7 +5223,7 @@ void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, - depctl.d32 = 0; - if (ep->bInterval == 1) { - dsts.d32 = -- dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - ep->next_frame = dsts.b.soffn + ep->bInterval; - - if (ep->next_frame & 0x1) { -@@ -3949,15 +5243,15 @@ void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, - depctl.b.epena = 1; - depctl.b.cnak = 1; - -- dwc_modify_reg32(addr, 0, depctl.d32); -- depctl.d32 = dwc_read_reg32(addr); -+ DWC_MODIFY_REG32(addr, 0, depctl.d32); -+ depctl.d32 = DWC_READ_REG32(addr); - - if (ep->is_in && core_if->dma_enable == 0) { - write_isoc_frame_data(core_if, ep); - } - - } --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ - - static void dwc_otg_set_uninitialized(int32_t * p, int size) - { -@@ -4048,8 +5342,17 @@ static int dwc_otg_setup_params(dwc_otg_core_if_t * 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); -+ dwc_otg_set_param_ahb_thr_ratio(core_if, -+ dwc_param_ahb_thr_ratio_default); -+ dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default); -+ dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default); -+ dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default); -+ dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default); -+ dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default); -+ dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default); -+ dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default); - DWC_PRINTF("Finished setting default values for core params\n"); -+ - return 0; - } - -@@ -4090,7 +5393,7 @@ int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val) - && (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_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) { - valid = 0; - } - break; -@@ -4119,7 +5422,7 @@ int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t * core_if, int32_t val) - } - - core_if->core_params->otg_cap = val; -- out: -+out: - return retval; - } - -@@ -4288,11 +5591,11 @@ int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val) - return -DWC_E_INVALID; - } - -- if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) { -- if(dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) { -+ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { -+ if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) { - DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val); - } -- val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz); -+ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); - retval = -DWC_E_INVALID; - } - -@@ -4316,7 +5619,7 @@ int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if, - return -DWC_E_INVALID; - } - -- if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { -+ 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)) { - DWC_ERROR -@@ -4324,7 +5627,7 @@ int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if, - val); - } - val = -- (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> -+ (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> - 16); - retval = -DWC_E_INVALID; - } -@@ -4349,14 +5652,14 @@ int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t * core_if, - return -DWC_E_INVALID; - } - -- if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) { -+ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { - if (dwc_otg_param_initialized - (core_if->core_params->host_rx_fifo_size)) { - DWC_ERROR - ("%d invalid for host_rx_fifo_size. Check HW configuration.\n", - val); - } -- val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz); -+ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); - retval = -DWC_E_INVALID; - } - -@@ -4381,7 +5684,7 @@ int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if, - return -DWC_E_INVALID; - } - -- if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { -+ 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)) { - DWC_ERROR -@@ -4389,7 +5692,7 @@ int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t * core_if, - val); - } - val = -- (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> -+ (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> - 16); - retval = -DWC_E_INVALID; - } -@@ -4414,16 +5717,14 @@ int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, - } - - if (val > -- ((dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16))) { -+ ((core_if->hptxfsiz.d32)>> 16)) { - if (dwc_otg_param_initialized - (core_if->core_params->host_perio_tx_fifo_size)) { - DWC_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); -+ val = (core_if->hptxfsiz.d32) >> 16; - retval = -DWC_E_INVALID; - } - -@@ -4652,9 +5953,11 @@ int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t * core_if, - - 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)) { -- DWC_ERROR("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n", -- val); -+ if (dwc_otg_param_initialized -+ (core_if->core_params->host_ls_low_power_phy_clk)) { -+ DWC_ERROR -+ ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n", -+ val); - } - val = - (dwc_otg_get_param_phy_type(core_if) == -@@ -4769,9 +6072,10 @@ int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t * core_if, int32_t val) - } - #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)) { -- DWC_ERROR("%d invalid for i2c_enable. Check HW configuration.\n", -- val); -+ if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) { -+ DWC_ERROR -+ ("%d invalid for i2c_enable. Check HW configuration.\n", -+ val); - } - val = 0; - retval = -DWC_E_INVALID; -@@ -4798,12 +6102,15 @@ int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, - return -DWC_E_INVALID; - } - -- 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])) { -- DWC_ERROR("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", -- val, fifo_num); -+ if (val > -+ (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) { -+ DWC_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])); -+ val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num])); - retval = -DWC_E_INVALID; - } - -@@ -4828,9 +6135,11 @@ int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t * core_if, - } - - if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) { -- if(dwc_otg_param_initialized(core_if->core_params->en_multiple_tx_fifo)) { -- DWC_ERROR("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", -- val); -+ if (dwc_otg_param_initialized -+ (core_if->core_params->en_multiple_tx_fifo)) { -+ DWC_ERROR -+ ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", -+ val); - } - val = 0; - retval = -DWC_E_INVALID; -@@ -4856,12 +6165,15 @@ int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, int32_t val, - return -DWC_E_INVALID; - } - -- 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])) { -- DWC_ERROR("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n", -- val, fifo_num); -+ if (val > -+ (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->dev_tx_fifo_size[fifo_num])) { -+ DWC_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])); -+ val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num])); - retval = -DWC_E_INVALID; - } - -@@ -4888,9 +6200,10 @@ int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t * core_if, int32_t val) - 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)) { -- DWC_ERROR("%d invalid for parameter thr_ctl. Check HW configuration.\n", -- val); -+ if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) { -+ DWC_ERROR -+ ("%d invalid for parameter thr_ctl. Check HW configuration.\n", -+ val); - } - val = 0; - retval = -DWC_E_INVALID; -@@ -4916,9 +6229,10 @@ int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t * core_if, int32_t val) - } - - if (val && !core_if->hwcfg3.b.otg_lpm_en) { -- if(dwc_otg_param_initialized(core_if->core_params->lpm_enable)) { -- DWC_ERROR("%d invalid for parameter lpm_enable. Check HW configuration.\n", -- val); -+ if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) { -+ DWC_ERROR -+ ("%d invalid for parameter lpm_enable. Check HW configuration.\n", -+ val); - } - val = 0; - retval = -DWC_E_INVALID; -@@ -4998,7 +6312,8 @@ int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t * core_if, int32_t val) - } - if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) { - if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) { -- DWC_ERROR("%d invalid for parameter pti_enable. Check HW configuration.\n", -+ DWC_ERROR -+ ("%d invalid for parameter pti_enable. Check HW configuration.\n", - val); - } - retval = -DWC_E_INVALID; -@@ -5022,7 +6337,8 @@ int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, int32_t val) - } - if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) { - if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) { -- DWC_ERROR("%d invalid for parameter mpi_enable. Check HW configuration.\n", -+ DWC_ERROR -+ ("%d invalid for parameter mpi_enable. Check HW configuration.\n", - val); - } - retval = -DWC_E_INVALID; -@@ -5037,8 +6353,37 @@ 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 dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val) -+{ -+ int retval = 0; -+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { -+ DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val); -+ return -DWC_E_INVALID; -+ } -+ if (val && (core_if->hwcfg3.b.adp_supp == 0)) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->adp_supp_enable)) { -+ DWC_ERROR -+ ("%d invalid for parameter adp_enable. Check HW configuration.\n", -+ val); -+ } -+ retval = -DWC_E_INVALID; -+ val = 0; -+ } -+ core_if->core_params->adp_supp_enable = val; -+ /*Set OTG version 2.0 in case of enabling ADP*/ -+ if (val) -+ dwc_otg_set_param_otg_ver(core_if, 1); -+ -+ return retval; -+} -+ -+int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->core_params->adp_supp_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)) { -@@ -5047,9 +6392,10 @@ int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, - return -DWC_E_INVALID; - } - -- if (val && (core_if->hwcfg3.b.otg_enable_ic_usb == 0)) { -+ if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) { - if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) { -- DWC_ERROR("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", -+ DWC_ERROR -+ ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", - val); - } - retval = -DWC_E_INVALID; -@@ -5058,6 +6404,7 @@ int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, - 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; -@@ -5068,20 +6415,27 @@ 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)) { -+ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { - DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val); - DWC_WARN("ahb_thr_ratio must be 0 - 3\n"); - return -DWC_E_INVALID; - } - -- if(val && (core_if->snpsid < OTG_CORE_REV_2_81a || !dwc_otg_get_param_thr_ctl(core_if))) { -+ 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)) { -+ } 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)) { -- DWC_ERROR("%d invalid for parameter ahb_thr_ratio. Chack HW configuration.\n", val); -+ if (valid == 0) { -+ if (dwc_otg_param_initialized -+ (core_if->core_params->ahb_thr_ratio)) { -+ DWC_ERROR -+ ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n", -+ val); - } - retval = -DWC_E_INVALID; - val = 0; -@@ -5090,32 +6444,214 @@ int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val) - 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; - } - -+int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val) -+{ -+ int retval = 0; -+ int valid = 1; -+ -+ if (DWC_OTG_PARAM_TEST(val, 0, 2)) { -+ DWC_WARN("`%d' invalid for parameter `power_down'\n", val); -+ DWC_WARN("power_down must be 0 - 2\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) { -+ valid = 0; -+ } -+ if (valid == 0) { -+ if (dwc_otg_param_initialized(core_if->core_params->power_down)) { -+ DWC_ERROR -+ ("%d invalid for parameter power_down. Check HW configuration.\n", -+ val); -+ } -+ retval = -DWC_E_INVALID; -+ val = 0; -+ } -+ core_if->core_params->power_down = val; -+ return retval; -+} -+ -+int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->core_params->power_down; -+} -+ -+int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val) -+{ -+ int retval = 0; -+ int valid = 1; -+ -+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { -+ DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val); -+ DWC_WARN("reload_ctl must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) { -+ valid = 0; -+ } -+ if (valid == 0) { -+ if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) { -+ DWC_ERROR("%d invalid for parameter reload_ctl." -+ "Check HW configuration.\n", val); -+ } -+ retval = -DWC_E_INVALID; -+ val = 0; -+ } -+ core_if->core_params->reload_ctl = val; -+ return retval; -+} -+ -+int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->core_params->reload_ctl; -+} -+ -+int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val) -+{ -+ int retval = 0; -+ int valid = 1; -+ -+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { -+ DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val); -+ DWC_WARN("dev_out_nak must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) || -+ !(core_if->core_params->dma_desc_enable))) { -+ valid = 0; -+ } -+ if (valid == 0) { -+ if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) { -+ DWC_ERROR("%d invalid for parameter dev_out_nak." -+ "Check HW configuration.\n", val); -+ } -+ retval = -DWC_E_INVALID; -+ val = 0; -+ } -+ core_if->core_params->dev_out_nak = val; -+ return retval; -+} -+ -+int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->core_params->dev_out_nak; -+} -+ -+int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val) -+{ -+ int retval = 0; -+ int valid = 1; -+ -+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { -+ DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val); -+ DWC_WARN("cont_on_bna must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) || -+ !(core_if->core_params->dma_desc_enable))) { -+ valid = 0; -+ } -+ if (valid == 0) { -+ if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) { -+ DWC_ERROR("%d invalid for parameter cont_on_bna." -+ "Check HW configuration.\n", val); -+ } -+ retval = -DWC_E_INVALID; -+ val = 0; -+ } -+ core_if->core_params->cont_on_bna = val; -+ return retval; -+} -+ -+int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->core_params->cont_on_bna; -+} -+ -+int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val) -+{ -+ int retval = 0; -+ int valid = 1; -+ -+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { -+ DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val); -+ DWC_WARN("ahb_single must be 0 or 1\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) { -+ valid = 0; -+ } -+ if (valid == 0) { -+ if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) { -+ DWC_ERROR("%d invalid for parameter ahb_single." -+ "Check HW configuration.\n", val); -+ } -+ retval = -DWC_E_INVALID; -+ val = 0; -+ } -+ core_if->core_params->ahb_single = val; -+ return retval; -+} -+ -+int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->core_params->ahb_single; -+} -+ -+int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val) -+{ -+ int retval = 0; -+ -+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { -+ DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val); -+ DWC_WARN -+ ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ core_if->core_params->otg_ver = val; -+ return retval; -+} -+ -+int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->core_params->otg_ver; -+} - - 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); -+ 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); -+ 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); -+ if(core_if->otg_ver == 0) { -+ 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); -+ } else { -+ core_if->otg_sts = val; -+ } - } - - uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if) -@@ -5125,45 +6661,47 @@ uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if) - - 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; -+ gintsts_data_t gintsts; -+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); -+ return gintsts.b.curmode; - } - - 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); -+ 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.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); -+ 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); -+ 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.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); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); - } - - uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if) - { - dcfg_data_t dcfg; -- dcfg.d32 = -1; //GRAYG -+ /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */ -+ -+ dcfg.d32 = -1; //GRAYG - DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if); - if (NULL == core_if) - DWC_ERROR("reg request with NULL core_if\n"); -@@ -5183,7 +6721,7 @@ uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if) - core_if, core_if->dev_if, - core_if->dev_if->dev_global_regs, - &core_if->dev_if->dev_global_regs->dcfg); -- dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); - } - return dcfg.b.devspd; - } -@@ -5191,45 +6729,50 @@ uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if) - void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val) - { - dcfg_data_t dcfg; -- dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); - dcfg.b.devspd = val; -- dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.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); -+ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); - return hprt0.b.prtconnsts; - } - - uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if) - { - dsts_data_t dsts; -- dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - return dsts.b.enumspd; - } - - 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); -+ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); - return hprt0.b.prtpwr; - - } - -+uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if) -+{ -+ return core_if->hibernation_suspend; -+} -+ - 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.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtpwr = val; -- dwc_write_reg32(core_if->host_if->hprt0, 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); -+ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); - return hprt0.b.prtsusp; - - } -@@ -5237,30 +6780,119 @@ uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if) - 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.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtsusp = val; -- dwc_write_reg32(core_if->host_if->hprt0, val); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+} -+ -+uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if) -+{ -+ hfir_data_t hfir; -+ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); -+ return hfir.b.frint; -+ -+} -+ -+void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val) -+{ -+ hfir_data_t hfir; -+ uint32_t fram_int; -+ fram_int = calc_frame_interval(core_if); -+ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); -+ if (!core_if->core_params->reload_ctl) { -+ DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is" -+ "not set to 1.\nShould load driver with reload_ctl=1" -+ " module parameter\n"); -+ return; -+ } -+ switch (fram_int) { -+ case 3750: -+ if ((val < 3350) || (val > 4150)) { -+ DWC_WARN("HFIR interval for HS core and 30 MHz" -+ "clock freq should be from 3350 to 4150\n"); -+ return; -+ } -+ break; -+ case 30000: -+ if ((val < 26820) || (val > 33180)) { -+ DWC_WARN("HFIR interval for FS/LS core and 30 MHz" -+ "clock freq should be from 26820 to 33180\n"); -+ return; -+ } -+ break; -+ case 6000: -+ if ((val < 5360) || (val > 6640)) { -+ DWC_WARN("HFIR interval for HS core and 48 MHz" -+ "clock freq should be from 5360 to 6640\n"); -+ return; -+ } -+ break; -+ case 48000: -+ if ((val < 42912) || (val > 53088)) { -+ DWC_WARN("HFIR interval for FS/LS core and 48 MHz" -+ "clock freq should be from 42912 to 53088\n"); -+ return; -+ } -+ break; -+ case 7500: -+ if ((val < 6700) || (val > 8300)) { -+ DWC_WARN("HFIR interval for HS core and 60 MHz" -+ "clock freq should be from 6700 to 8300\n"); -+ return; -+ } -+ break; -+ case 60000: -+ if ((val < 53640) || (val > 65536)) { -+ DWC_WARN("HFIR interval for FS/LS core and 60 MHz" -+ "clock freq should be from 53640 to 65536\n"); -+ return; -+ } -+ break; -+ default: -+ DWC_WARN("Unknown frame interval\n"); -+ return; -+ break; -+ -+ } -+ hfir.b.frint = val; -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32); -+} -+ -+uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if) -+{ -+ hcfg_data_t hcfg; -+ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); -+ return hcfg.b.modechtimen; -+ -+} -+ -+void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val) -+{ -+ hcfg_data_t hcfg; -+ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); -+ hcfg.b.modechtimen = val; -+ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.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.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtres = val; -- dwc_write_reg32(core_if->host_if->hprt0, val); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - } - - uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if) - { - dctl_data_t dctl; -- dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl); -+ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); - return dctl.b.rmtwkupsig; - } - - 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); -+ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - - DWC_ASSERT(! - ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts), -@@ -5273,44 +6905,44 @@ uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if) - 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); -+ 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); -+ 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.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); -+ 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); -+ 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.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); -+ 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); -+ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - return lpmcfg.b.inv_sel_hsic; - - } -@@ -5318,93 +6950,132 @@ uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if) - 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.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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ 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); -+ return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); -+} -+ -+uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if) -+{ -+ return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103); -+} -+ -+/** -+ * Start the SRP timer to detect when the SRP does not complete within -+ * 6 seconds. -+ * -+ * @param core_if the pointer to core_if strucure. -+ */ -+void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if) -+{ -+ core_if->srp_timer_started = 1; -+ DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ ); -+} -+ -+void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if) -+{ -+ uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl); -+ gotgctl_data_t mem; -+ gotgctl_data_t val; -+ -+ val.d32 = DWC_READ_REG32(addr); -+ if (val.b.sesreq) { -+ DWC_ERROR("Session Request Already active!\n"); -+ return; -+ } -+ -+ DWC_INFO("Session Request Initated\n"); //NOTICE -+ mem.d32 = DWC_READ_REG32(addr); -+ mem.b.sesreq = 1; -+ DWC_WRITE_REG32(addr, mem.d32); -+ -+ /* Start the SRP timer */ -+ dwc_otg_pcd_start_srp_timer(core_if); -+ return; - } -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -index 1176166..b76fdd9 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cil.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -@@ -1,13 +1,13 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $ -- * $Revision: #99 $ -- * $Date: 2009/04/21 $ -- * $Change: 1237466 $ -+ * $Revision: #122 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871160 $ - * - * 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 -@@ -17,7 +17,7 @@ - * 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 -@@ -34,15 +34,14 @@ - #if !defined(__DWC_CIL_H__) - #define __DWC_CIL_H__ - --//#define HW2937_WORKAROUND - #define DBG_HW2937 0x400 - --#include "dwc_os.h" - #include "dwc_list.h" - #include "dwc_otg_dbg.h" - #include "dwc_otg_regs.h" - - #include "dwc_otg_core_if.h" -+#include "dwc_otg_adp.h" - - /** - * @file -@@ -63,16 +62,20 @@ - BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */ - BM_ALIGN = 4 /* data buffer is in buffer alignment mode */ - } data_buffer_mode_e; --#endif //DWC_UTE_CFI -+#endif //DWC_UTE_CFI - --/** Macros defined for DWC OTG HW Release verison */ -+/** Macros defined for DWC OTG HW Release version */ - - #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 OTG_CORE_REV_2_90a 0x4F54290A -+#define OTG_CORE_REV_2_91a 0x4F54291A -+#define OTG_CORE_REV_2_92a 0x4F54292A -+#define OTG_CORE_REV_2_93a 0x4F54293A -+#define OTG_CORE_REV_2_94a 0x4F54294A - - /** - * Information for each ISOC packet. -@@ -96,8 +99,9 @@ - /** EP active. */ - unsigned active:1; - -- /** Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic Tx FIFO -- If dedicated Tx FIFOs are enabled for all IN Eps - Tx FIFO # FOR IN EPs*/ -+ /** -+ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic -+ * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/ - unsigned tx_fifo_num:4; - /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ - unsigned type:2; -@@ -159,9 +163,27 @@ - uint32_t cfi_req_len; - #endif //DWC_UTE_CFI - -+/** Max DMA Descriptor count for any EP */ -+#define MAX_DMA_DESC_CNT 256 - /** Allocated DMA Desc count */ - uint32_t desc_cnt; -+ -+ /** bInterval */ -+ uint32_t bInterval; -+ /** Next frame num to setup next ISOC transfer */ -+ uint32_t frame_num; -+ /** Indicates SOF number overrun in DSTS */ -+ uint8_t frm_overrun; - -+#ifdef DWC_UTE_PER_IO -+ /** Next frame num for which will be setup DMA Desc */ -+ uint32_t xiso_frame_num; -+ /** bInterval */ -+ uint32_t xiso_bInterval; -+ /** Count of currently active transfers - shall be either 0 or 1 */ -+ int xiso_active_xfers; -+ int xiso_queued_xfers; -+#endif - #ifdef DWC_EN_ISOC - /** - * Variables specific for ISOC EPs -@@ -230,9 +252,6 @@ - DWC_OTG_HC_XFER_AHB_ERR, - DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE, - DWC_OTG_HC_XFER_URB_DEQUEUE --#ifdef HW2937_WORKAROUND -- , DWC_OTG_HC_XFER_PAUSE_IN --#endif - } dwc_otg_halt_status_e; - - /** -@@ -301,7 +320,7 @@ - - /** Pointer to the current transfer buffer position. */ - uint8_t *xfer_buff; -- /** -+ /** - * In Buffer DMA mode this buffer will be used - * if xfer_buff is not DWORD aligned. - */ -@@ -358,9 +377,9 @@ - uint8_t hub_addr; /**< Address of high speed hub */ - - uint8_t port_addr; /**< Port of the low/full speed device */ -- /** Split transaction position -+ /** Split transaction position - * One of the following values: -- * - DWC_HCSPLIT_XACTPOS_MID -+ * - DWC_HCSPLIT_XACTPOS_MID - * - DWC_HCSPLIT_XACTPOS_BEGIN - * - DWC_HCSPLIT_XACTPOS_END - * - DWC_HCSPLIT_XACTPOS_ALL */ -@@ -384,19 +403,19 @@ - - /** Entry in list of host channels. */ - DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry; -- -+ - /** @name Descriptor DMA support */ - /** @{ */ -- -+ - /** Number of Transfer Descriptors */ - uint16_t ntd; -- -+ - /** Descriptor List DMA address */ - dwc_dma_t desc_list_addr; -- -+ - /** Scheduling micro-frame bitmap. */ - uint8_t schinfo; -- -+ - /** @} */ - } dwc_hc_t; - -@@ -426,9 +445,9 @@ - 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. -+ * When DMA mode is enabled specifies whether to use address DMA or DMA -+ * Descriptor mode for accessing the data FIFOs in device mode. The driver -+ * will automatically detect the value for this if none is specified. - * 0 - address DMA - * 1 - DMA Descriptor(default, if available) - */ -@@ -447,7 +466,7 @@ - * 1 - Full Speed - */ - int32_t speed; -- /** Specifies whether low power mode is supported when attached -+ /** 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 -@@ -456,7 +475,7 @@ - - /** 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 -+ * 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 -@@ -470,21 +489,21 @@ - */ - 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 -+ /** 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 -+ /** 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 -+ /** 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) - */ -@@ -496,52 +515,52 @@ - */ - uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; - -- /** Number of 4-byte words in the Rx FIFO in host mode when dynamic -+ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic - * FIFO sizing is enabled. -- * 16 to 32768 (default 1024) -+ * 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. -+ /** 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. -+ /** 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. -+ /** The maximum transfer size supported in bytes. - * 2047 to 65,535 (default 65,535) - */ - int32_t max_transfer_size; - -- /** The maximum number of packets in a transfer. -+ /** 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) -+ /** 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 -+ /** 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 -@@ -549,13 +568,13 @@ - int32_t phy_type; - - /** -- * Specifies the UTMI+ Data Width. This parameter is -+ * 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. -+ * configured to work at either data path width. - * - * 8 or 16 bits (default 16) - */ -@@ -565,7 +584,7 @@ - * 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 -@@ -574,7 +593,7 @@ - int32_t phy_ulpi_ddr; - - /** -- * Specifies whether to use the internal or external supply to -+ * Specifies whether to use the internal or external supply to - * drive the vbus with a ULPI phy. - */ - int32_t phy_ulpi_ext_vbus; -@@ -592,9 +611,9 @@ - int32_t ts_dline; - - /** -- * Specifies whether dedicated transmit FIFOs are -+ * Specifies whether dedicated transmit FIFOs are - * enabled for non periodic IN endpoints in device mode -- * 0 - No -+ * 0 - No - * 1 - Yes - */ - int32_t en_multiple_tx_fifo; -@@ -605,19 +624,19 @@ - */ - uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; - -- /** Thresholding enable flag- -+ /** 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 -+ /** Thresholding length for Tx - * FIFOs in 32 bit DWORDs - */ - uint32_t tx_thr_length; - -- /** Thresholding length for Rx -+ /** Thresholding length for Rx - * FIFOs in 32 bit DWORDs - */ - uint32_t rx_thr_length; -@@ -627,14 +646,14 @@ - */ - int32_t lpm_enable; - -- /** Per Transfer Interrupt -+ /** Per Transfer Interrupt - * mode enable flag - * 1 - Enabled - * 0 - Disabled - */ - int32_t pti_enable; - -- /** Multi Processor Interrupt -+ /** Multi Processor Interrupt - * mode enable flag - * 1 - Enabled - * 0 - Disabled -@@ -655,6 +674,53 @@ - */ - int32_t ahb_thr_ratio; - -+ /** ADP Support -+ * 1 - Enabled -+ * 0 - Disabled -+ */ -+ int32_t adp_supp_enable; -+ -+ /** HFIR Reload Control -+ * 0 - The HFIR cannot be reloaded dynamically. -+ * 1 - Allow dynamic reloading of the HFIR register during runtime. -+ */ -+ int32_t reload_ctl; -+ -+ /** DCFG: Enable device Out NAK -+ * 0 - The core does not set NAK after Bulk Out transfer complete. -+ * 1 - The core sets NAK after Bulk OUT transfer complete. -+ */ -+ int32_t dev_out_nak; -+ -+ /** DCFG: Enable Continue on BNA -+ * After receiving BNA interrupt the core disables the endpoint,when the -+ * endpoint is re-enabled by the application the core starts processing -+ * 0 - from the DOEPDMA descriptor -+ * 1 - from the descriptor which received the BNA. -+ */ -+ int32_t cont_on_bna; -+ -+ /** GAHBCFG: AHB Single Support -+ * This bit when programmed supports SINGLE transfers for remainder -+ * data in a transfer for DMA mode of operation. -+ * 0 - in this case the remainder data will be sent using INCR burst size. -+ * 1 - in this case the remainder data will be sent using SINGLE burst size. -+ */ -+ int32_t ahb_single; -+ -+ /** Core Power down mode -+ * 0 - No Power Down is enabled -+ * 1 - Reserved -+ * 2 - Complete Power Down (Hibernation) -+ */ -+ int32_t power_down; -+ -+ /** OTG revision supported -+ * 0 - OTG 1.3 revision -+ * 1 - OTG 2.0 revision -+ */ -+ int32_t otg_ver; -+ - } dwc_otg_core_params_t; - - #ifdef DEBUG -@@ -664,6 +730,12 @@ - dwc_hc_t *hc; - } hc_xfer_info_t; - #endif -+ -+typedef struct ep_xfer_info { -+ struct dwc_otg_core_if *core_if; -+ dwc_ep_t *ep; -+ uint8_t state; -+} ep_xfer_info_t; - /* - * Device States - */ -@@ -678,6 +750,42 @@ - DWC_OTG_L3 - } dwc_otg_lx_state_e; - -+struct dwc_otg_global_regs_backup { -+ uint32_t gotgctl_local; -+ uint32_t gintmsk_local; -+ uint32_t gahbcfg_local; -+ uint32_t gusbcfg_local; -+ uint32_t grxfsiz_local; -+ uint32_t gnptxfsiz_local; -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ uint32_t glpmcfg_local; -+#endif -+ uint32_t gi2cctl_local; -+ uint32_t hptxfsiz_local; -+ uint32_t pcgcctl_local; -+ uint32_t gdfifocfg_local; -+ uint32_t dtxfsiz_local[MAX_EPS_CHANNELS]; -+ uint32_t gpwrdn_local; -+}; -+ -+struct dwc_otg_host_regs_backup { -+ uint32_t hcfg_local; -+ uint32_t haintmsk_local; -+ uint32_t hcintmsk_local[MAX_EPS_CHANNELS]; -+ uint32_t hprt0_local; -+ uint32_t hfir_local; -+}; -+ -+struct dwc_otg_dev_regs_backup { -+ uint32_t dcfg; -+ uint32_t dctl; -+ uint32_t daintmsk; -+ uint32_t diepmsk; -+ uint32_t doepmsk; -+ uint32_t diepctl[MAX_EPS_CHANNELS]; -+ uint32_t dieptsiz[MAX_EPS_CHANNELS]; -+ uint32_t diepdma[MAX_EPS_CHANNELS]; -+}; - /** - * The dwc_otg_core_if structure contains information needed to manage - * the DWC_otg controller acting in either host or device mode. It -@@ -709,7 +817,17 @@ struct dwc_otg_core_if { - */ - uint8_t srp_success; - uint8_t srp_timer_started; -+ /** Timer for SRP. If it expires before SRP is successful -+ * clear the SRP. */ -+ dwc_timer_t *srp_timer; - -+#ifdef DWC_DEV_SRPCAP -+ /* This timer is needed to power on the hibernated host core if SRP is not -+ * initiated on connected SRP capable device for limited period of time -+ */ -+ uint8_t pwron_timer_started; -+ dwc_timer_t *pwron_timer; -+#endif - /* Common configuration information */ - /** Power and Clock Gating Control Register */ - volatile uint32_t *pcgcctl; -@@ -751,6 +869,7 @@ struct dwc_otg_core_if { - hwcfg2_data_t hwcfg2; - hwcfg3_data_t hwcfg3; - hwcfg4_data_t hwcfg4; -+ fifosize_data_t hptxfsiz; - - /** Host and Device Configuration -- stored here for convenience.*/ - hcfg_data_t hcfg; -@@ -797,7 +916,10 @@ struct dwc_otg_core_if { - - /** Timer object used for handling "Wakeup Detected" Interrupt */ - dwc_timer_t *wkp_timer; -- -+ /** This arrays used for debug purposes for DEV OUT NAK enhancement */ -+ uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS]; -+ ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS]; -+ dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS]; - #ifdef DEBUG - uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; - -@@ -825,6 +947,48 @@ struct dwc_otg_core_if { - /** Lx state of device */ - dwc_otg_lx_state_e lx_state; - -+ /** Saved Core Global registers */ -+ struct dwc_otg_global_regs_backup *gr_backup; -+ /** Saved Host registers */ -+ struct dwc_otg_host_regs_backup *hr_backup; -+ /** Saved Device registers */ -+ struct dwc_otg_dev_regs_backup *dr_backup; -+ -+ /** Power Down Enable */ -+ uint32_t power_down; -+ -+ /** ADP support Enable */ -+ uint32_t adp_enable; -+ -+ /** ADP structure object */ -+ dwc_otg_adp_t adp; -+ -+ /** hibernation/suspend flag */ -+ int hibernation_suspend; -+ -+ /** OTG revision supported */ -+ uint32_t otg_ver; -+ -+ /** OTG status flag used for HNP polling */ -+ uint8_t otg_sts; -+ -+ /** Pointer to either hcd->lock or pcd->lock */ -+ dwc_spinlock_t *lock; -+ -+ /** Start predict NextEP based on Learning Queue if equal 1, -+ * also used as counter of disabled NP IN EP's */ -+ uint8_t start_predict; -+ -+ /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and -+ * active, 0xff otherwise */ -+ uint8_t nextep_seq[MAX_EPS_CHANNELS]; -+ -+ /** Index of fisrt EP in nextep_seq array which should be re-enabled **/ -+ uint8_t first_in_nextep_seq; -+ -+ /** Frame number while entering to ISR - needed for ISOCs **/ -+ uint32_t frame_num; -+ - }; - - #ifdef DEBUG -@@ -835,13 +999,40 @@ struct dwc_otg_core_if { - #endif - - /* -- * The following functions are functions for works -+ * This function is called when transfer is timed out on endpoint. -+ */ -+extern void ep_xfer_timeout(void *ptr); -+ -+/* -+ * The following functions are functions for works - * using during handling some interrupts - */ - extern void w_conn_id_status_change(void *p); - - extern void w_wakeup_detected(void *p); - -+/** Saves global register values into system memory. */ -+extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if); -+/** Saves device register values into system memory. */ -+extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if); -+/** Saves host register values into system memory. */ -+extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if); -+/** Restore global register values. */ -+extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if); -+/** Restore host register values. */ -+extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset); -+/** Restore device register values. */ -+extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, -+ int rem_wakeup); -+extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if); -+extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, -+ int is_host); -+ -+extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, -+ int restore_mode, int reset); -+extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, -+ int rem_wakeup, int reset); -+ - /* - * The following functions support initialization of the CIL driver component - * and the DWC_otg controller. -@@ -881,7 +1072,7 @@ extern void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, - dwc_ep_t * ep); - extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, - dwc_ep_t * ep); --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ - /**@}*/ - - /** @name Host CIL Functions -@@ -903,14 +1094,17 @@ extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if, - extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if); - extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if); - --extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc); -+extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, -+ dwc_hc_t * hc); -+ -+extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if); - - /* Macro used to clear one channel interrupt */ - #define clear_hc_int(_hc_regs_, _intr_) \ - do { \ - hcint_data_t hcint_clear = {.d32 = 0}; \ - hcint_clear.b._intr_ = 1; \ -- dwc_write_reg32(&(_hc_regs_)->hcint, hcint_clear.d32); \ -+ DWC_WRITE_REG32(&(_hc_regs_)->hcint, hcint_clear.d32); \ - } while (0) - - /* -@@ -924,18 +1118,18 @@ extern void dwc_otg_hc_write_packet(dwc_otg_core_if_t * _core_if, - do { \ - hcintmsk_data_t hcintmsk = {.d32 = 0}; \ - hcintmsk.b._intr_ = 1; \ -- dwc_modify_reg32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \ -+ DWC_MODIFY_REG32(&(_hc_regs_)->hcintmsk, hcintmsk.d32, 0); \ - } while (0) -- -+ - /** -- * This function Reads HPRT0 in preparation to modify. It keeps the -+ * 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 -+ * write it back - */ - static inline 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.d32 = DWC_READ_REG32(_core_if->host_if->hprt0); - hprt0.b.prtena = 0; - hprt0.b.prtconndet = 0; - hprt0.b.prtenchng = 0; -@@ -963,8 +1157,8 @@ extern void dwc_otg_read_packet(dwc_otg_core_if_t * core_if, - */ - static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if) - { -- return (dwc_read_reg32(&core_if->core_global_regs->gintsts) & -- dwc_read_reg32(&core_if->core_global_regs->gintmsk)); -+ return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) & -+ DWC_READ_REG32(&core_if->core_global_regs->gintmsk)); - } - - /** -@@ -972,7 +1166,7 @@ static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if) - */ - static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if) - { -- return (dwc_read_reg32(&core_if->core_global_regs->gotgint)); -+ return (DWC_READ_REG32(&core_if->core_global_regs->gotgint)); - } - - /** -@@ -986,13 +1180,13 @@ static inline uint32_t dwc_otg_read_dev_all_in_ep_intr(dwc_otg_core_if_t * - uint32_t v; - - if (core_if->multiproc_int_enable) { -- v = dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -- deachint) & dwc_read_reg32(&core_if->dev_if-> -- dev_global_regs-> -- deachintmsk); -+ v = DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->deachint) & -+ DWC_READ_REG32(&core_if-> -+ dev_if->dev_global_regs->deachintmsk); - } else { -- v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & -- dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); -+ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); - } - return (v & 0xffff); - } -@@ -1007,13 +1201,13 @@ static inline uint32_t dwc_otg_read_dev_all_out_ep_intr(dwc_otg_core_if_t * - uint32_t v; - - if (core_if->multiproc_int_enable) { -- v = dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -- deachint) & dwc_read_reg32(&core_if->dev_if-> -- dev_global_regs-> -- deachintmsk); -+ v = DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->deachint) & -+ DWC_READ_REG32(&core_if-> -+ dev_if->dev_global_regs->deachintmsk); - } else { -- v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & -- dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); -+ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); - } - - return ((v & 0xffff0000) >> 16); -@@ -1030,20 +1224,20 @@ static inline uint32_t dwc_otg_read_dev_in_ep_intr(dwc_otg_core_if_t * core_if, - - if (core_if->multiproc_int_enable) { - msk = -- dwc_read_reg32(&dev_if->dev_global_regs-> -- diepeachintmsk[ep->num]); -+ DWC_READ_REG32(&dev_if-> -+ dev_global_regs->diepeachintmsk[ep->num]); - emp = -- dwc_read_reg32(&dev_if->dev_global_regs-> -- dtknqr4_fifoemptymsk); -+ DWC_READ_REG32(&dev_if-> -+ dev_global_regs->dtknqr4_fifoemptymsk); - msk |= ((emp >> ep->num) & 0x1) << 7; -- v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; -+ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; - } else { -- msk = dwc_read_reg32(&dev_if->dev_global_regs->diepmsk); -+ msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk); - emp = -- dwc_read_reg32(&dev_if->dev_global_regs-> -- dtknqr4_fifoemptymsk); -+ DWC_READ_REG32(&dev_if-> -+ dev_global_regs->dtknqr4_fifoemptymsk); - msk |= ((emp >> ep->num) & 0x1) << 7; -- v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; -+ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; - } - - return v; -@@ -1061,20 +1255,20 @@ static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t * - - if (_core_if->multiproc_int_enable) { - msk.d32 = -- dwc_read_reg32(&dev_if->dev_global_regs-> -- doepeachintmsk[_ep->num]); -+ DWC_READ_REG32(&dev_if-> -+ dev_global_regs->doepeachintmsk[_ep->num]); - if (_core_if->pti_enh_enable) { - msk.b.pktdrpsts = 1; - } -- v = dwc_read_reg32(&dev_if->out_ep_regs[_ep->num]-> -- doepint) & msk.d32; -+ v = DWC_READ_REG32(&dev_if-> -+ out_ep_regs[_ep->num]->doepint) & msk.d32; - } else { -- msk.d32 = dwc_read_reg32(&dev_if->dev_global_regs->doepmsk); -+ msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk); - if (_core_if->pti_enh_enable) { - msk.b.pktdrpsts = 1; - } -- v = dwc_read_reg32(&dev_if->out_ep_regs[_ep->num]-> -- doepint) & msk.d32; -+ v = DWC_READ_REG32(&dev_if-> -+ out_ep_regs[_ep->num]->doepint) & msk.d32; - } - return v; - } -@@ -1085,30 +1279,30 @@ static inline uint32_t dwc_otg_read_dev_out_ep_intr(dwc_otg_core_if_t * - 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)); -+ 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, dwc_hc_t * _hc) - { -- return (dwc_read_reg32 -+ return (DWC_READ_REG32 - (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint)); - } - - /** - * This function returns the mode of the operation, host or device. - * -- * @return 0 - Device Mode, 1 - Host Mode -+ * @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); -+ return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1); - } - - /**@}*/ - - /** -- * DWC_otg CIL callback structure. This structure allows the HCD and -+ * DWC_otg CIL callback structure. This structure allows the HCD and - * PCD to register functions used for starting and stopping the PCD - * and HCD for role change on for a DRD. - */ -@@ -1140,4 +1334,124 @@ extern void dwc_otg_cil_register_hcd_callbacks(dwc_otg_core_if_t * _core_if, - dwc_otg_cil_callbacks_t * _cb, - void *_p); - -+void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if); -+ -+////////////////////////////////////////////////////////////////////// -+/** Start the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_hcd_start(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->start) { -+ core_if->hcd_cb->start(core_if->hcd_cb->p); -+ } -+} -+ -+/** Stop the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_hcd_stop(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->stop) { -+ core_if->hcd_cb->stop(core_if->hcd_cb->p); -+ } -+} -+ -+/** Disconnect the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_hcd_disconnect(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->disconnect) { -+ core_if->hcd_cb->disconnect(core_if->hcd_cb->p); -+ } -+} -+ -+/** Inform the HCD the a New Session has begun. Helper function for -+ * using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_hcd_session_start(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->session_start) { -+ core_if->hcd_cb->session_start(core_if->hcd_cb->p); -+ } -+} -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+/** -+ * Inform the HCD about LPM sleep. -+ * Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->sleep) { -+ core_if->hcd_cb->sleep(core_if->hcd_cb->p); -+ } -+} -+#endif -+ -+/** Resume the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { -+ core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); -+ } -+} -+ -+/** Start the PCD. Helper function for using the PCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_pcd_start(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->start) { -+ core_if->pcd_cb->start(core_if->pcd_cb->p); -+ } -+} -+ -+/** Stop the PCD. Helper function for using the PCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_pcd_stop(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->stop) { -+ core_if->pcd_cb->stop(core_if->pcd_cb->p); -+ } -+} -+ -+/** Suspend the PCD. Helper function for using the PCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_pcd_suspend(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->suspend) { -+ core_if->pcd_cb->suspend(core_if->pcd_cb->p); -+ } -+} -+ -+/** Resume the PCD. Helper function for using the PCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void cil_pcd_resume(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); -+ } -+} -+ -+////////////////////////////////////////////////////////////////////// -+ - #endif -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -index b8b2740..edc5c92 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ -- * $Revision: #15 $ -- * $Date: 2009/04/15 $ -- * $Change: 1234129 $ -+ * $Revision: #31 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871286 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -42,6 +42,9 @@ - #include "dwc_os.h" - #include "dwc_otg_regs.h" - #include "dwc_otg_cil.h" -+#include "dwc_otg_driver.h" -+#include "dwc_otg_pcd.h" -+#include "dwc_otg_hcd.h" - - #ifdef DEBUG - inline const char *op_state_str(dwc_otg_core_if_t * core_if) -@@ -67,125 +70,10 @@ int32_t dwc_otg_handle_mode_mismatch_intr(dwc_otg_core_if_t * core_if) - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.modemismatch = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - return 1; - } - --/** Start the HCD. Helper function for using the HCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void hcd_start(dwc_otg_core_if_t * core_if) --{ -- if (core_if->hcd_cb && core_if->hcd_cb->start) { -- core_if->hcd_cb->start(core_if->hcd_cb->p); -- } --} -- --/** Stop the HCD. Helper function for using the HCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void hcd_stop(dwc_otg_core_if_t * core_if) --{ -- if (core_if->hcd_cb && core_if->hcd_cb->stop) { -- core_if->hcd_cb->stop(core_if->hcd_cb->p); -- } --} -- --/** Disconnect the HCD. Helper function for using the HCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void hcd_disconnect(dwc_otg_core_if_t * core_if) --{ -- if (core_if->hcd_cb && core_if->hcd_cb->disconnect) { -- core_if->hcd_cb->disconnect(core_if->hcd_cb->p); -- } --} -- --/** Inform the HCD the a New Session has begun. Helper function for -- * using the HCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void hcd_session_start(dwc_otg_core_if_t * core_if) --{ -- if (core_if->hcd_cb && core_if->hcd_cb->session_start) { -- core_if->hcd_cb->session_start(core_if->hcd_cb->p); -- } --} -- --#ifdef CONFIG_USB_DWC_OTG_LPM --/** -- * Inform the HCD about LPM sleep. -- * Helper function for using the HCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void hcd_sleep(dwc_otg_core_if_t * core_if) --{ -- if (core_if->hcd_cb && core_if->hcd_cb->sleep) { -- core_if->hcd_cb->sleep(core_if->hcd_cb->p); -- } --} --#endif -- --/** Resume the HCD. Helper function for using the HCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void hcd_resume(dwc_otg_core_if_t * core_if) --{ -- if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { -- core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); -- } --} -- --/** Start the PCD. Helper function for using the PCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void pcd_start(dwc_otg_core_if_t * core_if) --{ -- if (core_if->pcd_cb && core_if->pcd_cb->start) { -- core_if->pcd_cb->start(core_if->pcd_cb->p); -- } --} -- --/** Stop the PCD. Helper function for using the PCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void pcd_stop(dwc_otg_core_if_t * core_if) --{ -- if (core_if->pcd_cb && core_if->pcd_cb->stop) { -- core_if->pcd_cb->stop(core_if->pcd_cb->p); -- } --} -- --/** Suspend the PCD. Helper function for using the PCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void pcd_suspend(dwc_otg_core_if_t * core_if) --{ -- if (core_if->pcd_cb && core_if->pcd_cb->suspend) { -- core_if->pcd_cb->suspend(core_if->pcd_cb->p); -- } --} -- --/** Resume the PCD. Helper function for using the PCD callbacks. -- * -- * @param core_if Programming view of DWC_otg controller. -- */ --static inline void pcd_resume(dwc_otg_core_if_t * core_if) --{ -- if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -- core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); -- } --} -- - /** - * This function handles the OTG Interrupts. It reads the OTG - * Interrupt Register (GOTGINT) to determine what interrupt has -@@ -199,9 +87,10 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - gotgint_data_t gotgint; - gotgctl_data_t gotgctl; - gintmsk_data_t gintmsk; -+ gpwrdn_data_t gpwrdn; - -- gotgint.d32 = dwc_read_reg32(&global_regs->gotgint); -- gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ gotgint.d32 = DWC_READ_REG32(&global_regs->gotgint); -+ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); - DWC_DEBUGPL(DBG_CIL, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint.d32, - op_state_str(core_if)); - -@@ -209,10 +98,10 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " - "Session End Detected++ (%s)\n", - op_state_str(core_if)); -- gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); - - if (core_if->op_state == B_HOST) { -- pcd_start(core_if); -+ cil_pcd_start(core_if); - core_if->op_state = B_PERIPHERAL; - } else { - /* If not B_HOST and Device HNP still set. HNP -@@ -227,26 +116,50 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - /* Reset PCD and Gadget driver to a - * clean state. */ - core_if->lx_state = DWC_OTG_L0; -- pcd_stop(core_if); -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_pcd_stop(core_if); -+ DWC_SPINLOCK(core_if->lock); -+ -+ if (core_if->adp_enable) { -+ if (core_if->power_down == 2) { -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs-> -+ gpwrdn, gpwrdn.d32, 0); -+ } -+ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ -+ dwc_otg_adp_sense_start(core_if); -+ } - } -+ - gotgctl.d32 = 0; - gotgctl.b.devhnpen = 1; -- dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); -+ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); - } - if (gotgint.b.sesreqsucstschng) { - DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " - "Session Reqeust Success Status Change++\n"); -- gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); - if (gotgctl.b.sesreqscs) { -+ - if ((core_if->core_params->phy_type == - DWC_PHY_TYPE_PARAM_FS) && (core_if->core_params->i2c_enable)) { - core_if->srp_success = 1; - } else { -- pcd_resume(core_if); -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_pcd_resume(core_if); -+ DWC_SPINLOCK(core_if->lock); - /* Clear Session Request */ - gotgctl.d32 = 0; - gotgctl.b.sesreq = 1; -- dwc_modify_reg32(&global_regs->gotgctl, -+ DWC_MODIFY_REG32(&global_regs->gotgctl, - gotgctl.d32, 0); - } - } -@@ -254,7 +167,7 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - if (gotgint.b.hstnegsucstschng) { - /* Print statements during the HNP interrupt handling - * can cause it to fail.*/ -- gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); -+ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); - if (gotgctl.b.hstnegscs) { - if (dwc_otg_is_host_mode(core_if)) { - core_if->op_state = B_HOST; -@@ -270,20 +183,23 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - */ - gintmsk.d32 = 0; - gintmsk.b.sofintr = 1; -- dwc_modify_reg32(&global_regs->gintmsk, -+ DWC_MODIFY_REG32(&global_regs->gintmsk, - gintmsk.d32, 0); -- pcd_stop(core_if); -+ /* Call callback function with spin lock released */ -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_pcd_stop(core_if); - /* - * Initialize the Core for Host mode. - */ -- hcd_start(core_if); -+ cil_hcd_start(core_if); -+ DWC_SPINLOCK(core_if->lock); - core_if->op_state = B_HOST; - } - } else { - gotgctl.d32 = 0; - gotgctl.b.hnpreq = 1; - gotgctl.b.devhnpen = 1; -- dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); -+ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); - DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); - __DWC_ERROR("Device Not Connected/Responding\n"); - } -@@ -301,8 +217,10 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - if (dwc_otg_is_device_mode(core_if)) { - DWC_DEBUGPL(DBG_ANY, "a_suspend->a_peripheral (%d)\n", - core_if->op_state); -- hcd_disconnect(core_if); -- pcd_start(core_if); -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_hcd_disconnect(core_if); -+ cil_pcd_start(core_if); -+ DWC_SPINLOCK(core_if->lock); - core_if->op_state = A_PERIPHERAL; - } else { - /* -@@ -316,9 +234,11 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - */ - gintmsk.d32 = 0; - gintmsk.b.sofintr = 1; -- dwc_modify_reg32(&global_regs->gintmsk, gintmsk.d32, 0); -- pcd_stop(core_if); -- hcd_start(core_if); -+ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0); -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_pcd_stop(core_if); -+ cil_hcd_start(core_if); -+ DWC_SPINLOCK(core_if->lock); - core_if->op_state = A_HOST; - } - } -@@ -331,7 +251,7 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - } - - /* Clear GOTGINT */ -- dwc_write_reg32(&core_if->core_global_regs->gotgint, gotgint.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, gotgint.d32); - - return 1; - } -@@ -342,7 +262,7 @@ void w_conn_id_status_change(void *p) - uint32_t count = 0; - gotgctl_data_t gotgctl = {.d32 = 0 }; - -- gotgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); -+ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); - DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); - DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); - -@@ -362,7 +282,7 @@ void w_conn_id_status_change(void *p) - core_if->op_state = B_PERIPHERAL; - dwc_otg_core_init(core_if); - dwc_otg_enable_global_interrupts(core_if); -- pcd_start(core_if); -+ cil_pcd_start(core_if); - } else { - /* A-Device connector (Host Mode) */ - while (!dwc_otg_is_host_mode(core_if)) { -@@ -381,7 +301,7 @@ void w_conn_id_status_change(void *p) - */ - dwc_otg_core_init(core_if); - dwc_otg_enable_global_interrupts(core_if); -- hcd_start(core_if); -+ cil_hcd_start(core_if); - } - } - -@@ -389,7 +309,7 @@ void w_conn_id_status_change(void *p) - * This function handles the Connector ID Status Change Interrupt. It - * reads the OTG Interrupt Register (GOTCTL) to determine whether this - * is a Device to Host Mode transition or a Host Mode to Device -- * Transition. -+ * Transition. - * - * This only occurs when the cable is connected/removed from the PHY - * connector. -@@ -410,21 +330,26 @@ int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if) - gintsts_data_t gintsts = {.d32 = 0 }; - - gintmsk.b.sofintr = 1; -- dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); - - DWC_DEBUGPL(DBG_CIL, - " ++Connector ID Status Change Interrupt++ (%s)\n", - (dwc_otg_is_host_mode(core_if) ? "Host" : "Device")); -+ -+ DWC_SPINUNLOCK(core_if->lock); - - /* - * Need to schedule a work, as there are possible DELAY function calls -+ * Release lock before scheduling workq as it holds spinlock during scheduling - */ -+ - DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change, - core_if, "connection id status change"); -+ DWC_SPINLOCK(core_if->lock); - - /* Set flag and clear interrupt */ - gintsts.b.conidstschng = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - - return 1; - } -@@ -440,7 +365,6 @@ int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t * core_if) - */ - int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if) - { -- hprt0_data_t hprt0; - gintsts_data_t gintsts; - - #ifndef DWC_HOST_ONLY -@@ -449,23 +373,24 @@ int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if) - if (dwc_otg_is_device_mode(core_if)) { - DWC_PRINTF("SRP: Device mode\n"); - } else { -+ hprt0_data_t hprt0; - DWC_PRINTF("SRP: Host mode\n"); - - /* Turn on the port power bit. */ - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtpwr = 1; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - - /* Start the Connection timer. So a message can be displayed - * if connect does not occur within 10 seconds. */ -- hcd_session_start(core_if); -+ cil_hcd_session_start(core_if); - } - #endif - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.sessreqintr = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - - return 1; - } -@@ -482,22 +407,21 @@ void w_wakeup_detected(void *p) - pcgcctl_data_t pcgcctl = {.d32 = 0 }; - /* Restart the Phy Clock */ - pcgcctl.b.stoppclk = 1; -- dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); -+ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); - dwc_udelay(10); --#endif //0 -+#endif //0 - hprt0.d32 = dwc_otg_read_hprt0(core_if); - DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); - // dwc_mdelay(70); - hprt0.b.prtres = 0; /* Resume */ -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - DWC_DEBUGPL(DBG_ANY, "Clear Resume: HPRT0=%0x\n", -- dwc_read_reg32(core_if->host_if->hprt0)); -+ DWC_READ_REG32(core_if->host_if->hprt0)); - -- hcd_resume(core_if); -+ cil_hcd_resume(core_if); - - /** Change to L0 state*/ - core_if->lx_state = DWC_OTG_L0; -- - } - - /** -@@ -519,42 +443,43 @@ int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) - if (dwc_otg_is_device_mode(core_if)) { - dctl_data_t dctl = {.d32 = 0 }; - DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", -- dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -- dsts)); -+ DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->dsts)); - if (core_if->lx_state == DWC_OTG_L2) { - #ifdef PARTIAL_POWER_DOWN - if (core_if->hwcfg4.b.power_optimiz) { - pcgcctl_data_t power = {.d32 = 0 }; - -- power.d32 = dwc_read_reg32(core_if->pcgcctl); -+ power.d32 = DWC_READ_REG32(core_if->pcgcctl); - DWC_DEBUGPL(DBG_CIL, "PCGCCTL=%0x\n", - power.d32); - - power.b.stoppclk = 0; -- dwc_write_reg32(core_if->pcgcctl, power.d32); -+ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); - - power.b.pwrclmp = 0; -- dwc_write_reg32(core_if->pcgcctl, power.d32); -+ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); - - power.b.rstpdwnmodule = 0; -- dwc_write_reg32(core_if->pcgcctl, power.d32); -+ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); - } - #endif -- /* Clear the Remote Wakeup Signalling */ -+ /* Clear the Remote Wakeup Signaling */ - dctl.b.rmtwkupsig = 1; -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -- dctl, dctl.d32, 0); -+ DWC_MODIFY_REG32(&core_if->dev_if-> -+ dev_global_regs->dctl, dctl.d32, 0); - -+ DWC_SPINUNLOCK(core_if->lock); - if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -- core_if->pcd_cb->resume_wakeup(core_if->pcd_cb-> -- p); -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); - } -+ DWC_SPINLOCK(core_if->lock); - } else { - glpmcfg_data_t lpmcfg; - lpmcfg.d32 = -- dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - lpmcfg.b.hird_thres &= (~(1 << 4)); -- dwc_write_reg32(&core_if->core_global_regs->glpmcfg, -+ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, - lpmcfg.d32); - } - /** Change to L0 state*/ -@@ -565,8 +490,7 @@ int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) - - /* Restart the Phy Clock */ - pcgcctl.b.stoppclk = 1; -- dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); -- -+ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); - DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71); - } else { - /** Change to L0 state*/ -@@ -577,14 +501,434 @@ int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.wkupintr = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that the Wakeup Logic has detected a -+ * Device disconnect. -+ */ -+static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if) -+{ -+ gpwrdn_data_t gpwrdn = { .d32 = 0 }; -+ gpwrdn_data_t gpwrdn_temp = { .d32 = 0 }; -+ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ -+ DWC_PRINTF("%s called\n", __FUNCTION__); -+ -+ if (!core_if->hibernation_suspend) { -+ DWC_PRINTF("Already exited from Hibernation\n"); -+ return 1; -+ } -+ -+ /* Switch on the voltage to the core */ -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Reset the core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Disable power clamps*/ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Remove reset the core signal */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable PMU interrupt */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ core_if->hibernation_suspend = 0; -+ -+ /* Disable PMU */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ if (gpwrdn_temp.b.idsts) { -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ } else { -+ core_if->op_state = A_HOST; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_hcd_start(core_if); -+ } -+ -+ return 1; -+} -+ -+/** -+ * This interrupt indicates that the Wakeup Logic has detected a -+ * remote wakeup sequence. -+ */ -+static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if) -+{ -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ DWC_DEBUGPL(DBG_ANY, -+ "++Powerdown Remote Wakeup Detected Interrupt++\n"); -+ -+ if (!core_if->hibernation_suspend) { -+ DWC_PRINTF("Already exited from Hibernation\n"); -+ return 1; -+ } -+ -+ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ if (gpwrdn.b.idsts) { // Device Mode -+ if ((core_if->power_down == 2) -+ && (core_if->hibernation_suspend == 1)) { -+ dwc_otg_device_hibernation_restore(core_if, 0, 0); -+ } -+ } else { -+ if ((core_if->power_down == 2) -+ && (core_if->hibernation_suspend == 1)) { -+ dwc_otg_host_hibernation_restore(core_if, 1, 0); -+ } -+ } -+ return 1; -+} -+ -+static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev) -+{ -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; -+ dwc_otg_core_if_t *core_if = otg_dev->core_if; -+ -+ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); -+ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ if (core_if->power_down == 2) -+ { -+ if (!core_if->hibernation_suspend) { -+ DWC_PRINTF("Already exited from Hibernation\n"); -+ return 1; -+ } -+ DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n"); -+ /* Switch on the voltage to the core */ -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Reset the core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Disable power clamps */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Remove reset the core signal */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable PMU interrupt */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /*Indicates that we are exiting from hibernation */ -+ core_if->hibernation_suspend = 0; -+ -+ /* Disable PMU */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ gpwrdn.d32 = core_if->gr_backup->gpwrdn_local; -+ if (gpwrdn.b.dis_vbus == 1) { -+ gpwrdn.d32 = 0; -+ gpwrdn.b.dis_vbus = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ } -+ -+ if (gpwrdn_temp.b.idsts) { -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ } else { -+ core_if->op_state = A_HOST; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_hcd_start(core_if); -+ } -+ } -+ -+ if (core_if->adp_enable) -+ { -+ uint8_t is_host = 0; -+ DWC_SPINUNLOCK(core_if->lock); -+ /* Change the core_if's lock to hcd/pcd lock depend on mode? */ -+#ifndef DWC_HOST_ONLY -+ if (gpwrdn_temp.b.idsts) -+ core_if->lock = otg_dev->pcd->lock; -+#endif -+#ifndef DWC_DEVICE_ONLY -+ if (!gpwrdn_temp.b.idsts) { -+ core_if->lock = otg_dev->hcd->lock; -+ is_host = 1; -+ } -+#endif -+ DWC_PRINTF("RESTART ADP\n"); -+ if (core_if->adp.probe_enabled) -+ dwc_otg_adp_probe_stop(core_if); -+ if (core_if->adp.sense_enabled) -+ dwc_otg_adp_sense_stop(core_if); -+ if (core_if->adp.sense_timer_started) -+ DWC_TIMER_CANCEL(core_if->adp.sense_timer); -+ if (core_if->adp.vbuson_timer_started) -+ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); -+ core_if->adp.probe_timer_values[0] = -1; -+ core_if->adp.probe_timer_values[1] = -1; -+ core_if->adp.sense_timer_started = 0; -+ core_if->adp.vbuson_timer_started = 0; -+ core_if->adp.probe_counter = 0; -+ core_if->adp.gpwrdn = 0; -+ -+ /* Disable PMU and restart ADP */ -+ gpwrdn_temp.d32 = 0; -+ gpwrdn_temp.b.pmuactv = 1; -+ gpwrdn_temp.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ DWC_PRINTF("Check point 1\n"); -+ dwc_mdelay(110); -+ dwc_otg_adp_start(core_if, is_host); -+ DWC_SPINLOCK(core_if->lock); -+ } -+ -+ -+ return 1; -+} -+ -+static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if) -+{ -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ int32_t otg_cap_param = core_if->core_params->otg_cap; -+ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); -+ -+ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ if (core_if->power_down == 2) { -+ if (!core_if->hibernation_suspend) { -+ DWC_PRINTF("Already exited from Hibernation\n"); -+ return 1; -+ } -+ -+ if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || -+ otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) && -+ gpwrdn.b.bsessvld == 0) { -+ /* Save gpwrdn register for further usage if stschng interrupt */ -+ core_if->gr_backup->gpwrdn_local = -+ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */ -+ return 1; -+ } -+ -+ /* Switch on the voltage to the core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Reset the core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Disable power clamps */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Remove reset the core signal */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable PMU interrupt */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /*Indicates that we are exiting from hibernation */ -+ core_if->hibernation_suspend = 0; -+ -+ /* Disable PMU */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ -+ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || -+ otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) { -+ /* -+ * Initiate SRP after initial ADP probe. -+ */ -+ dwc_otg_initiate_srp(core_if); -+ } -+ } -+ -+ return 1; -+} -+/** -+ * This interrupt indicates that the Wakeup Logic has detected a -+ * status change either on IDDIG or BSessVld. -+ */ -+static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev) -+{ -+ int retval; -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; -+ dwc_otg_core_if_t *core_if = otg_dev->core_if; -+ -+ DWC_PRINTF("%s called\n", __FUNCTION__); -+ -+ if (core_if->power_down == 2) { -+ if (core_if->hibernation_suspend <= 0) { -+ DWC_PRINTF("Already exited from Hibernation\n"); -+ return 1; -+ } else -+ gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local; -+ -+ } else { -+ gpwrdn_temp.d32 = core_if->adp.gpwrdn; -+ } -+ -+ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ -+ if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) { -+ retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev); -+ } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) { -+ retval = dwc_otg_handle_pwrdn_session_change(core_if); -+ } -+ -+ return retval; -+} -+ -+/** -+ * This interrupt indicates that the Wakeup Logic has detected a -+ * SRP. -+ */ -+static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if) -+{ -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ -+ DWC_PRINTF("%s called\n", __FUNCTION__); -+ -+ if (!core_if->hibernation_suspend) { -+ DWC_PRINTF("Already exited from Hibernation\n"); -+ return 1; -+ } -+#ifdef DWC_DEV_SRPCAP -+ if (core_if->pwron_timer_started) { -+ core_if->pwron_timer_started = 0; -+ DWC_TIMER_CANCEL(core_if->pwron_timer); -+ } -+#endif -+ -+ /* Switch on the voltage to the core */ -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Reset the core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Disable power clamps */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Remove reset the core signal */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable PMU interrupt */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Indicates that we are exiting from hibernation */ -+ core_if->hibernation_suspend = 0; -+ -+ /* Disable PMU */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Programm Disable VBUS to 0 */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.dis_vbus = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /*Initialize the core as Host */ -+ core_if->op_state = A_HOST; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_hcd_start(core_if); - - return 1; - } - --/** -+/** This interrupt indicates that restore command after Hibernation -+ * was completed by the core. */ -+int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if) -+{ -+ pcgcctl_data_t pcgcctl; -+ DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n"); -+ -+ //TODO De-assert restore signal. 8.a -+ pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl); -+ if (pcgcctl.b.restoremode == 1) { -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ /* -+ * If restore mode is Remote Wakeup, -+ * unmask Remote Wakeup interrupt. -+ */ -+ gintmsk.b.wkupintr = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, -+ 0, gintmsk.d32); -+ } -+ -+ return 1; -+} -+ -+/** - * This interrupt indicates that a device has been disconnected from -- * the root port. -+ * the root port. - */ - int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) - { -@@ -599,13 +943,15 @@ int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) - if (core_if->op_state == B_HOST) { - /* If in device mode Disconnect and stop the HCD, then - * start the PCD. */ -- hcd_disconnect(core_if); -- pcd_start(core_if); -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_hcd_disconnect(core_if); -+ cil_pcd_start(core_if); -+ DWC_SPINLOCK(core_if->lock); - core_if->op_state = B_PERIPHERAL; - } else if (dwc_otg_is_device_mode(core_if)) { - gotgctl_data_t gotgctl = {.d32 = 0 }; - gotgctl.d32 = -- dwc_read_reg32(&core_if->core_global_regs->gotgctl); -+ DWC_READ_REG32(&core_if->core_global_regs->gotgctl); - if (gotgctl.b.hstsethnpen == 1) { - /* Do nothing, if HNP in process the OTG - * interrupt "Host Negotiation Detected" -@@ -614,8 +960,10 @@ int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) - } else if (gotgctl.b.devhnpen == 0) { - /* If in device mode Disconnect and stop the HCD, then - * start the PCD. */ -- hcd_disconnect(core_if); -- pcd_start(core_if); -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_hcd_disconnect(core_if); -+ cil_pcd_start(core_if); -+ DWC_SPINLOCK(core_if->lock); - core_if->op_state = B_PERIPHERAL; - } else { - DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); -@@ -623,7 +971,25 @@ int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) - } else { - if (core_if->op_state == A_HOST) { - /* A-Cable still connected but device disconnected. */ -- hcd_disconnect(core_if); -+ cil_hcd_disconnect(core_if); -+ if (core_if->adp_enable) { -+ gpwrdn_data_t gpwrdn = { .d32 = 0 }; -+ cil_hcd_stop(core_if); -+ /* Enable Power Down Logic */ -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_otg_adp_probe_start(core_if); -+ -+ /* Power off the core */ -+ if (core_if->power_down == 2) { -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs-> -+ gpwrdn, gpwrdn.d32, 0); -+ } -+ } - } - } - #endif -@@ -632,14 +998,14 @@ int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) - - gintsts.d32 = 0; - gintsts.b.disconnect = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - return 1; - } - - /** - * This interrupt indicates that SUSPEND state has been detected on - * the USB. -- * -+ * - * For HNP the USB Suspend interrupt signals the change from - * "a_peripheral" to "a_host". - * -@@ -650,6 +1016,7 @@ int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) - { - dsts_data_t dsts; - gintsts_data_t gintsts; -+ dcfg_data_t dcfg; - - DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); - -@@ -657,7 +1024,7 @@ int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) - /* Check the Device status register to determine if the Suspend - * state is active. */ - dsts.d32 = -- dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", dsts.d32); - DWC_DEBUGPL(DBG_PCD, "DSTS.Suspend Status=%d " - "HWCFG4.power Optimize=%d\n", -@@ -671,26 +1038,118 @@ int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) - DWC_DEBUGPL(DBG_CIL, "suspend\n"); - - power.b.pwrclmp = 1; -- dwc_write_reg32(core_if->pcgcctl, power.d32); -+ DWC_WRITE_REG32(core_if->pcgcctl, power.d32); - - power.b.rstpdwnmodule = 1; -- dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); - - power.b.stoppclk = 1; -- dwc_modify_reg32(core_if->pcgcctl, 0, power.d32); -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, power.d32); - - } else { - DWC_DEBUGPL(DBG_ANY, "disconnect?\n"); - } - #endif -- /* PCD callback for suspend. */ -- pcd_suspend(core_if); -+ /* PCD callback for suspend. Release the lock inside of callback function */ -+ cil_pcd_suspend(core_if); -+ if (core_if->power_down == 2) -+ { -+ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); -+ DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state); -+ DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr); -+ -+ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ gusbcfg_data_t gusbcfg = {.d32 = 0 }; -+ -+ /* Change to L2(suspend) state */ -+ core_if->lx_state = DWC_OTG_L2; -+ -+ /* Clear interrupt in gintsts */ -+ gintsts.d32 = 0; -+ gintsts.b.usbsuspend = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs-> -+ gintsts, gintsts.d32); -+ DWC_PRINTF("Start of hibernation completed\n"); -+ dwc_otg_save_global_regs(core_if); -+ dwc_otg_save_dev_regs(core_if); -+ -+ gusbcfg.d32 = -+ DWC_READ_REG32(&core_if->core_global_regs-> -+ gusbcfg); -+ if (gusbcfg.b.ulpi_utmi_sel == 1) { -+ /* ULPI interface */ -+ /* Suspend the Phy Clock */ -+ pcgcctl.d32 = 0; -+ pcgcctl.b.stoppclk = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, -+ pcgcctl.d32); -+ dwc_udelay(10); -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ } else { -+ /* UTMI+ Interface */ -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ pcgcctl.b.stoppclk = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, -+ pcgcctl.d32); -+ dwc_udelay(10); -+ } -+ -+ /* Set flag to indicate that we are in hibernation */ -+ core_if->hibernation_suspend = 1; -+ /* Enable interrupts from wake up logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Unmask device mode interrupts in GPWRDN */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.rst_det_msk = 1; -+ gpwrdn.b.lnstchng_msk = 1; -+ gpwrdn.b.sts_chngint_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Enable Power Down Clamp */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Switch off VDD */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ -+ /* Save gpwrdn register for further usage if stschng interrupt */ -+ core_if->gr_backup->gpwrdn_local = -+ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ DWC_PRINTF("Hibernation completed\n"); -+ -+ return 1; -+ } -+ } - } else { - if (core_if->op_state == A_PERIPHERAL) { - DWC_DEBUGPL(DBG_ANY, "a_peripheral->a_host\n"); - /* Clear the a_peripheral flag, back to a_host. */ -- pcd_stop(core_if); -- hcd_start(core_if); -+ DWC_SPINUNLOCK(core_if->lock); -+ cil_pcd_stop(core_if); -+ cil_hcd_start(core_if); -+ DWC_SPINLOCK(core_if->lock); - core_if->op_state = A_HOST; - } - } -@@ -701,7 +1160,7 @@ int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.usbsuspend = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - - return 1; - } -@@ -719,20 +1178,20 @@ static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) - DWC_PRINTF("Unexpected LPM interrupt\n"); - } - -- lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32); - - if (dwc_otg_is_host_mode(core_if)) { -- hcd_sleep(core_if); -+ cil_hcd_sleep(core_if); - } else { - lpmcfg.b.hird_thres |= (1 << 4); -- dwc_write_reg32(&core_if->core_global_regs->glpmcfg, -+ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, - lpmcfg.d32); - } - -- /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ -+ /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ - dwc_udelay(10); -- lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - if (lpmcfg.b.prt_sleep_sts) { - /* Save the current state */ - core_if->lx_state = DWC_OTG_L1; -@@ -741,16 +1200,17 @@ static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.lpmtranrcvd = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - return 1; - } --#endif /* CONFIG_USB_DWC_OTG_LPM */ -+#endif /* CONFIG_USB_DWC_OTG_LPM */ - - /** - * This function returns the Core Interrupt register. - */ - static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) - { -+ gahbcfg_data_t gahbcfg = {.d32 = 0 }; - gintsts_data_t gintsts; - gintmsk_data_t gintmsk; - gintmsk_data_t gintmsk_common = {.d32 = 0 }; -@@ -764,13 +1224,16 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) - #ifdef CONFIG_USB_DWC_OTG_LPM - gintmsk_common.b.lpmtranrcvd = 1; - #endif -- /** @todo: The port interrupt occurs while in device -- * mode. Added code to CIL to clear the interrupt for now! -+ gintmsk_common.b.restoredone = 1; -+ /** @todo: The port interrupt occurs while in device -+ * mode. Added code to CIL to clear the interrupt for now! - */ - gintmsk_common.b.portintr = 1; - -- gintsts.d32 = dwc_read_reg32(&core_if->core_global_regs->gintsts); -- gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk); -+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); -+ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); -+ gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); -+ - #ifdef DEBUG - /* if any common interrupts set */ - if (gintsts.d32 & gintmsk_common.d32) { -@@ -778,15 +1241,26 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) - gintsts.d32, gintmsk.d32); - } - #endif -- -- return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); -+ if (gahbcfg.b.glblintrmsk) -+ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); -+ else -+ return 0; - - } - -+/* MACRO for clearing interupt bits in GPWRDN register */ -+#define CLEAR_GPWRDN_INTR(__core_if,__intr) \ -+do { \ -+ gpwrdn_data_t gpwrdn = {.d32=0}; \ -+ gpwrdn.b.__intr = 1; \ -+ DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \ -+ 0, gpwrdn.d32); \ -+} while (0) -+ - /** - * Common interrupt handler. - * -- * The common interrupts are those that occur in both Host and Device mode. -+ * The common interrupts are those that occur in both Host and Device mode. - * This handler handles the following interrupts: - * - Mode Mismatch Interrupt - * - Disconnect Interrupt -@@ -794,53 +1268,124 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) - * - Connector ID Status Change Interrupt - * - Session Request Interrupt. - * - Resume / Remote Wakeup Detected Interrupt. -- * - LPM Transaction Received Interrutp -- * -+ * - LPM Transaction Received Interrupt -+ * - ADP Transaction Received Interrupt -+ * - */ --int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t * core_if) -+int32_t dwc_otg_handle_common_intr(void *dev) - { - int retval = 0; - gintsts_data_t gintsts; -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ dwc_otg_device_t *otg_dev = dev; -+ dwc_otg_core_if_t *core_if = otg_dev->core_if; -+ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ if (dwc_otg_is_device_mode(core_if)) -+ core_if->frame_num = dwc_otg_get_frame_number(core_if); -+ -+ if (core_if->lock) -+ DWC_SPINLOCK(core_if->lock); -+ -+ if (core_if->hibernation_suspend <= 0) { -+ gintsts.d32 = dwc_otg_read_common_intr(core_if); -+ -+ if (gintsts.b.modemismatch) { -+ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); -+ } -+ if (gintsts.b.otgintr) { -+ retval |= dwc_otg_handle_otg_intr(core_if); -+ } -+ if (gintsts.b.conidstschng) { -+ retval |= dwc_otg_handle_conn_id_status_change_intr(core_if); -+ } -+ if (gintsts.b.disconnect) { -+ retval |= dwc_otg_handle_disconnect_intr(core_if); -+ } -+ if (gintsts.b.sessreqintr) { -+ retval |= dwc_otg_handle_session_req_intr(core_if); -+ } -+ if (gintsts.b.wkupintr) { -+ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); -+ } -+ if (gintsts.b.usbsuspend) { -+ retval |= dwc_otg_handle_usb_suspend_intr(core_if); -+ } -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ if (gintsts.b.lpmtranrcvd) { -+ retval |= dwc_otg_handle_lpm_intr(core_if); -+ } -+#endif -+ if (gintsts.b.restoredone) { -+ gintsts.d32 = 0; -+ if (core_if->power_down == 2) -+ core_if->hibernation_suspend = -1; -+ gintsts.b.restoredone = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); -+ DWC_PRINTF(" --Restore done interrupt received-- \n"); -+ retval |= 1; -+ } -+ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { -+ /* The port interrupt occurs while in device mode with HPRT0 -+ * Port Enable/Disable. -+ */ -+ gintsts.d32 = 0; -+ gintsts.b.portintr = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); -+ retval |= 1; - -- gintsts.d32 = dwc_otg_read_common_intr(core_if); -+ } -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); - -- if (gintsts.b.modemismatch) { -- retval |= dwc_otg_handle_mode_mismatch_intr(core_if); -- } -- if (gintsts.b.otgintr) { -- retval |= dwc_otg_handle_otg_intr(core_if); -- } -- if (gintsts.b.conidstschng) { -- retval |= dwc_otg_handle_conn_id_status_change_intr(core_if); -- } -- if (gintsts.b.disconnect) { -- retval |= dwc_otg_handle_disconnect_intr(core_if); -- } -- if (gintsts.b.sessreqintr) { -- retval |= dwc_otg_handle_session_req_intr(core_if); -- } -- if (gintsts.b.wkupintr) { -- retval |= dwc_otg_handle_wakeup_detected_intr(core_if); -- } -- if (gintsts.b.usbsuspend) { -- retval |= dwc_otg_handle_usb_suspend_intr(core_if); -+ if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) { -+ CLEAR_GPWRDN_INTR(core_if, disconn_det); -+ if (gpwrdn.b.linestate == 0) { -+ dwc_otg_handle_pwrdn_disconnect_intr(core_if); -+ } else { -+ DWC_PRINTF("Disconnect detected while linestate is not 0\n"); -+ } -+ -+ retval |= 1; -+ } -+ if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) { -+ CLEAR_GPWRDN_INTR(core_if, lnstschng); -+ /* remote wakeup from hibernation */ -+ if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) { -+ dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if); -+ } else { -+ DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate); -+ } -+ retval |= 1; -+ } -+ if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) { -+ CLEAR_GPWRDN_INTR(core_if, rst_det); -+ if (gpwrdn.b.linestate == 0) { -+ DWC_PRINTF("Reset detected\n"); -+ retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1); -+ } -+ } -+ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { -+ CLEAR_GPWRDN_INTR(core_if, srp_det); -+ dwc_otg_handle_pwrdn_srp_intr(core_if); -+ retval |= 1; -+ } - } --#ifdef CONFIG_USB_DWC_OTG_LPM -- if (gintsts.b.lpmtranrcvd) { -- retval |= dwc_otg_handle_lpm_intr(core_if); -+ /* Handle ADP interrupt here */ -+ if (gpwrdn.b.adp_int) { -+ DWC_PRINTF("ADP interrupt\n"); -+ CLEAR_GPWRDN_INTR(core_if, adp_int); -+ dwc_otg_adp_handle_intr(core_if); -+ retval |= 1; - } --#endif -+ if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) { -+ DWC_PRINTF("STS CHNG interrupt asserted\n"); -+ CLEAR_GPWRDN_INTR(core_if, sts_chngint); -+ dwc_otg_handle_pwrdn_stschng_intr(otg_dev); - -- if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { -- /* The port interrupt occurs while in device mode with HPRT0 -- * Port Enable/Disable. -- */ -- gintsts.d32 = 0; -- gintsts.b.portintr = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, -- gintsts.d32); - retval |= 1; -- - } -+ if (core_if->lock) -+ DWC_SPINUNLOCK(core_if->lock); -+ - return retval; - } -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -index 25aae5e..3207cb6 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $ -- * $Revision: #4 $ -- * $Date: 2008/12/18 $ -- * $Change: 1155299 $ -+ * $Revision: #12 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871159 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -63,7 +63,7 @@ - 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); -+extern int32_t dwc_otg_handle_common_intr(void *otg_dev); - - /** @name OTG Core Parameters */ - /** @{ */ -@@ -268,7 +268,7 @@ 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 --#define dwc_param_host_channels_default 8// Broadcom BCM2708 -+#define dwc_param_host_channels_default 8 // Broadcom BCM2708 - - /** The number of endpoints in addition to EP0 available for device - * mode operations. -@@ -297,7 +297,7 @@ extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t * core_if, - #define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI - - /** -- * Specifies the UTMI+ Data Width. This parameter is -+ * 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 -@@ -379,7 +379,7 @@ 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 -+#define dwc_param_dev_tx_fifo_size_default 768 - - /** Thresholding enable flag- - * bit 0 - enable non-ISO Tx thresholding -@@ -431,17 +431,56 @@ extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t * core_if, - #define dwc_param_mpi_enable_default 0 - - /** -+ * Specifies whether ADP capability is enabled -+ */ -+extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, -+ int32_t val); -+extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if); -+#define dwc_param_adp_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 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 - -+extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, -+ int32_t val); -+extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if); -+#define dwc_param_power_down_default 0 -+ -+extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, -+ int32_t val); -+extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if); -+#define dwc_param_reload_ctl_default 0 -+ -+extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, -+ int32_t val); -+extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if); -+#define dwc_param_dev_out_nak_default 0 -+ -+extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, -+ int32_t val); -+extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if); -+#define dwc_param_cont_on_bna_default 0 -+ -+extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, -+ int32_t val); -+extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if); -+#define dwc_param_ahb_single_default 0 -+ -+extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val); -+extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if); -+#define dwc_param_otg_ver_default 0 -+ - /** @} */ - - /** @name Access to registers and bit-fields */ -@@ -521,6 +560,12 @@ extern int dwc_otg_set_param_ic_usb_cap(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); -+ -+/** -+ * Get value of flag indicating core state - hibernated or not -+ */ -+extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if); -+ - /** - * Set value of prtpwr field from the HPRT0 register - */ -@@ -536,6 +581,24 @@ extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, - extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val); - - /** -+ * Get value of ModeChTimEn field from the HCFG regsiter -+ */ -+extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if); -+/** -+ * Set value of ModeChTimEn field from the HCFG regsiter -+ */ -+extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val); -+ -+/** -+ * Get value of Fram Interval field from the HFIR regsiter -+ */ -+extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if); -+/** -+ * Set value of Frame Interval field from the HFIR regsiter -+ */ -+extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val); -+ -+/** - * Set value of prtres field from the HPRT0 register - *FIXME Remove? - */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h -index e81d093..8681aa9 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h -@@ -68,6 +68,9 @@ static inline uint32_t SET_DEBUG_LEVEL(const uint32_t new) - /** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host - * mode. */ - #define DBG_HCD_URB (0x800) -+/** When debug level has the DBG_HCDI bit set, display host interrupt -+ * messages. */ -+#define DBG_HCDI (0x1000) - - /** When debug level has any bit set, display debug messages */ - #define DBG_ANY (0xFF) -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -index 0e22013..8a6e207 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ -- * $Revision: #76 $ -- * $Date: 2009/05/03 $ -- * $Change: 1245589 $ -+ * $Revision: #91 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871159 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -48,43 +48,7 @@ - * device. - */ - --#include --#include --#include --#include --#include --#include --#include --#include /* permission constants */ --#include --#include -- --#ifdef LM_INTERFACE --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --#include --#include --#else --/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - -- here we use definitions stolen from arm-integrator headers --*/ --#include --#include --#endif --#include --#include -- --#elif defined(PLATFORM_INTERFACE) -- --#include --#include -- --#endif -- --# include -- --#include -- -- -+#include "dwc_otg_os_dep.h" - #include "dwc_os.h" - #include "dwc_otg_dbg.h" - #include "dwc_otg_driver.h" -@@ -93,49 +57,51 @@ - #include "dwc_otg_pcd_if.h" - #include "dwc_otg_hcd_if.h" - --#define DWC_DRIVER_VERSION "2.90b 6-MAY-2010" -+#define DWC_DRIVER_VERSION "2.94b 27-OCT-2011 (rev 01-DEC-2011)" - #define DWC_DRIVER_DESC "HS OTG USB Controller driver" - - static const char dwc_driver_name[] = "dwc_otg"; - - extern int pcd_init( - #ifdef LM_INTERFACE -- struct lm_device *_dev -+ struct lm_device *_dev - #elif defined(PCI_INTERFACE) -- struct pci_dev *_dev -+ struct pci_dev *_dev - #elif defined(PLATFORM_INTERFACE) - struct platform_device *dev - #endif -- ); -+ ); - extern int hcd_init( - #ifdef LM_INTERFACE -- struct lm_device *_dev -+ struct lm_device *_dev - #elif defined(PCI_INTERFACE) -- struct pci_dev *_dev -+ struct pci_dev *_dev - #elif defined(PLATFORM_INTERFACE) - struct platform_device *dev - #endif -- ); -+ ); - - extern int pcd_remove( - #ifdef LM_INTERFACE -- struct lm_device *_dev -+ struct lm_device *_dev - #elif defined(PCI_INTERFACE) -- struct pci_dev *_dev -+ struct pci_dev *_dev - #elif defined(PLATFORM_INTERFACE) - struct platform_device *_dev - #endif -- ); -+ ); - - extern void hcd_remove( - #ifdef LM_INTERFACE -- struct lm_device *_dev -+ struct lm_device *_dev - #elif defined(PCI_INTERFACE) -- struct pci_dev *_dev -+ struct pci_dev *_dev - #elif defined(PLATFORM_INTERFACE) - struct platform_device *_dev - #endif -- ); -+ ); -+ -+extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); - - /*-------------------------------------------------------------------------*/ - /* Encapsulate the module parameter settings */ -@@ -178,6 +144,13 @@ struct dwc_otg_driver_module_params { - int32_t lpm_enable; - int32_t ic_usb_cap; - int32_t ahb_thr_ratio; -+ int32_t power_down; -+ int32_t reload_ctl; -+ int32_t dev_out_nak; -+ int32_t cont_on_bna; -+ int32_t ahb_single; -+ int32_t otg_ver; -+ int32_t adp_enable; - }; - - static struct dwc_otg_driver_module_params dwc_otg_module_params = { -@@ -254,6 +227,13 @@ struct dwc_otg_driver_module_params { - .lpm_enable = -1, - .ic_usb_cap = -1, - .ahb_thr_ratio = -1, -+ .power_down = -1, -+ .reload_ctl = -1, -+ .dev_out_nak = -1, -+ .cont_on_bna = -1, -+ .ahb_single = -1, -+ .otg_ver = -1, -+ .adp_enable = -1, - }; - - /** -@@ -436,7 +416,8 @@ static int set_parameters(dwc_otg_core_if_t * core_if) - } - if (dwc_otg_module_params.ulpi_fs_ls != -1) { - retval += -- dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_otg_module_params.ulpi_fs_ls); -+ dwc_otg_set_param_ulpi_fs_ls(core_if, -+ dwc_otg_module_params.ulpi_fs_ls); - } - if (dwc_otg_module_params.ts_dline != -1) { - retval += -@@ -513,9 +494,50 @@ static int set_parameters(dwc_otg_core_if_t * core_if) - dwc_otg_module_params. - rx_thr_length); - } -- if(dwc_otg_module_params.ahb_thr_ratio != -1) { -+ if (dwc_otg_module_params.ahb_thr_ratio != -1) { -+ retval += -+ dwc_otg_set_param_ahb_thr_ratio(core_if, -+ dwc_otg_module_params.ahb_thr_ratio); -+ } -+ if (dwc_otg_module_params.power_down != -1) { - retval += -- dwc_otg_set_param_ahb_thr_ratio(core_if, dwc_otg_module_params.ahb_thr_ratio); -+ dwc_otg_set_param_power_down(core_if, -+ dwc_otg_module_params.power_down); -+ } -+ if (dwc_otg_module_params.reload_ctl != -1) { -+ retval += -+ dwc_otg_set_param_reload_ctl(core_if, -+ dwc_otg_module_params.reload_ctl); -+ } -+ -+ if (dwc_otg_module_params.dev_out_nak != -1) { -+ retval += -+ dwc_otg_set_param_dev_out_nak(core_if, -+ dwc_otg_module_params.dev_out_nak); -+ } -+ -+ if (dwc_otg_module_params.cont_on_bna != -1) { -+ retval += -+ dwc_otg_set_param_cont_on_bna(core_if, -+ dwc_otg_module_params.cont_on_bna); -+ } -+ -+ if (dwc_otg_module_params.ahb_single != -1) { -+ retval += -+ dwc_otg_set_param_ahb_single(core_if, -+ dwc_otg_module_params.ahb_single); -+ } -+ -+ if (dwc_otg_module_params.otg_ver != -1) { -+ retval += -+ dwc_otg_set_param_otg_ver(core_if, -+ dwc_otg_module_params.otg_ver); -+ } -+ if (dwc_otg_module_params.adp_enable != -1) { -+ retval += -+ dwc_otg_set_param_adp_enable(core_if, -+ dwc_otg_module_params. -+ adp_enable); - } - return retval; - } -@@ -526,10 +548,9 @@ static int set_parameters(dwc_otg_core_if_t * core_if) - */ - static irqreturn_t dwc_otg_common_irq(int irq, void *dev) - { -- dwc_otg_device_t *otg_dev = dev; - int32_t retval = IRQ_NONE; - -- retval = dwc_otg_handle_common_intr(otg_dev->core_if); -+ retval = dwc_otg_handle_common_intr(dev); - if (retval != 0) { - S3C2410X_CLEAR_EINTPEND(); - } -@@ -546,54 +567,41 @@ static irqreturn_t dwc_otg_common_irq(int irq, void *dev) - * @param _dev - */ - #ifdef LM_INTERFACE --static void dwc_otg_driver_remove( -- struct lm_device *_dev -+#define REM_RETVAL(n) -+static void dwc_otg_driver_remove( struct lm_device *_dev ) -+{ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); - #elif defined(PCI_INTERFACE) --static void dwc_otg_driver_remove( -- struct pci_dev *_dev -+#define REM_RETVAL(n) -+static void dwc_otg_driver_remove( struct pci_dev *_dev ) -+{ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); - #elif defined(PLATFORM_INTERFACE) --static int dwc_otg_driver_remove( -- struct platform_device *_dev -+#define REM_RETVAL(n) n -+static int dwc_otg_driver_remove( struct platform_device *_dev ) -+{ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); - #endif --) -- --{ --#ifdef LM_INTERFACE -- dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); --#endif -- - - DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev); - - if (!otg_dev) { - /* Memory allocation for the dwc_otg_device failed. */ - DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); --#ifdef PLATFORM_INTERFACE -- return -ENOMEM; --#else -- return; --#endif -+ return REM_RETVAL(-ENOMEM); - } - #ifndef DWC_DEVICE_ONLY - if (otg_dev->hcd) { - hcd_remove(_dev); - } else { - DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); --#ifdef PLATFORM_INTERFACE -- return -EINVAL; --#else -- return; --#endif -+ return REM_RETVAL(-EINVAL); - } - #endif - - #ifndef DWC_HOST_ONLY - if (otg_dev->pcd) { - pcd_remove(_dev); -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__); -+ return REM_RETVAL(-EINVAL); - } - #endif - /* -@@ -605,10 +613,16 @@ static int dwc_otg_driver_remove( - #else - free_irq(_dev->irq, otg_dev); - #endif -- } -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__); -+ return REM_RETVAL(-ENXIO); -+ } - - if (otg_dev->core_if) { - dwc_otg_cil_remove(otg_dev->core_if); -+ } else { -+ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__); -+ return REM_RETVAL(-ENXIO); - } - - /* -@@ -619,23 +633,24 @@ static int dwc_otg_driver_remove( - /* - * Return the memory. - */ -- if (otg_dev->base) { -- iounmap(otg_dev->base); -+ if (otg_dev->os_dep.base) { -+ iounmap(otg_dev->os_dep.base); - } -- dwc_free(otg_dev); -+ DWC_FREE(otg_dev); - - /* - * Clear the drvdata pointer. - */ - #ifdef LM_INTERFACE - lm_set_drvdata(_dev, 0); --#elif defined(PCI_INTERFACE) -- release_mem_region(otg_dev->rsrc_start, otg_dev->rsrc_len); -- pci_set_drvdata(_dev, 0); -+#elif defined(PCI_INTERFACE) -+ release_mem_region(otg_dev->os_dep.rsrc_start, -+ otg_dev->os_dep.rsrc_len); -+ pci_set_drvdata(_dev, 0); - #elif defined(PLATFORM_INTERFACE) - platform_set_drvdata(_dev, 0); -- return 0; - #endif -+ return REM_RETVAL(0); - } - - /** -@@ -651,13 +666,14 @@ static int dwc_otg_driver_remove( - */ - static int dwc_otg_driver_probe( - #ifdef LM_INTERFACE --struct lm_device *_dev --#elif defined(PCI_INTERFACE) --struct pci_dev *_dev, const struct pci_device_id *id -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev, -+ const struct pci_device_id *id - #elif defined(PLATFORM_INTERFACE) --struct platform_device *_dev -+ struct platform_device *_dev - #endif --) -+ ) - { - int retval = 0; - dwc_otg_device_t *dwc_otg_device; -@@ -666,9 +682,9 @@ struct platform_device *_dev - dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev); - #ifdef LM_INTERFACE - dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start); --#elif defined(PCI_INTERFACE) -+#elif defined(PCI_INTERFACE) - if (!id) { -- DWC_ERROR("Invalid pci_device_id %p", id); -+ DWC_ERROR("Invalid pci_device_id %p", id); - return -EINVAL; - } - -@@ -685,76 +701,77 @@ struct platform_device *_dev - (unsigned)(_dev->resource->end - _dev->resource->start)); - #endif - -- -- dwc_otg_device = dwc_alloc(sizeof(dwc_otg_device_t)); -+ dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t)); - - if (!dwc_otg_device) { - dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n"); -- retval = -ENOMEM; -- goto fail; -+ return -ENOMEM; - } - - memset(dwc_otg_device, 0, sizeof(*dwc_otg_device)); -- dwc_otg_device->reg_offset = 0xFFFFFFFF; -+ dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF; - - /* - * Map the DWC_otg Core memory into virtual address space. - */ - #ifdef LM_INTERFACE --#if 1 -- dwc_otg_device->base = ioremap(_dev->resource.start, SZ_256K); --#else -- struct map_desc desc = { -- .virtual = IO_ADDRESS((unsigned)_dev->resource.start), -- .pfn = __phys_to_pfn((unsigned)_dev->resource.start), -- .length = SZ_128K, -- .type = MT_DEVICE -- }; -- iotable_init(&desc, 1); -- dwc_otg_device->base = (void *)desc.virtual; --#endif -+ dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K); - -- if (!dwc_otg_device->base) { -+ if (!dwc_otg_device->os_dep.base) { - dev_err(&_dev->dev, "ioremap() failed\n"); -- retval = -ENOMEM; -- goto fail; -+ DWC_FREE(dwc_otg_device); -+ return -ENOMEM; - } -- dev_dbg(&_dev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base); --#elif defined(PCI_INTERFACE) -+ dev_dbg(&_dev->dev, "base=0x%08x\n", -+ (unsigned)dwc_otg_device->os_dep.base); -+#elif defined(PCI_INTERFACE) - _dev->current_state = PCI_D0; - _dev->dev.power.power_state = PMSG_ON; -- -+ - if (!_dev->irq) { -- DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!", pci_name(_dev)); -- retval = -ENODEV; -- goto fail; -- } -+ DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!", -+ pci_name(_dev)); -+ iounmap(dwc_otg_device->os_dep.base); -+ DWC_FREE(dwc_otg_device); -+ return -ENODEV; -+ } - -- dwc_otg_device->rsrc_start = pci_resource_start(_dev,0); -- dwc_otg_device->rsrc_len = pci_resource_len(_dev,0); -- DWC_DEBUGPL(DBG_ANY,"PCI resource: start=%08x, len=%08x\n", -- dwc_otg_device->rsrc_start, -- dwc_otg_device->rsrc_len); -- if (!request_mem_region(dwc_otg_device->rsrc_start, dwc_otg_device->rsrc_len, "dwc_otg")) { -- dev_dbg(&_dev->dev, "error mapping memory\n"); -- retval = -EFAULT; -- goto fail; -- } -+ dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0); -+ dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0); -+ DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n", -+ (unsigned)dwc_otg_device->os_dep.rsrc_start, -+ (unsigned)dwc_otg_device->os_dep.rsrc_len); -+ if (!request_mem_region -+ (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len, -+ "dwc_otg")) { -+ dev_dbg(&_dev->dev, "error requesting memory\n"); -+ iounmap(dwc_otg_device->os_dep.base); -+ DWC_FREE(dwc_otg_device); -+ return -EFAULT; -+ } - -- dwc_otg_device->base = ioremap_nocache(dwc_otg_device->rsrc_start, dwc_otg_device->rsrc_len); -- if (dwc_otg_device->base == NULL) { -- dev_dbg(&_dev->dev, "error mapping memory\n"); -- retval = -EFAULT; -- goto fail; -- } -- dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n", dwc_otg_device->base); -- dwc_otg_device->base = (char *)dwc_otg_device->base; -- dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n", dwc_otg_device->base); -- dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__, -- (unsigned)dwc_otg_device->rsrc_start, dwc_otg_device->base); -- // -- pci_set_drvdata(_dev, dwc_otg_device); -- pci_set_master(_dev); -+ dwc_otg_device->os_dep.base = -+ ioremap_nocache(dwc_otg_device->os_dep.rsrc_start, -+ dwc_otg_device->os_dep.rsrc_len); -+ if (dwc_otg_device->os_dep.base == NULL) { -+ dev_dbg(&_dev->dev, "error mapping memory\n"); -+ release_mem_region(dwc_otg_device->os_dep.rsrc_start, -+ dwc_otg_device->os_dep.rsrc_len); -+ iounmap(dwc_otg_device->os_dep.base); -+ DWC_FREE(dwc_otg_device); -+ return -EFAULT; -+ } -+ dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n", -+ dwc_otg_device->os_dep.base); -+ dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base; -+ dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n", -+ dwc_otg_device->os_dep.base); -+ dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__, -+ (unsigned)dwc_otg_device->os_dep.rsrc_start, -+ dwc_otg_device->os_dep.base); -+ -+ pci_set_master(_dev); -+ pci_set_drvdata(_dev, dwc_otg_device); - #elif defined(PLATFORM_INTERFACE) - DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n", - _dev->resource->start, -@@ -768,9 +785,9 @@ struct platform_device *_dev - goto fail; - } - -- dwc_otg_device->base = ioremap_nocache(_dev->resource->start, -- _dev->resource->end - -- _dev->resource->start + 1); -+ dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource->start, -+ _dev->resource->end - -+ _dev->resource->start+1); - #else - { - struct map_desc desc = { -@@ -780,15 +797,16 @@ struct platform_device *_dev - .type = MT_DEVICE - }; - iotable_init(&desc, 1); -- dwc_otg_device->base = (void *)desc.virtual; -+ dwc_otg_device->os_dep.base = (void *)desc.virtual; - } - #endif -- if (!dwc_otg_device->base) { -+ if (!dwc_otg_device->os_dep.base) { - dev_err(&_dev->dev, "ioremap() failed\n"); - retval = -ENOMEM; - goto fail; - } -- dev_dbg(&_dev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base); -+ dev_dbg(&_dev->dev, "base=0x%08x\n", -+ (unsigned)dwc_otg_device->os_dep.base); - #endif - - /* -@@ -802,7 +820,7 @@ struct platform_device *_dev - #endif - dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device); - -- dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->base); -+ dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base); - DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n", - dwc_otg_device, dwc_otg_device->core_if);//GRAYG - -@@ -823,8 +841,6 @@ struct platform_device *_dev - 0x4F542000) { - dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n", - dwc_otg_get_gsnpsid(dwc_otg_device->core_if)); -- dwc_otg_cil_remove(dwc_otg_device->core_if); -- dwc_free(dwc_otg_device); - retval = -EINVAL; - goto fail; - } -@@ -834,7 +850,6 @@ struct platform_device *_dev - */ - dev_dbg(&_dev->dev, "Calling set_parameters\n"); - if (set_parameters(dwc_otg_device->core_if)) { -- dwc_otg_cil_remove(dwc_otg_device->core_if); - retval = -EINVAL; - goto fail; - } -@@ -856,6 +871,7 @@ struct platform_device *_dev - * Install the interrupt handler for the common interrupts before - * enabling common interrupts in core_init below. - */ -+ - #if defined(PLATFORM_INTERFACE) - devirq = platform_get_irq(_dev, 0); - #else -@@ -887,13 +903,13 @@ struct platform_device *_dev - ); - #endif - #endif /*IRQF_TRIGGER_LOW*/ -- -+ - /* - * Initialize the DWC_otg core. - */ - dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n"); - dwc_otg_core_init(dwc_otg_device->core_if); -- -+ - #ifndef DWC_HOST_ONLY - /* - * Initialize the PCD -@@ -904,7 +920,7 @@ struct platform_device *_dev - DWC_ERROR("pcd_init failed\n"); - dwc_otg_device->pcd = NULL; - goto fail; -- } -+ } - #endif - #ifndef DWC_DEVICE_ONLY - /* -@@ -925,19 +941,25 @@ struct platform_device *_dev - platform_set_drvdata(_dev, dwc_otg_device); - #elif defined(PCI_INTERFACE) - pci_set_drvdata(_dev, dwc_otg_device); -+ dwc_otg_device->os_dep.pcidev = _dev; - #endif - - /* - * Enable the global interrupt after all the interrupt -- * handlers are installed. -+ * handlers are installed if there is no ADP support else -+ * perform initial actions required for Internal ADP logic. - */ -- dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n"); -- dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); -- dev_dbg(&_dev->dev, "Done\n"); -+ if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) { -+ dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n"); -+ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); -+ dev_dbg(&_dev->dev, "Done\n"); -+ } else -+ dwc_otg_adp_start(dwc_otg_device->core_if, -+ dwc_otg_is_host_mode(dwc_otg_device->core_if)); - - return 0; - -- fail: -+fail: - dwc_otg_driver_remove(_dev); - return retval; - } -@@ -955,32 +977,32 @@ struct platform_device *_dev - */ - #ifdef LM_INTERFACE - static struct lm_driver dwc_otg_driver = { -- .drv = { -- .name = (char *)dwc_driver_name, -- }, -+ .drv = {.name = (char *)dwc_driver_name,}, - .probe = dwc_otg_driver_probe, - .remove = dwc_otg_driver_remove, - // 'suspend' and 'resume' absent - }; - #elif defined(PCI_INTERFACE) - static const struct pci_device_id pci_ids[] = { { -- PCI_DEVICE(0x16c3, 0xabcd), -- .driver_data = (unsigned long) 0xdeadbeef, -- }, { /* end: all zeroes */ } -+ PCI_DEVICE(0x16c3, 0xabcd), -+ .driver_data = -+ (unsigned long)0xdeadbeef, -+ }, { /* end: all zeroes */ } - }; -+ - MODULE_DEVICE_TABLE(pci, pci_ids); - - /* pci driver glue; this is a "new style" PCI driver module */ - static struct pci_driver dwc_otg_driver = { -- .name = "dwc_otg", -- .id_table = pci_ids, -+ .name = "dwc_otg", -+ .id_table = pci_ids, - -- .probe = dwc_otg_driver_probe, -- .remove = dwc_otg_driver_remove, -+ .probe = dwc_otg_driver_probe, -+ .remove = dwc_otg_driver_remove, - -- .driver = { -- .name = (char*)dwc_driver_name, -- }, -+ .driver = { -+ .name = (char *)dwc_driver_name, -+ }, - }; - #elif defined(PLATFORM_INTERFACE) - static struct platform_device_id platform_ids[] = { -@@ -1004,7 +1026,6 @@ struct platform_device *_dev - }; - #endif - -- - /** - * This function is called when the dwc_otg_driver is installed with the - * insmod command. It registers the dwc_otg_driver structure with the -@@ -1019,35 +1040,30 @@ static int __init dwc_otg_driver_init(void) - { - int retval = 0; - int error; -+ struct device_driver *drv; - printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name, - DWC_DRIVER_VERSION, - #ifdef LM_INTERFACE - "logicmodule"); - retval = lm_driver_register(&dwc_otg_driver); -+ drv = &dwc_otg_driver.drv; - #elif defined(PCI_INTERFACE) - "pci"); - retval = pci_register_driver(&dwc_otg_driver); -+ drv = &dwc_otg_driver.driver; - #elif defined(PLATFORM_INTERFACE) - "platform"); - retval = platform_driver_register(&dwc_otg_driver); -+ drv = &dwc_otg_driver.driver; - #endif - if (retval < 0) { - printk(KERN_ERR "%s retval=%d\n", __func__, retval); - return retval; - } --#ifdef LM_INTERFACE -- error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_version); -- error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_debuglevel); --#elif defined(PCI_INTERFACE) -- error = driver_create_file(&dwc_otg_driver.driver, -- &driver_attr_version); -- error = driver_create_file(&dwc_otg_driver.driver, -- &driver_attr_debuglevel); --#elif defined(PLATFORM_INTERFACE) -- error = driver_create_file(&dwc_otg_driver.driver, -- &driver_attr_version); -- error = driver_create_file(&dwc_otg_driver.driver, -- &driver_attr_debuglevel); -+ -+ error = driver_create_file(drv, &driver_attr_version); -+#ifdef DEBUG -+ error = driver_create_file(drv, &driver_attr_debuglevel); - #endif - return retval; - } -@@ -1080,6 +1096,7 @@ static void __exit dwc_otg_driver_cleanup(void) - - printk(KERN_INFO "%s module removed\n", dwc_driver_name); - } -+ - module_exit(dwc_otg_driver_cleanup); - - MODULE_DESCRIPTION(DWC_DRIVER_DESC); -@@ -1303,8 +1320,23 @@ static void __exit dwc_otg_driver_cleanup(void) - module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444); - MODULE_PARM_DESC(ic_usb_cap, - "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled"); --module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int, 0444); -+module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int, -+ 0444); - MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio"); -+module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444); -+MODULE_PARM_DESC(power_down, "Power Down Mode"); -+module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444); -+MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control"); -+module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444); -+MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK"); -+module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444); -+MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA"); -+module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444); -+MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support"); -+module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444); -+MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled"); -+module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444); -+MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0"); - - /** @page "Module Parameters" - * -@@ -1492,7 +1524,21 @@ static void __exit dwc_otg_driver_cleanup(void) - - - -- otg_en_multiple_tx_fifo -+ ulpi_fs_ls -+ Specifies whether to use ULPI FS/LS mode only. -+ - 0: Disabled (default) -+ - 1: Enabled -+ -+ -+ -+ ts_dline -+ Specifies whether term select D-Line pulsing for all PHYs is enabled. -+ - 0: Disabled (default) -+ - 1: Enabled -+ -+ -+ -+ en_multiple_tx_fifo - Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs. - The driver will automatically detect the value for this parameter if none is - specified. -@@ -1521,9 +1567,9 @@ static void __exit dwc_otg_driver_cleanup(void) - - - thr_ctl -- Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of this -- parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and Rx -- transfers accordingly. -+ Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of -+ this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and -+ Rx transfers accordingly. - The driver will automatically detect the value for this parameter if none is - specified. - - Values: 0 to 7 (default 0) -@@ -1547,7 +1593,7 @@ static void __exit dwc_otg_driver_cleanup(void) - The driver will automatically detect the value for this parameter if none is - specified. - - 0: MPI disabled (default) -- - 1: MPI enable -+ - 1: MPI enable - - - -@@ -1556,7 +1602,7 @@ static void __exit dwc_otg_driver_cleanup(void) - The driver will automatically detect the value for this parameter if none is - specified. - - 0: PTI disabled (default) -- - 1: PTI enable -+ - 1: PTI enable - - - -@@ -1568,10 +1614,82 @@ static void __exit dwc_otg_driver_cleanup(void) - - 1: LPM enable (default, if available) - - -- -+ -+ ic_usb_cap -+ Specifies whether to enable IC_USB capability. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: IC_USB disabled (default, if available) -+ - 1: IC_USB enable -+ -+ -+ - ahb_thr_ratio - Specifies AHB Threshold ratio. - - Values: 0 to 3 (default 0) - - -+ -+ power_down -+ Specifies Power Down(Hibernation) Mode. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: Power Down disabled (default) -+ - 2: Power Down enabled -+ -+ -+ -+ reload_ctl -+ Specifies whether dynamic reloading of the HFIR register is allowed during -+ run time. The driver will automatically detect the value for this parameter if -+ none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0 -+ the core might misbehave. -+ - 0: Reload Control disabled (default) -+ - 1: Reload Control enabled -+ -+ -+ -+ dev_out_nak -+ Specifies whether Device OUT NAK enhancement enabled or no. -+ The driver will automatically detect the value for this parameter if -+ none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1. -+ - 0: The core does not set NAK after Bulk OUT transfer complete (default) -+ - 1: The core sets NAK after Bulk OUT transfer complete -+ -+ -+ -+ cont_on_bna -+ Specifies whether Enable Continue on BNA enabled or no. -+ After receiving BNA interrupt the core disables the endpoint,when the -+ endpoint is re-enabled by the application the -+ - 0: Core starts processing from the DOEPDMA descriptor (default) -+ - 1: Core starts processing from the descriptor which received the BNA. -+ This parameter is valid only when OTG_EN_DESC_DMA == 1b1. -+ -+ -+ -+ ahb_single -+ This bit when programmed supports SINGLE transfers for remainder data -+ in a transfer for DMA mode of operation. -+ - 0: The remainder data will be sent using INCR burst size (default) -+ - 1: The remainder data will be sent using SINGLE burst size. -+ -+ -+ -+ adp_enable -+ Specifies whether ADP feature is enabled. -+ The driver will automatically detect the value for this parameter if none is -+ specified. -+ - 0: ADP feature disabled (default) -+ - 1: ADP feature enabled -+ -+ -+ -+ otg_ver -+ Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3 -+ USB OTG device. -+ - 0: OTG 2.0 support disabled (default) -+ - 1: OTG 2.0 support enabled -+ -+ - */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.h b/drivers/usb/host/dwc_otg/dwc_otg_driver.h -index f37d3ac..8a0e41b 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $ -- * $Revision: #16 $ -- * $Date: 2009/04/03 $ -- * $Change: 1225160 $ -+ * $Revision: #19 $ -+ * $Date: 2010/11/15 $ -+ * $Change: 1627671 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -37,41 +37,26 @@ - /** @file - * This file contains the interface to the Linux driver. - */ -+#include "dwc_otg_os_dep.h" - #include "dwc_otg_core_if.h" - - /* Type declarations */ - struct dwc_otg_pcd; - struct dwc_otg_hcd; - --#ifdef PCI_INTERFACE --#include --#endif -- -- -- - /** - * This structure is a wrapper that encapsulates the driver components used to - * manage a single DWC_otg controller. - */ - typedef struct dwc_otg_device { -- /** Base address returned from ioremap() */ -- void *base; -- --#ifdef LM_INTERFACE -- struct lm_device *lmdev; --#elif defined(PCI_INTERFACE) -- int rsrc_start; -- int rsrc_len; --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *platformdev; --#endif -+ /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE -+ * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD -+ * require this. */ -+ struct os_dependent os_dep; - - /** Pointer to the core interface structure. */ - dwc_otg_core_if_t *core_if; - -- /** Register offset for Diagnostic API. */ -- uint32_t reg_offset; -- - /** Pointer to the PCD structure. */ - struct dwc_otg_pcd *pcd; - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -index f07bb72..abe7093 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -1,9 +1,9 @@ - - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ -- * $Revision: #87 $ -- * $Date: 2009/04/23 $ -- * $Change: 1239143 $ -+ * $Revision: #104 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871159 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -34,7 +34,7 @@ - #ifndef DWC_DEVICE_ONLY - - /** @file -- * This file implements HCD Core. All code in this file is portable and don't -+ * This file implements HCD Core. All code in this file is portable and doesn't - * use any OS specific functions. - * Interface provided by HCD Core is defined in - * header file. -@@ -43,14 +43,9 @@ - #include "dwc_otg_hcd.h" - #include "dwc_otg_regs.h" - --#ifdef HW2937_WORKAROUND --//#include --#include --#endif -- - dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) - { -- return dwc_alloc(sizeof(dwc_otg_hcd_t)); -+ return DWC_ALLOC(sizeof(dwc_otg_hcd_t)); - } - - /** -@@ -64,7 +59,7 @@ void dwc_otg_hcd_connect_timeout(void *ptr) - __DWC_ERROR("Device Not Connected/Responding\n"); - } - --#ifdef DEBUG -+#if defined(DEBUG) - static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { - if (qh->channel != NULL) { -@@ -81,10 +76,10 @@ static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - uint32_t hcdma; - - hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -- hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -- hcdma = dwc_read_reg32(&hc_regs->hcdma); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); -+ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); -+ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); -+ hcdma = DWC_READ_REG32(&hc_regs->hcdma); - - DWC_PRINTF(" Assigned to channel %p:\n", hc); - DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, -@@ -120,7 +115,9 @@ static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - } - } - } --#endif /* DEBUG */ -+#else -+#define dump_channel_info(hcd, qh) -+#endif /* DEBUG */ - - /** - * Work queue function for starting the HCD when A-Cable is connected. -@@ -170,8 +167,7 @@ static void kill_urbs_in_qh_list(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) - qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); - if (qtd->urb != NULL) { - hcd->fops->complete(hcd, qtd->urb->priv, -- qtd->urb, -- -DWC_E_TIMEOUT); -+ qtd->urb, -DWC_E_TIMEOUT); - dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); - } - -@@ -242,7 +238,7 @@ static int32_t dwc_otg_hcd_start_cb(void *p) - */ - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtrst = 1; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - } - DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, - hcd_start_func, dwc_otg_hcd, 50, -@@ -276,9 +272,9 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p) - intr.b.nptxfempty = 1; - intr.b.ptxfempty = 1; - intr.b.hcintr = 1; -- dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, -+ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, - intr.d32, 0); -- dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, -+ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, - intr.d32, 0); - - del_timers(dwc_otg_hcd); -@@ -293,7 +289,7 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p) - hprt0_data_t hprt0 = {.d32 = 0 }; - DWC_PRINTF("Disconnect: PortPower off\n"); - hprt0.b.prtpwr = 0; -- dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, -+ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, - hprt0.d32); - } - -@@ -320,17 +316,17 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p) - if (DWC_CIRCLEQ_EMPTY_ENTRY - (channel, hc_list_entry)) { - hc_regs = -- dwc_otg_hcd->core_if->host_if-> -- hc_regs[i]; -+ dwc_otg_hcd->core_if-> -+ host_if->hc_regs[i]; - hcchar.d32 = -- dwc_read_reg32(&hc_regs->hcchar); -+ DWC_READ_REG32(&hc_regs->hcchar); - if (hcchar.b.chen) { - hcchar.b.chen = 0; - hcchar.b.chdis = 1; - hcchar.b.epdir = 0; -- dwc_write_reg32(&hc_regs-> -- hcchar, -- hcchar.d32); -+ DWC_WRITE_REG32 -+ (&hc_regs->hcchar, -+ hcchar.d32); - } - } - } -@@ -341,25 +337,25 @@ static int32_t dwc_otg_hcd_disconnect_cb(void *p) - if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) { - hc_regs = - dwc_otg_hcd->core_if->host_if->hc_regs[i]; -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - if (hcchar.b.chen) { - /* Halt the channel. */ - hcchar.b.chdis = 1; -- dwc_write_reg32(&hc_regs->hcchar, -+ DWC_WRITE_REG32(&hc_regs->hcchar, - hcchar.d32); - } - - dwc_otg_hc_cleanup(dwc_otg_hcd->core_if, - channel); -- DWC_CIRCLEQ_INSERT_TAIL(&dwc_otg_hcd-> -- free_hc_list, channel, -- hc_list_entry); -- /* -- * Added for Descriptor DMA to prevent channel double cleanup -+ DWC_CIRCLEQ_INSERT_TAIL -+ (&dwc_otg_hcd->free_hc_list, channel, -+ hc_list_entry); -+ /* -+ * Added for Descriptor DMA to prevent channel double cleanup - * in release_channel_ddma(). Which called from ep_disable - * when device disconnect. -- */ -- channel->qh = NULL; -+ */ -+ channel->qh = NULL; - } - } - } -@@ -386,7 +382,7 @@ static int32_t dwc_otg_hcd_stop_cb(void *p) - } - - #ifdef CONFIG_USB_DWC_OTG_LPM --/** -+/** - * HCD Callback function for sleep of HCD. - * - * @param p void pointer to the struct usb_hcd -@@ -443,44 +439,49 @@ void dwc_otg_hcd_stop(dwc_otg_hcd_t * hcd) - /* Turn off the vbus power */ - DWC_PRINTF("PortPower off\n"); - hprt0.b.prtpwr = 0; -- dwc_write_reg32(hcd->core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); - dwc_mdelay(1); - } - - int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, -- dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle) -+ dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle, -+ int atomic_alloc) - { -- uint64_t flags; -+ dwc_irqflags_t flags; - int retval = 0; - dwc_otg_qtd_t *qtd; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; - -- if (NULL == hcd->core_if) { //GRAYG -+#ifdef DEBUG /* integrity checks (Broadcom) */ -+ if (NULL == hcd->core_if) { - DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n"); - /* No longer connected. */ - return -DWC_E_INVALID; - } -- -+#endif - if (!hcd->flags.b.port_connect_status) { - /* No longer connected. */ -+ DWC_ERROR("Not connected\n"); - return -DWC_E_NO_DEVICE; - } - -- qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb); -+ qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc); - if (qtd == NULL) { - DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); - return -DWC_E_NO_MEMORY; - } -- if (qtd->urb == NULL) { //GRAYG -+#ifdef DEBUG /* integrity checks (Broadcom) */ -+ if (qtd->urb == NULL) { - DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n"); - return -DWC_E_NO_MEMORY; - } -- if (qtd->urb->priv == NULL) { //GRAYG -+ if (qtd->urb->priv == NULL) { - DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n"); - return -DWC_E_NO_MEMORY; - } -- -+#endif - retval = -- dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle); -+ dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc); - // creates a new queue in ep_handle if it doesn't exist already - if (retval < 0) { - DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " -@@ -489,11 +490,12 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, - } else { - qtd->qh = *ep_handle; - } -- -- if (hcd->core_if->dma_desc_enable && retval == 0) { -- dwc_otg_transaction_type_e tr_type; -- if ((qtd->qh->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { -- /* Do not schedule SG transcations until qtd has URB_GIVEBACK_ASAP set */ -+ intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); -+ if (!intr_mask.b.sofintr && retval == 0) { -+ dwc_otg_transaction_type_e tr_type; -+ if ((qtd->qh->ep_type == UE_BULK) -+ && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { -+ /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ - return 0; - } - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -@@ -510,42 +512,43 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, - int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, - dwc_otg_hcd_urb_t * dwc_otg_urb) - { -- uint64_t flags; -- - dwc_otg_qh_t *qh; - dwc_otg_qtd_t *urb_qtd; - -- DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -- -- if (hcd == NULL) { //GRAYG -+#ifdef DEBUG /* integrity checks (Broadcom) */ -+ -+ if (hcd == NULL) { - DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n"); - return -DWC_E_INVALID; - } -- if (dwc_otg_urb == NULL) { //GRAYG -+ if (dwc_otg_urb == NULL) { - DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n"); - return -DWC_E_INVALID; - } -- if (dwc_otg_urb->qtd == NULL) { //GRAYG -+ if (dwc_otg_urb->qtd == NULL) { - DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n"); - return -DWC_E_INVALID; - } - urb_qtd = dwc_otg_urb->qtd; -- if (urb_qtd->qh == NULL) { //GRAYG -+ if (urb_qtd->qh == NULL) { - DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n"); - return -DWC_E_INVALID; - } -+#else -+ urb_qtd = dwc_otg_urb->qtd; -+#endif - qh = urb_qtd->qh; --#ifdef DEBUG - if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { - if (urb_qtd->in_process) { - dump_channel_info(hcd, qh); - } - } --#endif -- if (hcd->core_if == NULL) { //GRAYG -+#ifdef DEBUG /* integrity checks (Broadcom) */ -+ if (hcd->core_if == NULL) { - DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n"); - return -DWC_E_INVALID; - } -+#endif - if (urb_qtd->in_process && qh->channel) { - /* The QTD is in process (it has been assigned to a channel). */ - if (hcd->flags.b.port_connect_status) { -@@ -565,12 +568,12 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, - * Free the QTD and clean up the associated QH. Leave the QH in the - * schedule if it has any remaining QTDs. - */ -- -+ - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - " - "delete %sQueue handler\n", -- hcd->core_if->dma_desc_enable?"DMA ":""); //GRAYG -+ hcd->core_if->dma_desc_enable?"DMA ":""); - if (!hcd->core_if->dma_desc_enable) { -- uint8_t b = urb_qtd->in_process; -+ uint8_t b = urb_qtd->in_process; - dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); - if (b) { - dwc_otg_hcd_qh_deactivate(hcd, qh, 0); -@@ -578,13 +581,9 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, - } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { - dwc_otg_hcd_qh_remove(hcd, qh); - } -- } -- else { -+ } else { - dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); - } -- -- DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -- - return 0; - } - -@@ -593,7 +592,7 @@ int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, - { - dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; - int retval = 0; -- uint64_t flags; -+ dwc_irqflags_t flags; - - if (retry < 0) { - retval = -DWC_E_INVALID; -@@ -601,11 +600,12 @@ int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, - } - - if (!qh) { -+ retval = -DWC_E_INVALID; - goto done; - } - - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -- -+ - while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) { - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - retry--; -@@ -614,19 +614,32 @@ int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, - } - - dwc_otg_hcd_qh_remove(hcd, qh); -- -+ - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -- /* -- * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove -- * and qh_free to prevent stack dump on dwc_dma_free() with -- * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() -+ /* -+ * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove -+ * and qh_free to prevent stack dump on DWC_DMA_FREE() with -+ * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() - * and dwc_otg_hcd_frame_list_alloc(). - */ - dwc_otg_hcd_qh_free(hcd, qh); - -- done: -+done: -+ return retval; -+} -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) -+int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle) -+{ -+ int retval = 0; -+ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; -+ if (!qh) -+ return -DWC_E_INVALID; -+ -+ qh->data_toggle = DWC_OTG_HC_PID_DATA0; - return retval; - } -+#endif - - /** - * HCD Callback structure for handling mode switching. -@@ -656,11 +669,11 @@ static void reset_tasklet_func(void *data) - - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtrst = 1; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - dwc_mdelay(60); - - hprt0.b.prtrst = 0; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - dwc_otg_hcd->flags.b.port_reset_change = 1; - } - -@@ -668,14 +681,20 @@ static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) - { - dwc_list_link_t *item; - dwc_otg_qh_t *qh; -+ dwc_irqflags_t flags; - - if (!qh_list->next) { - /* The list hasn't been initialized yet. */ - return; - } -- -+ /* -+ * Hold spinlock here. Not needed in that case if bellow -+ * function is being called from ISR -+ */ -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); - /* Ensure there are no QTDs or URBs left. */ - kill_urbs_in_qh_list(hcd, qh_list); -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - - DWC_LIST_FOREACH(item, qh_list) { - qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); -@@ -684,6 +703,68 @@ static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list) - } - - /** -+ * Exit from Hibernation if Host did not detect SRP from connected SRP capable -+ * Device during SRP time by host power up. -+ */ -+void dwc_otg_hcd_power_up(void *ptr) -+{ -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; -+ -+ DWC_PRINTF("%s called\n", __FUNCTION__); -+ -+ if (!core_if->hibernation_suspend) { -+ DWC_PRINTF("Already exited from Hibernation\n"); -+ return; -+ } -+ -+ /* Switch on the voltage to the core */ -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Reset the core */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Disable power clamps */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ /* Remove reset the core signal */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnrstn = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Disable PMU interrupt */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ core_if->hibernation_suspend = 0; -+ -+ /* Disable PMU */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ /* Enable VBUS */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.dis_vbus = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ -+ core_if->op_state = A_HOST; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_hcd_start(core_if); -+} -+ -+/** - * Frees secondary storage associated with the dwc_otg_hcd structure contained - * in the struct usb_hcd field. - */ -@@ -715,23 +796,33 @@ static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) - if (hc != NULL) { - DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", - i, hc); -- dwc_free(hc); -+ DWC_FREE(hc); - } - } - - if (dwc_otg_hcd->core_if->dma_enable) { - if (dwc_otg_hcd->status_buf_dma) { -- dwc_dma_free(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, - dwc_otg_hcd->status_buf, - dwc_otg_hcd->status_buf_dma); - } - } else if (dwc_otg_hcd->status_buf != NULL) { -- dwc_free(dwc_otg_hcd->status_buf); -+ DWC_FREE(dwc_otg_hcd->status_buf); - } - DWC_SPINLOCK_FREE(dwc_otg_hcd->lock); -+ /* Set core_if's lock pointer to NULL */ -+ dwc_otg_hcd->core_if->lock = NULL; -+ - DWC_TIMER_FREE(dwc_otg_hcd->conn_timer); - DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet); -- dwc_free(dwc_otg_hcd); -+ -+#ifdef DWC_DEV_SRPCAP -+ if (dwc_otg_hcd->core_if->power_down == 2 && -+ dwc_otg_hcd->core_if->pwron_timer) { -+ DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer); -+ } -+#endif -+ DWC_FREE(dwc_otg_hcd); - } - - int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) -@@ -742,11 +833,16 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - dwc_hc_t *channel; - - hcd->lock = DWC_SPINLOCK_ALLOC(); -- - DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n", -- hcd, core_if);//GRAYG -- -+ hcd, core_if); -+ if (!hcd->lock) { -+ DWC_ERROR("Could not allocate lock for pcd"); -+ DWC_FREE(hcd); -+ retval = -DWC_E_NO_MEMORY; -+ goto out; -+ } - hcd->core_if = core_if; -+ - /* Register the HCD CIL Callbacks */ - dwc_otg_cil_register_hcd_callbacks(hcd->core_if, - &hcd_cil_callbacks, hcd); -@@ -769,7 +865,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - num_channels = hcd->core_if->core_params->host_channels; - DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array)); - for (i = 0; i < num_channels; i++) { -- channel = dwc_alloc(sizeof(dwc_hc_t)); -+ channel = DWC_ALLOC(sizeof(dwc_hc_t)); - if (channel == NULL) { - retval = -DWC_E_NO_MEMORY; - DWC_ERROR("%s: host channel allocation failed\n", -@@ -793,7 +889,14 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - dwc_otg_hcd_connect_timeout, 0); - - /* Initialize reset tasklet. */ -- hcd->reset_tasklet = DWC_TASK_ALLOC(reset_tasklet_func, hcd); -+ hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd); -+#ifdef DWC_DEV_SRPCAP -+ if (hcd->core_if->power_down == 2) { -+ /* Initialize Power on timer for Host power up in case hibernation */ -+ hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER", -+ dwc_otg_hcd_power_up, core_if); -+ } -+#endif - - /* - * Allocate space for storing data on status transactions. Normally no -@@ -803,10 +906,10 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - */ - if (hcd->core_if->dma_enable) { - hcd->status_buf = -- dwc_dma_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE, -+ DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, - &hcd->status_buf_dma); - } else { -- hcd->status_buf = dwc_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE); -+ hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); - } - if (!hcd->status_buf) { - retval = -DWC_E_NO_MEMORY; -@@ -818,12 +921,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - hcd->otg_port = 1; - hcd->frame_list = NULL; - hcd->frame_list_dma = 0; -- --#ifdef HW2937_WORKAROUND -- hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IDLE; -- hcd->hw2937_assigned_channels = 0; --#endif -- -+ hcd->periodic_qh_count = 0; - out: - return retval; - } -@@ -871,6 +969,9 @@ static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd) - - /* Initialize the DWC core for host mode operation. */ - dwc_otg_core_host_init(hcd->core_if); -+ -+ /* Set core_if's lock pointer to the hcd->lock */ -+ hcd->core_if->lock = hcd->lock; - } - - /** -@@ -882,19 +983,12 @@ static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd) - * @param qh Transactions from the first QTD for this QH are selected and - * assigned to a free host channel. - */ --#ifdef HW2937_WORKAROUND --static int assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) --#else - static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) --#endif - { - dwc_hc_t *hc; - dwc_otg_qtd_t *qtd; - dwc_otg_hcd_urb_t *urb; - void* ptr = NULL; --#ifdef HW2937_WORKAROUND -- int ep_is_in; --#endif - - qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); - -@@ -902,13 +996,6 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - - DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length); - --#ifdef HW2937_WORKAROUND -- ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); -- if (ep_is_in && ((hcd->hw2937_xfer_mode == HW2937_XFER_MODE_OUT) || -- (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_PAUSEIN))) -- return 0; --#endif -- - if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) - urb->actual_length = urb->length; - -@@ -917,8 +1004,9 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - - /* Remove the host channel from the free list. */ - DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); -+ - qh->channel = hc; -- -+ - qtd->in_process = 1; - - /* -@@ -943,20 +1031,23 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - * started to accommodate the max widths of the XferSize and PktCnt - * fields in the HCTSIZn register. - */ -- hc->do_ping = qh->ping_state; --#ifdef HW2937_WORKAROUND -- hc->ep_is_in = ep_is_in; --#else -+ - hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); --#endif -+ if (hc->ep_is_in) { -+ hc->do_ping = 0; -+ } else { -+ hc->do_ping = qh->ping_state; -+ } -+ - hc->data_pid_start = qh->data_toggle; - hc->multi_count = 1; - - if (hcd->core_if->dma_enable) { - hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length; -- -+ - /* For non-dword aligned case */ -- if (((uint32_t)hc->xfer_buff & 0x3) && !hcd->core_if->dma_desc_enable) { -+ if (((unsigned long)hc->xfer_buff & 0x3) -+ && !hcd->core_if->dma_desc_enable) { - ptr = (uint8_t *) urb->buf + urb->actual_length; - } - } else { -@@ -1015,7 +1106,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - if (hc->ep_is_in) { - hc->do_ping = 0; - } -- -+ - hc->data_pid_start = DWC_OTG_HC_PID_DATA1; - - hc->xfer_len = 0; -@@ -1037,16 +1128,16 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - case UE_ISOCHRONOUS: - { - struct dwc_otg_hcd_iso_packet_desc *frame_desc; -- -+ - hc->ep_type = DWC_OTG_EP_TYPE_ISOC; -- -+ - if (hcd->core_if->dma_desc_enable) - break; -- -+ - frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; -- -+ - frame_desc->status = 0; -- -+ - if (hcd->core_if->dma_enable) { - hc->xfer_buff = (uint8_t *) urb->dma; - } else { -@@ -1058,12 +1149,14 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - frame_desc->length - qtd->isoc_split_offset; - - /* For non-dword aligned buffers */ -- if (((uint32_t)hc->xfer_buff & 0x3) && hcd->core_if->dma_enable) { -- ptr = (uint8_t *) urb->buf + frame_desc->offset + qtd->isoc_split_offset; -- } -- else -- ptr = NULL; -- -+ if (((unsigned long)hc->xfer_buff & 0x3) -+ && hcd->core_if->dma_enable) { -+ ptr = -+ (uint8_t *) urb->buf + frame_desc->offset + -+ qtd->isoc_split_offset; -+ } else -+ ptr = NULL; -+ - if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) { - if (hc->xfer_len <= 188) { - hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL; -@@ -1084,25 +1177,21 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - buf_size = 4096; - } - if (!qh->dw_align_buf) { -- qh->dw_align_buf = -- dwc_dma_alloc_atomic(buf_size, -- &qh->dw_align_buf_dma); -+ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, -+ &qh->dw_align_buf_dma); - if (!qh->dw_align_buf) { -- DWC_ERROR("%s: Failed to allocate memory to handle " -- "non-dword aligned buffer case\n", __func__); --#ifdef HW2937_WORKAROUND -- return 0; --#else -+ DWC_ERROR -+ ("%s: Failed to allocate memory to handle " -+ "non-dword aligned buffer case\n", -+ __func__); - return; --#endif - } - } - if (!hc->ep_is_in) { - dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len); - } - hc->align_buff = qh->dw_align_buf_dma; -- } -- else { -+ } else { - hc->align_buff = 0; - } - -@@ -1114,184 +1203,14 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - */ - hc->multi_count = dwc_hb_mult(qh->maxp); - } -- -+ - if (hcd->core_if->dma_desc_enable) - hc->desc_list_addr = qh->desc_list_dma; -- -+ - dwc_otg_hc_init(hcd->core_if, hc); - hc->qh = qh; --#ifdef HW2937_WORKAROUND -- hcd->hw2937_assigned_channels |= (1 << hc->hc_num); -- DWC_DEBUGPL(DBG_HW2937, " assign %d -> hw2937_ac %x\n", hc->hc_num, hcd->hw2937_assigned_channels); -- return 1; --#endif --} -- --#ifdef HW2937_WORKAROUND -- --void debug_halt(void) --{ -- spinlock_t mr_lock = SPIN_LOCK_UNLOCKED; -- unsigned long flags; -- extern void v6_flush_kern_cache_all(void); -- -- spin_lock_irqsave(&mr_lock, flags); --#ifdef CONFIG_MACH_BCM2708 -- v6_flush_kern_cache_all(); --#endif -- while (1) continue; --} -- --static --void dwc_otg_hcd_disable_in_channels(dwc_otg_hcd_t * hcd) --{ -- int num_channels = hcd->core_if->core_params->host_channels; -- static int stall_count = 0; -- static int max_stall_count = 1; -- static int last_stalled = 0; -- int stalled = 0; -- int i; -- -- DWC_DEBUGPL(DBG_HW2937, " Disable In Channels(%x)\n", hcd->hw2937_assigned_channels); -- -- for (i = 0; i < num_channels; i++) { -- if (hcd->hw2937_assigned_channels & (1 << i)) { -- dwc_hc_t *hc = hcd->hc_ptr_array[i]; -- if (!hc->halt_pending) { -- dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -- hctsiz_data_t hctsiz; -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -- DWC_DEBUGPL(DBG_HW2937, "pktcnt %d, xfersize %x, xfer_len %x\n", hctsiz.b.pktcnt, hctsiz.b.xfersize, hc->xfer_len); -- if (hctsiz.b.pktcnt == hc->start_pkt_count) -- { -- dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_PAUSE_IN); -- } -- else -- { -- /* Unless a receive is in progress */ -- stalled |= (1< max_stall_count) -- { -- max_stall_count = stall_count; -- DWC_PRINTF( "stall (%x) count -> %d\n", stalled, stall_count); -- if (stall_count == 10) -- { -- debug_halt(); -- } -- } -- } -- else -- { -- stall_count = 0; -- last_stalled = stalled; -- } --} -- --static --int dwc_otg_hcd_update_transaction_mode(dwc_otg_hcd_t * hcd) --{ -- dwc_list_link_t *qh_ptr; -- dwc_otg_qh_t *qh; -- dwc_otg_qtd_t *qtd; -- dwc_otg_hcd_urb_t *urb; -- int found_in = 0; -- -- /* If there are any existing out transactions, stay in OUT mode */ -- if (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_OUT) -- { -- return 1; -- } -- -- /* Scan entries in the periodic ready list. */ -- qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); -- -- while (qh_ptr != &hcd->periodic_sched_ready) { -- qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -- qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -- urb = qtd->urb; -- if (!dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) { -- /* Switch to OUT mode */ -- switch (hcd->hw2937_xfer_mode) -- { -- case HW2937_XFER_MODE_IDLE: -- DWC_DEBUGPL(DBG_HW2937, "utm -> OUT\n"); -- hcd->hw2937_xfer_mode = HW2937_XFER_MODE_OUT; -- /* Drop through... */ -- case HW2937_XFER_MODE_OUT: -- return 1; -- case HW2937_XFER_MODE_IN: -- DWC_DEBUGPL(DBG_HW2937, "utm - halting %x INs\n", hcd->hw2937_assigned_channels); -- /* Disable the channels with outstanding INs */ -- dwc_otg_hcd_disable_in_channels(hcd); -- -- DWC_DEBUGPL(DBG_HW2937, "utm -> PAUSEIN\n"); -- hcd->hw2937_xfer_mode = HW2937_XFER_MODE_PAUSEIN; -- /* Drop through... */ -- case HW2937_XFER_MODE_PAUSEIN: -- /* Delay until the halt completes */ -- return 0; -- } -- } -- found_in = 1; -- qh_ptr = DWC_LIST_NEXT(qh_ptr); -- } -- -- /* -- * Scan entries in the inactive portion of the non-periodic -- * schedule. -- */ -- qh_ptr = hcd->non_periodic_sched_inactive.next; -- while (qh_ptr != &hcd->non_periodic_sched_inactive) { -- qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -- qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -- urb = qtd->urb; -- if (!dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) { -- /* Switch to OUT mode */ -- switch (hcd->hw2937_xfer_mode) -- { -- case HW2937_XFER_MODE_IDLE: -- DWC_DEBUGPL(DBG_HW2937, "utm -> OUT\n"); -- hcd->hw2937_xfer_mode = HW2937_XFER_MODE_OUT; -- /* Drop through... */ -- case HW2937_XFER_MODE_OUT: -- return 1; -- case HW2937_XFER_MODE_IN: -- DWC_DEBUGPL(DBG_HW2937, "utm - halting %x INs\n", hcd->hw2937_assigned_channels); -- /* Disable the channels with outstanding INs */ -- dwc_otg_hcd_disable_in_channels(hcd); -- -- DWC_DEBUGPL(DBG_HW2937, "utm -> PAUSEIN\n"); -- hcd->hw2937_xfer_mode = HW2937_XFER_MODE_PAUSEIN; -- /* Drop through... */ -- case HW2937_XFER_MODE_PAUSEIN: -- /* Delay until the halt completes */ -- return 0; -- } -- } -- found_in = 1; -- qh_ptr = DWC_LIST_NEXT(qh_ptr); -- } -- -- if (found_in && (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_IDLE)) -- { -- DWC_DEBUGPL(DBG_HW2937, "utm -> IN\n"); -- hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IN; -- } -- return 1; - } - --#endif /* HW2937_WORKAROUND */ -- - /** - * This function selects transactions from the HCD transfer schedule and - * assigns them to available host channels. It is called from HCD interrupt -@@ -1312,24 +1231,13 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); - #endif - --#ifdef HW2937_WORKAROUND -- if (!dwc_otg_hcd_update_transaction_mode(hcd)) -- { -- return ret_val; -- } --#endif -- - /* Process entries in the periodic ready list. */ - qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); - - while (qh_ptr != &hcd->periodic_sched_ready && - !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { - qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); --#ifdef HW2937_WORKAROUND -- if (assign_and_init_hc(hcd, qh)) { --#else - assign_and_init_hc(hcd, qh); --#endif - - /* - * Move the QH from the periodic ready schedule to the -@@ -1340,11 +1248,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - &qh->qh_list_entry); - - ret_val = DWC_OTG_TRANSACTION_PERIODIC; --#ifdef HW2937_WORKAROUND -- } else { -- qh_ptr = DWC_LIST_NEXT(qh_ptr); -- } --#endif - } - - /* -@@ -1361,11 +1264,7 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - - qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); - --#ifdef HW2937_WORKAROUND -- if (assign_and_init_hc(hcd, qh)) { --#else - assign_and_init_hc(hcd, qh); --#endif - - /* - * Move the QH from the non-periodic inactive schedule to the -@@ -1382,15 +1281,11 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - } - - hcd->non_periodic_channels++; --#ifdef HW2937_WORKAROUND -- } else { -- qh_ptr = DWC_LIST_NEXT(qh_ptr); -- } --#endif - } - - return ret_val; - } -+ - /** - * Attempts to queue a single transaction request for a host channel - * associated with either a periodic or non-periodic transfer. This function -@@ -1416,12 +1311,12 @@ static int queue_transaction(dwc_otg_hcd_t * hcd, - - if (hcd->core_if->dma_enable) { - if (hcd->core_if->dma_desc_enable) { -- if (!hc->xfer_started || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { -+ if (!hc->xfer_started -+ || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { - dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh); - hc->qh->ping_state = 0; - } -- } -- else if (!hc->xfer_started) { -+ } else if (!hc->xfer_started) { - dwc_otg_hc_start_transfer(hcd->core_if, hc); - hc->qh->ping_state = 0; - } -@@ -1483,7 +1378,7 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd) - - DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); - #ifdef DEBUG -- tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); - DWC_DEBUGPL(DBG_HCDV, - " P Tx Req Queue Space Avail (before queue): %d\n", - tx_status.b.ptxqspcavail); -@@ -1493,7 +1388,7 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd) - - qh_ptr = hcd->periodic_sched_assigned.next; - while (qh_ptr != &hcd->periodic_sched_assigned) { -- tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); - if (tx_status.b.ptxqspcavail == 0) { - no_queue_space = 1; - break; -@@ -1546,7 +1441,7 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd) - global_regs = hcd->core_if->core_global_regs; - intr_mask.b.ptxfempty = 1; - #ifdef DEBUG -- tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); -+ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); - DWC_DEBUGPL(DBG_HCDV, - " P Tx Req Queue Space Avail (after queue): %d\n", - tx_status.b.ptxqspcavail); -@@ -1563,7 +1458,7 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd) - * level to ensure that new requests are loaded as - * soon as possible.) - */ -- dwc_modify_reg32(&global_regs->gintmsk, 0, -+ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, - intr_mask.d32); - } else { - /* -@@ -1573,7 +1468,7 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd) - * handlers to queue more transactions as transfer - * states change. - */ -- dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, -+ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, - 0); - } - } -@@ -1601,7 +1496,7 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) - - DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); - #ifdef DEBUG -- tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); - DWC_DEBUGPL(DBG_HCDV, - " NP Tx Req Queue Space Avail (before queue): %d\n", - tx_status.b.nptxqspcavail); -@@ -1622,7 +1517,7 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) - * available in the request queue or the Tx FIFO. - */ - do { -- tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); - if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { - no_queue_space = 1; - break; -@@ -1655,7 +1550,7 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) - intr_mask.b.nptxfempty = 1; - - #ifdef DEBUG -- tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); - DWC_DEBUGPL(DBG_HCDV, - " NP Tx Req Queue Space Avail (after queue): %d\n", - tx_status.b.nptxqspcavail); -@@ -1671,7 +1566,7 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) - * level to ensure that new requests are loaded as - * soon as possible.) - */ -- dwc_modify_reg32(&global_regs->gintmsk, 0, -+ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, - intr_mask.d32); - } else { - /* -@@ -1681,7 +1576,7 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) - * handlers to queue more transactions as transfer - * states change. - */ -- dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, -+ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, - 0); - } - } -@@ -1697,7 +1592,7 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) - * periodic, or both). - */ - void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, -- dwc_otg_transaction_type_e tr_type) -+ dwc_otg_transaction_type_e tr_type) - { - #ifdef DEBUG_SOF - DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); -@@ -1722,12 +1617,13 @@ void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, - */ - gintmsk_data_t gintmsk = {.d32 = 0 }; - gintmsk.b.nptxfempty = 1; -- dwc_modify_reg32(&hcd->core_if->core_global_regs-> -- gintmsk, gintmsk.d32, 0); -+ DWC_MODIFY_REG32(&hcd->core_if-> -+ core_global_regs->gintmsk, gintmsk.d32, -+ 0); - } - } - } -- -+ - #ifdef DWC_HS_ELECT_TST - /* - * Quick and dirty hack to implement the HS Electrical Test -@@ -1756,70 +1652,70 @@ static void do_setup(void) - hcint_data_t hcint; - - /* Enable HAINTs */ -- dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); -+ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); - - /* Enable HCINTs */ -- dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); -+ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* - * Send Setup packet (Get Device Descriptor) - */ - - /* Make sure channel is disabled */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - if (hcchar.b.chen) { - hcchar.b.chdis = 1; - // hcchar.b.chen = 1; -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - //sleep(1); - dwc_mdelay(1000); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - } - - /* Set HCTSIZ */ -@@ -1827,56 +1723,55 @@ static void do_setup(void) - 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->hctsiz, hctsiz.d32); - - /* Set HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; - hcchar.b.epdir = 0; - hcchar.b.epnum = 0; - hcchar.b.mps = 8; - hcchar.b.chen = 1; -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - - /* Fill FIFO with Setup data for Get Device Descriptor */ - data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); -- dwc_write_reg32(data_fifo++, 0x01000680); -- dwc_write_reg32(data_fifo++, 0x00080000); -+ DWC_WRITE_REG32(data_fifo++, 0x01000680); -+ DWC_WRITE_REG32(data_fifo++, 0x00080000); - -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Wait for host channel interrupt */ - do { -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - } while (gintsts.b.hcintr == 0); - -- - /* Disable HCINTs */ -- dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); -+ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); - - /* Disable HAINTs */ -- dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); -+ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); - - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - } - - static void do_in_ack(void) -@@ -1889,70 +1784,70 @@ static void do_in_ack(void) - host_grxsts_data_t grxsts; - - /* Enable HAINTs */ -- dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); -+ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); - - /* Enable HCINTs */ -- dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); -+ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* - * Receive Control In packet - */ - - /* Make sure channel is disabled */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - if (hcchar.b.chen) { - hcchar.b.chdis = 1; - hcchar.b.chen = 1; -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - //sleep(1); - dwc_mdelay(1000); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - } - - /* Set HCTSIZ */ -@@ -1960,32 +1855,31 @@ static void do_in_ack(void) - hctsiz.b.xfersize = 8; - 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->hctsiz, hctsiz.d32); - - /* Set HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; - hcchar.b.epdir = 1; - hcchar.b.epnum = 0; - hcchar.b.mps = 8; - hcchar.b.chen = 1; -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Wait for receive status queue interrupt */ - do { -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - } while (gintsts.b.rxstsqlvl == 0); - -- - /* Read RXSTS */ -- grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); -+ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); - - /* Clear RXSTSQLVL in GINTSTS */ - gintsts.d32 = 0; - gintsts.b.rxstsqlvl = 1; -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - switch (grxsts.b.pktsts) { - case DWC_GRXSTS_PKTSTS_IN: -@@ -1997,7 +1891,7 @@ static void do_in_ack(void) - data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); - - for (i = 0; i < word_count; i++) { -- (void)dwc_read_reg32(data_fifo++); -+ (void)DWC_READ_REG32(data_fifo++); - } - } - break; -@@ -2006,21 +1900,20 @@ static void do_in_ack(void) - break; - } - -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Wait for receive status queue interrupt */ - do { -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - } while (gintsts.b.rxstsqlvl == 0); - -- - /* Read RXSTS */ -- grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); -+ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); - - /* Clear RXSTSQLVL in GINTSTS */ - gintsts.d32 = 0; - gintsts.b.rxstsqlvl = 1; -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - switch (grxsts.b.pktsts) { - case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: -@@ -2030,34 +1923,33 @@ static void do_in_ack(void) - break; - } - -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Wait for host channel interrupt */ - do { -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - } while (gintsts.b.hcintr == 0); - -- - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - // usleep(100000); - // mdelay(100); -@@ -2068,57 +1960,57 @@ static void do_in_ack(void) - */ - - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Make sure channel is disabled */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - if (hcchar.b.chen) { - hcchar.b.chdis = 1; - hcchar.b.chen = 1; -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - //sleep(1); - dwc_mdelay(1000); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - } - - /* Set HCTSIZ */ -@@ -2126,51 +2018,50 @@ static void do_in_ack(void) - 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->hctsiz, hctsiz.d32); - - /* Set HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; - hcchar.b.epdir = 0; - hcchar.b.epnum = 0; - hcchar.b.mps = 8; - hcchar.b.chen = 1; -- dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); -+ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); - -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - - /* Wait for host channel interrupt */ - do { -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - } while (gintsts.b.hcintr == 0); - -- - /* Disable HCINTs */ -- dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); -+ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); - - /* Disable HAINTs */ -- dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); -+ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); - - /* Read HAINT */ -- haint.d32 = dwc_read_reg32(&hc_global_regs->haint); -+ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); - - /* Read HCINT */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - - /* Read HCCHAR */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - - /* Clear HCINT */ -- dwc_write_reg32(&hc_regs->hcint, hcint.d32); -+ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); - - /* Clear HAINT */ -- dwc_write_reg32(&hc_global_regs->haint, haint.d32); -+ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); - - /* Clear GINTSTS */ -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - /* Read GINTSTS */ -- gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); -+ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); - } - #endif - -@@ -2217,23 +2108,27 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - "ClearPortFeature USB_PORT_FEAT_ENABLE\n"); - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtena = 1; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - break; - case UHF_PORT_SUSPEND: - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); - -- dwc_write_reg32(core_if->pcgcctl, 0); -- dwc_mdelay(5); -+ if (core_if->power_down == 2) { -+ dwc_otg_host_hibernation_restore(core_if, 0, 0); -+ } else { -+ DWC_WRITE_REG32(core_if->pcgcctl, 0); -+ dwc_mdelay(5); - -- hprt0.d32 = dwc_otg_read_hprt0(core_if); -- hprt0.b.prtres = 1; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -- hprt0.b.prtsusp = 0; -- /* Clear Resume bit */ -- dwc_mdelay(100); -- hprt0.b.prtres = 0; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtres = 1; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ hprt0.b.prtsusp = 0; -+ /* Clear Resume bit */ -+ dwc_mdelay(100); -+ hprt0.b.prtres = 0; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ } - break; - #ifdef CONFIG_USB_DWC_OTG_LPM - case UHF_PORT_L1: -@@ -2242,24 +2137,25 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - glpmcfg_data_t lpmcfg = {.d32 = 0 }; - - lpmcfg.d32 = -- dwc_read_reg32(&core_if->core_global_regs-> -- glpmcfg); -+ DWC_READ_REG32(&core_if-> -+ core_global_regs->glpmcfg); - lpmcfg.b.en_utmi_sleep = 0; - lpmcfg.b.hird_thres &= (~(1 << 4)); - lpmcfg.b.prt_sleep_sts = 1; -- dwc_write_reg32(&core_if->core_global_regs-> -- glpmcfg, lpmcfg.d32); -+ DWC_WRITE_REG32(&core_if-> -+ core_global_regs->glpmcfg, -+ lpmcfg.d32); - - /* Clear Enbl_L1Gating bit. */ - pcgcctl.b.enbl_sleep_gating = 1; -- dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, -+ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, - 0); - - dwc_mdelay(5); - - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtres = 1; -- dwc_write_reg32(core_if->host_if->hprt0, -+ DWC_WRITE_REG32(core_if->host_if->hprt0, - hprt0.d32); - /* This bit will be cleared in wakeup interrupt handle */ - break; -@@ -2270,7 +2166,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - "ClearPortFeature USB_PORT_FEAT_POWER\n"); - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtpwr = 0; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - break; - case UHF_PORT_INDICATOR: - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -@@ -2343,7 +2239,8 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - break; - case UCR_GET_PORT_STATUS: - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -- "GetPortStatus\n"); -+ "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n", -+ wIndex, dwc_otg_hcd->flags.d32); - if (!wIndex || wIndex > 1) - goto error; - -@@ -2366,7 +2263,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - } - - if (dwc_otg_hcd->flags.b.port_over_current_change) { -- DWC_ERROR("Device Not Supported\n"); -+ DWC_WARN("Overcurrent change detected\n"); - port_status |= (1 << UHF_C_PORT_OVER_CURRENT); - } - -@@ -2382,7 +2279,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - break; - } - -- hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); -+ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); - DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); - - if (hprt0.b.prtconnsts) -@@ -2413,7 +2310,16 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) { - port_status |= (1 << UHF_PORT_L1); - } -- -+ /* -+ For Synopsys HW emulation of Power down wkup_control asserts the -+ hreset_n and prst_n on suspned. This causes the HPRT0 to be zero. -+ We intentionally tell the software that port is in L2Suspend state. -+ Only for STE. -+ */ -+ if ((core_if->power_down == 2) -+ && (core_if->hibernation_suspend == 1)) { -+ port_status |= (1 << UHF_PORT_SUSPEND); -+ } - /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ - - *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); -@@ -2443,19 +2349,149 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - case UHF_PORT_SUSPEND: - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); -+ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) { -+ goto error; -+ } -+ if (core_if->power_down == 2) { -+ int timeout = 300; -+ dwc_irqflags_t flags; -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ gusbcfg_data_t gusbcfg = {.d32 = 0 }; -+#ifdef DWC_DEV_SRPCAP -+ int32_t otg_cap_param = core_if->core_params->otg_cap; -+#endif -+ DWC_PRINTF("Preparing for complete power-off\n"); -+ -+ /* Save registers before hibernation */ -+ dwc_otg_save_global_regs(core_if); -+ dwc_otg_save_host_regs(core_if); -+ -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtsusp = 1; -+ hprt0.b.prtena = 0; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ /* Spin hprt0.b.prtsusp to became 1 */ -+ do { -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ if (hprt0.b.prtsusp) { -+ break; -+ } -+ dwc_mdelay(1); -+ } while (--timeout); -+ if (!timeout) { -+ DWC_WARN("Suspend wasn't genereted\n"); -+ } -+ dwc_udelay(10); -+ -+ /* -+ * We need to disable interrupts to prevent servicing of any IRQ -+ * during going to hibernation -+ */ -+ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); -+ core_if->lx_state = DWC_OTG_L2; -+#ifdef DWC_DEV_SRPCAP -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtpwr = 0; -+ hprt0.b.prtena = 0; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, -+ hprt0.d32); -+#endif -+ gusbcfg.d32 = -+ DWC_READ_REG32(&core_if->core_global_regs-> -+ gusbcfg); -+ if (gusbcfg.b.ulpi_utmi_sel == 1) { -+ /* ULPI interface */ -+ /* Suspend the Phy Clock */ -+ pcgcctl.d32 = 0; -+ pcgcctl.b.stoppclk = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, -+ pcgcctl.d32); -+ dwc_udelay(10); -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ } else { -+ /* UTMI+ Interface */ -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ pcgcctl.b.stoppclk = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); -+ dwc_udelay(10); -+ } -+#ifdef DWC_DEV_SRPCAP -+ gpwrdn.d32 = 0; -+ gpwrdn.b.dis_vbus = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+#endif -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ gpwrdn.d32 = 0; -+#ifdef DWC_DEV_SRPCAP -+ gpwrdn.b.srp_det_msk = 1; -+#endif -+ gpwrdn.b.disconn_det_msk = 1; -+ gpwrdn.b.lnstchng_msk = 1; -+ gpwrdn.b.sts_chngint_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Enable Power Down Clamp and all interrupts in GPWRDN */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnclmp = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ /* Switch off VDD */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ -+#ifdef DWC_DEV_SRPCAP -+ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) -+ { -+ core_if->pwron_timer_started = 1; -+ DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ ); -+ } -+#endif -+ /* Save gpwrdn register for further usage if stschng interrupt */ -+ core_if->gr_backup->gpwrdn_local = -+ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ -+ /* Set flag to indicate that we are in hibernation */ -+ core_if->hibernation_suspend = 1; -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags); -+ -+ DWC_PRINTF("Host hibernation completed\n"); -+ // Exit from case statement -+ break; -+ -+ } - if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex && - dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { - gotgctl_data_t gotgctl = {.d32 = 0 }; - gotgctl.b.hstsethnpen = 1; -- dwc_modify_reg32(&core_if->core_global_regs-> -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> - gotgctl, 0, gotgctl.d32); - core_if->op_state = A_SUSPEND; - } - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtsusp = 1; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - { -- uint64_t flags; -+ dwc_irqflags_t flags; - /* Update lx_state */ - DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); - core_if->lx_state = DWC_OTG_L2; -@@ -2465,64 +2501,111 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - { - pcgcctl_data_t pcgcctl = {.d32 = 0 }; - pcgcctl.b.stoppclk = 1; -- dwc_modify_reg32(core_if->pcgcctl, 0, -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, - pcgcctl.d32); -+ dwc_udelay(10); - } - - /* For HNP the bus must be suspended for at least 200ms. */ - if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ pcgcctl.b.stoppclk = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); - dwc_mdelay(200); - } -+ -+ /** @todo - check how sw can wait for 1 sec to check asesvld??? */ -+#if 0 //vahrama !!!!!!!!!!!!!!!!!! -+ if (core_if->adp_enable) { -+ gotgctl_data_t gotgctl = {.d32 = 0 }; -+ gpwrdn_data_t gpwrdn; -+ -+ while (gotgctl.b.asesvld == 1) { -+ gotgctl.d32 = -+ DWC_READ_REG32(&core_if-> -+ core_global_regs-> -+ gotgctl); -+ dwc_mdelay(100); -+ } -+ -+ /* Enable Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ -+ /* Unmask SRP detected interrupt from Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.srp_det_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); -+ -+ dwc_otg_adp_probe_start(core_if); -+ } -+#endif - break; - case UHF_PORT_POWER: - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " - "SetPortFeature - USB_PORT_FEAT_POWER\n"); - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prtpwr = 1; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - break; - case UHF_PORT_RESET: -- DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -- "SetPortFeature - USB_PORT_FEAT_RESET\n"); -- { -- pcgcctl_data_t pcgcctl = {.d32 = 0 }; -- pcgcctl.b.enbl_sleep_gating = 1; -- pcgcctl.b.stoppclk = 1; -- dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, -- 0); -- dwc_write_reg32(core_if->pcgcctl, 0); -- } -+ if ((core_if->power_down == 2) -+ && (core_if->hibernation_suspend == 1)) { -+ /* If we are going to exit from Hibernated -+ * state via USB RESET. -+ */ -+ dwc_otg_host_hibernation_restore(core_if, 0, 1); -+ } else { -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ -+ DWC_DEBUGPL(DBG_HCD, -+ "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_RESET\n"); -+ { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ pcgcctl.b.enbl_sleep_gating = 1; -+ pcgcctl.b.stoppclk = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); -+ DWC_WRITE_REG32(core_if->pcgcctl, 0); -+ } - #ifdef CONFIG_USB_DWC_OTG_LPM -- { -- glpmcfg_data_t lpmcfg; -- lpmcfg.d32 = -- dwc_read_reg32(&core_if->core_global_regs-> -- glpmcfg); -- if (lpmcfg.b.prt_sleep_sts) { -- lpmcfg.b.en_utmi_sleep = 0; -- lpmcfg.b.hird_thres &= (~(1 << 4)); -- dwc_write_reg32(&core_if-> -- core_global_regs-> -- glpmcfg, lpmcfg.d32); -- dwc_mdelay(1); -+ { -+ glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = -+ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); -+ if (lpmcfg.b.prt_sleep_sts) { -+ lpmcfg.b.en_utmi_sleep = 0; -+ lpmcfg.b.hird_thres &= (~(1 << 4)); -+ DWC_WRITE_REG32 -+ (&core_if->core_global_regs->glpmcfg, -+ lpmcfg.d32); -+ dwc_mdelay(1); -+ } - } -- } - #endif -- hprt0.d32 = dwc_otg_read_hprt0(core_if); -- /* When B-Host the Port reset bit is set in -- * the Start HCD Callback function, so that -- * the reset is started within 1ms of the HNP -- * success interrupt. */ -- if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) { -- hprt0.b.prtrst = 1; -- dwc_write_reg32(core_if->host_if->hprt0, -- hprt0.d32); -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ /* Clear suspend bit if resetting from suspended state. */ -+ hprt0.b.prtsusp = 0; -+ /* When B-Host the Port reset bit is set in -+ * the Start HCD Callback function, so that -+ * the reset is started within 1ms of the HNP -+ * success interrupt. */ -+ if (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) { -+ hprt0.b.prtpwr = 1; -+ hprt0.b.prtrst = 1; -+ DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, -+ hprt0.d32); -+ } -+ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ -+ dwc_mdelay(60); -+ hprt0.b.prtrst = 0; -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); -+ core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */ - } -- /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ -- dwc_mdelay(60); -- hprt0.b.prtrst = 0; -- dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -- core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */ - break; - #ifdef DWC_HS_ELECT_TST - case UHF_PORT_TEST: -@@ -2539,7 +2622,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - if (t < 6) { - hprt0.d32 = dwc_otg_read_hprt0(core_if); - hprt0.b.prttstctl = t; -- dwc_write_reg32(core_if->host_if->hprt0, -+ DWC_WRITE_REG32(core_if->host_if->hprt0, - hprt0.d32); - } else { - /* Setup global vars with reg addresses (quick and -@@ -2559,14 +2642,13 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ - /* Save current interrupt mask */ - gintmsk.d32 = -- dwc_read_reg32 -+ DWC_READ_REG32 - (&global_regs->gintmsk); - - /* Disable all interrupts while we muck with - * the hardware directly - */ -- dwc_write_reg32(&global_regs-> -- gintmsk, 0); -+ DWC_WRITE_REG32(&global_regs->gintmsk, 0); - - /* 15 second delay per the test spec */ - dwc_mdelay(15000); -@@ -2576,9 +2658,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - dwc_otg_read_hprt0(core_if); - hprt0.b.prtsusp = 1; - hprt0.b.prtres = 0; -- dwc_write_reg32(core_if-> -- host_if->hprt0, -- hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - - /* 15 second delay per the test spec */ - dwc_mdelay(15000); -@@ -2588,32 +2668,25 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - dwc_otg_read_hprt0(core_if); - hprt0.b.prtsusp = 0; - hprt0.b.prtres = 1; -- dwc_write_reg32(core_if-> -- host_if->hprt0, -- hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - dwc_mdelay(100); - - /* Clear the resume bit */ - hprt0.b.prtres = 0; -- dwc_write_reg32(core_if-> -- host_if->hprt0, -- hprt0.d32); -+ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); - - /* Restore interrupts */ -- dwc_write_reg32(&global_regs-> -- gintmsk, -- gintmsk.d32); -+ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); - } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ - /* Save current interrupt mask */ - gintmsk.d32 = -- dwc_read_reg32 -+ DWC_READ_REG32 - (&global_regs->gintmsk); - - /* Disable all interrupts while we muck with - * the hardware directly - */ -- dwc_write_reg32(&global_regs-> -- gintmsk, 0); -+ DWC_WRITE_REG32(&global_regs->gintmsk, 0); - - /* 15 second delay per the test spec */ - dwc_mdelay(15000); -@@ -2625,20 +2698,17 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - dwc_mdelay(15000); - - /* Restore interrupts */ -- dwc_write_reg32(&global_regs-> -- gintmsk, -- gintmsk.d32); -+ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); - } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ - /* Save current interrupt mask */ - gintmsk.d32 = -- dwc_read_reg32 -+ DWC_READ_REG32 - (&global_regs->gintmsk); - - /* Disable all interrupts while we muck with - * the hardware directly - */ -- dwc_write_reg32(&global_regs-> -- gintmsk, 0); -+ DWC_WRITE_REG32(&global_regs->gintmsk, 0); - - /* Send the Setup packet */ - do_setup(); -@@ -2653,14 +2723,12 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - dwc_mdelay(15000); - - /* Restore interrupts */ -- dwc_write_reg32(&global_regs-> -- gintmsk, -- gintmsk.d32); -+ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); - } - } - break; - } --#endif /* DWC_HS_ELECT_TST */ -+#endif /* DWC_HS_ELECT_TST */ - - case UHF_PORT_INDICATOR: - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -@@ -2695,7 +2763,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - } - /* Check if the port currently is in SLEEP state */ - lpmcfg.d32 = -- dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - if (lpmcfg.b.prt_sleep_sts) { - DWC_INFO("Port is already in sleep mode\n"); - buf[0] = 0; /* Return success */ -@@ -2721,7 +2789,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - /* Disable LPM interrupt */ - gintmsk.d32 = 0; - gintmsk.b.lpmtranrcvd = 1; -- dwc_modify_reg32(&core_if->core_global_regs->gintmsk, -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, - gintmsk.d32, 0); - - if (dwc_otg_hcd_send_lpm -@@ -2738,8 +2806,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - */ - do { - gintsts.d32 = -- dwc_read_reg32(&core_if->core_global_regs-> -- gintsts); -+ DWC_READ_REG32(&core_if->core_global_regs->gintsts); - if (gintsts.b.lpmtranrcvd) { - break; - } -@@ -2757,8 +2824,7 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd); - } else { - lpmcfg.d32 = -- dwc_read_reg32(&core_if->core_global_regs-> -- glpmcfg); -+ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - if (lpmcfg.b.lpm_resp == 0x3) { - /* ACK responce from the device */ - buf[0] = 0x00; /* Success */ -@@ -2772,14 +2838,14 @@ int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - } - DWC_PRINTF("Device responce to LPM trans is %x\n", - lpmcfg.b.lpm_resp); -- dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, - gintmsk.d32); - - break; - } --#endif /* CONFIG_USB_DWC_OTG_LPM */ -+#endif /* CONFIG_USB_DWC_OTG_LPM */ - default: -- error: -+error: - retval = -DWC_E_INVALID; - DWC_WARN("DWC OTG HCD - " - "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", -@@ -2808,7 +2874,7 @@ int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr) - - /* Mask host channel interrupts. */ - gintmsk.b.hcintr = 1; -- dwc_modify_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32, 0); - - /* Fill fields that core needs for LPM transaction */ - hcchar.b.devaddr = devaddr; -@@ -2817,7 +2883,7 @@ int dwc_otg_hcd_get_hc_for_lpm_tran(dwc_otg_hcd_t * hcd, uint8_t devaddr) - hcchar.b.mps = 64; - hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); - hcchar.b.epdir = 0; /* OUT */ -- dwc_write_reg32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, -+ DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, - hcchar.d32); - - /* Remove the host channel from the free list. */ -@@ -2835,7 +2901,7 @@ void dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd_t * hcd) - glpmcfg_data_t lpmcfg; - uint8_t hc_num; - -- lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg); -+ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); - hc_num = lpmcfg.b.lpm_chan_index; - - hc = hcd->hc_ptr_array[hc_num]; -@@ -2858,10 +2924,10 @@ int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird, - } - - pcgcctl.b.enbl_sleep_gating = 1; -- dwc_modify_reg32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); -+ DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); - - /* Read LPM config register */ -- lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg); -+ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); - - /* Program LPM transaction fields */ - lpmcfg.b.rem_wkup_en = bRemoteWake; -@@ -2870,16 +2936,16 @@ int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, uint8_t hird, - lpmcfg.b.lpm_chan_index = channel; - lpmcfg.b.en_utmi_sleep = 1; - /* Program LPM config register */ -- dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); -+ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); - - /* Send LPM transaction */ - lpmcfg.b.send_lpm = 1; -- dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); -+ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); - - return 0; - } - --#endif /* CONFIG_USB_DWC_OTG_LPM */ -+#endif /* CONFIG_USB_DWC_OTG_LPM */ - - int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port) - { -@@ -2916,8 +2982,9 @@ int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port) - int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd) - { - hfnum_data_t hfnum; -- hfnum.d32 = dwc_read_reg32(&dwc_otg_hcd->core_if-> -- host_if->host_global_regs->hfnum); -+ hfnum.d32 = -+ DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs-> -+ hfnum); - - #ifdef DEBUG_SOF - DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", -@@ -2932,7 +2999,8 @@ int dwc_otg_hcd_start(dwc_otg_hcd_t * hcd, - int retval = 0; - - hcd->fops = fops; -- if (!dwc_otg_is_device_mode(hcd->core_if)) { -+ if (!dwc_otg_is_device_mode(hcd->core_if) && -+ (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) { - dwc_otg_hcd_reinit(hcd); - } else { - retval = -DWC_E_NO_DEVICE; -@@ -2977,12 +3045,21 @@ dwc_otg_hcd_urb_t *dwc_otg_hcd_urb_alloc(dwc_otg_hcd_t * hcd, - size = - sizeof(*dwc_otg_urb) + - iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc); -- if (atomic_alloc) { -- dwc_otg_urb = dwc_alloc_atomic(size); -- } else { -- dwc_otg_urb = dwc_alloc(size); -- } -- dwc_otg_urb->packet_count = iso_desc_count; -+ if (atomic_alloc) -+ dwc_otg_urb = DWC_ALLOC_ATOMIC(size); -+ else -+ dwc_otg_urb = DWC_ALLOC(size); -+ -+ if (NULL != dwc_otg_urb) -+ dwc_otg_urb->packet_count = iso_desc_count; -+ else { -+ dwc_otg_urb->packet_count = 0; -+ if (size != 0) { -+ DWC_ERROR("**** DWC OTG HCD URB alloc - " -+ "%salloc of %db failed\n", -+ atomic_alloc?"atomic ":"", size); -+ } -+ } - - return dwc_otg_urb; - } -@@ -3130,20 +3207,20 @@ void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd) - hcint_data_t hcint; - hcintmsk_data_t hcintmsk; - hfnum.d32 = -- dwc_read_reg32(&hcd->core_if->host_if-> -- host_global_regs->hfnum); -+ DWC_READ_REG32(&hcd->core_if-> -+ host_if->host_global_regs->hfnum); - hcchar.d32 = -- dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -- hcchar); -+ DWC_READ_REG32(&hcd->core_if->host_if-> -+ hc_regs[i]->hcchar); - hctsiz.d32 = -- dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -- hctsiz); -+ DWC_READ_REG32(&hcd->core_if->host_if-> -+ hc_regs[i]->hctsiz); - hcint.d32 = -- dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -- hcint); -+ DWC_READ_REG32(&hcd->core_if->host_if-> -+ hc_regs[i]->hcint); - hcintmsk.d32 = -- dwc_read_reg32(&hcd->core_if->host_if->hc_regs[i]-> -- hcintmsk); -+ DWC_READ_REG32(&hcd->core_if->host_if-> -+ hc_regs[i]->hcintmsk); - DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32); - DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32); - DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32); -@@ -3155,7 +3232,7 @@ void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd) - dwc_otg_hcd_urb_t *urb; - - DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) { -- if(!qtd->in_process) -+ if (!qtd->in_process) - break; - - urb = qtd->urb; -@@ -3179,23 +3256,23 @@ void dwc_otg_hcd_dump_state(dwc_otg_hcd_t * hcd) - (void *)urb->dma); - DWC_PRINTF(" transfer_buffer_length: %d\n", - urb->length); -- DWC_PRINTF(" actual_length: %d\n", -- urb->actual_length); -+ DWC_PRINTF(" actual_length: %d\n", -+ urb->actual_length); -+ } - } - } - } -- } - DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels); - DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels); - DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs); - np_tx_status.d32 = -- dwc_read_reg32(&hcd->core_if->core_global_regs->gnptxsts); -+ DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts); - DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n", - np_tx_status.b.nptxqspcavail); - DWC_PRINTF(" NP Tx FIFO Space Avail: %d\n", - np_tx_status.b.nptxfspcavail); - p_tx_status.d32 = -- dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hptxsts); -+ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts); - DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n", - p_tx_status.b.ptxqspcavail); - DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); -@@ -3331,4 +3408,4 @@ void dwc_otg_hcd_dump_frrem(dwc_otg_hcd_t * hcd) - #endif - } - --#endif /* DWC_DEVICE_ONLY */ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -index f6e7870..c87cb5b 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ -- * $Revision: #52 $ -- * $Date: 2009/04/21 $ -- * $Change: 1237472 $ -+ * $Revision: #58 $ -+ * $Date: 2011/09/15 $ -+ * $Change: 1846647 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -34,7 +34,8 @@ - #ifndef __DWC_HCD_H__ - #define __DWC_HCD_H__ - --#include -+#include "dwc_otg_os_dep.h" -+#include "usb.h" - #include "dwc_otg_hcd_if.h" - #include "dwc_otg_core_if.h" - #include "dwc_list.h" -@@ -238,17 +239,17 @@ static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, - DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry; - - /** Indicates if this QTD is currently processed by HW. */ -- uint8_t in_process; -+ uint8_t in_process; - - /** Number of DMA descriptors for this QTD */ -- uint8_t n_desc; -- -+ uint8_t n_desc; -+ - /** - * Last activated frame(packet) index. - * Used in Descriptor DMA mode only. - */ - uint16_t isoc_frame_index_last; -- -+ - } dwc_otg_qtd_t; - - DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd); -@@ -331,36 +332,36 @@ static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, - */ - uint8_t *dw_align_buf; - dwc_dma_t dw_align_buf_dma; -- -+ - /** Entry for QH in either the periodic or non-periodic schedule. */ - dwc_list_link_t qh_list_entry; -- -+ - /** @name Descriptor DMA support */ - /** @{ */ -- -+ - /** Descriptor List. */ -- dwc_otg_host_dma_desc_t *desc_list; -- -+ dwc_otg_host_dma_desc_t *desc_list; -+ - /** Descriptor List physical address. */ - dwc_dma_t desc_list_dma; -- -+ - /** - * Xfer Bytes array. - * Each element corresponds to a descriptor and indicates - * original XferSize size value for the descriptor. - */ - uint32_t *n_bytes; -- -+ - /** Actual number of transfer descriptors in a list. */ - uint16_t ntd; -- -+ - /** First activated isochronous transfer descriptor index. */ - uint8_t td_first; - /** Last activated isochronous transfer descriptor index. */ - uint8_t td_last; -- -+ - /** @} */ -- -+ - } dwc_otg_qh_t; - - DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); -@@ -380,6 +381,8 @@ static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, - * periodic schedules. - */ - struct dwc_otg_hcd { -+ /** The DWC otg device pointer */ -+ struct dwc_otg_device *otg_dev; - /** DWC OTG Core Interface Layer */ - dwc_otg_core_if_t *core_if; - -@@ -480,6 +483,11 @@ struct dwc_otg_hcd { - uint16_t frame_number; - - /** -+ * Count of periodic QHs, if using several eps. For SOF enable/disable. -+ */ -+ uint16_t periodic_qh_count; -+ -+ /** - * Free host channels in the controller. This is a list of - * dwc_hc_t items. - */ -@@ -576,7 +584,7 @@ struct dwc_otg_hcd { - extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t - * hcd); - extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, -- dwc_otg_transaction_type_e tr_type); -+ dwc_otg_transaction_type_e tr_type); - - /** @} */ - -@@ -609,7 +617,7 @@ extern int32_t dwc_otg_hcd_handle_wakeup_detected_intr(dwc_otg_hcd_t * - - /* Implemented in dwc_otg_hcd_queue.c */ - extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, -- dwc_otg_hcd_urb_t * urb); -+ dwc_otg_hcd_urb_t * urb, int atomic_alloc); - extern void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); - extern int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); - extern void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); -@@ -620,27 +628,37 @@ extern void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd, - dwc_otg_qh_t * qh) - { -+ dwc_irqflags_t flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); - dwc_otg_hcd_qh_remove(hcd, qh); -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - dwc_otg_hcd_qh_free(hcd, qh); - } - - /** Allocates memory for a QH structure. - * @return Returns the memory allocate or NULL on error. */ --static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(void) -+static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc) - { -- return (dwc_otg_qh_t *) dwc_alloc_atomic(sizeof(dwc_otg_qh_t)); -+ if (atomic_alloc) -+ return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t)); -+ else -+ return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t)); - } - --extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb); -+extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, -+ int atomic_alloc); - extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb); - extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd, -- dwc_otg_qh_t ** qh); -+ dwc_otg_qh_t ** qh, int atomic_alloc); - - /** Allocates memory for a QTD structure. - * @return Returns the memory allocate or NULL on error. */ --static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void) -+static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc) - { -- return (dwc_otg_qtd_t *) dwc_alloc_atomic(sizeof(dwc_otg_qtd_t)); -+ if (atomic_alloc) -+ return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t)); -+ else -+ return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t)); - } - - /** Frees the memory for a QTD structure. QTD should already be removed from -@@ -648,7 +666,7 @@ static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(void) - * @param qtd QTD to free.*/ - static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd) - { -- dwc_free(qtd); -+ DWC_FREE(qtd); - } - - /** Removes a QTD from list. -@@ -660,13 +678,12 @@ static inline void dwc_otg_hcd_qtd_remove(dwc_otg_hcd_t * hcd, - dwc_otg_qtd_t * qtd, - dwc_otg_qh_t * qh) - { -- uint64_t flags; -- DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); - DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); -- DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - } - --/** Remove and free a QTD */ -+/** Remove and free a QTD -+ * Need to disable IRQ and hold hcd lock while calling this function out of -+ * interrupt servicing chain */ - static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd, - dwc_otg_qtd_t * qtd, - dwc_otg_qh_t * qh) -@@ -682,15 +699,15 @@ static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd, - - extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); - extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, -- dwc_hc_t * hc, -- dwc_otg_hc_regs_t * hc_regs, -- dwc_otg_halt_status_e halt_status); -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_halt_status_e halt_status); - - extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); - extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); - - /** @} */ -- -+ - /** @name Internal Functions */ - /** @{ */ - dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb); -@@ -761,8 +778,8 @@ static inline uint16_t dwc_micro_frame_num(uint16_t frame) - } - - void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, -- dwc_otg_hc_regs_t * hc_regs, -- dwc_otg_qtd_t * qtd); -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd); - - #ifdef DEBUG - /** -@@ -780,7 +797,7 @@ void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, - dwc_otg_qtd_t *qtd; \ - qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \ - if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \ -- hfnum.d32 = dwc_read_reg32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ -+ hfnum.d32 = DWC_READ_REG32(&_hcd->core_if->host_if->host_global_regs->hfnum); \ - switch (hfnum.b.frnum & 0x7) { \ - case 7: \ - _hcd->hfnum_7_samples_##_letter++; \ -@@ -801,4 +818,4 @@ void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, - #define dwc_sample_frrem(_hcd, _qh, _letter) - #endif - #endif --#endif /* DWC_DEVICE_ONLY */ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -index 01c4780..e5dfa4c 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -@@ -1,8 +1,8 @@ - /*========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ -- * $Revision: #2 $ -- * $Date: 2009/04/21 $ -- * $Change: 1237473 $ -+ * $Revision: #10 $ -+ * $Date: 2011/10/20 $ -+ * $Change: 1869464 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -35,11 +35,10 @@ - /** @file - * This file contains Descriptor DMA support implementation for host mode. - */ -- -+ - #include "dwc_otg_hcd.h" - #include "dwc_otg_regs.h" -- -- -+ - static inline uint8_t frame_list_idx(uint16_t frame) - { - return (frame & (MAX_FRLIST_EN_NUM - 1)); -@@ -47,91 +46,93 @@ static inline uint8_t frame_list_idx(uint16_t frame) - - static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed) - { -- return (idx + inc) & -- (((speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1); -+ return (idx + inc) & -+ (((speed == -+ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : -+ MAX_DMA_DESC_NUM_GENERIC) - 1); - } - - static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed) - { -- return (idx - inc) & -- (((speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1); -+ return (idx - inc) & -+ (((speed == -+ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : -+ MAX_DMA_DESC_NUM_GENERIC) - 1); - } - - static inline uint16_t max_desc_num(dwc_otg_qh_t * qh) - { -- return (((qh->ep_type == UE_ISOCHRONOUS) && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) -- ? -- MAX_DMA_DESC_NUM_HS_ISOC -- : -- MAX_DMA_DESC_NUM_GENERIC); -+ return (((qh->ep_type == UE_ISOCHRONOUS) -+ && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) -+ ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC); - } - static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) - { -- return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) -- ? ((qh->interval + 8 - 1) / 8) -- : -- qh->interval); -+ return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) -+ ? ((qh->interval + 8 - 1) / 8) -+ : qh->interval); - } - - static int desc_list_alloc(dwc_otg_qh_t * qh) - { - int retval = 0; -- -- qh->desc_list = (dwc_otg_host_dma_desc_t *) -- dwc_dma_alloc(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), -- &qh->desc_list_dma -- ); -- -+ -+ qh->desc_list = (dwc_otg_host_dma_desc_t *) -+ DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), -+ &qh->desc_list_dma); -+ - if (!qh->desc_list) { - retval = -DWC_E_NO_MEMORY; - DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__); - - } -- -- dwc_memset(qh->desc_list, 0x00, sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); -- - -- qh->n_bytes = (uint32_t *) dwc_alloc(sizeof(uint32_t) * max_desc_num(qh)); -- -+ dwc_memset(qh->desc_list, 0x00, -+ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); -+ -+ qh->n_bytes = -+ (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh)); -+ - if (!qh->n_bytes) { - retval = -DWC_E_NO_MEMORY; -- DWC_ERROR("%s: Failed to allocate array for descriptors' size actual values\n", -- __func__); -- -- } -+ DWC_ERROR -+ ("%s: Failed to allocate array for descriptors' size actual values\n", -+ __func__); -+ -+ } - return retval; - - } - - static void desc_list_free(dwc_otg_qh_t * qh) - { -- if(qh->desc_list) { -- dwc_dma_free(max_desc_num(qh), qh->desc_list, qh->desc_list_dma); -+ if (qh->desc_list) { -+ DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, -+ qh->desc_list_dma); - qh->desc_list = NULL; - } -- -+ - if (qh->n_bytes) { -- dwc_free(qh->n_bytes); -+ DWC_FREE(qh->n_bytes); - qh->n_bytes = NULL; - } - } - - static int frame_list_alloc(dwc_otg_hcd_t * hcd) - { -- int retval = 0; -+ int retval = 0; - if (hcd->frame_list) - return 0; -- -- hcd->frame_list = dwc_dma_alloc(4 * MAX_FRLIST_EN_NUM, -- &hcd->frame_list_dma -- ); -+ -+ hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, -+ &hcd->frame_list_dma); - if (!hcd->frame_list) { - retval = -DWC_E_NO_MEMORY; - DWC_ERROR("%s: Frame List allocation failed\n", __func__); - } -- -+ - dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM); -- -+ - return retval; - } - -@@ -140,60 +141,63 @@ static void frame_list_free(dwc_otg_hcd_t * hcd) - if (!hcd->frame_list) - return; - -- dwc_dma_free(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); -+ DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); - hcd->frame_list = NULL; - } - - static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en) - { -- -+ - hcfg_data_t hcfg; - -- hcfg.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hcfg); -+ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); - -- if (hcfg.b.perschedstat) { -- /* already enabled*/ -+ if (hcfg.b.perschedena) { -+ /* already enabled */ - return; - } -- -- dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hflbaddr, hcd->frame_list_dma); -- -- switch(fr_list_en) { -+ -+ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr, -+ hcd->frame_list_dma); -+ -+ switch (fr_list_en) { - case 64: -- hcfg.b.frlisten = 3; -- break; -+ hcfg.b.frlisten = 3; -+ break; - case 32: -- hcfg.b.frlisten = 2; -- break; -+ hcfg.b.frlisten = 2; -+ break; - case 16: -- hcfg.b.frlisten = 1; -- case 8: -- hcfg.b.frlisten = 0; -- default: -- break; -+ hcfg.b.frlisten = 1; -+ break; -+ case 8: -+ hcfg.b.frlisten = 0; -+ break; -+ default: -+ break; - } -- -+ - hcfg.b.perschedena = 1; - - DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n"); -- dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); -+ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); - - } -- -+ - static void per_sched_disable(dwc_otg_hcd_t * hcd) - { - hcfg_data_t hcfg; - -- hcfg.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hcfg); -+ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); - -- if (!hcfg.b.perschedstat) { -- /* already disabled */ -+ if (!hcfg.b.perschedena) { -+ /* already disabled */ - return; - } - hcfg.b.perschedena = 0; -- -+ - DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n"); -- dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); -+ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); - } - - /* -@@ -203,10 +207,25 @@ static void per_sched_disable(dwc_otg_hcd_t * hcd) - void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable) - { - uint16_t i, j, inc; -- dwc_hc_t *hc = qh->channel; -- -+ dwc_hc_t *hc = NULL; -+ -+ if (!qh->channel) { -+ DWC_ERROR("qh->channel = %p", qh->channel); -+ return; -+ } -+ -+ if (!hcd) { -+ DWC_ERROR("------hcd = %p", hcd); -+ return; -+ } -+ -+ if (!hcd->frame_list) { -+ DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list); -+ return; -+ } -+ -+ hc = qh->channel; - inc = frame_incr_val(qh); -- - if (qh->ep_type == UE_ISOCHRONOUS) - i = frame_list_idx(qh->sched_frame); - else -@@ -221,30 +240,30 @@ void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable) - j = (j + inc) & (MAX_FRLIST_EN_NUM - 1); - } - while (j != i); -- - if (!enable) - return; -- - hc->schinfo = 0; - if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) { - j = 1; -- for (i = 0 ; i < 8 / qh->interval; i++) { -+ /* TODO - check this */ -+ inc = (8 + qh->interval - 1) / qh->interval; -+ for (i = 0; i < inc; i++) { - hc->schinfo |= j; - j = j << qh->interval; - } -- } -- else { -+ } else { - hc->schinfo = 0xff; -- } --} -+ } -+} -+ - #if 1 - void dump_frame_list(dwc_otg_hcd_t * hcd) - { - int i = 0; -- DWC_PRINTF("--FRAME LIST (hex) --\n"); -+ DWC_PRINTF("--FRAME LIST (hex) --\n"); - for (i = 0; i < MAX_FRLIST_EN_NUM; i++) { -- DWC_PRINTF("%x\t",hcd->frame_list[i]); -- if (!(i % 8) && i) -+ DWC_PRINTF("%x\t", hcd->frame_list[i]); -+ if (!(i % 8) && i) - DWC_PRINTF("\n"); - } - DWC_PRINTF("\n----\n"); -@@ -255,28 +274,27 @@ void dump_frame_list(dwc_otg_hcd_t * hcd) - static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { - dwc_hc_t *hc = qh->channel; -- if (dwc_qh_is_non_per(qh)) { -- hcd->non_periodic_channels--; -- } -- else { -+ if (dwc_qh_is_non_per(qh)) -+ hcd->non_periodic_channels--; -+ else - update_frame_list(hcd, qh, 0); -- } -+ - /* - * The condition is added to prevent double cleanup try in case of device - * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb(). - */ -- if (hc->qh) { -+ if (hc->qh) { - dwc_otg_hc_cleanup(hcd->core_if, hc); - DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); - hc->qh = NULL; - } -- -+ - qh->channel = NULL; - qh->ntd = 0; -- -+ - if (qh->desc_list) { -- dwc_memset(qh->desc_list, 0x00, -- sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); -+ dwc_memset(qh->desc_list, 0x00, -+ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); - } - } - -@@ -290,29 +308,30 @@ static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - * @param qh The QH to init. - * - * @return 0 if successful, negative error code otherwise. -- */ -+ */ - int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { - int retval = 0; -- -- if (qh->do_split) { -+ -+ if (qh->do_split) { - DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n"); - return -1; - } - - retval = desc_list_alloc(qh); -- -- if ((retval == 0) && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { -- if(!hcd->frame_list) { -- retval = frame_list_alloc(hcd); -+ -+ if ((retval == 0) -+ && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { -+ if (!hcd->frame_list) { -+ retval = frame_list_alloc(hcd); - /* Enable periodic schedule on first periodic QH */ -- if (retval == 0) -+ if (retval == 0) - per_sched_enable(hcd, MAX_FRLIST_EN_NUM); - } - } -- -+ - qh->ntd = 0; -- -+ - return retval; - } - -@@ -338,13 +357,13 @@ void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - if (qh->channel) - release_channel_ddma(hcd, qh); - -- if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) -- && !hcd->periodic_channels && hcd->frame_list) { -- -- per_sched_disable(hcd); -- frame_list_free(hcd); -+ if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) -+ && !hcd->periodic_channels && hcd->frame_list) { -+ -+ per_sched_disable(hcd); -+ frame_list_free(hcd); - } --} -+} - - static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx) - { -@@ -352,19 +371,19 @@ static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx) - /* - * Descriptor set(8 descriptors) index - * which is 8-aligned. -- */ -+ */ - return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; -- } -- else { -+ } else { - return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1)); -- } -+ } - } - - /* - * Determine starting frame for Isochronous transfer. - * Few frames skipped to prevent race condition with HC. - */ --static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t* skip_frames) -+static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, -+ uint8_t * skip_frames) - { - uint16_t frame = 0; - hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd); -@@ -378,11 +397,11 @@ static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8 - * Example for FS: - * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor - * corresponding to curr_frame+1, the descriptor corresponding to frame 2 -- * will be fetched. If the number of descriptors is max=64 (or greather) the list will -- * be fully programmed with Active descriptors and it is possible case(rare) that the latest -- * descriptor(considering rollback) corresponding to frame 2 will be serviced first. -- * HS case is more probable because, in fact, up to 11 uframes(16 in the code) -- * may be skipped. -+ * will be fetched. If the number of descriptors is max=64 (or greather) the -+ * list will be fully programmed with Active descriptors and it is possible -+ * case(rare) that the latest descriptor(considering rollback) corresponding -+ * to frame 2 will be serviced first. HS case is more probable because, in fact, -+ * up to 11 uframes(16 in the code) may be skipped. - */ - if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { - /* -@@ -393,37 +412,37 @@ static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8 - * if the current frame is near to complete the next one - * is skipped as well. - */ -- -- if (dwc_micro_frame_num(hcd->frame_number) >= 5) { -+ -+ if (dwc_micro_frame_num(hcd->frame_number) >= 5) { - *skip_frames = 2 * 8; - frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); -- } -- else { -+ } else { - *skip_frames = 1 * 8; - frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); -- } -- -- frame = dwc_full_frame_num(frame); -+ } -+ -+ frame = dwc_full_frame_num(frame); - } else { - /* -- * Two frames are skipped for FS - the current and the next. -- * But for descriptor programming, 1 frame(descriptor) is enough, -- * see example above. -- */ -- *skip_frames = 1; -+ * Two frames are skipped for FS - the current and the next. -+ * But for descriptor programming, 1 frame(descriptor) is enough, -+ * see example above. -+ */ -+ *skip_frames = 1; - frame = dwc_frame_num_inc(hcd->frame_number, 2); - } -- -+ - return frame; - } -+ - /* - * Calculate initial descriptor index for isochronous transfer - * based on scheduled frame. - */ - static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { -- uint16_t frame = 0, fr_idx, fr_idx_tmp; -- uint8_t skip_frames = 0 ; -+ uint16_t frame = 0, fr_idx, fr_idx_tmp; -+ uint8_t skip_frames = 0; - /* - * With current ISOC processing algorithm the channel is being - * released when no more QTDs in the list(qh->ntd == 0). -@@ -437,99 +456,107 @@ static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - * starting frame and therefore starting desc_index are recalculated. - * In this case channel is released only on ep_disable. - */ -- -+ - /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */ - if (qh->channel) { -- frame = calc_starting_frame(hcd, qh, &skip_frames); -+ frame = calc_starting_frame(hcd, qh, &skip_frames); - /* -- * Calculate initial descriptor index based on FrameList current bitmap -- * and servicing period. -- */ -+ * Calculate initial descriptor index based on FrameList current bitmap -+ * and servicing period. -+ */ - fr_idx_tmp = frame_list_idx(frame); -- fr_idx = (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - fr_idx_tmp) -- % frame_incr_val(qh); -+ fr_idx = -+ (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - -+ fr_idx_tmp) -+ % frame_incr_val(qh); - fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM; -- } -- else { -- qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); -+ } else { -+ qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); - fr_idx = frame_list_idx(qh->sched_frame); - } -- -- qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); -- -+ -+ qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); -+ - return skip_frames; - } -- -+ - #define ISOC_URB_GIVEBACK_ASAP -- -+ - #define MAX_ISOC_XFER_SIZE_FS 1023 - #define MAX_ISOC_XFER_SIZE_HS 3072 - #define DESCNUM_THRESHOLD 4 - --static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t skip_frames) -+static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, -+ uint8_t skip_frames) - { - struct dwc_otg_hcd_iso_packet_desc *frame_desc; - dwc_otg_qtd_t *qtd; -- dwc_otg_host_dma_desc_t *dma_desc; -+ dwc_otg_host_dma_desc_t *dma_desc; - uint16_t idx, inc, n_desc, ntd_max, max_xfer_size; -- -+ - idx = qh->td_last; - inc = qh->interval; - n_desc = 0; -- -+ - ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval; - if (skip_frames && !qh->channel) -- ntd_max = ntd_max - skip_frames / qh->interval; -- -- max_xfer_size = (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS -- : MAX_ISOC_XFER_SIZE_FS; -- -+ ntd_max = ntd_max - skip_frames / qh->interval; -+ -+ max_xfer_size = -+ (qh->dev_speed == -+ DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS : -+ MAX_ISOC_XFER_SIZE_FS; -+ - DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { -- while ((qh->ntd < ntd_max) && (qtd->isoc_frame_index_last < qtd->urb->packet_count)) { -- -+ while ((qh->ntd < ntd_max) -+ && (qtd->isoc_frame_index_last < -+ qtd->urb->packet_count)) { -+ - dma_desc = &qh->desc_list[idx]; - dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t)); - - frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; -- -+ - if (frame_desc->length > max_xfer_size) - qh->n_bytes[idx] = max_xfer_size; - else - qh->n_bytes[idx] = frame_desc->length; - dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx]; - dma_desc->status.b_isoc.a = 1; -- -+ dma_desc->status.b_isoc.sts = 0; -+ - dma_desc->buf = qtd->urb->dma + frame_desc->offset; -- -+ - qh->ntd++; - - qtd->isoc_frame_index_last++; -- -- #ifdef ISOC_URB_GIVEBACK_ASAP -+ -+#ifdef ISOC_URB_GIVEBACK_ASAP - /* - * Set IOC for each descriptor corresponding to the - * last frame of the URB. -- */ -- if (qtd->isoc_frame_index_last == qtd->urb->packet_count) -+ */ -+ if (qtd->isoc_frame_index_last == -+ qtd->urb->packet_count) - dma_desc->status.b_isoc.ioc = 1; -- -- #endif -+ -+#endif - idx = desclist_idx_inc(idx, inc, qh->dev_speed); - n_desc++; -- -+ - } - qtd->in_process = 1; - } -- -+ - qh->td_last = idx; -- -+ - #ifdef ISOC_URB_GIVEBACK_ASAP -- /* Set IOC for the last descriptor if descriptor list is full */ -+ /* Set IOC for the last descriptor if descriptor list is full */ - if (qh->ntd == ntd_max) { - idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed); - qh->desc_list[idx].status.b_isoc.ioc = 1; - } --#else -+#else - /* - * Set IOC bit only for one descriptor. - * Always try to be ahead of HW processing, -@@ -545,81 +572,79 @@ static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t s - * Actually more than one QTD might be in the list if this function called - * from XferCompletion - QTDs was queued during HW processing of the previous - * descriptor chunk. -- */ -+ */ - idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed); -- } -- else { -+ } else { - /* - * Set the IOC for the latest descriptor - * if either number of descriptor is not greather than threshold - * or no more new descriptors activated. -- */ -+ */ - idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); - } -- -+ - qh->desc_list[idx].status.b_isoc.ioc = 1; - #endif - } - -- - static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { - - dwc_hc_t *hc; -- dwc_otg_host_dma_desc_t *dma_desc; -+ dwc_otg_host_dma_desc_t *dma_desc; - dwc_otg_qtd_t *qtd; -- int num_packets, len, n_desc = 0; -- -- hc = qh->channel; -- -+ int num_packets, len, n_desc = 0; -+ -+ hc = qh->channel; -+ - /* - * Start with hc->xfer_buff initialized in - * assign_and_init_hc(), then if SG transfer consists of multiple URBs, - * this pointer re-assigned to the buffer of the currently processed QTD. - * For non-SG request there is always one QTD active. - */ -- -+ - DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { -- -- if (n_desc) { -- /* SG request - more than 1 QTDs */ -+ -+ if (n_desc) { -+ /* SG request - more than 1 QTDs */ - hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length; - hc->xfer_len = qtd->urb->length - qtd->urb->actual_length; -- } -+ } - - qtd->n_desc = 0; -- -+ - do { - dma_desc = &qh->desc_list[n_desc]; - len = hc->xfer_len; -- - - if (len > MAX_DMA_DESC_SIZE) - len = MAX_DMA_DESC_SIZE - hc->max_packet + 1; -- -+ - if (hc->ep_is_in) { - if (len > 0) { - num_packets = (len + hc->max_packet - 1) / hc->max_packet; -- } -- else { -+ } else { - /* Need 1 packet for transfer length of 0. */ - num_packets = 1; - } - /* Always program an integral # of max packets for IN transfers. */ -- len = num_packets * hc->max_packet; -- } -- -+ len = num_packets * hc->max_packet; -+ } -+ - dma_desc->status.b.n_bytes = len; -- -+ - qh->n_bytes[n_desc] = len; -- - -- if ((qh->ep_type == UE_CONTROL) && (qtd->control_phase == DWC_OTG_CONTROL_SETUP)) -- dma_desc->status.b.sup = 1; /* Setup Packet */ -- -- dma_desc->status.b.a = 1; /* Active descriptor */ -- -- dma_desc->buf = (uint32_t) hc->xfer_buff; -+ if ((qh->ep_type == UE_CONTROL) -+ && (qtd->control_phase == DWC_OTG_CONTROL_SETUP)) -+ dma_desc->status.b.sup = 1; /* Setup Packet */ -+ -+ dma_desc->status.b.a = 1; /* Active descriptor */ -+ dma_desc->status.b.sts = 0; -+ -+ dma_desc->buf = -+ ((unsigned long)hc->xfer_buff & 0xffffffff); - - /* - * Last descriptor(or single) of IN transfer -@@ -627,12 +652,11 @@ static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - */ - if (len > hc->xfer_len) { - hc->xfer_len = 0; -- } -- else { -+ } else { - hc->xfer_buff += len; - hc->xfer_len -= len; - } -- -+ - qtd->n_desc++; - n_desc++; - } -@@ -640,17 +664,20 @@ static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - - - qtd->in_process = 1; -- -+ -+ if (qh->ep_type == UE_CONTROL) -+ break; -+ - if (n_desc == MAX_DMA_DESC_NUM_GENERIC) - break; - } - - if (n_desc) { - /* Request Transfer Complete interrupt for the last descriptor */ -- qh->desc_list[n_desc-1].status.b.ioc = 1; -+ qh->desc_list[n_desc - 1].status.b.ioc = 1; - /* End of List indicator */ -- qh->desc_list[n_desc-1].status.b.eol = 1; -- -+ qh->desc_list[n_desc - 1].status.b.eol = 1; -+ - hc->ntd = n_desc; - } - } -@@ -677,73 +704,71 @@ void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - /* Channel is already assigned */ - dwc_hc_t *hc = qh->channel; - uint8_t skip_frames = 0; -- -+ - switch (hc->ep_type) { - case DWC_OTG_EP_TYPE_CONTROL: - case DWC_OTG_EP_TYPE_BULK: - init_non_isoc_dma_desc(hcd, qh); -- -+ - dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); - break; - case DWC_OTG_EP_TYPE_INTR: - init_non_isoc_dma_desc(hcd, qh); -- -+ - update_frame_list(hcd, qh, 1); -- -+ - dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); - break; - case DWC_OTG_EP_TYPE_ISOC: -- -- if(!qh->ntd) -+ -+ if (!qh->ntd) - skip_frames = recalc_initial_desc_idx(hcd, qh); -- -+ - init_isoc_dma_desc(hcd, qh, skip_frames); - - if (!hc->xfer_started) { - - update_frame_list(hcd, qh, 1); -- -+ - /* - * Always set to max, instead of actual size. - * Otherwise ntd will be changed with - * channel being enabled. Not recommended. - * -- */ -+ */ - hc->ntd = max_desc_num(qh); -- /* Enable channel only once for ISOC */ -+ /* Enable channel only once for ISOC */ - dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); - } -- -+ - break; - default: -- -+ - break; - } - } - --static void complete_isoc_xfer_ddma(dwc_otg_hcd_t *hcd, -- dwc_hc_t *hc, -- dwc_otg_hc_regs_t *hc_regs, -- dwc_otg_halt_status_e halt_status) -+static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_halt_status_e halt_status) - { -- struct dwc_otg_hcd_iso_packet_desc *frame_desc; -- dwc_otg_qtd_t *qtd, *qtd_tmp; -- dwc_otg_qh_t *qh; -- dwc_otg_host_dma_desc_t *dma_desc; -- uint16_t idx, remain; -- uint8_t urb_compl; -- -+ struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ dwc_otg_qtd_t *qtd, *qtd_tmp; -+ dwc_otg_qh_t *qh; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ uint16_t idx, remain; -+ uint8_t urb_compl; -+ - qh = hc->qh; - idx = qh->td_first; -- - - if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { - DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) -- qtd->in_process = 0; -- return; -- } -- else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || -- (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) { -+ qtd->in_process = 0; -+ return; -+ } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || -+ (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) { - /* - * Channel is halted in these error cases. - * Considered as serious issues. -@@ -752,54 +777,52 @@ static void complete_isoc_xfer_ddma(dwc_otg_hcd_t *hcd, - * Pass error code to completion routine as well, to - * update urb->status, some of class drivers might use it to stop - * queing transfer requests. -- */ -- int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) -- ? (-DWC_E_IO) -- : (-DWC_E_OVERFLOW); -+ */ -+ int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) -+ ? (-DWC_E_IO) -+ : (-DWC_E_OVERFLOW); - - DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { -- for(idx = 0; idx < qtd->urb->packet_count; idx++) { -+ for (idx = 0; idx < qtd->urb->packet_count; idx++) { - frame_desc = &qtd->urb->iso_descs[idx]; - frame_desc->status = err; - } - hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err); - dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); - } -- return; -+ return; - } -- -- -+ - DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { -- -+ - if (!qtd->in_process) -- break; -- -+ break; -+ - urb_compl = 0; -- -+ - do { - - dma_desc = &qh->desc_list[idx]; - - frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; - remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0; -- -+ - if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) { - /* -- * XactError or, unable to complete all the transactions -- * in the scheduled micro-frame/frame, -- * both indicated by DMA_DESC_STS_PKTERR. -- */ -+ * XactError or, unable to complete all the transactions -+ * in the scheduled micro-frame/frame, -+ * both indicated by DMA_DESC_STS_PKTERR. -+ */ - qtd->urb->error_count++; - frame_desc->actual_length = qh->n_bytes[idx] - remain; - frame_desc->status = -DWC_E_PROTOCOL; -- } -- else { -- /* Success */ -+ } else { -+ /* Success */ - - frame_desc->actual_length = qh->n_bytes[idx] - remain; - frame_desc->status = 0; - } -- -+ - if (++qtd->isoc_frame_index == qtd->urb->packet_count) { - /* - * urb->status is not used for isoc transfers here. -@@ -808,53 +831,51 @@ static void complete_isoc_xfer_ddma(dwc_otg_hcd_t *hcd, - - hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); - dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -- -+ - /* - * This check is necessary because urb_dequeue can be called - * from urb complete callback(sound driver example). - * All pending URBs are dequeued there, so no need for - * further processing. -- */ -+ */ - if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { - return; - } -- -- urb_compl = 1; -- -+ -+ urb_compl = 1; -+ - } -- -+ - qh->ntd--; -- -+ - /* Stop if IOC requested descriptor reached */ - if (dma_desc->status.b_isoc.ioc) { - idx = desclist_idx_inc(idx, qh->interval, hc->speed); - goto stop_scan; - } -- -+ - idx = desclist_idx_inc(idx, qh->interval, hc->speed); -- -+ - if (urb_compl) - break; - } -- while(idx != qh->td_first); -+ while (idx != qh->td_first); - } --stop_scan: -+stop_scan: - qh->td_first = idx; - } -- -+ - uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, -- dwc_hc_t * hc, -- dwc_otg_qtd_t * qtd, -- dwc_otg_host_dma_desc_t * dma_desc, -- dwc_otg_halt_status_e halt_status, -- uint32_t n_bytes, -- uint8_t *xfer_done) -+ dwc_hc_t * hc, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_host_dma_desc_t * dma_desc, -+ dwc_otg_halt_status_e halt_status, -+ uint32_t n_bytes, uint8_t * xfer_done) - { - - uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0; - dwc_otg_hcd_urb_t *urb = qtd->urb; -- -- -+ - if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) { - urb->status = -DWC_E_IO; - return 1; -@@ -877,92 +898,94 @@ uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, - } - return 1; - } -- -+ - if (dma_desc->status.b.a == 1) { -- DWC_DEBUGPL(DBG_HCDV, "Active descriptor encountered on channel %d\n", hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, -+ "Active descriptor encountered on channel %d\n", -+ hc->hc_num); - return 0; - } -- -+ - if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) { -- if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { -+ if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { -+ urb->actual_length += n_bytes - remain; -+ if (remain || urb->actual_length == urb->length) { -+ /* -+ * For Control Data stage do not set urb->status=0 to prevent -+ * URB callback. Set it when Status phase done. See below. -+ */ -+ *xfer_done = 1; -+ } -+ -+ } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) { -+ urb->status = 0; -+ *xfer_done = 1; -+ } -+ /* No handling for SETUP stage */ -+ } else { -+ /* BULK and INTR */ - urb->actual_length += n_bytes - remain; -- if (remain || urb->actual_length >= urb->length) { -- /* -- * For Control Data stage do not set urb->status=0 to prevent -- * URB callback. Set it when Status phase done. See below. -- */ -+ if (remain || urb->actual_length == urb->length) { -+ urb->status = 0; - *xfer_done = 1; -- } -- -- } -- else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) { -- urb->status = 0; -- *xfer_done = 1; -- } -- /* No handling for SETUP stage */ -- -- } -- else { -- /* BULK and INTR */ -- urb->actual_length += n_bytes - remain; -- if (remain || urb->actual_length >= urb->length) { -- urb->status = 0; -- *xfer_done = 1; -- } -+ } - } - - return 0; - } - - static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, -- dwc_hc_t * hc, -- dwc_otg_hc_regs_t * hc_regs, -- dwc_otg_halt_status_e halt_status) -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_halt_status_e halt_status) - { -- dwc_otg_hcd_urb_t *urb = NULL; -- dwc_otg_qtd_t *qtd, *qtd_tmp; -- dwc_otg_qh_t *qh; -- dwc_otg_host_dma_desc_t *dma_desc; -- uint32_t n_bytes, n_desc, i; -- uint8_t failed = 0, xfer_done; -- -+ dwc_otg_hcd_urb_t *urb = NULL; -+ dwc_otg_qtd_t *qtd, *qtd_tmp; -+ dwc_otg_qh_t *qh; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ uint32_t n_bytes, n_desc, i; -+ uint8_t failed = 0, xfer_done; -+ - n_desc = 0; -- -+ - qh = hc->qh; - -- - if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { - DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { - qtd->in_process = 0; - } - return; - } -- -+ - DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { -- -+ - urb = qtd->urb; - -- n_bytes = 0; -- xfer_done = 0; -- -+ n_bytes = 0; -+ xfer_done = 0; -+ - for (i = 0; i < qtd->n_desc; i++) { - dma_desc = &qh->desc_list[n_desc]; -- -+ - n_bytes = qh->n_bytes[n_desc]; -- -- -- failed = update_non_isoc_urb_state_ddma(hcd, hc, qtd, dma_desc, -- halt_status, n_bytes, &xfer_done); -- -- if (failed || (xfer_done && (urb->status != -DWC_E_IN_PROGRESS))) { -- -- hcd->fops->complete(hcd, urb->priv, urb, urb->status); -+ -+ failed = -+ update_non_isoc_urb_state_ddma(hcd, hc, qtd, -+ dma_desc, -+ halt_status, n_bytes, -+ &xfer_done); -+ -+ if (failed -+ || (xfer_done -+ && (urb->status != -DWC_E_IN_PROGRESS))) { -+ -+ hcd->fops->complete(hcd, urb->priv, urb, -+ urb->status); - dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); - - if (failed) - goto stop_scan; -- } -- else if (qh->ep_type == UE_CONTROL) { -+ } else if (qh->ep_type == UE_CONTROL) { - if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) { - if (urb->length > 0) { - qtd->control_phase = DWC_OTG_CONTROL_DATA; -@@ -970,50 +993,47 @@ static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, - qtd->control_phase = DWC_OTG_CONTROL_STATUS; - } - DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); -- } -- else if(qtd->control_phase == DWC_OTG_CONTROL_DATA) { -+ } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { - if (xfer_done) { - qtd->control_phase = DWC_OTG_CONTROL_STATUS; - DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); -- } else if (i+1 == qtd->n_desc){ -+ } else if (i + 1 == qtd->n_desc) { - /* - * Last descriptor for Control data stage which is - * not completed yet. -- */ -+ */ - dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); - } - } - } -- -+ - n_desc++; - } -- -+ - } -- --stop_scan: -- -+ -+stop_scan: -+ - if (qh->ep_type != UE_CONTROL) { - /* - * Resetting the data toggle for bulk - * and interrupt endpoints in case of stall. See handle_hc_stall_intr() -- */ -- if (halt_status == DWC_OTG_HC_XFER_STALL) { -- qh->data_toggle = DWC_OTG_HC_PID_DATA0; -- } -- else { -+ */ -+ if (halt_status == DWC_OTG_HC_XFER_STALL) -+ qh->data_toggle = DWC_OTG_HC_PID_DATA0; -+ else - dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -- } - } -- -+ - if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { - hcint_data_t hcint; -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - if (hcint.b.nyet) { - /* -- * Got a NYET on the last transaction of the transfer. It -- * means that the endpoint should be in the PING state at the -- * beginning of the next transfer. -- */ -+ * Got a NYET on the last transaction of the transfer. It -+ * means that the endpoint should be in the PING state at the -+ * beginning of the next transfer. -+ */ - qh->ping_state = 1; - clear_hc_int(hc_regs, nyet); - } -@@ -1039,55 +1059,51 @@ static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, - * @param halt_status Reason the channel is being halted, - * or just XferComplete for isochronous transfer - */ --void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t *hcd, -- dwc_hc_t *hc, -- dwc_otg_hc_regs_t *hc_regs, -- dwc_otg_halt_status_e halt_status) -+void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_halt_status_e halt_status) - { - uint8_t continue_isoc_xfer = 0; - dwc_otg_transaction_type_e tr_type; - dwc_otg_qh_t *qh = hc->qh; -- -+ - if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { - - complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); -- -- /* Release the channel if halted or session completed */ -+ -+ /* Release the channel if halted or session completed */ - if (halt_status != DWC_OTG_HC_XFER_COMPLETE || -- DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -+ DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { - -- /* Halt the channel if session completed */ -+ /* Halt the channel if session completed */ - if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { - dwc_otg_hc_halt(hcd->core_if, hc, halt_status); -- } -- -+ } -+ - release_channel_ddma(hcd, qh); - dwc_otg_hcd_qh_remove(hcd, qh); -- } -- else { -+ } else { - /* Keep in assigned schedule to continue transfer */ - DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, - &qh->qh_list_entry); - continue_isoc_xfer = 1; -- -+ - } - /** @todo Consider the case when period exceeds FrameList size. - * Frame Rollover interrupt should be used. - */ -- } -- else { -- /* Scan descriptor list to complete the URB(s), then release the channel */ -+ } else { -+ /* Scan descriptor list to complete the URB(s), then release the channel */ - complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); -- -+ - release_channel_ddma(hcd, qh); -- - dwc_otg_hcd_qh_remove(hcd, qh); -- -+ - if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { - /* Add back to inactive non-periodic schedule on normal completion */ - dwc_otg_hcd_qh_add(hcd, qh); - } -- - - } - tr_type = dwc_otg_hcd_select_transactions(hcd); -@@ -1102,5 +1118,5 @@ void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t *hcd, - dwc_otg_hcd_queue_transactions(hcd, tr_type); - } - } -- --#endif /* DWC_DEVICE_ONLY */ -+ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -index d5a903b..b3dc806 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $ -- * $Revision: #6 $ -- * $Date: 2009/04/21 $ -- * $Change: 1237474 $ -+ * $Revision: #12 $ -+ * $Date: 2011/10/26 $ -+ * $Change: 1873028 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -175,6 +175,13 @@ extern int dwc_otg_hcd_hub_control(dwc_otg_hcd_t * dwc_otg_hcd, - extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd); - - /** -+ * Returns OTG version - either 1.3 or 2.0. -+ * -+ * @param core_if The core_if structure pointer -+ */ -+extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if); -+ -+/** - * Returns 1 if currently core is acting as B host, and 0 otherwise. - * - * @param hcd The HCD -@@ -223,7 +230,7 @@ extern int dwc_otg_hcd_send_lpm(dwc_otg_hcd_t * hcd, uint8_t devaddr, - - /** - * Allocates memory for dwc_otg_hcd_urb structure. -- * Allocated memory should be freed by call dwc_free function. -+ * Allocated memory should be freed by call of DWC_FREE. - * - * @param hcd The HCD - * @param iso_desc_count Count of ISOC descriptors -@@ -248,7 +255,7 @@ extern void dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_hcd_urb_t * hcd_urb, - uint8_t ep_type, uint8_t ep_dir, - uint16_t mps); - --/* Transfer flags */ -+/* Transfer flags */ - #define URB_GIVEBACK_ASAP 0x1 - #define URB_SEND_ZERO_PACKET 0x2 - -@@ -325,6 +332,7 @@ extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * - * @param dwc_otg_hcd The HCD - * @param dwc_otg_urb DWC_OTG URB - * @param ep_handle Out parameter for returning endpoint handle -+ * @param atomic_alloc Flag to do atomic allocation if needed - * - * Returns -DWC_E_NO_DEVICE if no device is connected. - * Returns -DWC_E_NO_MEMORY if there is no enough memory. -@@ -332,7 +340,7 @@ extern uint32_t dwc_otg_hcd_urb_get_iso_desc_actual_length(dwc_otg_hcd_urb_t * - */ - extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd, - dwc_otg_hcd_urb_t * dwc_otg_urb, -- void **ep_handle); -+ void **ep_handle, int atomic_alloc); - - /** De-queue the specified URB - * -@@ -355,6 +363,17 @@ extern int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * dwc_otg_hcd, - extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, - int retry); - -+/* Resets the data toggle in qh structure. This function can be called from -+ * usb_clear_halt routine. -+ * -+ * @param hcd The HCD -+ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function -+ * -+ * Returns -DWC_E_INVALID if invalid arguments are passed. -+ * Returns 0 on success -+ */ -+extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle); -+ - /** Returns 1 if status of specified port is changed and 0 otherwise. - * - * @param hcd The HCD -@@ -389,5 +408,5 @@ extern uint8_t dwc_otg_hcd_get_ep_bandwidth(dwc_otg_hcd_t * hcd, - - /** @} */ - --#endif /* __DWC_HCD_IF_H__ */ --#endif /* DWC_DEVICE_ONLY */ -+#endif /* __DWC_HCD_IF_H__ */ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -index 86fee99..130946c 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ -- * $Revision: #77 $ -- * $Date: 2009/04/21 $ -- * $Change: 1237475 $ -+ * $Revision: #89 $ -+ * $Date: 2011/10/20 $ -+ * $Change: 1869487 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -58,10 +58,16 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) - } - #endif - -+ /* Exit from ISR if core is hibernated */ -+ if (core_if->hibernation_suspend == 1) { -+ return retval; -+ } -+ DWC_SPINLOCK(dwc_otg_hcd->lock); - /* Check if HOST Mode */ - if (dwc_otg_is_host_mode(core_if)) { - gintsts.d32 = dwc_otg_read_core_intr(core_if); - if (!gintsts.d32) { -+ DWC_SPINUNLOCK(dwc_otg_hcd->lock); - return 0; - } - #ifdef DEBUG -@@ -69,14 +75,14 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) - #ifndef DEBUG_SOF - if (gintsts.d32 != DWC_SOF_INTR_MASK) - #endif -- DWC_DEBUGPL(DBG_HCD, "\n"); -+ DWC_DEBUGPL(DBG_HCDI, "\n"); - #endif - - #ifdef DEBUG - #ifndef DEBUG_SOF - if (gintsts.d32 != DWC_SOF_INTR_MASK) - #endif -- DWC_DEBUGPL(DBG_HCD, -+ DWC_DEBUGPL(DBG_HCDI, - "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n", - gintsts.d32, core_if); - #endif -@@ -113,12 +119,12 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) - if (gintsts.d32 != DWC_SOF_INTR_MASK) - #endif - { -- DWC_DEBUGPL(DBG_HCD, -+ DWC_DEBUGPL(DBG_HCDI, - "DWC OTG HCD Finished Servicing Interrupts\n"); - DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n", -- dwc_read_reg32(&global_regs->gintsts)); -+ DWC_READ_REG32(&global_regs->gintsts)); - DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n", -- dwc_read_reg32(&global_regs->gintmsk)); -+ DWC_READ_REG32(&global_regs->gintmsk)); - } - #endif - -@@ -126,11 +132,11 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) - #ifndef DEBUG_SOF - if (gintsts.d32 != DWC_SOF_INTR_MASK) - #endif -- DWC_DEBUGPL(DBG_HCD, "\n"); -+ DWC_DEBUGPL(DBG_HCDI, "\n"); - #endif - - } -- -+ DWC_SPINUNLOCK(dwc_otg_hcd->lock); - return retval; - } - -@@ -183,7 +189,7 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) - gintsts_data_t gintsts = {.d32 = 0 }; - - hfnum.d32 = -- dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum); -+ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); - - #ifdef DEBUG_SOF - DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); -@@ -219,7 +225,7 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) - - /* Clear interrupt */ - gintsts.b.sofintr = 1; -- dwc_write_reg32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); - - return 1; - } -@@ -235,9 +241,13 @@ int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd) - DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); - - grxsts.d32 = -- dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); -+ DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); - - hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; -+ if (!hc) { -+ DWC_ERROR("Unable to get corresponding channel\n"); -+ return 0; -+ } - - /* Packet Status */ - DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); -@@ -305,8 +315,8 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - hprt0_data_t hprt0; - hprt0_data_t hprt0_modify; - -- hprt0.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); -- hprt0_modify.d32 = dwc_read_reg32(dwc_otg_hcd->core_if->host_if->hprt0); -+ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); -+ hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); - - /* Clear appropriate bits in HPRT0 to clear the interrupt bit in - * GINTSTS */ -@@ -318,16 +328,41 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - - /* Port Connect Detected - * Set flag and clear if detected */ -- if (hprt0.b.prtconndet) { -- DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " -- "Port Connect Detected--\n", hprt0.d32); -- dwc_otg_hcd->flags.b.port_connect_status_change = 1; -- dwc_otg_hcd->flags.b.port_connect_status = 1; -+ if (dwc_otg_hcd->core_if->hibernation_suspend == 1) { -+ // Dont modify port status if we are in hibernation state - hprt0_modify.b.prtconndet = 1; -+ hprt0_modify.b.prtenchng = 1; -+ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); -+ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); -+ return retval; -+ } - -- /* B-Device has connected, Delete the connection timer. */ -- DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer); -- -+ if (hprt0.b.prtconndet) { -+ /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */ -+ if (dwc_otg_hcd->core_if->adp_enable && -+ dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) { -+ DWC_PRINTF("PORT CONNECT DETECTED ----------------\n"); -+ DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer); -+ dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; -+ /* TODO - check if this is required, as -+ * host initialization was already performed -+ * after initial ADP probing -+ */ -+ /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; -+ dwc_otg_core_init(dwc_otg_hcd->core_if); -+ dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if); -+ cil_hcd_start(dwc_otg_hcd->core_if);*/ -+ } else { -+ -+ DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x " -+ "Port Connect Detected--\n", hprt0.d32); -+ dwc_otg_hcd->flags.b.port_connect_status_change = 1; -+ dwc_otg_hcd->flags.b.port_connect_status = 1; -+ hprt0_modify.b.prtconndet = 1; -+ -+ /* B-Device has connected, Delete the connection timer. */ -+ DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer); -+ } - /* The Hub driver asserts a reset when it sees port connect - * status change flag */ - retval |= 1; -@@ -340,6 +375,7 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - "Port Enable Changed--\n", hprt0.d32); - hprt0_modify.b.prtenchng = 1; - if (hprt0.b.prtena == 1) { -+ hfir_data_t hfir; - int do_reset = 0; - dwc_otg_core_params_t *params = - dwc_otg_hcd->core_if->core_params; -@@ -347,6 +383,13 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - dwc_otg_hcd->core_if->core_global_regs; - dwc_otg_host_if_t *host_if = - dwc_otg_hcd->core_if->host_if; -+ -+ /* Every time when port enables calculate -+ * HFIR.FrInterval -+ */ -+ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); -+ hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if); -+ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); - - /* Check if we need to adjust the PHY clock speed for - * low power and adjust it */ -@@ -354,7 +397,7 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - gusbcfg_data_t usbcfg; - - usbcfg.d32 = -- dwc_read_reg32(&global_regs->gusbcfg); -+ DWC_READ_REG32(&global_regs->gusbcfg); - - if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED - || hprt0.b.prtspd == -@@ -366,20 +409,20 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - if (usbcfg.b.phylpwrclksel == 0) { - /* Set PHY low power clock select for FS/LS devices */ - usbcfg.b.phylpwrclksel = 1; -- dwc_write_reg32(&global_regs-> -- gusbcfg, -- usbcfg.d32); -+ DWC_WRITE_REG32 -+ (&global_regs->gusbcfg, -+ usbcfg.d32); - do_reset = 1; - } - - hcfg.d32 = -- dwc_read_reg32(&host_if-> -- host_global_regs->hcfg); -+ DWC_READ_REG32 -+ (&host_if->host_global_regs->hcfg); - - if (hprt0.b.prtspd == - DWC_HPRT0_PRTSPD_LOW_SPEED -- && params-> -- host_ls_low_power_phy_clk == -+ && params->host_ls_low_power_phy_clk -+ == - DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) - { - /* 6 MHZ */ -@@ -389,10 +432,9 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - DWC_HCFG_6_MHZ) { - hcfg.b.fslspclksel = - DWC_HCFG_6_MHZ; -- dwc_write_reg32 -- (&host_if-> -- host_global_regs-> -- hcfg, hcfg.d32); -+ DWC_WRITE_REG32 -+ (&host_if->host_global_regs->hcfg, -+ hcfg.d32); - do_reset = 1; - } - } else { -@@ -403,10 +445,9 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - DWC_HCFG_48_MHZ) { - hcfg.b.fslspclksel = - DWC_HCFG_48_MHZ; -- dwc_write_reg32 -- (&host_if-> -- host_global_regs-> -- hcfg, hcfg.d32); -+ DWC_WRITE_REG32 -+ (&host_if->host_global_regs->hcfg, -+ hcfg.d32); - do_reset = 1; - } - } -@@ -416,16 +457,15 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - */ - if (usbcfg.b.phylpwrclksel == 1) { - usbcfg.b.phylpwrclksel = 0; -- dwc_write_reg32(&global_regs-> -- gusbcfg, -- usbcfg.d32); -+ DWC_WRITE_REG32 -+ (&global_regs->gusbcfg, -+ usbcfg.d32); - do_reset = 1; - } - } - - if (do_reset) { -- DWC_TASK_SCHEDULE(dwc_otg_hcd-> -- reset_tasklet); -+ DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet); - } - } - -@@ -449,7 +489,7 @@ int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd) - } - - /* Clear Port Interrupts */ -- dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); -+ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); - - return retval; - } -@@ -478,8 +518,6 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) - return retval; - } - -- -- - /** - * Gets the actual length of a transfer after the transfer halts. _halt_status - * holds the reason for the halt. -@@ -502,7 +540,7 @@ static uint32_t get_actual_xfer_length(dwc_hc_t * hc, - if (short_read != NULL) { - *short_read = 0; - } -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); - - if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { - if (hc->ep_is_in) { -@@ -551,21 +589,23 @@ static int update_urb_state_xfer_comp(dwc_hc_t * hc, - - int xfer_length; - -- xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, -- DWC_OTG_HC_XFER_COMPLETE, -- &short_read); -+ xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_COMPLETE, -+ &short_read); - - - /* non DWORD-aligned buffer case handling. */ - if (hc->align_buff && xfer_length && hc->ep_is_in) { -- dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, xfer_length); -+ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, -+ xfer_length); - } - - urb->actual_length += xfer_length; - -- if(xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) && -- (urb->flags & URB_SEND_ZERO_PACKET) && (urb->actual_length == urb->length) && -- !(urb->length % hc->max_packet)) { -+ if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) && -+ (urb->flags & URB_SEND_ZERO_PACKET) -+ && (urb->actual_length == urb->length) -+ && !(urb->length % hc->max_packet)) { - xfer_done = 0; - } else if (short_read || urb->actual_length >= urb->length) { - xfer_done = 1; -@@ -575,7 +615,7 @@ static int update_urb_state_xfer_comp(dwc_hc_t * hc, - #ifdef DEBUG - { - hctsiz_data_t hctsiz; -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); - DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", - __func__, (hc->ep_is_in ? "IN" : "OUT"), - hc->hc_num); -@@ -603,7 +643,7 @@ void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, - dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd) - { - hctsiz_data_t hctsiz; -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); - - if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) { - dwc_otg_qh_t *qh = hc->qh; -@@ -646,10 +686,10 @@ void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, - frame_desc->status = 0; - frame_desc->actual_length = - get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); -- -+ - /* non DWORD-aligned buffer case handling. */ - if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { -- dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, -+ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, - hc->qh->dw_align_buf, frame_desc->actual_length); - } - -@@ -673,19 +713,19 @@ void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, - frame_desc->status = -DWC_E_PROTOCOL; - frame_desc->actual_length = - get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); -- -+ - /* non DWORD-aligned buffer case handling. */ - if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { -- dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, -+ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, - hc->qh->dw_align_buf, frame_desc->actual_length); - } - /* Skip whole frame */ -- if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && -- hc->ep_is_in && hcd->core_if->dma_enable) { -+ if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && -+ hc->ep_is_in && hcd->core_if->dma_enable) { - qtd->complete_split = 0; - qtd->isoc_split_offset = 0; - } -- -+ - break; - default: - DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status); -@@ -758,19 +798,6 @@ static void release_channel(dwc_otg_hcd_t * hcd, - DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", - __func__, hc->hc_num, halt_status, hc->xfer_len); - --#ifdef HW2937_WORKAROUND -- if (hcd->hw2937_assigned_channels & (1<hc_num)) -- { -- if ((hcd->hw2937_assigned_channels &= ~(1<hc_num)) == 0) -- hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IDLE; -- DWC_DEBUGPL(DBG_HW2937, " release %d, hw2937_ac -> %x\n", hc->hc_num, hcd->hw2937_assigned_channels); -- } -- else -- { -- DWC_DEBUGPL(DBG_ANY, " Unexpected release %d (hw2937_ac = %x)\n", hc->hc_num, hcd->hw2937_assigned_channels); -- } --#endif -- - switch (halt_status) { - case DWC_OTG_HC_XFER_URB_COMPLETE: - free_qtd = 1; -@@ -802,6 +829,14 @@ static void release_channel(dwc_otg_hcd_t * hcd, - case DWC_OTG_HC_XFER_NO_HALT_STATUS: - free_qtd = 0; - break; -+ case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE: -+ DWC_DEBUGPL(DBG_HCDV, -+ " Complete URB with I/O error\n"); -+ free_qtd = 1; -+ qtd->urb->status = -DWC_E_IO; -+ hcd->fops->complete(hcd, qtd->urb->priv, -+ qtd->urb, -DWC_E_IO); -+ break; - default: - free_qtd = 0; - break; -@@ -809,7 +844,7 @@ static void release_channel(dwc_otg_hcd_t * hcd, - - deactivate_qh(hcd, hc->qh, free_qtd); - -- cleanup: -+cleanup: - /* - * Release the host channel for use by other transfers. The cleanup - * function clears the channel interrupt enables and conditions, so -@@ -840,7 +875,6 @@ static void release_channel(dwc_otg_hcd_t * hcd, - } - } - -- - /** - * Halts a host channel. If the channel cannot be halted immediately because - * the request queue is full, this function ensures that the FIFO empty -@@ -876,7 +910,7 @@ static void halt_channel(dwc_otg_hcd_t * hcd, - * be processed. - */ - gintmsk.b.nptxfempty = 1; -- dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); -+ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); - } else { - /* - * Move the QH from the periodic queued schedule to -@@ -893,7 +927,7 @@ static void halt_channel(dwc_otg_hcd_t * hcd, - * processed. - */ - gintmsk.b.ptxfempty = 1; -- dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); -+ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); - } - } - } -@@ -913,7 +947,7 @@ static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd, - - qtd->error_count = 0; - -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); - if (hcint.b.nyet) { - /* - * Got a NYET on the last transaction of the transfer. This -@@ -964,7 +998,7 @@ static void complete_periodic_xfer(dwc_otg_hcd_t * hcd, - hctsiz_data_t hctsiz; - qtd->error_count = 0; - -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); - if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) { - /* Core halts channel in these cases. */ - release_channel(hcd, hc, qtd, halt_status); -@@ -975,47 +1009,46 @@ static void complete_periodic_xfer(dwc_otg_hcd_t * hcd, - } - - static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd, -- dwc_hc_t * hc, -- dwc_otg_hc_regs_t * hc_regs, -- dwc_otg_qtd_t * qtd) -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) - { -- uint32_t len; -+ uint32_t len; - struct dwc_otg_hcd_iso_packet_desc *frame_desc; - frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; -- -+ - len = get_actual_xfer_length(hc, hc_regs, qtd, -- DWC_OTG_HC_XFER_COMPLETE, -- NULL); -- -+ DWC_OTG_HC_XFER_COMPLETE, NULL); -+ - if (!len) { - qtd->complete_split = 0; - qtd->isoc_split_offset = 0; - return 0; - } - frame_desc->actual_length += len; -- -+ - if (hc->align_buff && len) -- dwc_memcpy(qtd->urb->buf + frame_desc->offset + qtd->isoc_split_offset, -- hc->qh->dw_align_buf, -- len); -+ dwc_memcpy(qtd->urb->buf + frame_desc->offset + -+ qtd->isoc_split_offset, hc->qh->dw_align_buf, len); - qtd->isoc_split_offset += len; -- -+ - if (frame_desc->length == frame_desc->actual_length) { - frame_desc->status = 0; - qtd->isoc_frame_index++; - qtd->complete_split = 0; - qtd->isoc_split_offset = 0; - } -- -+ - if (qtd->isoc_frame_index == qtd->urb->packet_count) { - hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); - release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); - } else { - release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); - } -- -- return 1; /* Indicates that channel released */ -+ -+ return 1; /* Indicates that channel released */ - } -+ - /** - * Handles a host channel Transfer Complete interrupt. This handler may be - * called in either DMA mode or Slave mode. -@@ -1030,13 +1063,13 @@ static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hcd_urb_t *urb = qtd->urb; - int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); - -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "Transfer Complete--\n", hc->hc_num); - - if (hcd->core_if->dma_desc_enable) { - dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status); - if (pipe_type == UE_ISOCHRONOUS) { -- /* Do not disable the interrupt, just clear it */ -+ /* Do not disable the interrupt, just clear it */ - clear_hc_int(hc_regs, xfercomp); - return 1; - } -@@ -1048,13 +1081,15 @@ static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd, - */ - - if (hc->qh->do_split) { -- if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in && hcd->core_if->dma_enable) { -- if (qtd->complete_split && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, qtd)) -+ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in -+ && hcd->core_if->dma_enable) { -+ if (qtd->complete_split -+ && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, -+ qtd)) - goto handle_xfercomp_done; -+ } else { -+ qtd->complete_split = 0; - } -- else { -- qtd->complete_split = 0; -- } - } - - /* Update the QTD and URB states. */ -@@ -1114,16 +1149,22 @@ static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd, - break; - case UE_INTERRUPT: - DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); -- update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); -+ urb_xfer_done = -+ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); - - /* - * Interrupt URB is done on the first transfer complete - * interrupt. - */ -- hcd->fops->complete(hcd, urb->priv, urb, urb->status); -+ if (urb_xfer_done) { -+ hcd->fops->complete(hcd, urb->priv, urb, urb->status); -+ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; -+ } else { -+ halt_status = DWC_OTG_HC_XFER_COMPLETE; -+ } -+ - dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -- complete_periodic_xfer(hcd, hc, hc_regs, qtd, -- DWC_OTG_HC_XFER_URB_COMPLETE); -+ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); - break; - case UE_ISOCHRONOUS: - DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); -@@ -1202,15 +1243,16 @@ static void update_urb_state_xfer_intr(dwc_hc_t * hc, - halt_status, NULL); - /* non DWORD-aligned buffer case handling. */ - if (hc->align_buff && bytes_transferred && hc->ep_is_in) { -- dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, bytes_transferred); -+ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, -+ bytes_transferred); - } -- -+ - urb->actual_length += bytes_transferred; - - #ifdef DEBUG - { - hctsiz_data_t hctsiz; -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); - DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n", - __func__, (hc->ep_is_in ? "IN" : "OUT"), - hc->hc_num); -@@ -1237,7 +1279,7 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hc_regs_t * hc_regs, - dwc_otg_qtd_t * qtd) - { -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "NAK Received--\n", hc->hc_num); - - /* -@@ -1257,11 +1299,6 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, - case UE_CONTROL: - case UE_BULK: - if (hcd->core_if->dma_enable && hc->ep_is_in) { --#ifdef HW2937_WORKAROUND -- if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -- halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -- } --#endif - /* - * NAK interrupts are enabled on bulk/control IN - * transfers in DMA mode for the sole purpose of -@@ -1287,7 +1324,7 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, - - if (hc->speed == DWC_OTG_EP_SPEED_HIGH) - hc->qh->ping_state = 1; -- } -+ } - - /* - * Halt the channel so the transfer can be re-started from -@@ -1301,18 +1338,12 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, - halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); - break; - case UE_ISOCHRONOUS: --#ifdef HW2937_WORKAROUND -- if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -- halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -- break; -- } --#endif - /* Should never get called for isochronous transfers. */ - DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n"); - break; - } - -- handle_nak_done: -+handle_nak_done: - disable_hc_int(hc_regs, nak); - - return 1; -@@ -1328,7 +1359,7 @@ static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hc_regs_t * hc_regs, - dwc_otg_qtd_t * qtd) - { -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "ACK Received--\n", hc->hc_num); - - if (hc->do_split) { -@@ -1362,11 +1393,11 @@ static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd, - */ - { - struct dwc_otg_hcd_iso_packet_desc -- *frame_desc; -+ *frame_desc; - - frame_desc = -- &qtd->urb->iso_descs[qtd-> -- isoc_frame_index]; -+ &qtd->urb-> -+ iso_descs[qtd->isoc_frame_index]; - qtd->isoc_split_offset += 188; - - if ((frame_desc->length - -@@ -1398,14 +1429,6 @@ static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd, - */ - halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); - } --#ifdef HW2937_WORKAROUND -- else if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -- dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -- update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, DWC_OTG_HC_XFER_PAUSE_IN); -- dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -- release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_PAUSE_IN); -- } --#endif - } - - /* -@@ -1430,7 +1453,7 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hc_regs_t * hc_regs, - dwc_otg_qtd_t * qtd) - { -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "NYET Received--\n", hc->hc_num); - - /* -@@ -1438,7 +1461,8 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, - * re-do the CSPLIT immediately on non-periodic - */ - if (hc->do_split && hc->complete_split) { -- if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hcd->core_if->dma_enable) { -+ if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) -+ && hcd->core_if->dma_enable) { - qtd->complete_split = 0; - qtd->isoc_split_offset = 0; - if (++qtd->isoc_frame_index == qtd->urb->packet_count) { -@@ -1494,7 +1518,7 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, - */ - halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); - -- handle_nyet_done: -+handle_nyet_done: - disable_hc_int(hc_regs, nyet); - return 1; - } -@@ -1508,11 +1532,12 @@ static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hc_regs_t * hc_regs, - dwc_otg_qtd_t * qtd) - { -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "Babble Error--\n", hc->hc_num); -- -+ - if (hcd->core_if->dma_desc_enable) { -- dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_BABBLE_ERR); -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, -+ DWC_OTG_HC_XFER_BABBLE_ERR); - goto handle_babble_done; - } - -@@ -1526,7 +1551,7 @@ static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd, - DWC_OTG_HC_XFER_BABBLE_ERR); - halt_channel(hcd, hc, qtd, halt_status); - } -- -+ - handle_babble_done: - disable_hc_int(hc_regs, bblerr); - return 1; -@@ -1549,13 +1574,13 @@ static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd, - - dwc_otg_hcd_urb_t *urb = qtd->urb; - -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "AHB Error--\n", hc->hc_num); - -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -- hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -- hcdma = dwc_read_reg32(&hc_regs->hcdma); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); -+ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); -+ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); -+ hcdma = DWC_READ_REG32(&hc_regs->hcdma); - - DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num); - DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32); -@@ -1566,45 +1591,44 @@ static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd, - DWC_ERROR(" Endpoint: %d, %s\n", - dwc_otg_hcd_get_ep_num(&urb->pipe_info), - (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT")); -- - - switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { --case UE_CONTROL: -- pipetype = "CONTROL"; -- break; -+ case UE_CONTROL: -+ pipetype = "CONTROL"; -+ break; - case UE_BULK: -- pipetype = "BULK"; -- break; -+ pipetype = "BULK"; -+ break; - case UE_INTERRUPT: -- pipetype = "INTERRUPT"; -- break; -+ pipetype = "INTERRUPT"; -+ break; - case UE_ISOCHRONOUS: -- pipetype = "ISOCHRONOUS"; -- break; -+ pipetype = "ISOCHRONOUS"; -+ break; - default: -- pipetype = "UNKNOWN"; -+ pipetype = "UNKNOWN"; - break; - } -- -+ - DWC_ERROR(" Endpoint type: %s\n", pipetype); - - switch (hc->speed) { - case DWC_OTG_EP_SPEED_HIGH: -- speed = "HIGH"; -- break; -+ speed = "HIGH"; -+ break; - case DWC_OTG_EP_SPEED_FULL: -- speed = "FULL"; -- break; -+ speed = "FULL"; -+ break; - case DWC_OTG_EP_SPEED_LOW: -- speed = "LOW"; -- break; -+ speed = "LOW"; -+ break; - default: -- speed = "UNKNOWN"; -+ speed = "UNKNOWN"; - break; -- }; -+ }; - - DWC_ERROR(" Speed: %s\n", speed); -- -+ - DWC_ERROR(" Max packet size: %d\n", - dwc_otg_hcd_get_mps(&urb->pipe_info)); - DWC_ERROR(" Data buffer length: %d\n", urb->length); -@@ -1616,7 +1640,8 @@ static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd, - - /* Core haltes the channel for Descriptor DMA mode */ - if (hcd->core_if->dma_desc_enable) { -- dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_AHB_ERR); -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, -+ DWC_OTG_HC_XFER_AHB_ERR); - goto handle_ahberr_done; - } - -@@ -1641,11 +1666,12 @@ static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hc_regs_t * hc_regs, - dwc_otg_qtd_t * qtd) - { -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "Transaction Error--\n", hc->hc_num); - - if (hcd->core_if->dma_desc_enable) { -- dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_XACT_ERR); -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, -+ DWC_OTG_HC_XFER_XACT_ERR); - goto handle_xacterr_done; - } - -@@ -1703,7 +1729,7 @@ static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hc_regs_t * hc_regs, - dwc_otg_qtd_t * qtd) - { -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "Frame Overrun--\n", hc->hc_num); - - switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { -@@ -1739,7 +1765,7 @@ static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hc_regs_t * hc_regs, - dwc_otg_qtd_t * qtd) - { -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "Data Toggle Error--\n", hc->hc_num); - - if (hc->ep_is_in) { -@@ -1777,11 +1803,11 @@ static inline int halt_status_ok(dwc_otg_hcd_t * hcd, - * This code is here only as a check. This condition should - * never happen. Ignore the halt if it does occur. - */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -- hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -- hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -- hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); -+ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); -+ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); -+ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); - DWC_WARN - ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, " - "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " -@@ -1802,7 +1828,7 @@ static inline int halt_status_ok(dwc_otg_hcd_t * hcd, - * never be set when the halt interrupt occurs. Halt the - * channel again if it does occur. - */ -- hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); - if (hcchar.b.chdis) { - DWC_WARN("%s: hcchar.chdis set unexpectedly, " - "hcchar 0x%08x, trying to halt again\n", -@@ -1842,7 +1868,8 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, - } - - if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || -- (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR && !hcd->core_if->dma_desc_enable)) { -+ (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR -+ && !hcd->core_if->dma_desc_enable)) { - /* - * Just release the channel. A dequeue can happen on a - * transfer timeout. In the case of an AHB Error, the channel -@@ -1850,15 +1877,16 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, - * recover. - */ - if (hcd->core_if->dma_desc_enable) -- dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, hc->halt_status); -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, -+ hc->halt_status); - else - release_channel(hcd, hc, qtd, hc->halt_status); - return; - } - - /* Read the HCINTn register to determine the cause for the halt. */ -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -- hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); -+ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); - - if (hcint.b.xfercomp) { - /** @todo This is here because of a possible hardware bug. Spec -@@ -1891,7 +1919,7 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, - handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); - } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) { - handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); -- } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { -+ } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { - handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); - } else if (hcint.b.bblerr) { - handle_hc_babble_intr(hcd, hc, hc_regs, qtd); -@@ -1943,10 +1971,11 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, - ("%s: Channel %d, DMA Mode -- ChHltd set, but reason " - "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n", - __func__, hc->hc_num, hcint.d32, -- dwc_read_reg32(&hcd->core_if-> -- core_global_regs->gintsts)); -+ DWC_READ_REG32(&hcd-> -+ core_if->core_global_regs-> -+ gintsts)); - } -- -+ - } - } else { - DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n", -@@ -1970,7 +1999,7 @@ static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, - dwc_otg_hc_regs_t * hc_regs, - dwc_otg_qtd_t * qtd) - { -- DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " -+ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " - "Channel Halted--\n", hc->hc_num); - - if (hcd->core_if->dma_enable) { -@@ -2003,8 +2032,8 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) - hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num]; - qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); - -- hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -- hcintmsk.d32 = dwc_read_reg32(&hc_regs->hcintmsk); -+ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); -+ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); - DWC_DEBUGPL(DBG_HCDV, - " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", - hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); -@@ -2062,4 +2091,4 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) - return retval; - } - --#endif /* DWC_DEVICE_ONLY */ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -index e9f4f31..4a985a6 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ -- * $Revision: #11 $ -- * $Date: 2009/04/21 $ -- * $Change: 1237476 $ -+ * $Revision: #20 $ -+ * $Date: 2011/10/26 $ -+ * $Change: 1872981 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -50,28 +50,23 @@ - #include - #include - #include -- --#ifdef LM_INTERFACE --//#include --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --#include --#include -+#include -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) -+#include <../drivers/usb/core/hcd.h> - #else --#include --#include --#endif --#elif defined(PLATFORM_INTERFACE) --#include -+#include - #endif - --#include --#include -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) -+#define USB_URB_EP_LINKING 1 -+#else -+#define USB_URB_EP_LINKING 0 -+#endif - - #include "dwc_otg_hcd_if.h" - #include "dwc_otg_dbg.h" - #include "dwc_otg_driver.h" - #include "dwc_otg_hcd.h" -- - /** - * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is - * qualified with its direction (possible 32 endpoints per device). -@@ -84,22 +79,25 @@ - /** @name Linux HC Driver API Functions */ - /** @{ */ - /* manage i/o requests, device state */ --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --static int urb_enqueue(struct usb_hcd *hcd, -+static int dwc_otg_urb_enqueue(struct usb_hcd *hcd, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) - struct usb_host_endpoint *ep, -+#endif - struct urb *urb, gfp_t mem_flags); - --static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb); --#else --static int urb_enqueue(struct usb_hcd *hcd, -- struct urb *urb, gfp_t mem_flags); -- --static int urb_dequeue(struct usb_hcd *hcd, -- struct urb *urb, int status); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); - #endif -+#else /* kernels at or post 2.6.30 */ -+static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, -+ struct urb *urb, int status); -+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */ - - static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep); -- -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) -+static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); -+#endif - static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); - extern int hcd_start(struct usb_hcd *hcd); - extern void hcd_stop(struct usb_hcd *hcd); -@@ -131,10 +129,12 @@ struct wrapper_priv_data { - //.resume = - .stop = hcd_stop, - -- .urb_enqueue = urb_enqueue, -- .urb_dequeue = urb_dequeue, -+ .urb_enqueue = dwc_otg_urb_enqueue, -+ .urb_dequeue = dwc_otg_urb_dequeue, - .endpoint_disable = endpoint_disable, -- -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) -+ .endpoint_reset = endpoint_reset, -+#endif - .get_frame_number = get_frame_number, - - .hub_status_data = hub_status_data, -@@ -264,9 +264,8 @@ static void free_bus_bandwidth(struct usb_hcd *hcd, uint32_t bw, - static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, - dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status) - { -- uint64_t flags; - struct urb *urb = (struct urb *)urb_handle; --#ifdef DEBUG -+ - if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { - DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n", - __func__, urb, usb_pipedevice(urb->pipe), -@@ -280,7 +279,6 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, - } - } - } --#endif - - urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb); - /* Convert status value. */ -@@ -319,8 +317,7 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, - dwc_otg_hcd_urb_get_iso_desc_actual_length - (dwc_otg_urb, i); - urb->iso_frame_desc[i].status = -- dwc_otg_hcd_urb_get_iso_desc_status -- (dwc_otg_urb, i); -+ dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); - } - } - -@@ -339,21 +336,24 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, - if (ep) { - free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd), - dwc_otg_hcd_get_ep_bandwidth(hcd, -- ep-> -- hcpriv), -+ ep->hcpriv), - urb); - } - } - -- dwc_free(dwc_otg_urb); --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ DWC_FREE(dwc_otg_urb); -+ -+#if USB_URB_EP_LINKING -+ usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb); -+#endif -+ DWC_SPINUNLOCK(hcd->lock); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); - #else -- DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -- usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb); -- DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); - #endif -+ DWC_SPINLOCK(hcd->lock); -+ - return 0; - } - -@@ -372,26 +372,11 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, - * USB bus with the core and calls the hc_driver->start() function. It returns - * a negative error on failure. - */ --int hcd_init( --#ifdef LM_INTERFACE -- struct lm_device *_dev --#elif defined(PCI_INTERFACE) -- struct pci_dev *_dev --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *_dev --#endif -- ) -+int hcd_init(dwc_bus_dev_t *_dev) - { - struct usb_hcd *hcd = NULL; - dwc_otg_hcd_t *dwc_otg_hcd = NULL; --#ifdef LM_INTERFACE -- dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); - int retval = 0; - u64 dmamask; - -@@ -415,21 +400,20 @@ int hcd_init( - * Allocate memory for the base HCD plus the DWC OTG HCD. - * Initialize the base HCD. - */ -- hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -- _dev->dev.bus_id); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) -+ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id); - #else -- dev_name(&_dev->dev)); -+ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev)); -+ hcd->has_tt = 1; -+// hcd->uses_new_polling = 1; -+// hcd->poll_rh = 0; - #endif - if (!hcd) { - retval = -ENOMEM; - goto error1; - } - -- hcd->regs = otg_dev->base; -- -- /* Integrate TT in root hub */ -- hcd->has_tt = 1; -+ hcd->regs = otg_dev->os_dep.base; - - /* Initialize the DWC OTG HCD. */ - dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); -@@ -444,17 +428,24 @@ int hcd_init( - goto error2; - } - -+ otg_dev->hcd->otg_dev = otg_dev; - hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); -- -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later -+ hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if); -+#endif -+ /* Don't support SG list at this point */ -+ hcd->self.sg_tablesize = 0; -+#endif - /* - * Finish generic HCD initialization and start the HCD. This function - * allocates the DMA buffer pool, registers the USB bus, requests the - * IRQ line, and calls hcd_start method. - */ - #ifdef PLATFORM_INTERFACE -- retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED); -+ retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED); - #else -- retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED); -+ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED); - #endif - if (retval < 0) { - goto error2; -@@ -463,9 +454,9 @@ int hcd_init( - dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd); - return 0; - -- error2: -+error2: - usb_put_hcd(hcd); -- error1: -+error1: - return retval; - } - -@@ -473,24 +464,9 @@ int hcd_init( - * Removes the HCD. - * Frees memory and resources associated with the HCD and deregisters the bus. - */ --void hcd_remove( --#ifdef LM_INTERFACE -- struct lm_device *_dev --#elif defined(PCI_INTERFACE) -- struct pci_dev *_dev --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *_dev --#endif -- ) -+void hcd_remove(dwc_bus_dev_t *_dev) - { --#ifdef LM_INTERFACE -- dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); --#endif -- -+ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); - dwc_otg_hcd_t *dwc_otg_hcd; - struct usb_hcd *hcd; - -@@ -616,26 +592,25 @@ static void dump_urb_info(struct urb *urb, char *fn_name) - } - } - } -- - #endif - - /** Starts processing a USB transfer request specified by a USB Request Block - * (URB). mem_flags indicates the type of memory allocation to use while - * processing this URB. */ --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --static int urb_enqueue(struct usb_hcd *hcd, -+static int dwc_otg_urb_enqueue(struct usb_hcd *hcd, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) - struct usb_host_endpoint *ep, -+#endif - struct urb *urb, gfp_t mem_flags) - { --#else --static int urb_enqueue(struct usb_hcd *hcd, -- struct urb *urb, -- gfp_t mem_flags) --{ -- struct usb_host_endpoint *ep = urb->ep; -+ int retval = 0; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) -+ struct usb_host_endpoint *ep = urb->ep; -+#endif -+#if USB_URB_EP_LINKING -+ dwc_irqflags_t irqflags; - #endif - void **ref_ep_hcpriv = &ep->hcpriv; -- int retval = 0; - dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); - dwc_otg_hcd_urb_t *dwc_otg_urb; - int i; -@@ -646,7 +621,7 @@ static int urb_enqueue(struct usb_hcd *hcd, - - #ifdef DEBUG - if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -- dump_urb_info(urb, "urb_enqueue"); -+ dump_urb_info(urb, "dwc_otg_urb_enqueue"); - } - #endif - -@@ -675,9 +650,10 @@ static int urb_enqueue(struct usb_hcd *hcd, - ep_type = USB_ENDPOINT_XFER_INT; - break; - default: -- DWC_WARN("Wrong ep type\n"); -+ DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe)); - } - -+ /* # of packets is often 0 - do we really need to call this then? */ - dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd, - urb->number_of_packets, - mem_flags == GFP_ATOMIC ? 1 : 0); -@@ -686,6 +662,8 @@ static int urb_enqueue(struct usb_hcd *hcd, - return -ENOMEM; - - urb->hcpriv = dwc_otg_urb; -+ if (!dwc_otg_urb && urb->number_of_packets) -+ return -ENOMEM; - - dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe), ep_type, -@@ -705,7 +683,7 @@ static int urb_enqueue(struct usb_hcd *hcd, - // DMA addresses are bus addresses not physical addresses! - buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma); - } -- -+ - if (!(urb->transfer_flags & URB_NO_INTERRUPT)) - flags |= URB_GIVEBACK_ASAP; - if (urb->transfer_flags & URB_ZERO_PACKET) -@@ -714,27 +692,28 @@ static int urb_enqueue(struct usb_hcd *hcd, - dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf, - urb->transfer_dma, - urb->transfer_buffer_length, -- urb->setup_packet, -- urb->setup_dma, -- flags, -- urb->interval); -+ urb->setup_packet, -+ urb->setup_dma, flags, urb->interval); - - for (i = 0; i < urb->number_of_packets; ++i) { - dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i, -- urb->iso_frame_desc[i]. -- offset, -- urb->iso_frame_desc[i]. -- length); -+ urb-> -+ iso_frame_desc[i].offset, -+ urb-> -+ iso_frame_desc[i].length); - } - --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) -+#if USB_URB_EP_LINKING -+ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags); - retval = usb_hcd_link_urb_to_ep(hcd, urb); -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags); - if (0 == retval) - #endif - { - retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, - /*(dwc_otg_qh_t **)*/ -- ref_ep_hcpriv); -+ ref_ep_hcpriv, -+ mem_flags == GFP_ATOMIC ? 1 : 0); - if (0 == retval) { - if (alloc_bandwidth) { - allocate_bus_bandwidth(hcd, -@@ -743,8 +722,12 @@ static int urb_enqueue(struct usb_hcd *hcd, - urb); - } - } else { --#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) -+#if USB_URB_EP_LINKING -+ dwc_irqflags_t irqflags; -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval); -+ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags); - usb_hcd_unlink_urb_from_ep(hcd, urb); -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags); - #endif - if (retval == -DWC_E_NO_DEVICE) { - retval = -ENODEV; -@@ -756,54 +739,61 @@ static int urb_enqueue(struct usb_hcd *hcd, - - /** Aborts/cancels a USB transfer request. Always returns 0 to indicate - * success. */ --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) - #else --static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -+static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) - #endif - { -- int rc; -- uint64_t flags; -+ dwc_irqflags_t flags; - dwc_otg_hcd_t *dwc_otg_hcd; -+ int rc; -+ - DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); - - dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); - - #ifdef DEBUG - if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -- dump_urb_info(urb, "urb_dequeue"); -+ dump_urb_info(urb, "dwc_otg_urb_dequeue"); - } - #endif -- if(urb->hcpriv != NULL) { -- dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv); - -- dwc_free(urb->hcpriv); -- urb->hcpriv = NULL; -- } -- -- /* Higher layer software sets URB status. */ --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -- usb_hcd_giveback_urb(hcd, urb); --#else - DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); - rc = usb_hcd_check_unlink_urb(hcd, urb, status); -- if(!rc) -- { -- usb_hcd_unlink_urb_from_ep(hcd, urb); -- } -+ if (0 == rc) { -+ if(urb->hcpriv != NULL) { -+ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, -+ (dwc_otg_hcd_urb_t *)urb->hcpriv); -+ -+ DWC_FREE(urb->hcpriv); -+ urb->hcpriv = NULL; -+ } -+ } - -- DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); -- if (!rc) -- { -- usb_hcd_giveback_urb(hcd, urb, status); -- } -+ if (0 == rc) { -+ /* Higher layer software sets URB status. */ -+#if USB_URB_EP_LINKING -+ usb_hcd_unlink_urb_from_ep(hcd, urb); - #endif -- if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -- DWC_PRINTF("Called usb_hcd_giveback_urb()\n"); -- DWC_PRINTF(" urb->status = %d\n", urb->status); -- } -- -- return 0; -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+ usb_hcd_giveback_urb(hcd, urb); -+#else -+ usb_hcd_giveback_urb(hcd, urb, status); -+#endif -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ DWC_PRINTF("Called usb_hcd_giveback_urb() \n"); -+ DWC_PRINTF(" 1urb->status = %d\n", urb->status); -+ } -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n"); -+ } else { -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n", -+ rc); -+ } -+ -+ return rc; - } - - /* Frees resources in the DWC_otg controller related to a given endpoint. Also -@@ -821,6 +811,38 @@ static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep) - ep->hcpriv = NULL; - } - -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) -+/* Resets endpoint specific parameter values, in current version used to reset -+ * the data toggle(as a WA). This function can be called from usb_clear_halt routine */ -+static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -+{ -+ dwc_irqflags_t flags; -+ struct usb_device *udev = NULL; -+ int epnum = usb_endpoint_num(&ep->desc); -+ int is_out = usb_endpoint_dir_out(&ep->desc); -+ int is_control = usb_endpoint_xfer_control(&ep->desc); -+ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); -+ struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep); -+ -+ if (dev) -+ udev = to_usb_device(dev); -+ else -+ return; -+ -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum); -+ -+ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); -+ usb_settoggle(udev, epnum, is_out, 0); -+ if (is_control) -+ usb_settoggle(udev, epnum, !is_out, 0); -+ -+ if (ep->hcpriv) { -+ dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv); -+ } -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); -+} -+#endif -+ - /** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if - * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid - * interrupt. -@@ -868,4 +890,4 @@ int hub_control(struct usb_hcd *hcd, - return retval; - } - --#endif /* DWC_DEVICE_ONLY */ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -index cfed807..903a902 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ -- * $Revision: #39 $ -- * $Date: 2009/04/21 $ -- * $Change: 1237477 $ -+ * $Revision: #44 $ -+ * $Date: 2011/10/26 $ -+ * $Change: 1873028 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -53,32 +53,28 @@ - void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { - dwc_otg_qtd_t *qtd, *qtd_tmp; -- uint64_t flags; - - /* Free each QTD in the QTD list */ -- DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ DWC_SPINLOCK(hcd->lock); - DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { - DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); - dwc_otg_hcd_qtd_free(qtd); - } -- DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - - if (hcd->core_if->dma_desc_enable) { - dwc_otg_hcd_qh_free_ddma(hcd, qh); -- } -- else if (qh->dw_align_buf) { -+ } else if (qh->dw_align_buf) { - uint32_t buf_size; -- if(qh->ep_type == UE_ISOCHRONOUS) { -+ if (qh->ep_type == UE_ISOCHRONOUS) { - buf_size = 4096; - } else { - buf_size = hcd->core_if->core_params->max_transfer_size; - } -- dwc_dma_free(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); -+ DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); - } -- -- -- -- dwc_free(qh); -+ -+ DWC_FREE(qh); -+ DWC_SPINUNLOCK(hcd->lock); - return; - } - -@@ -89,8 +85,7 @@ void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - #define NS_TO_US(ns) ((ns + 500) / 1000) - /* convert & round nanoseconds to microseconds */ - --static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, -- int bytecount) -+static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount) - { - unsigned long retval; - -@@ -144,7 +139,7 @@ static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, - DWC_WARN("Unknown device speed\n"); - retval = -1; - } -- -+ - return NS_TO_US(retval); - } - -@@ -157,18 +152,16 @@ static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, - * to initialize the QH. - */ - #define SCHEDULE_SLOP 10 --void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, -- dwc_otg_hcd_urb_t * urb) -+void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) - { - char *speed, *type; - int dev_speed; - uint32_t hub_addr, hub_port; - - dwc_memset(qh, 0, sizeof(dwc_otg_qh_t)); -- -+ - /* Initialize QH */ - qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); -- - qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; - - qh->data_toggle = DWC_OTG_HC_PID_DATA0; -@@ -180,17 +173,17 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - /* FS/LS Enpoint on HS Hub - * NOT virtual root hub */ - dev_speed = hcd->fops->speed(hcd, urb->priv); -+ - hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port); - qh->do_split = 0; -+ - if (((dev_speed == USB_SPEED_LOW) || - (dev_speed == USB_SPEED_FULL)) && - (hub_addr != 0 && hub_addr != 1)) { -- - DWC_DEBUGPL(DBG_HCD, - "QH init: EP %d: TT found at hub addr %d, for port %d\n", - dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, - hub_port); -- - qh->do_split = 1; - } - -@@ -202,22 +195,22 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - int bytecount = - dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); - -- qh->usecs = calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), -- qh->ep_is_in, -- (qh->ep_type == UE_ISOCHRONOUS), -- bytecount); -+ qh->usecs = -+ calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), -+ qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS), -+ bytecount); - /* Start in a slightly future (micro)frame. */ - qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, - SCHEDULE_SLOP); - qh->interval = urb->interval; -- -+ - #if 0 - /* Increase interrupt polling rate for debugging. */ - if (qh->ep_type == UE_INTERRUPT) { - qh->interval = 8; - } - #endif -- hprt.d32 = dwc_read_reg32(hcd->core_if->host_if->hprt0); -+ hprt.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0); - if ((hprt.b.prtspd == DWC_HPRT0_PRTSPD_HIGH_SPEED) && - ((dev_speed == USB_SPEED_LOW) || - (dev_speed == USB_SPEED_FULL))) { -@@ -271,7 +264,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - type = "?"; - break; - } -- -+ - DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", type); - - #ifdef DEBUG -@@ -291,27 +284,30 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - * @param hcd The HCD state structure for the DWC OTG controller. - * @param urb Holds the information about the device/endpoint that we need - * to initialize the QH. -+ * @param atomic_alloc Flag to do atomic allocation if needed - * - * @return Returns pointer to the newly allocated QH, or NULL on error. */ - dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, -- dwc_otg_hcd_urb_t * urb) -+ dwc_otg_hcd_urb_t * urb, int atomic_alloc) - { - dwc_otg_qh_t *qh; - - /* Allocate memory */ - /** @todo add memflags argument */ -- qh = dwc_otg_hcd_qh_alloc(); -+ qh = dwc_otg_hcd_qh_alloc(atomic_alloc); - if (qh == NULL) { -+ DWC_ERROR("qh allocation failed"); - return NULL; - } - - qh_init(hcd, qh, urb); -- -- if (hcd->core_if->dma_desc_enable && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { -- dwc_otg_hcd_qh_free(hcd, qh); -+ -+ if (hcd->core_if->dma_desc_enable -+ && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { -+ dwc_otg_hcd_qh_free(hcd, qh); - return NULL; - } -- -+ - return qh; - } - -@@ -331,8 +327,8 @@ static int periodic_channel_available(dwc_otg_hcd_t * hcd) - int num_channels; - - num_channels = hcd->core_if->core_params->host_channels; -- if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) && -- (hcd->periodic_channels < num_channels - 1)) { -+ if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) -+ && (hcd->periodic_channels < num_channels - 1)) { - status = 0; - } else { - DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", -@@ -472,13 +468,11 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { - int status = 0; -- uint64_t flags; -- -- DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ gintmsk_data_t intr_mask = {.d32 = 0 }; - - if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { - /* QH already in a schedule. */ -- goto done; -+ return status; - } - - /* Add the new QH to the appropriate schedule */ -@@ -488,11 +482,14 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - &qh->qh_list_entry); - } else { - status = schedule_periodic(hcd, qh); -+ if ( !hcd->periodic_qh_count ) { -+ intr_mask.b.sofintr = 1; -+ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, -+ intr_mask.d32, intr_mask.d32); -+ } -+ hcd->periodic_qh_count++; - } - -- done: -- DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -- - return status; - } - -@@ -521,12 +518,11 @@ static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - * @param qh QH to remove from schedule. */ - void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { -- uint64_t flags; -- DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ gintmsk_data_t intr_mask = {.d32 = 0 }; - - if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { - /* QH is not in a schedule. */ -- goto done; -+ return; - } - - if (dwc_qh_is_non_per(qh)) { -@@ -537,10 +533,13 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); - } else { - deschedule_periodic(hcd, qh); -+ hcd->periodic_qh_count--; -+ if( !hcd->periodic_qh_count ) { -+ intr_mask.b.sofintr = 1; -+ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ } - } -- -- done: -- DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - } - - /** -@@ -558,10 +557,7 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - */ - void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - int sched_next_periodic_split) --{ -- uint64_t flags; -- DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -- -+{ - if (dwc_qh_is_non_per(qh)) { - dwc_otg_hcd_qh_remove(hcd, qh); - if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -@@ -577,9 +573,9 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - - qh->sched_frame = frame_number; - if (dwc_frame_num_le(frame_number, -- dwc_frame_num_inc(qh-> -- start_split_frame, -- 1))) { -+ dwc_frame_num_inc -+ (qh->start_split_frame, -+ 1))) { - /* - * Allow one frame to elapse after start - * split microframe before scheduling -@@ -623,14 +619,12 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, - &qh->qh_list_entry); - } else { -- DWC_LIST_MOVE_HEAD(&hcd-> -- periodic_sched_inactive, -- &qh->qh_list_entry); -+ DWC_LIST_MOVE_HEAD -+ (&hcd->periodic_sched_inactive, -+ &qh->qh_list_entry); - } - } - } -- -- DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - } - - /** -@@ -638,13 +632,14 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - * - * @param urb The URB to create a QTD from. Each URB-QTD pair will end up - * pointing to each other so each pair should have a unique correlation. -+ * @param atomic_alloc Flag to do atomic alloc if needed - * - * @return Returns pointer to the newly allocated QTD, or NULL on error. */ --dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb) -+dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc) - { - dwc_otg_qtd_t *qtd; - -- qtd = dwc_otg_hcd_qtd_alloc(); -+ qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc); - if (qtd == NULL) { - return NULL; - } -@@ -692,41 +687,40 @@ void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb) - * @param[in] qtd The QTD to add - * @param[in] hcd The DWC HCD structure - * @param[out] qh out parameter to return queue head -+ * @param atomic_alloc Flag to do atomic alloc if needed - * - * @return 0 if successful, negative error code otherwise. - */ - int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, -- dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh) -+ dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc) - { - int retval = 0; -- uint64_t flags; -+ dwc_irqflags_t flags; - - dwc_otg_hcd_urb_t *urb = qtd->urb; - -- DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -- - /* - * Get the QH which holds the QTD-list to insert to. Create QH if it - * doesn't exist. - */ - if (*qh == NULL) { -- *qh = dwc_otg_hcd_qh_create(hcd, urb); -+ *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc); - if (*qh == NULL) { - retval = -1; - goto done; - } - } -- -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); - retval = dwc_otg_hcd_qh_add(hcd, *qh); - if (retval == 0) { - DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd, - qtd_list_entry); - } -- -- done: - DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); - -+done: -+ - return retval; - } - --#endif /* DWC_DEVICE_ONLY */ -+#endif /* DWC_DEVICE_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h -new file mode 100644 -index 0000000..a7e9076 ---- /dev/null -+++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h -@@ -0,0 +1,185 @@ -+#ifndef _DWC_OS_DEP_H_ -+#define _DWC_OS_DEP_H_ -+ -+/** -+ * @file -+ * -+ * This file contains OS dependent structures. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) -+# include -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) -+# include -+#else -+# include -+#endif -+ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) -+# include -+#else -+# include -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -+# include -+#endif -+ -+#ifdef PCI_INTERFACE -+# include -+#endif -+ -+#ifdef LM_INTERFACE -+# include -+# include -+# include -+# include -+# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+# include -+# include -+# include -+# include -+# else -+/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - -+ here we assume that the machine architecture provides definitions -+ in its own header -+*/ -+# include -+# include -+# endif -+#endif -+ -+#ifdef PLATFORM_INTERFACE -+#include -+#include -+#endif -+ -+/** The OS page size */ -+#define DWC_OS_PAGE_SIZE PAGE_SIZE -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) -+typedef int gfp_t; -+#endif -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) -+# define IRQF_SHARED SA_SHIRQ -+#endif -+ -+typedef struct os_dependent { -+ /** Base address returned from ioremap() */ -+ void *base; -+ -+ /** Register offset for Diagnostic API */ -+ uint32_t reg_offset; -+ -+#ifdef LM_INTERFACE -+ struct lm_device *lmdev; -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *pcidev; -+ -+ /** Start address of a PCI region */ -+ resource_size_t rsrc_start; -+ -+ /** Length address of a PCI region */ -+ resource_size_t rsrc_len; -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platformdev; -+#endif -+ -+} os_dependent_t; -+ -+#ifdef __cplusplus -+} -+#endif -+ -+ -+ -+/* Type for the our device on the chosen bus */ -+#if defined(LM_INTERFACE) -+typedef struct lm_device dwc_bus_dev_t; -+#elif defined(PCI_INTERFACE) -+typedef struct pci_dev dwc_bus_dev_t; -+#elif defined(PLATFORM_INTERFACE) -+typedef struct platform_device dwc_bus_dev_t; -+#endif -+ -+/* Helper macro to retrieve drvdata from the device on the chosen bus */ -+#if defined(LM_INTERFACE) -+#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev) -+#elif defined(PCI_INTERFACE) -+#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev) -+#elif defined(PLATFORM_INTERFACE) -+#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev) -+#endif -+ -+/** -+ * Helper macro returning the otg_device structure of a given struct device -+ * -+ * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev) -+ */ -+#ifdef LM_INTERFACE -+#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ -+ struct lm_device *lm_dev = \ -+ container_of(_dev, struct lm_device, dev); \ -+ _var = lm_get_drvdata(lm_dev); \ -+ } while (0) -+ -+#elif defined(PCI_INTERFACE) -+#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ -+ _var = dev_get_drvdata(_dev); \ -+ } while (0) -+ -+#elif defined(PLATFORM_INTERFACE) -+#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ -+ struct platform_device *platform_dev = \ -+ container_of(_dev, struct platform_device, dev); \ -+ _var = platform_get_drvdata(platform_dev); \ -+ } while (0) -+#endif -+ -+ -+/** -+ * Helper macro returning the struct dev of the given struct os_dependent -+ * -+ * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep) -+ */ -+#ifdef LM_INTERFACE -+#define DWC_OTG_OS_GETDEV(_osdep) \ -+ ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev) -+#elif defined(PCI_INTERFACE) -+#define DWC_OTG_OS_GETDEV(_osdep) \ -+ ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev) -+#elif defined(PLATFORM_INTERFACE) -+#define DWC_OTG_OS_GETDEV(_osdep) \ -+ ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev) -+#endif -+ -+ -+ -+ -+#endif /* _DWC_OS_DEP_H_ */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -index 6043b99..2f9642d 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ -- * $Revision: #79 $ -- * $Date: 2009/04/10 $ -- * $Change: 1230501 $ -+ * $Revision: #99 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871160 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -33,7 +33,7 @@ - #ifndef DWC_HOST_ONLY - - /** @file -- * This file implements PCD Core. All code in this file is portable and don't -+ * This file implements PCD Core. All code in this file is portable and doesn't - * use any OS specific functions. - * PCD Core provides Interface, defined in - * header file, which can be used to implement OS specific PCD interface. -@@ -56,6 +56,9 @@ - extern int init_cfi(cfiobject_t * cfiobj); - #endif - -+/** -+ * Choose endpoint from ep arrays using usb_ep structure. -+ */ - static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) - { - int i; -@@ -79,23 +82,22 @@ void dwc_otg_request_done(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req, - int32_t status) - { - unsigned stopped = ep->stopped; -- -- DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, ep); -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req); - DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); - - /* don't modify queue heads during completion callback */ - ep->stopped = 1; -- DWC_SPINUNLOCK(ep->pcd->lock); -+ /* spin_unlock/spin_lock now done in fops->complete() */ - ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status, - req->actual); -- DWC_SPINLOCK(ep->pcd->lock); - - if (ep->pcd->request_pending > 0) { - --ep->pcd->request_pending; - } - - ep->stopped = stopped; -- dwc_free(req); -+ DWC_FREE(req); - } - - /** -@@ -129,12 +131,15 @@ void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, - static int32_t dwc_otg_pcd_start_cb(void *p) - { - dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); - - /* - * Initialized the Core for Device mode. - */ -- if (dwc_otg_is_device_mode(GET_CORE_IF(pcd))) { -- dwc_otg_core_dev_init(GET_CORE_IF(pcd)); -+ if (dwc_otg_is_device_mode(core_if)) { -+ dwc_otg_core_dev_init(core_if); -+ /* Set core_if's lock pointer to the pcd->lock */ -+ core_if->lock = pcd->lock; - } - return 1; - } -@@ -146,6 +151,11 @@ uint8_t *cfiw_ep_alloc_buffer(dwc_otg_pcd_t * pcd, void *pep, dwc_dma_t * addr, - { - dwc_otg_pcd_ep_t *ep; - ep = get_ep_from_handle(pcd, pep); -+ if (!ep) { -+ DWC_WARN("bad ep\n"); -+ return -DWC_E_INVALID; -+ } -+ - return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen, - flags); - } -@@ -173,7 +183,7 @@ static int32_t dwc_otg_pcd_resume_cb(void *p) - || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) { - if (GET_CORE_IF(pcd)->srp_timer_started) { - GET_CORE_IF(pcd)->srp_timer_started = 0; -- DWC_TIMER_CANCEL(pcd->srp_timer); -+ DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer); - } - } - return 1; -@@ -189,7 +199,9 @@ static int32_t dwc_otg_pcd_suspend_cb(void *p) - dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; - - if (pcd->fops->suspend) { -+ DWC_SPINUNLOCK(pcd->lock); - pcd->fops->suspend(pcd); -+ DWC_SPINLOCK(pcd->lock); - } - - return 1; -@@ -222,14 +234,14 @@ static int32_t dwc_otg_pcd_stop_cb(void *p) - }; - - /** -- * This function allocates a DMA Descriptor chain for the Endpoint -+ * This function allocates a DMA Descriptor chain for the Endpoint - * buffer to be used for a transfer to/from the specified endpoint. - */ --dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(uint32_t * dma_desc_addr, -- uint32_t count) -+dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, -+ uint32_t count) - { -- -- return dwc_dma_alloc(count * sizeof(dwc_otg_dev_dma_desc_t), dma_desc_addr); -+ return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), -+ dma_desc_addr); - } - - /** -@@ -238,7 +250,7 @@ dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(uint32_t * dma_desc_addr, - void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, - uint32_t dma_desc_addr, uint32_t count) - { -- dwc_dma_free(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, -+ DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, - dma_desc_addr); - } - -@@ -259,6 +271,7 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - depctl_data_t depctl = {.d32 = 0 }; - volatile uint32_t *addr; - int i, j; -+ uint32_t len; - - if (dwc_ep->is_in) - dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval; -@@ -276,7 +289,7 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - return; - } - -- dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - - /** ISO OUT EP */ - if (dwc_ep->is_in == 0) { -@@ -289,7 +302,7 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - int offset; - - addr = &core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl; -- dma_ad = (dma_addr_t) dwc_read_reg32(&(out_regs->doepdma)); -+ dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma)); - - /** Buffer 0 descriptors setup */ - dma_ad = dwc_ep->dma_addr0; -@@ -307,16 +320,17 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - i += dwc_ep->pkt_per_frm) { - - for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { -- data_per_desc = -- ((j + 1) * dwc_ep->maxpacket > -- dwc_ep->data_per_frame) ? dwc_ep-> -- data_per_frame - -- j * dwc_ep->maxpacket : dwc_ep->maxpacket; -- -- data_per_desc += -- (data_per_desc % 4) ? (4 - -- data_per_desc % -- 4) : 0; -+ uint32_t len = (j + 1) * dwc_ep->maxpacket; -+ if (len > dwc_ep->data_per_frame) -+ data_per_desc = -+ dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket; -+ else -+ data_per_desc = dwc_ep->maxpacket; -+ len = data_per_desc % 4; -+ if (len) -+ data_per_desc += 4 - len; -+ - sts.b_iso_out.rxbytes = data_per_desc; - dma_desc->buf = dma_ad; - dma_desc->status.d32 = sts.d32; -@@ -328,12 +342,16 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - } - - for (j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { -- data_per_desc = -- ((j + 1) * dwc_ep->maxpacket > -- dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -- j * dwc_ep->maxpacket : dwc_ep->maxpacket; -- data_per_desc += -- (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ uint32_t len = (j + 1) * dwc_ep->maxpacket; -+ if (len > dwc_ep->data_per_frame) -+ data_per_desc = -+ dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket; -+ else -+ data_per_desc = dwc_ep->maxpacket; -+ len = data_per_desc % 4; -+ if (len) -+ data_per_desc += 4 - len; - sts.b_iso_out.rxbytes = data_per_desc; - dma_desc->buf = dma_ad; - dma_desc->status.d32 = sts.d32; -@@ -344,12 +362,15 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - } - - sts.b_iso_out.ioc = 1; -- data_per_desc = -- ((j + 1) * dwc_ep->maxpacket > -- dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - -- j * dwc_ep->maxpacket : dwc_ep->maxpacket; -- data_per_desc += -- (data_per_desc % 4) ? (4 - data_per_desc % 4) : 0; -+ len = (j + 1) * dwc_ep->maxpacket; -+ if (len > dwc_ep->data_per_frame) -+ data_per_desc = -+ dwc_ep->data_per_frame - j * dwc_ep->maxpacket; -+ else -+ data_per_desc = dwc_ep->maxpacket; -+ len = data_per_desc % 4; -+ if (len) -+ data_per_desc += 4 - len; - sts.b_iso_out.rxbytes = data_per_desc; - - dma_desc->buf = dma_ad; -@@ -364,16 +385,19 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - for (i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; - i += dwc_ep->pkt_per_frm) { - for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { -+ uint32_t len = (j + 1) * dwc_ep->maxpacket; -+ if (len > dwc_ep->data_per_frame) -+ data_per_desc = -+ dwc_ep->data_per_frame - -+ j * dwc_ep->maxpacket; -+ else -+ data_per_desc = dwc_ep->maxpacket; -+ len = data_per_desc % 4; -+ if (len) -+ data_per_desc += 4 - len; -+ - data_per_desc = -- ((j + 1) * dwc_ep->maxpacket > -- dwc_ep->data_per_frame) ? dwc_ep-> -- data_per_frame - -- j * dwc_ep->maxpacket : dwc_ep->maxpacket; -- data_per_desc += -- (data_per_desc % 4) ? (4 - -- data_per_desc % -- 4) : 0; -- sts.b_iso_out.rxbytes = data_per_desc; -+ sts.b_iso_out.rxbytes = data_per_desc; - dma_desc->buf = dma_ad; - dma_desc->status.d32 = sts.d32; - -@@ -414,7 +438,7 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - dwc_ep->next_frame = 0; - - /** Write dma_ad into DOEPDMA register */ -- dwc_write_reg32(&(out_regs->doepdma), -+ DWC_WRITE_REG32(&(out_regs->doepdma), - (uint32_t) dwc_ep->iso_dma_desc_addr); - - } -@@ -429,17 +453,17 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - fifosize_data_t txfifosize, rxfifosize; - - txfifosize.d32 = -- dwc_read_reg32(&core_if->dev_if->in_ep_regs[dwc_ep->num]-> -- dtxfsts); -+ DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[dwc_ep->num]->dtxfsts); - rxfifosize.d32 = -- dwc_read_reg32(&core_if->core_global_regs->grxfsiz); -+ DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); - - addr = &core_if->dev_if->in_ep_regs[dwc_ep->num]->diepctl; - - dma_ad = dwc_ep->dma_addr0; - - dsts.d32 = -- dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - - sts.b_iso_in.bs = BS_HOST_READY; - sts.b_iso_in.txsts = 0; -@@ -493,7 +517,7 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval; - - /** Write dma_ad into diepdma register */ -- dwc_write_reg32(&(in_regs->diepdma), -+ DWC_WRITE_REG32(&(in_regs->diepdma), - (uint32_t) dwc_ep->iso_dma_desc_addr); - } - /** Enable endpoint, clear nak */ -@@ -502,8 +526,8 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - depctl.b.usbactep = 1; - depctl.b.cnak = 1; - -- dwc_modify_reg32(addr, depctl.d32, depctl.d32); -- depctl.d32 = dwc_read_reg32(addr); -+ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); -+ depctl.d32 = DWC_READ_REG32(addr); - } - - /** -@@ -513,7 +537,6 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - * @param ep The EP to start the transfer on. - * - */ -- - void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, - dwc_ep_t * ep) - { -@@ -545,19 +568,21 @@ void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, - /* Program the transfer size and packet count - * as follows: xfersize = N * maxpacket + - * short_packet pktcnt = N + (short_packet -- * exist ? 1 : 0) -+ * exist ? 1 : 0) - */ - deptsiz.b.mc = ep->pkt_per_frm; - deptsiz.b.xfersize = ep->xfer_len; - deptsiz.b.pktcnt = - (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; -- dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -- dieptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ in_ep_regs[ep->num]->dieptsiz, -+ deptsiz.d32); - - /* Write the DMA register */ -- dwc_write_reg32(& -- (core_if->dev_if->in_ep_regs[ep->num]-> -- diepdma), (uint32_t) ep->dma_addr); -+ DWC_WRITE_REG32(& -+ (core_if->dev_if-> -+ in_ep_regs[ep->num]->diepdma), -+ (uint32_t) ep->dma_addr); - - } else { - deptsiz.b.pktcnt = -@@ -565,31 +590,31 @@ void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, - ep->maxpacket; - deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; - -- dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> -- doeptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ out_ep_regs[ep->num]->doeptsiz, -+ deptsiz.d32); - - /* Write the DMA register */ -- dwc_write_reg32(& -- (core_if->dev_if->out_ep_regs[ep->num]-> -- doepdma), (uint32_t) ep->dma_addr); -+ DWC_WRITE_REG32(& -+ (core_if->dev_if-> -+ out_ep_regs[ep->num]->doepdma), -+ (uint32_t) ep->dma_addr); - - } - /** Enable endpoint, clear nak */ - depctl.d32 = 0; -- dwc_modify_reg32(addr, depctl.d32, depctl.d32); -- - depctl.b.epena = 1; - depctl.b.cnak = 1; - -- dwc_modify_reg32(addr, depctl.d32, depctl.d32); -+ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); - } - } - - /** - * This function does the setup for a data transfer for an EP and -- * starts the transfer. For an IN transfer, the packets will be -+ * starts the transfer. For an IN transfer, the packets will be - * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, -- * the packets are unloaded from the Rx FIFO in the ISR. the ISR. -+ * the packets are unloaded from the Rx FIFO in the ISR. - * - * @param core_if Programming view of DWC_otg controller. - * @param ep The EP to start the transfer on. -@@ -611,11 +636,11 @@ static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if, - dwc_otg_iso_ep_start_buf_transfer(core_if, ep); - } else { - ep->cur_pkt_addr = -- (ep->proc_buf_num) ? ep->xfer_buff1 : ep-> -- xfer_buff0; -+ (ep->proc_buf_num) ? ep-> -+ xfer_buff1 : ep->xfer_buff0; - ep->cur_pkt_dma_addr = -- (ep->proc_buf_num) ? ep->dma_addr1 : ep-> -- dma_addr0; -+ (ep->proc_buf_num) ? ep-> -+ dma_addr1 : ep->dma_addr0; - dwc_otg_iso_ep_start_frm_transfer(core_if, ep); - } - } -@@ -629,10 +654,8 @@ static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if, - } - - /** -- * This function does the setup for a data transfer for an EP and -- * starts the transfer. For an IN transfer, the packets will be -- * loaded into the appropriate Tx FIFO in the ISR. For OUT transfers, -- * the packets are unloaded from the Rx FIFO in the ISR. the ISR. -+ * This function stops transfer for an EP and -+ * resets the ep's variables. - * - * @param core_if Programming view of DWC_otg controller. - * @param ep The EP to start the transfer on. -@@ -650,12 +673,12 @@ void dwc_otg_iso_ep_stop_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - } - - /* disable the ep */ -- depctl.d32 = dwc_read_reg32(addr); -+ depctl.d32 = DWC_READ_REG32(addr); - - depctl.b.epdis = 1; - depctl.b.snak = 1; - -- dwc_write_reg32(addr, depctl.d32); -+ DWC_WRITE_REG32(addr, depctl.d32); - - if (core_if->dma_desc_enable && - ep->iso_desc_addr && ep->iso_dma_desc_addr) { -@@ -690,7 +713,7 @@ int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, - int atomic_alloc) - { - dwc_otg_pcd_ep_t *ep; -- uint64_t flags = 0; -+ dwc_irqflags_t flags = 0; - dwc_ep_t *dwc_ep; - int32_t frm_data; - dsts_data_t dsts; -@@ -698,7 +721,7 @@ int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, - - ep = get_ep_from_handle(pcd, ep_handle); - -- if (!ep->desc || ep->dwc_ep.num == 0) { -+ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { - DWC_WARN("bad ep\n"); - return -DWC_E_INVALID; - } -@@ -736,7 +759,7 @@ int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, - frm_data -= ep->dwc_ep.maxpacket; - } - -- dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - - if (start_frame == -1) { - dwc_ep->next_frame = dsts.b.soffn + 1; -@@ -769,10 +792,10 @@ int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, - - if (atomic_alloc) { - dwc_ep->pkt_info = -- dwc_alloc_atomic(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); -+ DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); - } else { - dwc_ep->pkt_info = -- dwc_alloc(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); -+ DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); - } - if (!dwc_ep->pkt_info) { - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -@@ -794,7 +817,7 @@ int dwc_otg_pcd_iso_ep_start(dwc_otg_pcd_t * pcd, void *ep_handle, - int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, - void *req_handle) - { -- uint64_t flags = 0; -+ dwc_irqflags_t flags = 0; - dwc_otg_pcd_ep_t *ep; - dwc_ep_t *dwc_ep; - -@@ -807,7 +830,7 @@ int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, - - dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep); - -- dwc_free(dwc_ep->pkt_info); -+ DWC_FREE(dwc_ep->pkt_info); - DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); - if (ep->iso_req_handle != req_handle) { - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -@@ -824,7 +847,7 @@ int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, - * This function is used for perodical data exchnage between PCD and gadget drivers. - * for Isochronous EPs - * -- * - Every time a sync period completes this function is called to -+ * - Every time a sync period completes this function is called to - * perform data exchange between PCD and gadget - */ - void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, -@@ -854,6 +877,10 @@ int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, void *ep_handle, - dwc_ep_t *dwc_ep; - - ep = get_ep_from_handle(pcd, ep_handle); -+ if (!ep->desc || ep->dwc_ep.num == 0) { -+ DWC_WARN("bad ep\n"); -+ return -DWC_E_INVALID; -+ } - dwc_ep = &ep->dwc_ep; - - return dwc_ep->pkt_cnt; -@@ -867,6 +894,9 @@ void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle, - dwc_ep_t *dwc_ep; - - ep = get_ep_from_handle(pcd, ep_handle); -+ if (!ep) -+ DWC_WARN("bad ep\n"); -+ - dwc_ep = &ep->dwc_ep; - - *status = dwc_ep->pkt_info[packet].status; -@@ -874,7 +904,7 @@ void dwc_otg_pcd_get_iso_packet_params(dwc_otg_pcd_t * pcd, void *ep_handle, - *offset = dwc_ep->pkt_info[packet].offset; - } - --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ - - static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep, - uint32_t is_in, uint32_t ep_num) -@@ -906,7 +936,7 @@ static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep, - } - - /** -- * Initialise ep's -+ * Initialize ep's - */ - static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd) - { -@@ -964,7 +994,7 @@ static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd) - } - - /** -- * This function is called when the SRP timer expires. The SRP should -+ * This function is called when the SRP timer expires. The SRP should - * complete within 6 seconds. - */ - static void srp_timeout(void *ptr) -@@ -973,9 +1003,34 @@ static void srp_timeout(void *ptr) - dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; - volatile uint32_t *addr = &core_if->core_global_regs->gotgctl; - -- gotgctl.d32 = dwc_read_reg32(addr); -+ gotgctl.d32 = DWC_READ_REG32(addr); - - core_if->srp_timer_started = 0; -+ -+ if (core_if->adp_enable) { -+ if (gotgctl.b.bsesvld == 0) { -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ DWC_PRINTF("SRP Timeout BSESSVLD = 0\n"); -+ /* Power off the core */ -+ if (core_if->power_down == 2) { -+ gpwrdn.b.pwrdnswtch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, gpwrdn.d32, 0); -+ } -+ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuintsel = 1; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ dwc_otg_adp_probe_start(core_if); -+ } else { -+ DWC_PRINTF("SRP Timeout BSESSVLD = 1\n"); -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ } -+ } - - if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) && - (core_if->core_params->i2c_enable)) { -@@ -983,28 +1038,27 @@ static void srp_timeout(void *ptr) - - if ((core_if->srp_success) && (gotgctl.b.bsesvld)) { - if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -- core_if->pcd_cb->resume_wakeup(core_if->pcd_cb-> -- p); -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); - } - - /* Clear Session Request */ - gotgctl.d32 = 0; - gotgctl.b.sesreq = 1; -- dwc_modify_reg32(&core_if->core_global_regs->gotgctl, -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, - gotgctl.d32, 0); - - core_if->srp_success = 0; - } else { - __DWC_ERROR("Device not connected/responding\n"); - gotgctl.b.sesreq = 0; -- dwc_write_reg32(addr, gotgctl.d32); -+ DWC_WRITE_REG32(addr, gotgctl.d32); - } - } else if (gotgctl.b.sesreq) { - DWC_PRINTF("SRP Timeout\n"); - - __DWC_ERROR("Device not connected/responding\n"); - gotgctl.b.sesreq = 0; -- dwc_write_reg32(addr, gotgctl.d32); -+ DWC_WRITE_REG32(addr, gotgctl.d32); - } else { - DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32); - } -@@ -1026,7 +1080,7 @@ static void start_xfer_tasklet_func(void *data) - - DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n"); - -- diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -+ diepctl.d32 = DWC_READ_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl); - - if (pcd->ep0.queue_sof) { - pcd->ep0.queue_sof = 0; -@@ -1037,7 +1091,7 @@ static void start_xfer_tasklet_func(void *data) - for (i = 0; i < core_if->dev_if->num_in_eps; i++) { - depctl_data_t diepctl; - diepctl.d32 = -- dwc_read_reg32(&core_if->dev_if->in_ep_regs[i]->diepctl); -+ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); - - if (pcd->in_ep[i].queue_sof) { - pcd->in_ep[i].queue_sof = 0; -@@ -1055,28 +1109,33 @@ static void start_xfer_tasklet_func(void *data) - */ - dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - { -- dwc_otg_pcd_t *pcd = 0; -+ dwc_otg_pcd_t *pcd = NULL; - dwc_otg_dev_if_t *dev_if; -+ int i; - - /* - * Allocate PCD structure - */ -- pcd = dwc_alloc(sizeof(dwc_otg_pcd_t)); -+ pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t)); - -- if (pcd == 0) { -+ if (pcd == NULL) { - return NULL; - } - - pcd->lock = DWC_SPINLOCK_ALLOC(); - DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n", - pcd, core_if);//GRAYG -- pcd->core_if = core_if; - if (!pcd->lock) { - DWC_ERROR("Could not allocate lock for pcd"); -- dwc_free(pcd); -+ DWC_FREE(pcd); - return NULL; - } -+ /* Set core_if's lock pointer to hcd->lock */ -+ core_if->lock = pcd->lock; -+ pcd->core_if = core_if; -+ - dev_if = core_if->dev_if; -+ dev_if->isoc_ep = NULL; - - if (core_if->hwcfg4.b.ded_fifo_en) { - DWC_PRINTF("Dedicated Tx FIFOs mode\n"); -@@ -1085,9 +1144,10 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - } - - /* -- * Initialized the Core for Device mode. -- */ -- if (dwc_otg_is_device_mode(core_if)) { -+ * Initialized the Core for Device mode here if there is nod ADP support. -+ * Otherwise it will be done later in dwc_otg_adp_start routine. -+ */ -+ if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) { - dwc_otg_core_dev_init(core_if); - } - -@@ -1101,20 +1161,20 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - */ - if (GET_CORE_IF(pcd)->dma_enable) { - pcd->setup_pkt = -- dwc_dma_alloc(sizeof(*pcd->setup_pkt) * 5, -+ DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, - &pcd->setup_pkt_dma_handle); -- if (pcd->setup_pkt == 0) { -- dwc_free(pcd); -+ if (pcd->setup_pkt == NULL) { -+ DWC_FREE(pcd); - return NULL; - } - - pcd->status_buf = -- dwc_dma_alloc(sizeof(uint16_t), -+ DWC_DMA_ALLOC(sizeof(uint16_t), - &pcd->status_buf_dma_handle); -- if (pcd->status_buf == 0) { -- dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, -+ if (pcd->status_buf == NULL) { -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, - pcd->setup_pkt, pcd->setup_pkt_dma_handle); -- dwc_free(pcd); -+ DWC_FREE(pcd); - return NULL; - } - -@@ -1166,29 +1226,29 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - dma_setup_desc_addr - [0], 1); - -- dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, - pcd->setup_pkt, - pcd->setup_pkt_dma_handle); -- dwc_dma_free(sizeof(*pcd->status_buf), -+ DWC_DMA_FREE(sizeof(*pcd->status_buf), - pcd->status_buf, - pcd->status_buf_dma_handle); - -- dwc_free(pcd); -+ DWC_FREE(pcd); - - return NULL; - } - } - } else { -- pcd->setup_pkt = dwc_alloc(sizeof(*pcd->setup_pkt) * 5); -- if (pcd->setup_pkt == 0) { -- dwc_free(pcd); -+ pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5); -+ if (pcd->setup_pkt == NULL) { -+ DWC_FREE(pcd); - return NULL; - } - -- pcd->status_buf = dwc_alloc(sizeof(uint16_t)); -- if (pcd->status_buf == 0) { -- dwc_free(pcd->setup_pkt); -- dwc_free(pcd); -+ pcd->status_buf = DWC_ALLOC(sizeof(uint16_t)); -+ if (pcd->status_buf == NULL) { -+ DWC_FREE(pcd->setup_pkt); -+ DWC_FREE(pcd); - return NULL; - } - } -@@ -1197,39 +1257,80 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - - /* Allocate the cfi object for the PCD */ - #ifdef DWC_UTE_CFI -- pcd->cfi = dwc_alloc(sizeof(cfiobject_t)); -+ pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t)); - if (NULL == pcd->cfi) -- return NULL; -+ goto fail; - if (init_cfi(pcd->cfi)) { - CFI_INFO("%s: Failed to init the CFI object\n", __func__); -- return NULL; -+ goto fail; - } - #endif - - /* Initialize tasklets */ -- pcd->start_xfer_tasklet = DWC_TASK_ALLOC(start_xfer_tasklet_func, pcd); -- pcd->test_mode_tasklet = DWC_TASK_ALLOC(do_test_mode, pcd); -- /* Initialize timer */ -- pcd->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if); -+ pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet", -+ start_xfer_tasklet_func, pcd); -+ pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet", -+ do_test_mode, pcd); -+ -+ /* Initialize SRP timer */ -+ core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if); -+ -+ if (core_if->core_params->dev_out_nak) { -+ /** -+ * Initialize xfer timeout timer. Implemented for -+ * 2.93a feature "Device DDMA OUT NAK Enhancement" -+ */ -+ for(i = 0; i < MAX_EPS_CHANNELS; i++) { -+ pcd->core_if->ep_xfer_timer[i] = -+ DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout, -+ &pcd->core_if->ep_xfer_info[i]); -+ } -+ } -+ - return pcd; -+#ifdef DWC_UTE_CFI -+fail: -+#endif -+ if (pcd->setup_pkt) -+ DWC_FREE(pcd->setup_pkt); -+ if (pcd->status_buf) -+ DWC_FREE(pcd->status_buf); -+#ifdef DWC_UTE_CFI -+ if (pcd->cfi) -+ DWC_FREE(pcd->cfi); -+#endif -+ if (pcd) -+ DWC_FREE(pcd); -+ return NULL; -+ - } - -+/** -+ * Remove PCD specific data -+ */ - void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) - { - dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; -+ int i; -+ if (pcd->core_if->core_params->dev_out_nak) { -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); -+ pcd->core_if->ep_xfer_info[i].state = 0; -+ } -+ } - - if (GET_CORE_IF(pcd)->dma_enable) { -- dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, -+ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, - pcd->setup_pkt_dma_handle); -- dwc_dma_free(sizeof(uint16_t), pcd->status_buf, -+ DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, - pcd->status_buf_dma_handle); - if (GET_CORE_IF(pcd)->dma_desc_enable) { - dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], -- dev_if-> -- dma_setup_desc_addr[0], 1); -+ dev_if->dma_setup_desc_addr -+ [0], 1); - dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], -- dev_if-> -- dma_setup_desc_addr[1], 1); -+ dev_if->dma_setup_desc_addr -+ [1], 1); - dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, - dev_if->dma_in_desc_addr, 1); - dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, -@@ -1237,13 +1338,22 @@ void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) - 1); - } - } else { -- dwc_free(pcd->setup_pkt); -- dwc_free(pcd->status_buf); -+ DWC_FREE(pcd->setup_pkt); -+ DWC_FREE(pcd->status_buf); - } - DWC_SPINLOCK_FREE(pcd->lock); -+ /* Set core_if's lock pointer to NULL */ -+ pcd->core_if->lock = NULL; -+ - DWC_TASK_FREE(pcd->start_xfer_tasklet); - DWC_TASK_FREE(pcd->test_mode_tasklet); -- DWC_TIMER_FREE(pcd->srp_timer); -+ if (pcd->core_if->core_params->dev_out_nak) { -+ for (i = 0; i < MAX_EPS_CHANNELS; i++) { -+ if (pcd->core_if->ep_xfer_timer[i]) { -+ DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]); -+ } -+ } -+ } - - /* Release the CFI object's dynamic memory */ - #ifdef DWC_UTE_CFI -@@ -1252,9 +1362,12 @@ void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) - } - #endif - -- dwc_free(pcd); -+ DWC_FREE(pcd); - } - -+/** -+ * Returns whether registered pcd is dual speed or not -+ */ - uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd) - { - dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -@@ -1269,12 +1382,15 @@ uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd) - return 1; - } - -+/** -+ * Returns whether registered pcd is OTG capable or not -+ */ - uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd) - { - dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); - gusbcfg_data_t usbcfg = {.d32 = 0 }; - -- usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg); -+ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); - if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) { - return 0; - } -@@ -1340,14 +1456,22 @@ static void release_tx_fifo(dwc_otg_core_if_t * core_if, uint32_t fifo_num) - (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk; - } - -+/** -+ * This function is being called from gadget -+ * to enable PCD endpoint. -+ */ - int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - const uint8_t * ep_desc, void *usb_ep) - { - int num, dir; -- dwc_otg_pcd_ep_t *ep = 0; -+ dwc_otg_pcd_ep_t *ep = NULL; - const usb_endpoint_descriptor_t *desc; -- uint64_t flags; -+ dwc_irqflags_t flags; -+ fifosize_data_t dptxfsiz = {.d32 = 0 }; -+ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; -+ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; - int retval = 0; -+ int i, epcount; - - desc = (const usb_endpoint_descriptor_t *)ep_desc; - -@@ -1368,9 +1492,27 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - } - - if (dir == UE_DIR_IN) { -- ep = &pcd->in_ep[num - 1]; -+ epcount = pcd->core_if->dev_if->num_in_eps; -+ for (i = 0; i < epcount; i++) { -+ if (num == pcd->in_ep[i].dwc_ep.num) { -+ ep = &pcd->in_ep[i]; -+ break; -+ } -+ } - } else { -- ep = &pcd->out_ep[num - 1]; -+ epcount = pcd->core_if->dev_if->num_out_eps; -+ for (i = 0; i < epcount; i++) { -+ if (num == pcd->out_ep[i].dwc_ep.num) { -+ ep = &pcd->out_ep[i]; -+ break; -+ } -+ } -+ } -+ -+ if (!ep) { -+ DWC_WARN("bad address\n"); -+ retval = -DWC_E_INVALID; -+ goto out; - } - - DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -@@ -1405,7 +1547,23 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - */ - ep->dwc_ep.tx_fifo_num = - assign_tx_fifo(GET_CORE_IF(pcd)); -+ } - -+ /* Calculating EP info controller base address */ -+ if (ep->dwc_ep.tx_fifo_num && GET_CORE_IF(pcd)->en_multiple_tx_fifo) { -+ gdfifocfg.d32 = -+ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs-> -+ gdfifocfg); -+ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; -+ dptxfsiz.d32 = -+ (DWC_READ_REG32 -+ (&GET_CORE_IF(pcd)-> -+ core_global_regs->dtxfsiz[ep->dwc_ep. -+ tx_fifo_num-1]) >> 16); -+ gdfifocfg.b.epinfobase = -+ gdfifocfgbase.d32 + dptxfsiz.d32; -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs-> -+ gdfifocfg, gdfifocfg.d32); - } - } - /* Set initial data PID. */ -@@ -1415,10 +1573,12 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - - /* Alloc DMA Descriptors */ - if (GET_CORE_IF(pcd)->dma_desc_enable) { -+#ifndef DWC_UTE_PER_IO - if (ep->dwc_ep.type != UE_ISOCHRONOUS) { -+#endif - ep->dwc_ep.desc_addr = -- dwc_otg_ep_alloc_desc_chain(&ep->dwc_ep. -- dma_desc_addr, -+ dwc_otg_ep_alloc_desc_chain(&ep-> -+ dwc_ep.dma_desc_addr, - MAX_DMA_DESC_CNT); - if (!ep->dwc_ep.desc_addr) { - DWC_WARN("%s, can't allocate DMA descriptor\n", -@@ -1427,12 +1587,21 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); - goto out; - } -+#ifndef DWC_UTE_PER_IO - } -+#endif - } - - DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n", - (ep->dwc_ep.is_in ? "IN" : "OUT"), - ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc); -+#ifdef DWC_UTE_PER_IO -+ ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1); -+#endif -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { -+ ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1); -+ ep->dwc_ep.frame_num = 0xFFFFFFFF; -+ } - - dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); - -@@ -1444,22 +1613,28 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); - -- out: -+out: - return retval; - } - -+/** -+ * This function is being called from gadget -+ * to disable PCD endpoint. -+ */ - int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - { - dwc_otg_pcd_ep_t *ep; -- uint64_t flags; -+ dwc_irqflags_t flags; - dwc_otg_dev_dma_desc_t *desc_addr; - dwc_dma_t dma_desc_addr; -+ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; -+ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; -+ fifosize_data_t dptxfsiz = {.d32 = 0 }; - - ep = get_ep_from_handle(pcd, ep_handle); - - if (!ep || !ep->desc) { -- DWC_DEBUGPL(DBG_PCD, "%s, %d %s not enabled\n", __func__, -- ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); -+ DWC_DEBUGPL(DBG_PCD, "bad ep address\n"); - return -DWC_E_INVALID; - } - -@@ -1468,13 +1643,35 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - dwc_otg_request_nuke(ep); - - dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep); -- ep->desc = 0; -+ if (pcd->core_if->core_params->dev_out_nak) -+ { -+ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]); -+ pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0; -+ } -+ ep->desc = NULL; - ep->stopped = 1; - -+ gdfifocfg.d32 = -+ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg); -+ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; -+ - if (ep->dwc_ep.is_in) { -- dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); -+ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { -+ /* Flush the Tx FIFO */ -+ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); -+ } - release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); - release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); -+ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { -+ /* Decreasing EPinfo Base Addr */ -+ dptxfsiz.d32 = -+ (DWC_READ_REG32 -+ (&GET_CORE_IF(pcd)-> -+ core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16); -+ gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32; -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg, -+ gdfifocfg.d32); -+ } - } - - /* Free DMA Descriptors */ -@@ -1491,36 +1688,415 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - goto out_unlocked; - } - } -- - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); - -- out_unlocked: -+out_unlocked: - DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num, - ep->dwc_ep.is_in ? "IN" : "OUT"); - return 0; - - } - -+/******************************************************************************/ -+#ifdef DWC_UTE_PER_IO -+ -+/** -+ * Free the request and its extended parts -+ * -+ */ -+void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req) -+{ -+ DWC_FREE(req->ext_req.per_io_frame_descs); -+ DWC_FREE(req); -+} -+ -+/** -+ * Start the next request in the endpoint's queue. -+ * -+ */ -+int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd, -+ dwc_otg_pcd_ep_t * ep) -+{ -+ int i; -+ dwc_otg_pcd_request_t *req = NULL; -+ dwc_ep_t *dwcep = NULL; -+ struct dwc_iso_xreq_port *ereq = NULL; -+ struct dwc_iso_pkt_desc_port *ddesc_iso; -+ uint16_t nat; -+ depctl_data_t diepctl; -+ -+ dwcep = &ep->dwc_ep; -+ -+ if (dwcep->xiso_active_xfers > 0) { -+#if 0 //Disable this to decrease s/w overhead that is crucial for Isoc transfers -+ DWC_WARN("There are currently active transfers for EP%d \ -+ (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers, -+ dwcep->xiso_queued_xfers); -+#endif -+ return 0; -+ } -+ -+ nat = UGETW(ep->desc->wMaxPacketSize); -+ nat = (nat >> 11) & 0x03; -+ -+ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ ereq = &req->ext_req; -+ ep->stopped = 0; -+ -+ /* Get the frame number */ -+ dwcep->xiso_frame_num = -+ dwc_otg_get_frame_number(GET_CORE_IF(pcd)); -+ DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num); -+ -+ ddesc_iso = ereq->per_io_frame_descs; -+ -+ if (dwcep->is_in) { -+ /* Setup DMA Descriptor chain for IN Isoc request */ -+ for (i = 0; i < ereq->pio_pkt_count; i++) { -+ //if ((i % (nat + 1)) == 0) -+ if ( i > 0 ) -+ dwcep->xiso_frame_num = (dwcep->xiso_bInterval + -+ dwcep->xiso_frame_num) & 0x3FFF; -+ dwcep->desc_addr[i].buf = -+ req->dma + ddesc_iso[i].offset; -+ dwcep->desc_addr[i].status.b_iso_in.txbytes = -+ ddesc_iso[i].length; -+ dwcep->desc_addr[i].status.b_iso_in.framenum = -+ dwcep->xiso_frame_num; -+ dwcep->desc_addr[i].status.b_iso_in.bs = -+ BS_HOST_READY; -+ dwcep->desc_addr[i].status.b_iso_in.txsts = 0; -+ dwcep->desc_addr[i].status.b_iso_in.sp = -+ (ddesc_iso[i].length % -+ dwcep->maxpacket) ? 1 : 0; -+ dwcep->desc_addr[i].status.b_iso_in.ioc = 0; -+ dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1; -+ dwcep->desc_addr[i].status.b_iso_in.l = 0; -+ -+ /* Process the last descriptor */ -+ if (i == ereq->pio_pkt_count - 1) { -+ dwcep->desc_addr[i].status.b_iso_in.ioc = 1; -+ dwcep->desc_addr[i].status.b_iso_in.l = 1; -+ } -+ } -+ -+ /* Setup and start the transfer for this endpoint */ -+ dwcep->xiso_active_xfers++; -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if-> -+ in_ep_regs[dwcep->num]->diepdma, -+ dwcep->dma_desc_addr); -+ diepctl.d32 = 0; -+ diepctl.b.epena = 1; -+ diepctl.b.cnak = 1; -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> -+ in_ep_regs[dwcep->num]->diepctl, 0, -+ diepctl.d32); -+ } else { -+ /* Setup DMA Descriptor chain for OUT Isoc request */ -+ for (i = 0; i < ereq->pio_pkt_count; i++) { -+ //if ((i % (nat + 1)) == 0) -+ dwcep->xiso_frame_num = (dwcep->xiso_bInterval + -+ dwcep->xiso_frame_num) & 0x3FFF; -+ dwcep->desc_addr[i].buf = -+ req->dma + ddesc_iso[i].offset; -+ dwcep->desc_addr[i].status.b_iso_out.rxbytes = -+ ddesc_iso[i].length; -+ dwcep->desc_addr[i].status.b_iso_out.framenum = -+ dwcep->xiso_frame_num; -+ dwcep->desc_addr[i].status.b_iso_out.bs = -+ BS_HOST_READY; -+ dwcep->desc_addr[i].status.b_iso_out.rxsts = 0; -+ dwcep->desc_addr[i].status.b_iso_out.sp = -+ (ddesc_iso[i].length % -+ dwcep->maxpacket) ? 1 : 0; -+ dwcep->desc_addr[i].status.b_iso_out.ioc = 0; -+ dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1; -+ dwcep->desc_addr[i].status.b_iso_out.l = 0; -+ -+ /* Process the last descriptor */ -+ if (i == ereq->pio_pkt_count - 1) { -+ dwcep->desc_addr[i].status.b_iso_out.ioc = 1; -+ dwcep->desc_addr[i].status.b_iso_out.l = 1; -+ } -+ } -+ -+ /* Setup and start the transfer for this endpoint */ -+ dwcep->xiso_active_xfers++; -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if-> -+ out_ep_regs[dwcep->num]->doepdma, -+ dwcep->dma_desc_addr); -+ diepctl.d32 = 0; -+ diepctl.b.epena = 1; -+ diepctl.b.cnak = 1; -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> -+ out_ep_regs[dwcep->num]->doepctl, 0, -+ diepctl.d32); -+ } -+ -+ } else { -+ ep->stopped = 1; -+ } -+ -+ return 0; -+} -+ -+/** -+ * - Remove the request from the queue -+ */ -+void complete_xiso_ep(dwc_otg_pcd_ep_t * ep) -+{ -+ dwc_otg_pcd_request_t *req = NULL; -+ struct dwc_iso_xreq_port *ereq = NULL; -+ struct dwc_iso_pkt_desc_port *ddesc_iso = NULL; -+ dwc_ep_t *dwcep = NULL; -+ int i; -+ -+ //DWC_DEBUG(); -+ dwcep = &ep->dwc_ep; -+ -+ /* Get the first pending request from the queue */ -+ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ if (!req) { -+ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); -+ return; -+ } -+ dwcep->xiso_active_xfers--; -+ dwcep->xiso_queued_xfers--; -+ /* Remove this request from the queue */ -+ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); -+ } else { -+ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); -+ return; -+ } -+ -+ ep->stopped = 1; -+ ereq = &req->ext_req; -+ ddesc_iso = ereq->per_io_frame_descs; -+ -+ if (dwcep->xiso_active_xfers < 0) { -+ DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num, -+ dwcep->xiso_active_xfers); -+ } -+ -+ /* Fill the Isoc descs of portable extended req from dma descriptors */ -+ for (i = 0; i < ereq->pio_pkt_count; i++) { -+ if (dwcep->is_in) { /* IN endpoints */ -+ ddesc_iso[i].actual_length = ddesc_iso[i].length - -+ dwcep->desc_addr[i].status.b_iso_in.txbytes; -+ ddesc_iso[i].status = -+ dwcep->desc_addr[i].status.b_iso_in.txsts; -+ } else { /* OUT endpoints */ -+ ddesc_iso[i].actual_length = ddesc_iso[i].length - -+ dwcep->desc_addr[i].status.b_iso_out.rxbytes; -+ ddesc_iso[i].status = -+ dwcep->desc_addr[i].status.b_iso_out.rxsts; -+ } -+ } -+ -+ DWC_SPINUNLOCK(ep->pcd->lock); -+ -+ /* Call the completion function in the non-portable logic */ -+ ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0, -+ &req->ext_req); -+ -+ DWC_SPINLOCK(ep->pcd->lock); -+ -+ /* Free the request - specific freeing needed for extended request object */ -+ dwc_pcd_xiso_ereq_free(ep, req); -+ -+ /* Start the next request */ -+ dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep); -+ -+ return; -+} -+ -+/** -+ * Create and initialize the Isoc pkt descriptors of the extended request. -+ * -+ */ -+static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req, -+ void *ereq_nonport, -+ int atomic_alloc) -+{ -+ struct dwc_iso_xreq_port *ereq = NULL; -+ struct dwc_iso_xreq_port *req_mapped = NULL; -+ struct dwc_iso_pkt_desc_port *ipds = NULL; /* To be created in this function */ -+ uint32_t pkt_count; -+ int i; -+ -+ ereq = &req->ext_req; -+ req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport; -+ pkt_count = req_mapped->pio_pkt_count; -+ -+ /* Create the isoc descs */ -+ if (atomic_alloc) { -+ ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count); -+ } else { -+ ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count); -+ } -+ -+ if (!ipds) { -+ DWC_ERROR("Failed to allocate isoc descriptors"); -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ /* Initialize the extended request fields */ -+ ereq->per_io_frame_descs = ipds; -+ ereq->error_count = 0; -+ ereq->pio_alloc_pkt_count = pkt_count; -+ ereq->pio_pkt_count = pkt_count; -+ ereq->tr_sub_flags = req_mapped->tr_sub_flags; -+ -+ /* Init the Isoc descriptors */ -+ for (i = 0; i < pkt_count; i++) { -+ ipds[i].length = req_mapped->per_io_frame_descs[i].length; -+ ipds[i].offset = req_mapped->per_io_frame_descs[i].offset; -+ ipds[i].status = req_mapped->per_io_frame_descs[i].status; /* 0 */ -+ ipds[i].actual_length = -+ req_mapped->per_io_frame_descs[i].actual_length; -+ } -+ -+ return 0; -+} -+ -+static void prn_ext_request(struct dwc_iso_xreq_port *ereq) -+{ -+ struct dwc_iso_pkt_desc_port *xfd = NULL; -+ int i; -+ -+ DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs); -+ DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags); -+ DWC_DEBUG("error_count=%d", ereq->error_count); -+ DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count); -+ DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count); -+ DWC_DEBUG("res=%d", ereq->res); -+ -+ for (i = 0; i < ereq->pio_pkt_count; i++) { -+ xfd = &ereq->per_io_frame_descs[0]; -+ DWC_DEBUG("FD #%d", i); -+ -+ DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length); -+ DWC_DEBUG("xfd->length=%d", xfd->length); -+ DWC_DEBUG("xfd->offset=%d", xfd->offset); -+ DWC_DEBUG("xfd->status=%d", xfd->status); -+ } -+} -+ -+/** -+ * -+ */ -+int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, -+ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, -+ int zero, void *req_handle, int atomic_alloc, -+ void *ereq_nonport) -+{ -+ dwc_otg_pcd_request_t *req = NULL; -+ dwc_otg_pcd_ep_t *ep; -+ dwc_irqflags_t flags; -+ int res; -+ -+ ep = get_ep_from_handle(pcd, ep_handle); -+ if (!ep) { -+ DWC_WARN("bad ep\n"); -+ return -DWC_E_INVALID; -+ } -+ -+ /* We support this extension only for DDMA mode */ -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -+ if (!GET_CORE_IF(pcd)->dma_desc_enable) -+ return -DWC_E_INVALID; -+ -+ /* Create a dwc_otg_pcd_request_t object */ -+ if (atomic_alloc) { -+ req = DWC_ALLOC_ATOMIC(sizeof(*req)); -+ } else { -+ req = DWC_ALLOC(sizeof(*req)); -+ } -+ -+ if (!req) { -+ return -DWC_E_NO_MEMORY; -+ } -+ -+ /* Create the Isoc descs for this request which shall be the exact match -+ * of the structure sent to us from the non-portable logic */ -+ res = -+ dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc); -+ if (res) { -+ DWC_WARN("Failed to init the Isoc descriptors"); -+ DWC_FREE(req); -+ return res; -+ } -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ -+ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); -+ req->buf = buf; -+ req->dma = dma_buf; -+ req->length = buflen; -+ req->sent_zlp = zero; -+ req->priv = req_handle; -+ -+ //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ ep->dwc_ep.dma_addr = dma_buf; -+ ep->dwc_ep.start_xfer_buff = buf; -+ ep->dwc_ep.xfer_buff = buf; -+ ep->dwc_ep.xfer_len = 0; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = buflen; -+ -+ /* Add this request to the tail */ -+ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); -+ ep->dwc_ep.xiso_queued_xfers++; -+ -+//DWC_DEBUG("CP_0"); -+//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags); -+//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport); -+//prn_ext_request(&req->ext_req); -+ -+ //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ -+ /* If the req->status == ASAP then check if there is any active transfer -+ * for this endpoint. If no active transfers, then get the first entry -+ * from the queue and start that transfer -+ */ -+ if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) { -+ res = dwc_otg_pcd_xiso_start_next_request(pcd, ep); -+ if (res) { -+ DWC_WARN("Failed to start the next Isoc transfer"); -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ DWC_FREE(req); -+ return res; -+ } -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ return 0; -+} -+ -+#endif -+/* END ifdef DWC_UTE_PER_IO ***************************************************/ - int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, - int zero, void *req_handle, int atomic_alloc) - { -- int prevented = 0; -- uint64_t flags; -+ dwc_irqflags_t flags; - dwc_otg_pcd_request_t *req; - dwc_otg_pcd_ep_t *ep; - uint32_t max_transfer; - - ep = get_ep_from_handle(pcd, ep_handle); -- if ((!ep->desc && ep->dwc_ep.num != 0)) { -+ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { - DWC_WARN("bad ep\n"); - return -DWC_E_INVALID; - } - - if (atomic_alloc) { -- req = dwc_alloc_atomic(sizeof(*req)); -+ req = DWC_ALLOC_ATOMIC(sizeof(*req)); - } else { -- req = dwc_alloc(sizeof(*req)); -+ req = DWC_ALLOC(sizeof(*req)); - } - - if (!req) { -@@ -1539,10 +2115,38 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - req->length = buflen; - req->sent_zlp = zero; - req->priv = req_handle; -- -+ req->dw_align_buf = NULL; -+ if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable -+ && !GET_CORE_IF(pcd)->dma_desc_enable) -+ req->dw_align_buf = DWC_DMA_ALLOC(buflen, -+ &req->dw_align_buf_dma); - DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); - - /* -+ * After adding request to the queue for IN ISOC wait for In Token Received -+ * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token -+ * Received when EP is disabled interrupt to obtain starting microframe -+ * (odd/even) start transfer -+ */ -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -+ { -+ if (req != 0) { -+ depctl_data_t depctl = {.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->diepctl)}; -+ ++pcd->request_pending; -+ -+ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); -+ if (ep->dwc_ep.is_in) -+ { -+ depctl.b.cnak = 1; -+ DWC_WRITE_REG32(&pcd->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->diepctl, depctl.d32); -+ } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -+ } -+ return 0; -+ } -+ -+ /* - * For EP0 IN without premature status, zlp is required? - */ - if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) { -@@ -1612,53 +2216,61 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - ep->dwc_ep.cfi_req_len = buflen; - pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, - ep, req); -- } else { -+ } else { - #endif - max_transfer = -- GET_CORE_IF(ep->pcd)->core_params-> -- max_transfer_size; -- -- /* Setup and start the Transfer */ -- ep->dwc_ep.dma_addr = dma_buf; -- ep->dwc_ep.start_xfer_buff = buf; -- ep->dwc_ep.xfer_buff = buf; -- ep->dwc_ep.xfer_len = 0; -- ep->dwc_ep.xfer_count = 0; -- ep->dwc_ep.sent_zlp = 0; -- ep->dwc_ep.total_len = buflen; -+ GET_CORE_IF(ep->pcd)-> -+ core_params->max_transfer_size; -+ -+ /* Setup and start the Transfer */ -+ if (req->dw_align_buf){ -+ if (ep->dwc_ep.is_in) -+ dwc_memcpy(req->dw_align_buf, buf, buflen); -+ ep->dwc_ep.dma_addr = req->dw_align_buf_dma; -+ ep->dwc_ep.start_xfer_buff = req->dw_align_buf; -+ ep->dwc_ep.xfer_buff = req->dw_align_buf; -+ } else { -+ ep->dwc_ep.dma_addr = dma_buf; -+ ep->dwc_ep.start_xfer_buff = buf; -+ ep->dwc_ep.xfer_buff = buf; -+ } -+ ep->dwc_ep.xfer_len = 0; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = buflen; - -- ep->dwc_ep.maxxfer = max_transfer; -- if (GET_CORE_IF(pcd)->dma_desc_enable) { -+ ep->dwc_ep.maxxfer = max_transfer; -+ if (GET_CORE_IF(pcd)->dma_desc_enable) { - uint32_t out_max_xfer = - DDMA_MAX_TRANSFER_SIZE - - (DDMA_MAX_TRANSFER_SIZE % 4); -- if (ep->dwc_ep.is_in) { -- if (ep->dwc_ep.maxxfer > -- DDMA_MAX_TRANSFER_SIZE) { -- ep->dwc_ep.maxxfer = -- DDMA_MAX_TRANSFER_SIZE; -- } -- } else { -+ if (ep->dwc_ep.is_in) { -+ if (ep->dwc_ep.maxxfer > -+ DDMA_MAX_TRANSFER_SIZE) { -+ ep->dwc_ep.maxxfer = -+ DDMA_MAX_TRANSFER_SIZE; -+ } -+ } else { - if (ep->dwc_ep.maxxfer > - out_max_xfer) { -- ep->dwc_ep.maxxfer = -- out_max_xfer; -+ ep->dwc_ep.maxxfer = -+ out_max_xfer; -+ } - } - } -- } -- if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { -- ep->dwc_ep.maxxfer -= -+ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { -+ ep->dwc_ep.maxxfer -= - (ep->dwc_ep.maxxfer % - ep->dwc_ep.maxpacket); -- } -+ } - -- if (zero) { -- if ((ep->dwc_ep.total_len % -+ if (zero) { -+ if ((ep->dwc_ep.total_len % - ep->dwc_ep.maxpacket == 0) - && (ep->dwc_ep.total_len != 0)) { -- ep->dwc_ep.sent_zlp = 1; -+ ep->dwc_ep.sent_zlp = 1; -+ } - } -- } - #ifdef DWC_UTE_CFI - } - #endif -@@ -1667,7 +2279,7 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - } - } - -- if ((req != 0) || prevented) { -+ if (req != 0) { - ++pcd->request_pending; - DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); - if (ep->dwc_ep.is_in && ep->stopped -@@ -1676,32 +2288,32 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - diepmsk_data_t diepmsk = {.d32 = 0 }; - diepmsk.b.intktxfemp = 1; - if (GET_CORE_IF(pcd)->multiproc_int_enable) { -- dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> - dev_global_regs-> - diepeachintmsk[ep->dwc_ep.num], - 0, diepmsk.d32); - } else { -- dwc_modify_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> - dev_global_regs->diepmsk, 0, - diepmsk.d32); - } - - } - } -- - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); - - return 0; - } -+ - int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, - void *req_handle) - { -- uint64_t flags; -+ dwc_irqflags_t flags; - dwc_otg_pcd_request_t *req; - dwc_otg_pcd_ep_t *ep; - - ep = get_ep_from_handle(pcd, ep_handle); -- if (!ep->desc && ep->dwc_ep.num != 0) { -+ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { - DWC_WARN("bad argument\n"); - return -DWC_E_INVALID; - } -@@ -1723,7 +2335,7 @@ int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, - if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) { - dwc_otg_request_done(ep, req, -DWC_E_RESTART); - } else { -- req = 0; -+ req = NULL; - } - - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -@@ -1744,7 +2356,7 @@ int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, - int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle) - { - dwc_otg_pcd_ep_t *ep; -- uint64_t flags; -+ dwc_irqflags_t flags; - int retval = 0; - - ep = get_ep_from_handle(pcd, ep_handle); -@@ -1767,11 +2379,10 @@ int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle) - fifosize_data_t txfifosize; - - txfifosize.d32 = -- dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs-> -- dptxfsiz_dieptxf[ep->dwc_ep. -- tx_fifo_num]); -+ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs-> -+ dtxfsiz[ep->dwc_ep.tx_fifo_num]); - txstatus.d32 = -- dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> - in_ep_regs[ep->dwc_ep.num]->dtxfsts); - - if (txstatus.b.txfspcavail < txfifosize.b.depth) { -@@ -1804,12 +2415,12 @@ int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle) - int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value) - { - dwc_otg_pcd_ep_t *ep; -- uint64_t flags; -+ dwc_irqflags_t flags; - int retval = 0; - - ep = get_ep_from_handle(pcd, ep_handle); - -- if ((!ep->desc && ep != &pcd->ep0) || -+ if (!ep || (!ep->desc && ep != &pcd->ep0) || - (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { - DWC_WARN("%s, bad ep\n", __func__); - return -DWC_E_INVALID; -@@ -1828,11 +2439,10 @@ int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value) - fifosize_data_t txfifosize; - - txfifosize.d32 = -- dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs-> -- dptxfsiz_dieptxf[ep->dwc_ep. -- tx_fifo_num]); -+ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs-> -+ dtxfsiz[ep->dwc_ep.tx_fifo_num]); - txstatus.d32 = -- dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> - in_ep_regs[ep->dwc_ep.num]->dtxfsts); - - if (txstatus.b.txfspcavail < txfifosize.b.depth) { -@@ -1875,20 +2485,50 @@ void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set) - dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); - dsts_data_t dsts; - -- dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - if (!dsts.b.suspsts) { - DWC_WARN("Remote wakeup while is not in suspend state\n"); - } - /* Check if DEVICE_REMOTE_WAKEUP feature enabled */ - if (pcd->remote_wakeup_enable) { - if (set) { -+ -+ if (core_if->adp_enable) { -+ gpwrdn_data_t gpwrdn; -+ -+ dwc_otg_adp_probe_stop(core_if); -+ -+ /* Mask SRP detected interrupt from Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.srp_det_msk = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, gpwrdn.d32, 0); -+ -+ /* Disable Power Down Logic */ -+ gpwrdn.d32 = 0; -+ gpwrdn.b.pmuactv = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, gpwrdn.d32, 0); -+ -+ /* -+ * Initialize the Core for Device mode. -+ */ -+ core_if->op_state = B_PERIPHERAL; -+ dwc_otg_core_init(core_if); -+ dwc_otg_enable_global_interrupts(core_if); -+ cil_pcd_start(core_if); -+ -+ dwc_otg_initiate_srp(core_if); -+ } -+ - dctl.b.rmtwkupsig = 1; -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -- dctl, 0, dctl.d32); -+ DWC_MODIFY_REG32(&core_if->dev_if-> -+ dev_global_regs->dctl, 0, dctl.d32); - DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); -+ - dwc_mdelay(2); -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -- dctl, dctl.d32, 0); -+ DWC_MODIFY_REG32(&core_if->dev_if-> -+ dev_global_regs->dctl, dctl.d32, 0); - DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); - } - } else { -@@ -1905,7 +2545,7 @@ void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set) - glpmcfg_data_t lpmcfg; - dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); - -- lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - - /* Check if we are in L1 state */ - if (!lpmcfg.b.prt_sleep_sts) { -@@ -1925,10 +2565,10 @@ void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set) - return; - } - -- lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); -+ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); - lpmcfg.b.en_utmi_sleep = 0; - lpmcfg.b.hird_thres &= (~(1 << 4)); -- dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); - - if (set) { - dctl_data_t dctl = {.d32 = 0 }; -@@ -1936,7 +2576,7 @@ void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set) - /* Set RmtWkUpSig bit to start remote wakup signaling. - * Hardware will automatically clear this bit. - */ -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, - 0, dctl.d32); - DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); - } -@@ -1950,7 +2590,9 @@ void dwc_otg_pcd_rem_wkup_from_sleep(dwc_otg_pcd_t * pcd, int set) - void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set) - { - dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dwc_irqflags_t flags; - if (dwc_otg_is_device_mode(core_if)) { -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); - #ifdef CONFIG_USB_DWC_OTG_LPM - if (core_if->lx_state == DWC_OTG_L1) { - dwc_otg_pcd_rem_wkup_from_sleep(pcd, set); -@@ -1960,17 +2602,34 @@ void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set) - #ifdef CONFIG_USB_DWC_OTG_LPM - } - #endif -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); - } - return; - } - -+void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs) -+{ -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dctl_data_t dctl = { 0 }; -+ -+ if (dwc_otg_is_device_mode(core_if)) { -+ dctl.b.sftdiscon = 1; -+ DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs); -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ dwc_udelay(no_of_usecs); -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0); -+ -+ } else{ -+ DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n"); -+ } -+ return; -+ -+} -+ - int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) - { - dsts_data_t dsts; - gotgctl_data_t gotgctl; -- uint64_t flags; -- -- DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); - - /* - * This function starts the Protocol if no session is in progress. If -@@ -1980,13 +2639,13 @@ int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) - - /* Check if valid session */ - gotgctl.d32 = -- dwc_read_reg32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); -+ DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); - if (gotgctl.b.bsesvld) { - /* Check if suspend state */ - dsts.d32 = -- dwc_read_reg32(& -- (GET_CORE_IF(pcd)->dev_if->dev_global_regs-> -- dsts)); -+ DWC_READ_REG32(& -+ (GET_CORE_IF(pcd)->dev_if-> -+ dev_global_regs->dsts)); - if (dsts.b.suspsts) { - dwc_otg_pcd_remote_wakeup(pcd, 1); - } -@@ -1994,7 +2653,6 @@ int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) - dwc_otg_pcd_initiate_srp(pcd); - } - -- DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); - return 0; - - } -@@ -2005,33 +2663,12 @@ int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) - * - * @param pcd the pcd structure. - */ --void dwc_otg_pcd_start_srp_timer(dwc_otg_pcd_t * pcd) --{ -- GET_CORE_IF(pcd)->srp_timer_started = 1; -- DWC_TIMER_SCHEDULE(pcd->srp_timer, 6000 /* 6 secs */ ); --} -- - void dwc_otg_pcd_initiate_srp(dwc_otg_pcd_t * pcd) - { -- uint32_t *addr = -- (uint32_t *) & (GET_CORE_IF(pcd)->core_global_regs->gotgctl); -- gotgctl_data_t mem; -- gotgctl_data_t val; -- -- val.d32 = dwc_read_reg32(addr); -- if (val.b.sesreq) { -- DWC_ERROR("Session Request Already active!\n"); -- return; -- } -- -- DWC_INFO("Session Request Initated\n"); //NOTICE -- mem.d32 = dwc_read_reg32(addr); -- mem.b.sesreq = 1; -- dwc_write_reg32(addr, mem.d32); -- -- /* Start the SRP timer */ -- dwc_otg_pcd_start_srp_timer(pcd); -- return; -+ dwc_irqflags_t flags; -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); -+ dwc_otg_initiate_srp(GET_CORE_IF(pcd)); -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); - } - - int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd) -@@ -2064,4 +2701,4 @@ int dwc_otg_pcd_get_rmwkup_enable(dwc_otg_pcd_t * pcd) - return pcd->remote_wakeup_enable; - } - --#endif /* DWC_HOST_ONLY */ -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -index d38e169..4b2dde9 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ -- * $Revision: #39 $ -- * $Date: 2008/12/16 $ -- * $Change: 1153731 $ -+ * $Revision: #46 $ -+ * $Date: 2011/10/20 $ -+ * $Change: 1870124 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -34,6 +34,7 @@ - #if !defined(__DWC_PCD_H__) - #define __DWC_PCD_H__ - -+#include "dwc_otg_os_dep.h" - #include "usb.h" - #include "dwc_otg_cil.h" - #include "dwc_otg_pcd_if.h" -@@ -46,7 +47,7 @@ - * the Perpherial Contoller Driver (PCD). - * - * The Peripheral Controller Driver (PCD) for Linux will implement the -- * Gadget API, so that the existing Gadget drivers can be used. For -+ * Gadget API, so that the existing Gadget drivers can be used. For - * the Mass Storage Function driver the File-backed USB Storage Gadget - * (FBS) driver will be used. The FBS driver supports the - * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only -@@ -54,12 +55,12 @@ - * - */ - -+/** Invalid DMA Address */ -+#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) -+ - /** Max Transfer size for any EP */ - #define DDMA_MAX_TRANSFER_SIZE 65535 - --/** Max DMA Descriptor count for any EP */ --#define MAX_DMA_DESC_CNT 64 -- - /** - * Get the pointer to the core_if from the pcd pointer. - */ -@@ -86,6 +87,42 @@ - */ - typedef struct usb_iso_request dwc_otg_pcd_iso_request_t; - -+#ifdef DWC_UTE_PER_IO -+ -+/** -+ * This shall be the exact analogy of the same type structure defined in the -+ * usb_gadget.h. Each descriptor contains -+ */ -+struct dwc_iso_pkt_desc_port { -+ uint32_t offset; -+ uint32_t length; /* expected length */ -+ uint32_t actual_length; -+ uint32_t status; -+}; -+ -+struct dwc_iso_xreq_port { -+ /** transfer/submission flag */ -+ uint32_t tr_sub_flags; -+ /** Start the request ASAP */ -+#define DWC_EREQ_TF_ASAP 0x00000002 -+ /** Just enqueue the request w/o initiating a transfer */ -+#define DWC_EREQ_TF_ENQUEUE 0x00000004 -+ -+ /** -+ * count of ISO packets attached to this request - shall -+ * not exceed the pio_alloc_pkt_count -+ */ -+ uint32_t pio_pkt_count; -+ /** count of ISO packets allocated for this request */ -+ uint32_t pio_alloc_pkt_count; -+ /** number of ISO packet errors */ -+ uint32_t error_count; -+ /** reserved for future extension */ -+ uint32_t res; -+ /** Will be allocated and freed in the UTE gadget and based on the CFC value */ -+ struct dwc_iso_pkt_desc_port *per_io_frame_descs; -+}; -+#endif - /** DWC_otg request structure. - * This structure is a list of requests. - */ -@@ -96,8 +133,18 @@ - uint32_t length; - uint32_t actual; - unsigned sent_zlp:1; -+ /** -+ * Used instead of original buffer if -+ * it(physical address) is not dword-aligned. -+ **/ -+ uint8_t *dw_align_buf; -+ dwc_dma_t dw_align_buf_dma; - - DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry; -+#ifdef DWC_UTE_PER_IO -+ struct dwc_iso_xreq_port ext_req; -+ //void *priv_ereq_nport; /* */ -+#endif - } dwc_otg_pcd_request_t; - - DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request); -@@ -136,6 +183,8 @@ - */ - struct dwc_otg_pcd { - const struct dwc_otg_pcd_function_ops *fops; -+ /** The DWC otg device pointer */ -+ struct dwc_otg_device *otg_dev; - /** Core Interface */ - dwc_otg_core_if_t *core_if; - /** State of EP0 */ -@@ -180,9 +229,6 @@ struct dwc_otg_pcd { - /** number of valid EPs in the above array. */ - // unsigned num_eps : 4; - dwc_spinlock_t *lock; -- /** Timer for SRP. If it expires before SRP is successful -- * clear the SRP. */ -- dwc_timer_t *srp_timer; - - /** Tasklet to defer starting of TEST mode transmissions until - * Status Phase has been completed. -@@ -195,7 +241,7 @@ struct dwc_otg_pcd { - /** The test mode to enter when the tasklet is executed. */ - unsigned test_mode; - /** The cfi_api structure that implements most of the CFI API -- * and OTG specific core configuration functionality -+ * and OTG specific core configuration functionality - */ - #ifdef DWC_UTE_CFI - struct cfiobject *cfi; -@@ -213,4 +259,4 @@ void dwc_otg_iso_buffer_done(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep, - - extern void do_test_mode(void *data); - #endif --#endif /* DWC_HOST_ONLY */ -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -index 66e9db7..c8d2e0e 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ -- * $Revision: #6 $ -- * $Date: 2009/04/03 $ -- * $Change: 1225059 $ -+ * $Revision: #11 $ -+ * $Date: 2011/10/26 $ -+ * $Change: 1873028 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -35,10 +35,10 @@ - #if !defined(__DWC_PCD_IF_H__) - #define __DWC_PCD_IF_H__ - --#include "dwc_os.h" -+//#include "dwc_os.h" - #include "dwc_otg_core_if.h" - --/** @file -+/** @file - * This file defines DWC_OTG PCD Core API. - */ - -@@ -103,6 +103,15 @@ typedef int (*dwc_isoc_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, - - typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes); - -+/** -+ * -+ * @param ep_handle Void pointer to the usb_ep structure -+ * @param ereq_port Pointer to the extended request structure created in the -+ * portable part. -+ */ -+typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle, int32_t status, -+ void *ereq_port); - /** Function Driver Ops Data Structure */ - struct dwc_otg_pcd_function_ops { - dwc_connect_cb_t connect; -@@ -116,6 +125,9 @@ struct dwc_otg_pcd_function_ops { - dwc_reset_cb_t reset; - dwc_hnp_params_changed_cb_t hnp_changed; - cfi_setup_cb_t cfi_setup; -+#ifdef DWC_UTE_PER_IO -+ xiso_completion_cb_t xisoc_complete; -+#endif - }; - /** @} */ - -@@ -156,15 +168,15 @@ extern void dwc_otg_pcd_start(dwc_otg_pcd_t * pcd, - * - * @param pcd The PCD - * @param ep_desc Endpoint descriptor -- * @param ep_handle Handle on endpoint, that will be used to identify endpoint. -+ * @param usb_ep Handle on endpoint, that will be used to identify endpoint. - */ - extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, -- const uint8_t * ep_desc, void *ep_handle); -+ const uint8_t * ep_desc, void *usb_ep); - - /** Disable the endpoint referenced by ep_handle. - * - * Returns -DWC_E_INVALID if invalid parameters were passed. -- * Returns -DWC_E_SHUTDOWN if any other error ocurred. -+ * Returns -DWC_E_SHUTDOWN if any other error occurred. - * Returns 0 on success. */ - extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle); - -@@ -190,6 +202,19 @@ extern int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - uint8_t * buf, dwc_dma_t dma_buf, - uint32_t buflen, int zero, void *req_handle, - int atomic_alloc); -+#ifdef DWC_UTE_PER_IO -+/** -+ * -+ * @param ereq_nonport Pointer to the extended request part of the -+ * usb_request structure defined in usb_gadget.h file. -+ */ -+extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, -+ uint8_t * buf, dwc_dma_t dma_buf, -+ uint32_t buflen, int zero, -+ void *req_handle, int atomic_alloc, -+ void *ereq_nonport); -+ -+#endif - - /** De-queue the specified data transfer that has not yet completed. - * -@@ -307,6 +332,8 @@ extern int dwc_otg_pcd_get_iso_packet_count(dwc_otg_pcd_t * pcd, - /** Starts remote wakeup signaling. */ - extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set); - -+/** Starts micorsecond soft disconnect. */ -+extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs); - /** This function returns whether device is dualspeed.*/ - extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd); - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -index f89e878..4a6520f 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ -- * $Revision: #93 $ -- * $Date: 2009/04/02 $ -- * $Change: 1224216 $ -+ * $Revision: #113 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871160 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -38,6 +38,9 @@ - #include "dwc_otg_cfi.h" - #endif - -+#ifdef DWC_UTE_PER_IO -+extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep); -+#endif - //#define PRINT_CFI_DMA_DESCS - - #define DEBUG_EP0 -@@ -108,6 +111,40 @@ static inline void print_ep0_state(dwc_otg_pcd_t * pcd) - #endif - } - -+/** -+ * This function calculate the size of the payload in the memory -+ * for out endpoints and prints size for debug purposes(used in -+ * 2.93a DevOutNak feature). -+ */ -+static inline void print_memory_payload(dwc_otg_pcd_t * pcd, dwc_ep_t * ep) -+{ -+#ifdef DEBUG -+ deptsiz_data_t deptsiz_init = {.d32 = 0 }; -+ deptsiz_data_t deptsiz_updt = {.d32 = 0 }; -+ int pack_num; -+ unsigned payload; -+ -+ deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num]; -+ deptsiz_updt.d32 = -+ DWC_READ_REG32(&pcd->core_if->dev_if-> -+ out_ep_regs[ep->num]->doeptsiz); -+ /* Payload will be */ -+ payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize; -+ /* Packet count is decremented every time a packet -+ * is written to the RxFIFO not in to the external memory -+ * So, if payload == 0, then it means no packet was sent to ext memory*/ -+ pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt); -+ DWC_DEBUGPL(DBG_PCDV, -+ "Payload for EP%d-%s\n", -+ ep->num, (ep->is_in ? "IN" : "OUT")); -+ DWC_DEBUGPL(DBG_PCDV, -+ "Number of transfered bytes = 0x%08x\n", payload); -+ DWC_DEBUGPL(DBG_PCDV, -+ "Number of transfered packets = %d\n", pack_num); -+#endif -+} -+ -+ - #ifdef DWC_UTE_CFI - static inline void print_desc(struct dwc_otg_dma_desc *ddesc, - const uint8_t * epname, int descnum) -@@ -200,48 +237,57 @@ void start_next_request(dwc_otg_pcd_ep_t * ep) - pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req); - } else { - #endif -- /* Setup and start the Transfer */ -- ep->dwc_ep.dma_addr = req->dma; -- ep->dwc_ep.start_xfer_buff = req->buf; -- ep->dwc_ep.xfer_buff = req->buf; -- ep->dwc_ep.sent_zlp = 0; -- ep->dwc_ep.total_len = req->length; -- ep->dwc_ep.xfer_len = 0; -- ep->dwc_ep.xfer_count = 0; -+ /* Setup and start the Transfer */ -+ if (req->dw_align_buf) { -+ ep->dwc_ep.dma_addr = req->dw_align_buf_dma; -+ ep->dwc_ep.start_xfer_buff = req->dw_align_buf; -+ ep->dwc_ep.xfer_buff = req->dw_align_buf; -+ } else { -+ ep->dwc_ep.dma_addr = req->dma; -+ ep->dwc_ep.start_xfer_buff = req->buf; -+ ep->dwc_ep.xfer_buff = req->buf; -+ } -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = req->length; -+ ep->dwc_ep.xfer_len = 0; -+ ep->dwc_ep.xfer_count = 0; - -- ep->dwc_ep.maxxfer = max_transfer; -- if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { -- uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE -- - (DDMA_MAX_TRANSFER_SIZE % 4); -- if (ep->dwc_ep.is_in) { -+ ep->dwc_ep.maxxfer = max_transfer; -+ if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { -+ uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE -+ - (DDMA_MAX_TRANSFER_SIZE % 4); -+ if (ep->dwc_ep.is_in) { - if (ep->dwc_ep.maxxfer > - DDMA_MAX_TRANSFER_SIZE) { -- ep->dwc_ep.maxxfer = -- DDMA_MAX_TRANSFER_SIZE; -- } -- } else { -- if (ep->dwc_ep.maxxfer > out_max_xfer) { -+ ep->dwc_ep.maxxfer = -+ DDMA_MAX_TRANSFER_SIZE; -+ } -+ } else { -+ if (ep->dwc_ep.maxxfer > out_max_xfer) { - ep->dwc_ep.maxxfer = - out_max_xfer; -+ } - } - } -- } -- if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { -- ep->dwc_ep.maxxfer -= -- (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket); -- } -- if (req->sent_zlp) { -+ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { -+ ep->dwc_ep.maxxfer -= -+ (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket); -+ } -+ if (req->sent_zlp) { - if ((ep->dwc_ep.total_len % - ep->dwc_ep.maxpacket == 0) - && (ep->dwc_ep.total_len != 0)) { -- ep->dwc_ep.sent_zlp = 1; -- } -+ ep->dwc_ep.sent_zlp = 1; -+ } - -- } -+ } - #ifdef DWC_UTE_CFI - } - #endif - dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep); -+ } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { -+ DWC_PRINTF("There are no more ISOC requests \n"); -+ ep->dwc_ep.frame_num = 0xFFFFFFFF; - } - } - -@@ -260,7 +306,7 @@ int32_t dwc_otg_pcd_handle_sof_intr(dwc_otg_pcd_t * pcd) - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.sofintr = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - - return 1; - } -@@ -297,10 +343,10 @@ int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd) - //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); - /* Disable the Rx Status Queue Level interrupt */ - gintmask.b.rxstsqlvl = 1; -- dwc_modify_reg32(&global_regs->gintmsk, gintmask.d32, 0); -+ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmask.d32, 0); - - /* Get the Status from the top of the FIFO */ -- status.d32 = dwc_read_reg32(&global_regs->grxstsp); -+ status.d32 = DWC_READ_REG32(&global_regs->grxstsp); - - DWC_DEBUGPL(DBG_PCD, "EP:%d BCnt:%d DPID:%s " - "pktsts:%x Frame:%d(0x%0x)\n", -@@ -353,11 +399,11 @@ int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(dwc_otg_pcd_t * pcd) - } - - /* Enable the Rx Status Queue Level interrupt */ -- dwc_modify_reg32(&global_regs->gintmsk, 0, gintmask.d32); -+ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmask.d32); - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.rxstsqlvl = 1; -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__); - return 1; -@@ -393,7 +439,7 @@ static inline int get_ep_of_last_in_token(dwc_otg_core_if_t * core_if) - - /* Read the DTKNQ Registers */ - for (i = 0; i < DTKNQ_REG_CNT; i++) { -- in_tkn_epnums[i] = dwc_read_reg32(addr); -+ in_tkn_epnums[i] = DWC_READ_REG32(addr); - DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, - in_tkn_epnums[i]); - if (addr == &dev_global_regs->dvbusdis) { -@@ -477,7 +523,7 @@ int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd) - - /* While there is space in the queue and space in the FIFO and - * More data to tranfer, Write packets to the Tx FIFO */ -- txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); - DWC_DEBUGPL(DBG_PCDV, "b4 GNPTXSTS=0x%08x\n", txstatus.d32); - - while (txstatus.b.nptxqspcavail > 0 && -@@ -492,17 +538,17 @@ int32_t dwc_otg_pcd_handle_np_tx_fifo_empty_intr(dwc_otg_pcd_t * pcd) - } - - dwords = (len + 3) / 4; -- txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts); -+ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); - DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32); - } - - DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", -- dwc_read_reg32(&global_regs->gnptxsts)); -+ DWC_READ_REG32(&global_regs->gnptxsts)); - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.nptxfempty = 1; -- dwc_write_reg32(&global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); - - return 1; - } -@@ -538,7 +584,7 @@ static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum) - - /* While there is space in the queue and space in the FIFO and - * More data to tranfer, Write packets to the Tx FIFO */ -- txstatus.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts); -+ txstatus.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); - DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); - - while (txstatus.b.txfspcavail > dwords && -@@ -554,13 +600,13 @@ static int32_t write_empty_tx_fifo(dwc_otg_pcd_t * pcd, uint32_t epnum) - - dwords = (len + 3) / 4; - txstatus.d32 = -- dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts); -+ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); - DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, - txstatus.d32); - } - - DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, -- dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts)); -+ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); - - return 1; - } -@@ -586,6 +632,7 @@ void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd) - /* don't disconnect drivers more than once */ - if (pcd->ep0state == EP0_DISCONNECT) { - DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__); -+ DWC_SPINUNLOCK(pcd->lock); - return; - } - pcd->ep0state = EP0_DISCONNECT; -@@ -595,7 +642,7 @@ void dwc_otg_pcd_stop(dwc_otg_pcd_t * pcd) - - /* Disable the NP Tx Fifo Empty Interrupt. */ - intr_mask.b.nptxfempty = 1; -- dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0); - - /* Flush the FIFOs */ -@@ -636,13 +683,13 @@ int32_t dwc_otg_pcd_handle_i2c_intr(dwc_otg_pcd_t * pcd) - - DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr"); - intr_mask.b.i2cintr = 1; -- dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0); - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.i2cintr = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - return 1; - } -@@ -656,10 +703,11 @@ int32_t dwc_otg_pcd_handle_early_suspend_intr(dwc_otg_pcd_t * pcd) - #if defined(VERBOSE) - DWC_PRINTF("Early Suspend Detected\n"); - #endif -+ - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.erlysuspend = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - return 1; - } -@@ -691,7 +739,7 @@ static inline void ep0_out_start(dwc_otg_core_if_t * core_if, - - #ifdef VERBOSE - DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__, -- dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); -+ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); - #endif - - doeptsize0.b.supcnt = 3; -@@ -701,11 +749,11 @@ static inline void ep0_out_start(dwc_otg_core_if_t * core_if, - if (core_if->dma_enable) { - if (!core_if->dma_desc_enable) { - /** put here as for Hermes mode deptisz register should not be written */ -- dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz, -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, - doeptsize0.d32); - - /** @todo dma needs to handle multiple setup packets (up to 3) */ -- dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, - pcd->setup_pkt_dma_handle); - } else { - dev_if->setup_desc_index = -@@ -719,35 +767,37 @@ static inline void ep0_out_start(dwc_otg_core_if_t * core_if, - dma_desc->status.b.ioc = 1; - dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket; - dma_desc->buf = pcd->setup_pkt_dma_handle; -+ dma_desc->status.b.sts = 0; - dma_desc->status.b.bs = BS_HOST_READY; - - /** DOEPDMA0 Register write */ -- dwc_write_reg32(&dev_if->out_ep_regs[0]->doepdma, -- dev_if->dma_setup_desc_addr[dev_if-> -- setup_desc_index]); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, -+ dev_if-> -+ dma_setup_desc_addr -+ [dev_if->setup_desc_index]); - } - - } else { - /** put here as for Hermes mode deptisz register should not be written */ -- dwc_write_reg32(&dev_if->out_ep_regs[0]->doeptsiz, -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, - doeptsize0.d32); - } - - /** DOEPCTL0 Register write */ - doepctl.b.epena = 1; - doepctl.b.cnak = 1; -- dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); - - #ifdef VERBOSE - DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", -- dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); -+ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); - DWC_DEBUGPL(DBG_PCDV, "diepctl0=%0x\n", -- dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl)); -+ DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); - #endif - } - - /** -- * This interrupt occurs when a USB Reset is detected. When the USB -+ * This interrupt occurs when a USB Reset is detected. When the USB - * Reset Interrupt occurs the device state is set to DEFAULT and the - * EP0 state is set to IDLE. - * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) -@@ -774,6 +824,7 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); - dwc_otg_dev_if_t *dev_if = core_if->dev_if; - depctl_data_t doepctl = {.d32 = 0 }; -+ depctl_data_t diepctl = {.d32 = 0 }; - daint_data_t daintmsk = {.d32 = 0 }; - doepmsk_data_t doepmsk = {.d32 = 0 }; - diepmsk_data_t diepmsk = {.d32 = 0 }; -@@ -784,17 +835,17 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - gintsts_data_t gintsts; - pcgcctl_data_t power = {.d32 = 0 }; - -- power.d32 = dwc_read_reg32(core_if->pcgcctl); -+ power.d32 = DWC_READ_REG32(core_if->pcgcctl); - if (power.b.stoppclk) { - power.d32 = 0; - power.b.stoppclk = 1; -- dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); -+ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); - - power.b.pwrclmp = 1; -- dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); -+ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); - - power.b.rstpdwnmodule = 1; -- dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); -+ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); - } - - core_if->lx_state = DWC_OTG_L0; -@@ -810,31 +861,54 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - dwc_ep->next_frame = 0xffffffff; - } - } --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ - - /* reset the HNP settings */ - dwc_otg_pcd_update_otg(pcd, 1); - - /* Clear the Remote Wakeup Signalling */ - dctl.b.rmtwkupsig = 1; -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); - - /* Set NAK for all OUT EPs */ - doepctl.b.snak = 1; - for (i = 0; i <= dev_if->num_out_eps; i++) { -- dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); - } - - /* Flush the NP Tx FIFO */ - dwc_otg_flush_tx_fifo(core_if, 0x10); - /* Flush the Learning Queue */ - resetctl.b.intknqflsh = 1; -- dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); -+ -+ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { -+ core_if->start_predict = 0; -+ for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) { -+ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active -+ } -+ core_if->nextep_seq[0] = 0; -+ core_if->first_in_nextep_seq = 0; -+ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); -+ diepctl.b.nextep = 0; -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); -+ -+ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ -+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); -+ dcfg.b.epmscnt = 2; -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ -+ DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ __func__, core_if->first_in_nextep_seq); -+ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -+ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); -+ } -+ } - - if (core_if->multiproc_int_enable) { - daintmsk.b.inep0 = 1; - daintmsk.b.outep0 = 1; -- dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk, -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, - daintmsk.d32); - - doepmsk.b.setup = 1; -@@ -850,33 +924,36 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - doepmsk.b.babble = 1; - doepmsk.b.nyet = 1; - -- if(core_if->dma_enable) { -+ if (core_if->dma_enable) { - doepmsk.b.nak = 1; - } - */ -- dwc_write_reg32(&dev_if->dev_global_regs->doepeachintmsk[0], -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepeachintmsk[0], - doepmsk.d32); - - diepmsk.b.xfercompl = 1; - diepmsk.b.timeout = 1; - diepmsk.b.epdisabled = 1; - diepmsk.b.ahberr = 1; -- diepmsk.b.intknepmis = 1; -+ diepmsk.b.intknepmis = 1; -+ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) -+ diepmsk.b.intknepmis = 0; - -- if (core_if->dma_desc_enable) { -+/* if (core_if->dma_desc_enable) { - diepmsk.b.bna = 1; - } -+*/ - /* -- if(core_if->dma_enable) { -+ if (core_if->dma_enable) { - diepmsk.b.nak = 1; - } - */ -- dwc_write_reg32(&dev_if->dev_global_regs->diepeachintmsk[0], -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepeachintmsk[0], - diepmsk.d32); - } else { - daintmsk.b.inep0 = 1; - daintmsk.b.outep0 = 1; -- dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, - daintmsk.d32); - - doepmsk.b.setup = 1; -@@ -888,25 +965,27 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - doepmsk.b.stsphsercvd = 1; - doepmsk.b.bna = 1; - } -- dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); - - diepmsk.b.xfercompl = 1; - diepmsk.b.timeout = 1; - diepmsk.b.epdisabled = 1; - diepmsk.b.ahberr = 1; -- diepmsk.b.intknepmis = 1; -- -+ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) -+ diepmsk.b.intknepmis = 0; -+/* - if (core_if->dma_desc_enable) { - diepmsk.b.bna = 1; - } -+*/ - -- dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); - } - - /* Reset Device Address */ -- dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg); -+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); - dcfg.b.devaddr = 0; -- dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); - - /* setup EP0 to receive SETUP packets */ - ep0_out_start(core_if, pcd); -@@ -914,7 +993,7 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.usbreset = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - - return 1; - } -@@ -929,7 +1008,7 @@ static int get_device_speed(dwc_otg_core_if_t * core_if) - { - dsts_data_t dsts; - int speed = 0; -- dsts.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); -+ dsts.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); - - switch (dsts.b.enumspd) { - case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: -@@ -965,7 +1044,7 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) - DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); - - if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { -- utmi16b = 6; -+ utmi16b = 6; //vahrama old value was 6; - utmi8b = 9; - } else { - utmi16b = 4; -@@ -991,7 +1070,7 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) - pcd->fops->connect(pcd, speed); - - /* Set USB turnaround time based on device speed and PHY interface. */ -- gusbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); -+ gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); - if (speed == USB_SPEED_HIGH) { - if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == - DWC_HWCFG2_HS_PHY_TYPE_ULPI) { -@@ -1003,11 +1082,11 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) - /* UTMI+ interface */ - if (GET_CORE_IF(pcd)->hwcfg4.b.utmi_phy_data_width == 0) { - gusbcfg.b.usbtrdtim = utmi8b; -- } else if (GET_CORE_IF(pcd)->hwcfg4.b. -- utmi_phy_data_width == 1) { -+ } else if (GET_CORE_IF(pcd)->hwcfg4. -+ b.utmi_phy_data_width == 1) { - gusbcfg.b.usbtrdtim = utmi16b; -- } else if (GET_CORE_IF(pcd)->core_params-> -- phy_utmi_width == 8) { -+ } else if (GET_CORE_IF(pcd)-> -+ core_params->phy_utmi_width == 8) { - gusbcfg.b.usbtrdtim = utmi8b; - } else { - gusbcfg.b.usbtrdtim = utmi16b; -@@ -1021,8 +1100,8 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) - gusbcfg.b.usbtrdtim = 9; - } else { - /* UTMI+ interface */ -- if (GET_CORE_IF(pcd)->core_params-> -- phy_utmi_width == 16) { -+ if (GET_CORE_IF(pcd)-> -+ core_params->phy_utmi_width == 16) { - gusbcfg.b.usbtrdtim = utmi16b; - } else { - gusbcfg.b.usbtrdtim = utmi8b; -@@ -1033,12 +1112,12 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) - /* Full or low speed */ - gusbcfg.b.usbtrdtim = 9; - } -- dwc_write_reg32(&global_regs->gusbcfg, gusbcfg.d32); -+ DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32); - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.enumdone = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - return 1; - } -@@ -1053,17 +1132,17 @@ int32_t dwc_otg_pcd_handle_isoc_out_packet_dropped_intr(dwc_otg_pcd_t * pcd) - gintmsk_data_t intr_mask = {.d32 = 0 }; - gintsts_data_t gintsts; - -- DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -- "ISOC Out Dropped"); -+ DWC_WARN("INTERRUPT Handler not implemented for %s\n", -+ "ISOC Out Dropped"); - - intr_mask.b.isooutdrop = 1; -- dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0); - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.isooutdrop = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - - return 1; -@@ -1081,13 +1160,13 @@ int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd) - DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP"); - - intr_mask.b.eopframe = 1; -- dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0); - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.eopframe = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - - return 1; -@@ -1098,24 +1177,84 @@ int32_t dwc_otg_pcd_handle_end_periodic_frame_intr(dwc_otg_pcd_t * pcd) - * non-periodic Tx FIFO does not match EP of the IN Token received. - * - * The "Device IN Token Queue" Registers are read to determine the -- * order the IN Tokens have been received. The non-periodic Tx FIFO -+ * order the IN Tokens have been received. The non-periodic Tx FIFO - * is flushed, so it can be reloaded in the order seen in the IN Token - * Queue. - */ --int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_core_if_t * core_if) -+int32_t dwc_otg_pcd_handle_ep_mismatch_intr(dwc_otg_pcd_t * pcd) - { - gintsts_data_t gintsts; -- DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ dctl_data_t dctl; -+ gintmsk_data_t intr_mask = {.d32 = 0 }; - -+ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) { -+ core_if->start_predict = 1; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); -+ -+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); -+ if (!gintsts.b.ginnakeff) { -+ /* Disable EP Mismatch interrupt */ -+ intr_mask.d32 = 0; -+ intr_mask.b.epmismatch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0); -+ /* Enable the Global IN NAK Effective Interrupt */ -+ intr_mask.d32 = 0; -+ intr_mask.b.ginnakeff = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); -+ /* Set the global non-periodic IN NAK handshake */ -+ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); -+ dctl.b.sgnpinnak = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); -+ } else { -+ DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n"); -+ } -+ /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective() -+ * handler after Global IN NAK Effective interrupt will be asserted */ -+ } - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.epmismatch = 1; -- dwc_write_reg32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); - - return 1; - } - - /** -+ * This interrupt is valid only in DMA mode. This interrupt indicates that the -+ * core has stopped fetching data for IN endpoints due to the unavailability of -+ * TxFIFO space or Request Queue space. This interrupt is used by the -+ * application for an endpoint mismatch algorithm. -+ * -+ * @param pcd The PCD -+ */ -+int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd) -+{ -+ gintsts_data_t gintsts; -+ gintmsk_data_t gintmsk_data; -+ dctl_data_t dctl; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); -+ -+ /* Clear the global non-periodic IN NAK handshake */ -+ dctl.d32 = 0; -+ dctl.b.cgnpinnak = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); -+ -+ /* Mask GINTSTS.FETSUSP interrupt */ -+ gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); -+ gintmsk_data.b.fetsusp = 0; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32); -+ -+ /* Clear interrupt */ -+ gintsts.d32 = 0; -+ gintsts.b.fetsusp = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ -+ return 1; -+} -+/** - * This funcion stalls EP0. - */ - static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val) -@@ -1149,12 +1288,12 @@ static inline void do_gadget_setup(dwc_otg_pcd_t * pcd, - /** @todo This is a g_file_storage gadget driver specific - * workaround: a DELAYED_STATUS result from the fsg_setup - * routine will result in the gadget queueing a EP0 IN status -- * phase for a two-stage control transfer. Exactly the same as -+ * phase for a two-stage control transfer. Exactly the same as - * a SET_CONFIGURATION/SET_INTERFACE except that this is a class - * specific request. Need a generic way to know when the gadget -- * driver will queue the status phase. Can we assume when we -+ * driver will queue the status phase. Can we assume when we - * call the gadget driver setup() function that it will always -- * queue and require the following flag? Need to look into -+ * queue and require the following flag? Need to look into - * this. - */ - -@@ -1290,7 +1429,7 @@ void do_test_mode(void *data) - - // DWC_WARN("%s() has not been tested since being rewritten!\n", __func__); - -- dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl); -+ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); - switch (test_mode) { - case 1: // TEST_J - dctl.b.tstctl = 1; -@@ -1312,7 +1451,7 @@ void do_test_mode(void *data) - dctl.b.tstctl = 5; - break; - } -- dwc_write_reg32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); - } - - /** -@@ -1324,6 +1463,7 @@ static inline void do_get_status(dwc_otg_pcd_t * pcd) - dwc_otg_pcd_ep_t *ep; - dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; - uint16_t *status = pcd->status_buf; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); - - #ifdef DEBUG_EP0 - DWC_DEBUGPL(DBG_PCD, -@@ -1335,10 +1475,34 @@ static inline void do_get_status(dwc_otg_pcd_t * pcd) - - switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { - case UT_DEVICE: -- *status = 0x1; /* Self powered */ -- *status |= pcd->remote_wakeup_enable << 1; -- break; -- -+ if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */ -+ DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex)); -+ DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver); -+ DWC_PRINTF("OTG CAP - %d, %d\n", core_if->core_params->otg_cap, -+ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); -+ if(core_if->otg_ver == 1 && -+ core_if->core_params->otg_cap == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { -+ uint8_t *otgsts = (uint8_t*)pcd->status_buf; -+ *otgsts = (core_if->otg_sts & 0x1); -+ pcd->ep0_pending = 1; -+ ep0->dwc_ep.start_xfer_buff = (uint8_t *) otgsts; -+ ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts; -+ ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle; -+ ep0->dwc_ep.xfer_len = 1; -+ ep0->dwc_ep.xfer_count = 0; -+ ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; -+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); -+ return; -+ } else { -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; -+ } -+ break; -+ } else { -+ *status = 0x1; /* Self powered */ -+ *status |= pcd->remote_wakeup_enable << 1; -+ break; -+ } - case UT_INTERFACE: - *status = 0; - break; -@@ -1413,10 +1577,11 @@ static inline void do_set_feature(dwc_otg_pcd_t * pcd) - * by a USB Reset? */ - gotgctl.b.devhnpen = 1; - gotgctl.b.hnpreq = 1; -- dwc_write_reg32(&global_regs->gotgctl, -+ DWC_WRITE_REG32(&global_regs->gotgctl, - gotgctl.d32); - } else { - ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; - } - break; - -@@ -1429,6 +1594,7 @@ static inline void do_set_feature(dwc_otg_pcd_t * pcd) - dwc_otg_pcd_update_otg(pcd, 0); - } else { - ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; - } - break; - -@@ -1441,8 +1607,14 @@ static inline void do_set_feature(dwc_otg_pcd_t * pcd) - dwc_otg_pcd_update_otg(pcd, 0); - } else { - ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; - } - break; -+ -+ default: -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; -+ - } - do_setup_in_status_phase(pcd); - break; -@@ -1490,6 +1662,10 @@ static inline void do_clear_feature(dwc_otg_pcd_t * pcd) - case UF_TEST_MODE: - /** @todo Add CLEAR_FEATURE for TEST modes. */ - break; -+ -+ default: -+ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -+ return; - } - do_setup_in_status_phase(pcd); - break; -@@ -1522,13 +1698,13 @@ static inline void do_set_address(dwc_otg_pcd_t * pcd) - // DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); - #endif - dcfg.b.devaddr = UGETW(ctrl.wValue); -- dwc_modify_reg32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); - do_setup_in_status_phase(pcd); - } - } - - /** -- * This function processes SETUP commands. In Linux, the USB Command -+ * This function processes SETUP commands. In Linux, the USB Command - * processing is done in two places - the first being the PCD and the - * second in the Gadget Driver (for example, the File-Backed Storage - * Gadget Driver). -@@ -1598,7 +1774,7 @@ static inline void pcd_setup(dwc_otg_pcd_t * pcd) - UGETW(ctrl.wLength)); - #endif - -- doeptsize0.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doeptsiz); -+ doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz); - - /** @todo handle > 1 setup packet , assert error for now */ - -@@ -1630,7 +1806,8 @@ static inline void pcd_setup(dwc_otg_pcd_t * pcd) - #ifdef DWC_UTE_CFI - DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t)); - -- //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ctrl.bRequestType, ctrl.bRequest); -+ //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", -+ ctrl.bRequestType, ctrl.bRequest); - if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) { - if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) { - retval = cfi_setup(pcd, &cfi_req); -@@ -1644,8 +1821,8 @@ static inline void pcd_setup(dwc_otg_pcd_t * pcd) - if (pcd->cfi->need_gadget_att) { - retval = - cfi_gadget_setup(pcd, -- &pcd->cfi-> -- ctrl_req); -+ &pcd-> -+ cfi->ctrl_req); - if (retval < 0) { - pcd->ep0_pending = 0; - return; -@@ -1728,6 +1905,8 @@ static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep) - int retval = -DWC_E_NOT_SUPPORTED; - #endif - -+ desc_sts.b.bytes = 0; -+ - if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) { - if (ep->dwc_ep.is_in) { - #ifdef DEBUG_EP0 -@@ -1809,7 +1988,7 @@ static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep) - || pcd->ep0state == EP0_IN_STATUS_PHASE) { - is_last = 1; - } else if (ep->dwc_ep.is_in) { -- deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz); -+ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); - if (core_if->dma_desc_enable != 0) - desc_sts = dev_if->in_desc_addr->status; - #ifdef DEBUG_EP0 -@@ -1835,7 +2014,7 @@ static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep) - } else { - /* ep0-OUT */ - #ifdef DEBUG_EP0 -- deptsiz.d32 = dwc_read_reg32(&out_ep_regs->doeptsiz); -+ deptsiz.d32 = DWC_READ_REG32(&out_ep_regs->doeptsiz); - DWC_DEBUGPL(DBG_PCDV, "%d len=%d xsize=%d pktcnt=%d\n", - ep->dwc_ep.num, ep->dwc_ep.xfer_len, - deptsiz.b.xfersize, deptsiz.b.pktcnt); -@@ -1905,7 +2084,7 @@ static inline int cfi_calc_desc_residue(dwc_otg_pcd_ep_t * ep) - #endif - - /** -- * This function completes the request for the EP. If there are -+ * This function completes the request for the EP. If there are - * additional requests for the EP in the queue they will be started. - */ - static void complete_ep(dwc_otg_pcd_ep_t * ep) -@@ -1940,7 +2119,7 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - DWC_DEBUGPL(DBG_PCD, "Requests %d\n", ep->pcd->request_pending); - - if (ep->dwc_ep.is_in) { -- deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz); -+ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); - - if (core_if->dma_enable) { - if (core_if->dma_desc_enable == 0) { -@@ -1968,20 +2147,20 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - dwc_otg_ep_start_transfer - (core_if, &ep->dwc_ep); - } else if (ep->dwc_ep.sent_zlp) { -- /* -- * This fragment of code should initiate 0 -- * length trasfer in case if it is queued -- * a trasfer with size divisible to EPs max -- * packet size and with usb_request zero field -- * is set, which means that after data is transfered, -- * it is also should be transfered -- * a 0 length packet at the end. For Slave and -- * Buffer DMA modes in this case SW has -- * to initiate 2 transfers one with transfer size, -- * and the second with 0 size. For Desriptor -- * DMA mode SW is able to initiate a transfer, -- * which will handle all the packets including -- * the last 0 legth. -+ /* -+ * This fragment of code should initiate 0 -+ * length transfer in case if it is queued -+ * a transfer with size divisible to EPs max -+ * packet size and with usb_request zero field -+ * is set, which means that after data is transfered, -+ * it is also should be transfered -+ * a 0 length packet at the end. For Slave and -+ * Buffer DMA modes in this case SW has -+ * to initiate 2 transfers one with transfer size, -+ * and the second with 0 size. For Descriptor -+ * DMA mode SW is able to initiate a transfer, -+ * which will handle all the packets including -+ * the last 0 length. - */ - ep->dwc_ep.sent_zlp = 0; - dwc_otg_ep_start_zl_transfer -@@ -1990,12 +2169,24 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - is_last = 1; - } - } else { -- DWC_WARN -- ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", -- ep->dwc_ep.num, -- (ep->dwc_ep.is_in ? "IN" : "OUT"), -- deptsiz.b.xfersize, -- deptsiz.b.pktcnt); -+ if(ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -+ { -+ req->actual = 0; -+ dwc_otg_request_done(ep, req, 0); -+ -+ ep->dwc_ep.start_xfer_buff = 0; -+ ep->dwc_ep.xfer_buff = 0; -+ ep->dwc_ep.xfer_len = 0; -+ -+ /* If there is a request in the queue start it. */ -+ start_next_request(ep); -+ } else -+ DWC_WARN -+ ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", -+ ep->dwc_ep.num, -+ (ep->dwc_ep.is_in ? "IN" : "OUT"), -+ deptsiz.b.xfersize, -+ deptsiz.b.pktcnt); - } - } else { - dma_desc = ep->dwc_ep.desc_addr; -@@ -2042,32 +2233,31 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - deptsiz.b.xfersize, - deptsiz.b.pktcnt); - -- /* Check if the whole transfer was completed, -+ /* Check if the whole transfer was completed, - * if no, setup transfer for next portion of data - */ - if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { - dwc_otg_ep_start_transfer(core_if, - &ep->dwc_ep); - } else if (ep->dwc_ep.sent_zlp) { -- /* -- * This fragment of code should initiate 0 -+ /* -+ * This fragment of code should initiate 0 - * length trasfer in case if it is queued -- * a trasfer with size divisible to EPs max -- * packet size and with usb_request zero field -- * is set, which means that after data is transfered, -- * it is also should be transfered -- * a 0 length packet at the end. For Slave and -- * Buffer DMA modes in this case SW has -- * to initiate 2 transfers one with transfer size, -- * and the second with 0 size. For Desriptor -- * DMA mode SW is able to initiate a transfer, -- * which will handle all the packets including -+ * a trasfer with size divisible to EPs max -+ * packet size and with usb_request zero field -+ * is set, which means that after data is transfered, -+ * it is also should be transfered -+ * a 0 length packet at the end. For Slave and -+ * Buffer DMA modes in this case SW has -+ * to initiate 2 transfers one with transfer size, -+ * and the second with 0 size. For Desriptor -+ * DMA mode SW is able to initiate a transfer, -+ * which will handle all the packets including - * the last 0 legth. - */ - ep->dwc_ep.sent_zlp = 0; - dwc_otg_ep_start_zl_transfer(core_if, -- &ep-> -- dwc_ep); -+ &ep->dwc_ep); - } else { - is_last = 1; - } -@@ -2103,22 +2293,44 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - - for (i = 0; i < ep->dwc_ep.desc_cnt; - ++i) { -- desc_sts = dma_desc->status; -- byte_count += desc_sts.b.bytes; -- dma_desc++; -- } -+ desc_sts = dma_desc->status; -+ byte_count += desc_sts.b.bytes; -+ dma_desc++; -+ } - - #ifdef DWC_UTE_CFI - } - #endif -- ep->dwc_ep.xfer_count = ep->dwc_ep.total_len -- - byte_count + -- ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3); -- is_last = 1; -+ /* Checking for interrupt Out transfers with not -+ * dword aligned mps sizes -+ */ -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR && -+ (ep->dwc_ep.maxpacket%4)) { -+ ep->dwc_ep.xfer_count = ep->dwc_ep.total_len - byte_count; -+ if ((ep->dwc_ep.xfer_len % ep->dwc_ep.maxpacket) && -+ (ep->dwc_ep.xfer_len/ep->dwc_ep.maxpacket < MAX_DMA_DESC_CNT)) -+ ep->dwc_ep.xfer_len -= -+ (ep->dwc_ep.desc_cnt - 1) * ep->dwc_ep.maxpacket + -+ ep->dwc_ep.xfer_len % ep->dwc_ep.maxpacket; -+ else -+ ep->dwc_ep.xfer_len -= -+ ep->dwc_ep.desc_cnt * ep->dwc_ep.maxpacket; -+ if (ep->dwc_ep.xfer_len > 0) { -+ dwc_otg_ep_start_transfer(core_if, -+ &ep->dwc_ep); -+ } else { -+ is_last = 1; -+ } -+ } else { -+ ep->dwc_ep.xfer_count = ep->dwc_ep.total_len -+ - byte_count + -+ ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3); -+ is_last = 1; -+ } - } else { - deptsiz.d32 = 0; - deptsiz.d32 = -- dwc_read_reg32(&out_ep_regs->doeptsiz); -+ DWC_READ_REG32(&out_ep_regs->doeptsiz); - - byte_count = (ep->dwc_ep.xfer_len - - ep->dwc_ep.xfer_count - -@@ -2127,57 +2339,56 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - ep->dwc_ep.dma_addr += byte_count; - ep->dwc_ep.xfer_count += byte_count; - -- /* Check if the whole transfer was completed, -+ /* Check if the whole transfer was completed, - * if no, setup transfer for next portion of data - */ - if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { - dwc_otg_ep_start_transfer(core_if, - &ep->dwc_ep); - } else if (ep->dwc_ep.sent_zlp) { -- /* -- * This fragment of code should initiate 0 -+ /* -+ * This fragment of code should initiate 0 - * length trasfer in case if it is queued -- * a trasfer with size divisible to EPs max -- * packet size and with usb_request zero field -- * is set, which means that after data is transfered, -- * it is also should be transfered -- * a 0 length packet at the end. For Slave and -- * Buffer DMA modes in this case SW has -- * to initiate 2 transfers one with transfer size, -- * and the second with 0 size. For Desriptor -- * DMA mode SW is able to initiate a transfer, -- * which will handle all the packets including -+ * a trasfer with size divisible to EPs max -+ * packet size and with usb_request zero field -+ * is set, which means that after data is transfered, -+ * it is also should be transfered -+ * a 0 length packet at the end. For Slave and -+ * Buffer DMA modes in this case SW has -+ * to initiate 2 transfers one with transfer size, -+ * and the second with 0 size. For Desriptor -+ * DMA mode SW is able to initiate a transfer, -+ * which will handle all the packets including - * the last 0 legth. - */ - ep->dwc_ep.sent_zlp = 0; - dwc_otg_ep_start_zl_transfer(core_if, -- &ep-> -- dwc_ep); -+ &ep->dwc_ep); - } else { - is_last = 1; - } - } - } else { -- /* Check if the whole transfer was completed, -+ /* Check if the whole transfer was completed, - * if no, setup transfer for next portion of data - */ - if (ep->dwc_ep.xfer_len < ep->dwc_ep.total_len) { - dwc_otg_ep_start_transfer(core_if, &ep->dwc_ep); - } else if (ep->dwc_ep.sent_zlp) { -- /* -- * This fragment of code should initiate 0 -- * length trasfer in case if it is queued -- * a trasfer with size divisible to EPs max -- * packet size and with usb_request zero field -- * is set, which means that after data is transfered, -- * it is also should be transfered -- * a 0 length packet at the end. For Slave and -- * Buffer DMA modes in this case SW has -- * to initiate 2 transfers one with transfer size, -- * and the second with 0 size. For Desriptor -- * DMA mode SW is able to initiate a transfer, -- * which will handle all the packets including -- * the last 0 legth. -+ /* -+ * This fragment of code should initiate 0 -+ * length transfer in case if it is queued -+ * a transfer with size divisible to EPs max -+ * packet size and with usb_request zero field -+ * is set, which means that after data is transfered, -+ * it is also should be transfered -+ * a 0 length packet at the end. For Slave and -+ * Buffer DMA modes in this case SW has -+ * to initiate 2 transfers one with transfer size, -+ * and the second with 0 size. For Descriptor -+ * DMA mode SW is able to initiate a transfer, -+ * which will handle all the packets including -+ * the last 0 length. - */ - ep->dwc_ep.sent_zlp = 0; - dwc_otg_ep_start_zl_transfer(core_if, -@@ -2202,10 +2413,17 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - req->actual = ep->dwc_ep.cfi_req_len - byte_count; - } else { - #endif -- req->actual = ep->dwc_ep.xfer_count; -+ req->actual = ep->dwc_ep.xfer_count; - #ifdef DWC_UTE_CFI - } - #endif -+ if (req->dw_align_buf) { -+ if (!ep->dwc_ep.is_in) { -+ dwc_memcpy(req->buf, req->dw_align_buf, req->length); -+ } -+ DWC_DMA_FREE(req->length, req->dw_align_buf, -+ req->dw_align_buf_dma); -+ } - - dwc_otg_request_done(ep, req, 0); - -@@ -2254,14 +2472,14 @@ static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t * ep) - - if (dwc_ep->is_in == 0) { - addr = -- &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]-> -- doepctl; -+ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep-> -+ num]->doepctl; - } else { - addr = - &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; - } - depctl.b.epena = 1; -- dwc_modify_reg32(addr, depctl.d32, depctl.d32); -+ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); - } - - /** -@@ -2284,13 +2502,13 @@ void set_current_pkt_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - if (ep->is_in) { - deptsiz.d32 = -- dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -- dieptsiz); -+ DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[ep->num]->dieptsiz); - offset = ep->data_per_frame; - } else { - deptsiz.d32 = -- dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> -- doeptsiz); -+ DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[ep->num]->doeptsiz); - offset = - ep->data_per_frame + - (0x4 & (0x4 - (ep->data_per_frame & 0x3))); -@@ -2344,8 +2562,8 @@ static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if, - for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { - data_per_desc = - ((j + 1) * dwc_ep->maxpacket > -- dwc_ep->data_per_frame) ? dwc_ep-> -- data_per_frame - -+ dwc_ep-> -+ data_per_frame) ? dwc_ep->data_per_frame - - j * dwc_ep->maxpacket : dwc_ep->maxpacket; - data_per_desc += - (data_per_desc % 4) ? (4 - -@@ -2371,8 +2589,7 @@ static void set_ddma_iso_pkts_info(dwc_otg_core_if_t * core_if, - iso_packet->length = - data_per_desc - - sts.b_iso_out.rxbytes + (4 - -- dwc_ep-> -- data_per_frame -+ dwc_ep->data_per_frame - % 4); - } - -@@ -2526,8 +2743,8 @@ static void reinit_ddma_iso_xfer(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) - for (j = 0; j < dwc_ep->pkt_per_frm; ++j) { - data_per_desc = - ((j + 1) * dwc_ep->maxpacket > -- dwc_ep->data_per_frame) ? dwc_ep-> -- data_per_frame - -+ dwc_ep-> -+ data_per_frame) ? dwc_ep->data_per_frame - - j * dwc_ep->maxpacket : dwc_ep->maxpacket; - data_per_desc += - (data_per_desc % 4) ? (4 - -@@ -2628,8 +2845,8 @@ static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if, - int i; - - deptsiz.d32 = -- dwc_read_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]-> -- doeptsiz); -+ DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[dwc_ep->num]->doeptsiz); - - drp_pkt = dwc_ep->pkt_cnt - deptsiz.b.pktcnt; - drp_pkt_cnt = dwc_ep->pkt_per_frm - (drp_pkt % dwc_ep->pkt_per_frm); -@@ -2650,7 +2867,7 @@ static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if, - deptsiz.b.pktcnt = 0; - } - -- dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, - deptsiz.d32); - - if (deptsiz.b.pktcnt > 0) { -@@ -2664,16 +2881,17 @@ static uint32_t handle_iso_out_pkt_dropped(dwc_otg_core_if_t * core_if, - deptsiz.b.xfersize;; - } - -- dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]-> -- doepdma, dma_addr); -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ out_ep_regs[dwc_ep->num]->doepdma, dma_addr); - - /** Re-enable endpoint, clear nak */ - depctl.d32 = 0; - depctl.b.epena = 1; - depctl.b.cnak = 1; - -- dwc_modify_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]-> -- doepctl, depctl.d32, depctl.d32); -+ DWC_MODIFY_REG32(&core_if->dev_if-> -+ out_ep_regs[dwc_ep->num]->doepctl, depctl.d32, -+ depctl.d32); - return 0; - } else { - return 1; -@@ -2706,12 +2924,12 @@ static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - if (ep->is_in) { - deptsiz.d32 = -- dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -- dieptsiz); -+ DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[ep->num]->dieptsiz); - } else { - deptsiz.d32 = -- dwc_read_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> -- doeptsiz); -+ DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[ep->num]->doeptsiz); - } - - if (!deptsiz.b.xfersize) { -@@ -2720,8 +2938,8 @@ static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - frame_data = ep->data_per_frame; - for (j = 0; j < ep->pkt_per_frm; ++j) { - -- /* Packet status - is not set as initially -- * it is set to 0 and if packet was sent -+ /* Packet status - is not set as initially -+ * it is set to 0 and if packet was sent - successfully, status field will remain 0*/ - - /* Bytes has been transfered */ -@@ -2739,11 +2957,11 @@ static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - } - return 1; - } else { -- /* This is a workaround for in case of Transfer Complete with -- * PktDrpSts interrupts merging - in this case Transfer complete -- * interrupt for Isoc Out Endpoint is asserted without PktDrpSts -+ /* This is a workaround for in case of Transfer Complete with -+ * PktDrpSts interrupts merging - in this case Transfer complete -+ * interrupt for Isoc Out Endpoint is asserted without PktDrpSts - * set and with DOEPTSIZ register non zero. Investigations showed, -- * that this happens when Out packet is dropped, but because of -+ * that this happens when Out packet is dropped, but because of - * interrupts merging during first interrupt handling PktDrpSts - * bit is cleared and for next merged interrupts it is not reset. - * In this case SW hadles the interrupt as if PktDrpSts bit is set. -@@ -2769,7 +2987,7 @@ static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) - dwc_ep_t *dwc_ep = &ep->dwc_ep; - uint8_t is_last = 0; - -- if(ep->dwc_ep.next_frame == 0xffffffff) { -+ if (ep->dwc_ep.next_frame == 0xffffffff) { - DWC_WARN("Next frame is not set!\n"); - return; - } -@@ -2832,7 +3050,58 @@ static void complete_iso_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * ep) - if (is_last) - dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle); - } --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ -+ -+/** -+ * This function handle BNA interrupt for Non Isochronous EPs -+ * -+ */ -+static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep) -+{ -+ dwc_ep_t *dwc_ep = &ep->dwc_ep; -+ volatile uint32_t *addr; -+ depctl_data_t depctl = {.d32 = 0 }; -+ dwc_otg_pcd_t *pcd = ep->pcd; -+ dwc_otg_dev_dma_desc_t *dma_desc; -+ dev_dma_desc_sts_t sts = {.d32 = 0 }; -+ dwc_otg_core_if_t *core_if = ep->pcd->core_if; -+ int i, start; -+ -+ if (!dwc_ep->desc_cnt) -+ DWC_WARN("Descriptor count = %d\n", dwc_ep->desc_cnt); -+ -+ if (core_if->core_params->cont_on_bna && !dwc_ep->is_in -+ && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) { -+ uint32_t doepdma; -+ dwc_otg_dev_out_ep_regs_t *out_regs = -+ core_if->dev_if->out_ep_regs[dwc_ep->num]; -+ doepdma = DWC_READ_REG32(&(out_regs->doepdma)); -+ start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t); -+ dma_desc = &(dwc_ep->desc_addr[start]); -+ } else { -+ start = 0; -+ dma_desc = dwc_ep->desc_addr; -+ } -+ -+ -+ for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { -+ sts.d32 = dma_desc->status.d32; -+ sts.b.bs = BS_HOST_READY; -+ dma_desc->status.d32 = sts.d32; -+ } -+ -+ if (dwc_ep->is_in == 0) { -+ addr = -+ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep-> -+ num]->doepctl; -+ } else { -+ addr = -+ &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; -+ } -+ depctl.b.epena = 1; -+ depctl.b.cnak = 1; -+ DWC_MODIFY_REG32(addr, 0, depctl.d32); -+} - - /** - * This function handles EP0 Control transfers. -@@ -2882,8 +3151,9 @@ static void handle_ep0(dwc_otg_pcd_t * pcd) - */ - if (core_if->dma_desc_enable == 0) { - deptsiz.d32 = -- dwc_read_reg32(&core_if->dev_if-> -- in_ep_regs[0]->dieptsiz); -+ DWC_READ_REG32(&core_if-> -+ dev_if->in_ep_regs[0]-> -+ dieptsiz); - byte_count = - ep0->dwc_ep.xfer_len - deptsiz.b.xfersize; - } else { -@@ -2919,8 +3189,9 @@ static void handle_ep0(dwc_otg_pcd_t * pcd) - if (core_if->dma_enable != 0) { - if (core_if->dma_desc_enable == 0) { - deptsiz.d32 = -- dwc_read_reg32(&core_if->dev_if-> -- out_ep_regs[0]->doeptsiz); -+ DWC_READ_REG32(&core_if-> -+ dev_if->out_ep_regs[0]-> -+ doeptsiz); - byte_count = - ep0->dwc_ep.maxpacket - deptsiz.b.xfersize; - } else { -@@ -2987,12 +3258,12 @@ static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum) - if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { - return; - } --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ - - core_if = GET_CORE_IF(pcd); - dev_if = core_if->dev_if; - -- dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz); -+ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); - - DWC_DEBUGPL(DBG_PCD, "xfer_buff=%p xfer_count=%0x xfer_len=%0x" - " stopped=%d\n", ep->dwc_ep.xfer_buff, -@@ -3026,6 +3297,173 @@ static void restart_transfer(dwc_otg_pcd_t * pcd, const uint32_t epnum) - } - } - -+/* -+ * This function create new nextep sequnce based on Learn Queue. -+ * -+ * @param core_if Programming view of DWC_otg controller -+ */ -+void predict_nextep_seq( dwc_otg_core_if_t * core_if) -+{ -+ dwc_otg_device_global_regs_t *dev_global_regs = -+ core_if->dev_if->dev_global_regs; -+ const uint32_t TOKEN_Q_DEPTH = core_if->hwcfg2.b.dev_token_q_depth; -+ /* Number of Token Queue Registers */ -+ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; -+ dtknq1_data_t dtknqr1; -+ uint32_t in_tkn_epnums[4]; -+ uint8_t seqnum[MAX_EPS_CHANNELS]; -+ uint8_t intkn_seq[TOKEN_Q_DEPTH]; -+ grstctl_t resetctl = {.d32 = 0 }; -+ uint8_t temp; -+ int ndx = 0; -+ int start = 0; -+ int end = 0; -+ int sort_done = 0; -+ int i = 0; -+ volatile uint32_t *addr = &dev_global_regs->dtknqr1; -+ -+ -+ DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH); -+ -+ /* Read the DTKNQ Registers */ -+ for (i = 0; i < DTKNQ_REG_CNT; i++) { -+ in_tkn_epnums[i] = DWC_READ_REG32(addr); -+ DWC_DEBUGPL(DBG_PCDV, "DTKNQR%d=0x%08x\n", i + 1, -+ in_tkn_epnums[i]); -+ if (addr == &dev_global_regs->dvbusdis) { -+ addr = &dev_global_regs->dtknqr3_dthrctl; -+ } else { -+ ++addr; -+ } -+ -+ } -+ -+ /* Copy the DTKNQR1 data to the bit field. */ -+ dtknqr1.d32 = in_tkn_epnums[0]; -+ if (dtknqr1.b.wrap_bit) { -+ ndx = dtknqr1.b.intknwptr; -+ end = ndx -1; -+ if (end < 0) -+ end = TOKEN_Q_DEPTH -1; -+ } else { -+ ndx = 0; -+ end = dtknqr1.b.intknwptr -1; -+ if (end < 0) -+ end = 0; -+ } -+ start = ndx; -+ -+ /* Fill seqnum[] by initial values: EP number + 31 */ -+ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -+ seqnum[i] = i +31; -+ } -+ -+ /* Fill intkn_seq[] from in_tkn_epnums[0] */ -+ for (i=0; i < 6; i++) -+ intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf; -+ -+ if (TOKEN_Q_DEPTH > 6) { -+ /* Fill intkn_seq[] from in_tkn_epnums[1] */ -+ for (i=6; i < 14; i++) -+ intkn_seq[i] = (in_tkn_epnums[1] >> ((7-(i-6)) * 4)) & 0xf; -+ } -+ -+ if (TOKEN_Q_DEPTH > 14) { -+ /* Fill intkn_seq[] from in_tkn_epnums[1] */ -+ for (i=14; i < 22; i++) -+ intkn_seq[i] = (in_tkn_epnums[2] >> ((7-(i-14)) * 4)) & 0xf; -+ } -+ -+ if (TOKEN_Q_DEPTH > 22) { -+ /* Fill intkn_seq[] from in_tkn_epnums[1] */ -+ for (i=22; i < 30; i++) -+ intkn_seq[i] = (in_tkn_epnums[3] >> ((7-(i-22)) * 4)) & 0xf; -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV,"%s start=%d end=%d intkn_seq[]:\n", __func__, start, end); -+ for (i=0; idev_if->num_in_eps; i++) { -+ if (core_if->nextep_seq[i] == 0xff ) -+ seqnum[i] = 0xff; -+ } -+ -+ /* Sort seqnum[] */ -+ sort_done = 0; -+ while (!sort_done) { -+ sort_done = 1; -+ for (i=0; idev_if->num_in_eps; i++) { -+ if (seqnum[i] > seqnum[i+1]) { -+ temp = seqnum[i]; -+ seqnum[i] = seqnum[i+1]; -+ seqnum[i+1] = temp; -+ sort_done = 0; -+ } -+ } -+ } -+ -+ ndx = start + seqnum[0]; -+ if (ndx >= TOKEN_Q_DEPTH) -+ ndx = ndx % TOKEN_Q_DEPTH; -+ core_if->first_in_nextep_seq = intkn_seq[ndx]; -+ -+ /* Update seqnum[] by EP numbers */ -+ for (i=0; i<=core_if->dev_if->num_in_eps; i++) { -+ ndx = start + i; -+ if (seqnum[i] < 31) { -+ ndx = start + seqnum[i]; -+ if (ndx >= TOKEN_Q_DEPTH) -+ ndx = ndx % TOKEN_Q_DEPTH; -+ seqnum[i] = intkn_seq[ndx]; -+ } else { -+ if (seqnum[i] < 0xff) { -+ seqnum[i] = seqnum[i] - 31; -+ } else { -+ break; -+ } -+ } -+ } -+ -+ /* Update nextep_seq[] based on seqnum[] */ -+ for (i=0; idev_if->num_in_eps; i++) { -+ if (seqnum[i] != 0xff) { -+ if (seqnum[i+1] != 0xff) { -+ core_if->nextep_seq[seqnum[i]] = seqnum[i+1]; -+ } else { -+ core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq; -+ break; -+ } -+ } else { -+ break; -+ } -+ } -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ __func__, core_if->first_in_nextep_seq); -+ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -+ DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]); -+ } -+ -+ /* Flush the Learning Queue */ -+ resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl); -+ resetctl.b.intknqflsh = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); -+ -+ -+} -+ - /** - * handle the IN EP disable interrupt. - */ -@@ -3038,40 +3476,135 @@ static inline void handle_in_ep_disable_intr(dwc_otg_pcd_t * pcd, - dctl_data_t dctl = {.d32 = 0 }; - dwc_otg_pcd_ep_t *ep; - dwc_ep_t *dwc_ep; -- -+ gintmsk_data_t gintmsk_data; -+ depctl_data_t depctl; -+ uint32_t diepdma; -+ uint32_t remain_to_transfer = 0; -+ uint8_t i; -+ uint32_t xfer_size; -+ - ep = get_in_ep(pcd, epnum); - dwc_ep = &ep->dwc_ep; - - if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { - dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); -+ complete_ep(ep); - return; - } - - DWC_DEBUGPL(DBG_PCD, "diepctl%d=%0x\n", epnum, -- dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl)); -- dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dieptsiz); -+ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl)); -+ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); -+ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); - - DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", - dieptsiz.b.pktcnt, dieptsiz.b.xfersize); -+ -+ if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) { -+ if (ep->stopped) { -+ if (core_if->en_multiple_tx_fifo) -+ /* Flush the Tx FIFO */ -+ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); -+ /* Clear the Global IN NP NAK */ -+ dctl.d32 = 0; -+ dctl.b.cgnpinnak = 1; -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); -+ /* Restart the transaction */ -+ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { -+ restart_transfer(pcd, epnum); -+ } -+ } else { -+ /* Restart the transaction */ -+ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { -+ restart_transfer(pcd, epnum); -+ } -+ DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); -+ } -+ return; -+ } - -- if (ep->stopped) { -- /* Flush the Tx FIFO */ -- dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); -- /* Clear the Global IN NP NAK */ -- dctl.d32 = 0; -- dctl.b.cgnpinnak = 1; -- dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, 0); -- /* Restart the transaction */ -- if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { -- restart_transfer(pcd, epnum); -+ if (core_if->start_predict > 2) { // NP IN EP -+ core_if->start_predict--; -+ return; -+ } -+ -+ core_if->start_predict--; -+ -+ if (core_if->start_predict == 1) { // All NP IN Ep's disabled now -+ -+ predict_nextep_seq(core_if); -+ -+ /* Update all active IN EP's NextEP field based of nextep_seq[] */ -+ for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) { -+ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); -+ if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP -+ depctl.b.nextep = core_if->nextep_seq[i]; -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); -+ } - } -- } else { -- /* Restart the transaction */ -- if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { -- restart_transfer(pcd, epnum); -+ /* Flush Shared NP TxFIFO */ -+ dwc_otg_flush_tx_fifo(core_if, 0); -+ /* Rewind buffers */ -+ if (!core_if->dma_desc_enable) { -+ i = core_if->first_in_nextep_seq; -+ do { -+ ep = get_in_ep(pcd, i); -+ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); -+ xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count; -+ if (xfer_size > ep->dwc_ep.maxxfer) -+ xfer_size = ep->dwc_ep.maxxfer; -+ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); -+ if (dieptsiz.b.pktcnt != 0) { -+ if (xfer_size == 0) { -+ remain_to_transfer = 0; -+ } else { -+ if ((xfer_size % ep->dwc_ep.maxpacket) == 0) { -+ remain_to_transfer = -+ dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket; -+ } else { -+ remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket) -+ + (xfer_size % ep->dwc_ep.maxpacket); -+ } -+ } -+ diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma); -+ dieptsiz.b.xfersize = remain_to_transfer; -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32); -+ diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer); -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma); -+ } -+ i = core_if->nextep_seq[i]; -+ } while (i != core_if->first_in_nextep_seq); -+ } else { // dma_desc_enable -+ DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__); - } -- DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); -- } -+ -+ /* Restart transfers in predicted sequences */ -+ i = core_if->first_in_nextep_seq; -+ do { -+ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); -+ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); -+ if (dieptsiz.b.pktcnt != 0) { -+ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); -+ depctl.b.epena = 1; -+ depctl.b.cnak = 1; -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); -+ } -+ i = core_if->nextep_seq[i]; -+ } while (i != core_if->first_in_nextep_seq); -+ -+ /* Clear the global non-periodic IN NAK handshake */ -+ dctl.d32 = 0; -+ dctl.b.cgnpinnak = 1; -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); -+ -+ /* Unmask EP Mismatch interrupt */ -+ gintmsk_data.d32 = 0; -+ gintmsk_data.b.epmismatch = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32); -+ -+ core_if->start_predict = 0; -+ -+ } - } - - /** -@@ -3097,7 +3630,7 @@ static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd, - /* Disable the NP Tx Fifo Empty Interrrupt */ - if (!core_if->dma_enable) { - intr_mask.b.nptxfempty = 1; -- dwc_modify_reg32(&core_if->core_global_regs->gintmsk, -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, - intr_mask.d32, 0); - } - /** @todo NGS Check EP type. -@@ -3107,16 +3640,16 @@ static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd, - */ - /* Enable the Global IN NAK Effective Interrupt */ - intr_mask.b.ginnakeff = 1; -- dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); - - /* Set Global IN NAK */ - dctl.b.sgnpinnak = 1; -- dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); - - ep->stopped = 1; - - #ifdef DEBUG -- dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[num]->dieptsiz); -+ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[num]->dieptsiz); - DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", - dieptsiz.b.pktcnt, dieptsiz.b.xfersize); - #endif -@@ -3128,7 +3661,7 @@ static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd, - */ - diepctl.d32 = 0; - diepctl.b.snak = 1; -- dwc_modify_reg32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, -+ DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, - diepctl.d32); - ep->disabling = 1; - ep->stopped = 1; -@@ -3136,7 +3669,7 @@ static inline void handle_in_ep_timeout_intr(dwc_otg_pcd_t * pcd, - } - - /** -- * Handler for the IN EP NAK interrupt. -+ * Handler for the IN EP NAK interrupt. - */ - static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd, - const uint32_t epnum) -@@ -3150,10 +3683,10 @@ static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd, - intr_mask.b.nak = 1; - - if (core_if->multiproc_int_enable) { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> - diepeachintmsk[epnum], intr_mask.d32, 0); - } else { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs->diepmsk, -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk, - intr_mask.d32, 0); - } - -@@ -3161,7 +3694,7 @@ static inline int32_t handle_in_ep_nak_intr(dwc_otg_pcd_t * pcd, - } - - /** -- * Handler for the OUT EP Babble interrupt. -+ * Handler for the OUT EP Babble interrupt. - */ - static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd, - const uint32_t epnum) -@@ -3176,10 +3709,10 @@ static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd, - intr_mask.b.babble = 1; - - if (core_if->multiproc_int_enable) { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> - doepeachintmsk[epnum], intr_mask.d32, 0); - } else { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, - intr_mask.d32, 0); - } - -@@ -3187,7 +3720,7 @@ static inline int32_t handle_out_ep_babble_intr(dwc_otg_pcd_t * pcd, - } - - /** -- * Handler for the OUT EP NAK interrupt. -+ * Handler for the OUT EP NAK interrupt. - */ - static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd, - const uint32_t epnum) -@@ -3201,10 +3734,10 @@ static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd, - intr_mask.b.nak = 1; - - if (core_if->multiproc_int_enable) { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> - doepeachintmsk[epnum], intr_mask.d32, 0); - } else { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, - intr_mask.d32, 0); - } - -@@ -3212,7 +3745,7 @@ static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd, - } - - /** -- * Handler for the OUT EP NYET interrupt. -+ * Handler for the OUT EP NYET interrupt. - */ - static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd, - const uint32_t epnum) -@@ -3226,10 +3759,10 @@ static inline int32_t handle_out_ep_nyet_intr(dwc_otg_pcd_t * pcd, - intr_mask.b.nyet = 1; - - if (core_if->multiproc_int_enable) { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> - doepeachintmsk[epnum], intr_mask.d32, 0); - } else { -- dwc_modify_reg32(&core_if->dev_if->dev_global_regs->doepmsk, -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, - intr_mask.d32, 0); - } - -@@ -3258,14 +3791,13 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - do { \ - diepint_data_t diepint = {.d32=0}; \ - diepint.b.__intr = 1; \ -- dwc_write_reg32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ -+ DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ - diepint.d32); \ - } while (0) - - dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); - dwc_otg_dev_if_t *dev_if = core_if->dev_if; - diepint_data_t diepint = {.d32 = 0 }; -- dctl_data_t dctl = {.d32 = 0 }; - depctl_data_t depctl = {.d32 = 0 }; - uint32_t ep_intr; - uint32_t epnum = 0; -@@ -3287,10 +3819,10 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - dwc_ep = &ep->dwc_ep; - - depctl.d32 = -- dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl); -+ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); - empty_msk = -- dwc_read_reg32(&dev_if->dev_global_regs-> -- dtknqr4_fifoemptymsk); -+ DWC_READ_REG32(&dev_if-> -+ dev_global_regs->dtknqr4_fifoemptymsk); - - DWC_DEBUGPL(DBG_PCDV, - "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n", -@@ -3313,17 +3845,15 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - * Interrrupt */ - if (core_if->en_multiple_tx_fifo == 0) { - intr_mask.b.nptxfempty = 1; -- dwc_modify_reg32(&core_if-> -- core_global_regs-> -- gintmsk, intr_mask.d32, -- 0); -+ DWC_MODIFY_REG32 -+ (&core_if->core_global_regs->gintmsk, -+ intr_mask.d32, 0); - } else { - /* Disable the Tx FIFO Empty Interrupt for this EP */ - uint32_t fifoemptymsk = - 0x1 << dwc_ep->num; -- dwc_modify_reg32(&core_if->dev_if-> -- dev_global_regs-> -- dtknqr4_fifoemptymsk, -+ DWC_MODIFY_REG32(&core_if-> -+ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, - fifoemptymsk, 0); - } - /* Clear the bit in DIEPINTn for this interrupt */ -@@ -3338,10 +3868,27 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - if (!ep->stopped) - complete_iso_ep(pcd, ep); - } --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ -+#ifdef DWC_UTE_PER_IO -+ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ if (!ep->stopped) -+ complete_xiso_ep(ep); -+ } -+#endif /* DWC_UTE_PER_IO */ - else { -- -+ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC && -+ dwc_ep->bInterval > 1) { -+ dwc_ep->frame_num += dwc_ep->bInterval; -+ if (dwc_ep->frame_num > 0x3FFF) -+ { -+ dwc_ep->frm_overrun = 1; -+ dwc_ep->frame_num &= 0x3FFF; -+ } else -+ dwc_ep->frm_overrun = 0; -+ } - complete_ep(ep); -+ if(diepint.b.nak) -+ CLEAR_IN_EP_INTR(core_if, epnum, nak); - } - } - /* Endpoint disable */ -@@ -3355,15 +3902,13 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - } - /* AHB Error */ - if (diepint.b.ahberr) { -- DWC_DEBUGPL(DBG_ANY, "EP%d IN AHB Error\n", -- epnum); -+ DWC_ERROR("EP%d IN AHB Error\n", epnum); - /* Clear the bit in DIEPINTn for this interrupt */ - CLEAR_IN_EP_INTR(core_if, epnum, ahberr); - } - /* TimeOUT Handshake (non-ISOC IN EPs) */ - if (diepint.b.timeout) { -- DWC_DEBUGPL(DBG_ANY, "EP%d IN Time-out\n", -- epnum); -+ DWC_ERROR("EP%d IN Time-out\n", epnum); - handle_in_ep_timeout_intr(pcd, epnum); - - CLEAR_IN_EP_INTR(core_if, epnum, timeout); -@@ -3379,18 +3924,13 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - diepmsk.b.intktxfemp = 1; - - if (core_if->multiproc_int_enable) { -- dwc_modify_reg32(&dev_if-> -- dev_global_regs-> -- diepeachintmsk -- [epnum], -- diepmsk.d32, -- 0); -+ DWC_MODIFY_REG32 -+ (&dev_if->dev_global_regs->diepeachintmsk -+ [epnum], diepmsk.d32, 0); - } else { -- dwc_modify_reg32(&dev_if-> -- dev_global_regs-> -- diepmsk, -- diepmsk.d32, -- 0); -+ DWC_MODIFY_REG32 -+ (&dev_if->dev_global_regs->diepmsk, -+ diepmsk.d32, 0); - } - } else if (core_if->dma_desc_enable - && epnum == 0 -@@ -3398,18 +3938,17 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - EP0_OUT_STATUS_PHASE) { - // EP0 IN set STALL - depctl.d32 = -- dwc_read_reg32(&dev_if-> -- in_ep_regs[epnum]-> -- diepctl); -+ DWC_READ_REG32(&dev_if->in_ep_regs -+ [epnum]->diepctl); - - /* set the disable and stall bits */ - if (depctl.b.epena) { - depctl.b.epdis = 1; - } - depctl.b.stall = 1; -- dwc_write_reg32(&dev_if-> -- in_ep_regs[epnum]-> -- diepctl, depctl.d32); -+ DWC_WRITE_REG32(&dev_if->in_ep_regs -+ [epnum]->diepctl, -+ depctl.d32); - } - CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp); - } -@@ -3417,7 +3956,7 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - if (diepint.b.intknepmis) { - DWC_DEBUGPL(DBG_ANY, - "EP%d IN TKN EP Mismatch\n", epnum); -- CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); -+ CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); - } - /** IN Endpoint NAK Effective */ - if (diepint.b.inepnakeff) { -@@ -3429,9 +3968,9 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - depctl.d32 = 0; - depctl.b.snak = 1; - depctl.b.epdis = 1; -- dwc_modify_reg32(&dev_if-> -- in_ep_regs[epnum]-> -- diepctl, depctl.d32, -+ DWC_MODIFY_REG32(&dev_if->in_ep_regs -+ [epnum]->diepctl, -+ depctl.d32, - depctl.d32); - } - CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff); -@@ -3457,35 +3996,16 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - if (dwc_ep->type == - DWC_OTG_EP_TYPE_ISOC) { - /* -- * This checking is performed to prevent first "false" BNA -- * handling occuring right after reconnect -+ * This checking is performed to prevent first "false" BNA -+ * handling occuring right after reconnect - */ - if (dwc_ep->next_frame != - 0xffffffff) -- dwc_otg_pcd_handle_iso_bna -- (ep); -+ dwc_otg_pcd_handle_iso_bna(ep); - } else - #endif /* DWC_EN_ISOC */ - { -- dctl.d32 = -- dwc_read_reg32(&dev_if-> -- dev_global_regs-> -- dctl); -- -- /* If Global Continue on BNA is disabled - disable EP */ -- if (!dctl.b.gcontbna) { -- depctl.d32 = 0; -- depctl.b.snak = 1; -- depctl.b.epdis = 1; -- dwc_modify_reg32 -- (&dev_if-> -- in_ep_regs[epnum]-> -- diepctl, -- depctl.d32, -- depctl.d32); -- } else { -- start_next_request(ep); -- } -+ dwc_otg_pcd_handle_noniso_bna(ep); - } - } - } -@@ -3493,7 +4013,35 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - if (diepint.b.nak) { - DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n", - epnum); -- handle_in_ep_nak_intr(pcd, epnum); -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -+ { -+ depctl_data_t depctl; -+ if (ep->dwc_ep.frame_num == 0xFFFFFFFF) -+ { -+ ep->dwc_ep.frame_num = core_if->frame_num; -+ if (ep->dwc_ep.bInterval > 1) -+ { -+ depctl.d32 = 0; -+ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); -+ if (ep->dwc_ep.frame_num & 0x1) { -+ depctl.b.setd1pid = 1; -+ depctl.b.setd0pid = 0; -+ } else { -+ depctl.b.setd0pid = 1; -+ depctl.b.setd1pid = 0; -+ } -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32); -+ } -+ start_next_request(ep); -+ } -+ ep->dwc_ep.frame_num += ep->dwc_ep.bInterval; -+ if (dwc_ep->frame_num > 0x3FFF) -+ { -+ dwc_ep->frm_overrun = 1; -+ dwc_ep->frame_num &= 0x3FFF; -+ } else -+ dwc_ep->frm_overrun = 0; -+ } - - CLEAR_IN_EP_INTR(core_if, epnum, nak); - } -@@ -3525,19 +4073,19 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - do { \ - doepint_data_t doepint = {.d32=0}; \ - doepint.b.__intr = 1; \ -- dwc_write_reg32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ -+ DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ - doepint.d32); \ - } while (0) - - dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); -- dwc_otg_dev_if_t *dev_if = core_if->dev_if; - uint32_t ep_intr; - doepint_data_t doepint = {.d32 = 0 }; -- dctl_data_t dctl = {.d32 = 0 }; -- depctl_data_t doepctl = {.d32 = 0 }; - uint32_t epnum = 0; - dwc_otg_pcd_ep_t *ep; - dwc_ep_t *dwc_ep; -+ dctl_data_t dctl = {.d32 = 0 }; -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ - - DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); - -@@ -3579,28 +4127,39 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - complete_iso_ep(pcd, ep); - } else { - -- doepint_data_t doepint = {.d32 = -- 0 }; -+ doepint_data_t doepint = {.d32 = 0 }; - doepint.b.xfercompl = 1; - doepint.b.pktdrpsts = 1; -- dwc_write_reg32(&core_if-> -- dev_if-> -- out_ep_regs -- [epnum]-> -- doepint, -- doepint.d32); -+ DWC_WRITE_REG32 -+ (&core_if->dev_if->out_ep_regs -+ [epnum]->doepint, -+ doepint.d32); - if (handle_iso_out_pkt_dropped - (core_if, dwc_ep)) { - complete_iso_ep(pcd, - ep); - } - } --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ -+#ifdef DWC_UTE_PER_IO -+ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); -+ if (!ep->stopped) -+ complete_xiso_ep(ep); -+#endif /* DWC_UTE_PER_IO */ - } else { - /* Clear the bit in DOEPINTn for this interrupt */ - CLEAR_OUT_EP_INTR(core_if, epnum, - xfercompl); -- complete_ep(ep); -+ -+ if (core_if->core_params->dev_out_nak) { -+ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]); -+ pcd->core_if->ep_xfer_info[epnum].state = 0; -+#ifdef DEBUG -+ print_memory_payload(pcd, dwc_ep); -+#endif -+ } -+ complete_ep(ep); - } - - } -@@ -3610,14 +4169,60 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - - /* Clear the bit in DOEPINTn for this interrupt */ - CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled); -+ if (core_if->core_params->dev_out_nak) { -+#ifdef DEBUG -+ print_memory_payload(pcd, dwc_ep); -+#endif -+ /* In case of timeout condition */ -+ if (core_if->ep_xfer_info[epnum].state == 2) { -+ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->dctl); -+ dctl.b.cgoutnak = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, -+ dctl.d32); -+ /* Unmask goutnakeff interrupt which was masked -+ * during handle nak out interrupt */ -+ gintmsk.b.goutnakeff = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, -+ 0, gintmsk.d32); -+ -+ complete_ep(ep); -+ } -+ } -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -+ { -+ dctl_data_t dctl; -+ gintmsk_data_t intr_mask = {.d32 = 0}; -+ dwc_otg_pcd_request_t *req = 0; -+ -+ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->dctl); -+ dctl.b.cgoutnak = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, -+ dctl.d32); -+ -+ intr_mask.d32 = 0; -+ intr_mask.b.incomplisoout = 1; -+ -+ /* Get any pending requests */ -+ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ if (!req) { -+ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); -+ } else { -+ dwc_otg_request_done(ep, req, 0); -+ start_next_request(ep); -+ } -+ } else { -+ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); -+ } -+ } - } - /* AHB Error */ - if (doepint.b.ahberr) { -- DWC_DEBUGPL(DBG_PCD, "EP%d OUT AHB Error\n", -- epnum); -- DWC_DEBUGPL(DBG_PCD, "EP DMA REG %d \n", -- core_if->dev_if-> -- out_ep_regs[epnum]->doepdma); -+ DWC_ERROR("EP%d OUT AHB Error\n", epnum); -+ DWC_ERROR("EP%d DEPDMA=0x%08x \n", -+ epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma); - CLEAR_OUT_EP_INTR(core_if, epnum, ahberr); - } - /* Setup Phase Done (contorl EPs) */ -@@ -3639,35 +4244,16 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - if (dwc_ep->type == - DWC_OTG_EP_TYPE_ISOC) { - /* -- * This checking is performed to prevent first "false" BNA -- * handling occuring right after reconnect -+ * This checking is performed to prevent first "false" BNA -+ * handling occuring right after reconnect - */ - if (dwc_ep->next_frame != - 0xffffffff) -- dwc_otg_pcd_handle_iso_bna -- (ep); -+ dwc_otg_pcd_handle_iso_bna(ep); - } else - #endif /* DWC_EN_ISOC */ - { -- dctl.d32 = -- dwc_read_reg32(&dev_if-> -- dev_global_regs-> -- dctl); -- -- /* If Global Continue on BNA is disabled - disable EP */ -- if (!dctl.b.gcontbna) { -- doepctl.d32 = 0; -- doepctl.b.snak = 1; -- doepctl.b.epdis = 1; -- dwc_modify_reg32 -- (&dev_if-> -- out_ep_regs -- [epnum]->doepctl, -- doepctl.d32, -- doepctl.d32); -- } else { -- start_next_request(ep); -- } -+ dwc_otg_pcd_handle_noniso_bna(ep); - } - } - } -@@ -3685,6 +4271,37 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - - CLEAR_OUT_EP_INTR(core_if, epnum, babble); - } -+ if (doepint.b.outtknepdis) -+ { -+ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \ -+ disabled\n",epnum); -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -+ { -+ doepmsk_data_t doepmsk = {.d32 = 0}; -+ ep->dwc_ep.frame_num = core_if->frame_num; -+ if (ep->dwc_ep.bInterval > 1) -+ { -+ depctl_data_t depctl; -+ depctl.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[epnum]->doepctl); -+ if (ep->dwc_ep.frame_num & 0x1) { -+ depctl.b.setd1pid = 1; -+ depctl.b.setd0pid = 0; -+ } else { -+ depctl.b.setd0pid = 1; -+ depctl.b.setd1pid = 0; -+ } -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ out_ep_regs[epnum]->doepctl, depctl.d32); -+ } -+ start_next_request(ep); -+ doepmsk.b.outtknepdis = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, -+ doepmsk.d32, 0); -+ } -+ CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis); -+ } -+ - /* NAK Interrutp */ - if (doepint.b.nak) { - DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum); -@@ -3709,7 +4326,15 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - - #undef CLEAR_OUT_EP_INTR - } -- -+static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun) -+{ -+ int retval = 0; -+ if(!frm_overrun && curr_fr >= trgt_fr) -+ retval = 1; -+ else if (frm_overrun && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF/2))) -+ retval = 1; -+ return retval; -+} - /** - * Incomplete ISO IN Transfer Interrupt. - * This interrupt indicates one of the following conditions occurred -@@ -3740,9 +4365,9 @@ int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) - dwc_ep = &pcd->in_ep[i].dwc_ep; - if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { - deptsiz.d32 = -- dwc_read_reg32(&dev_if->in_ep_regs[i]->dieptsiz); -+ DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); - depctl.d32 = -- dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); -+ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); - - if (depctl.b.epdis && deptsiz.d32) { - set_current_pkt_info(GET_CORE_IF(pcd), dwc_ep); -@@ -3766,7 +4391,7 @@ int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) - } - - dsts.d32 = -- dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> - dev_global_regs->dsts); - dwc_ep->next_frame = dsts.b.soffn; - -@@ -3778,19 +4403,40 @@ int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) - } - - #else -- gintmsk_data_t intr_mask = {.d32 = 0 }; -- DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -- "IN ISOC Incomplete"); -+ depctl_data_t depctl = {.d32 = 0 }; -+ dwc_ep_t *dwc_ep; -+ dwc_otg_dev_if_t *dev_if; -+ int i; -+ dev_if = GET_CORE_IF(pcd)->dev_if; - -- intr_mask.b.incomplisoin = 1; -- dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -- intr_mask.d32, 0); -+ DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n"); -+ -+ for (i = 1; i <= dev_if->num_in_eps; ++i) { -+ dwc_ep = &pcd->in_ep[i-1].dwc_ep; -+ depctl.d32 = -+ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); -+ if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num, -+ dwc_ep->frm_overrun)) -+ { -+ depctl.d32 = -+ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); -+ depctl.b.snak = 1; -+ depctl.b.epdis = 1; -+ DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32); -+ } -+ } -+ } -+ -+ /*intr_mask.b.incomplisoin = 1; -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); */ - #endif //DWC_EN_ISOC - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.incomplisoin = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - - return 1; -@@ -3800,7 +4446,7 @@ int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) - * Incomplete ISO OUT Transfer Interrupt. - * - * This interrupt indicates that the core has dropped an ISO OUT -- * packet. The following conditions can be the cause: -+ * packet. The following conditions can be the cause: - * - FIFO Full, the entire packet would not fit in the FIFO. - * - CRC Error - * - Corrupted Token -@@ -3808,7 +4454,7 @@ int32_t dwc_otg_pcd_handle_incomplete_isoc_in_intr(dwc_otg_pcd_t * pcd) - * -# Determine the EP - * -# Set incomplete flag in dwc_ep structure - * -# Read any data from the FIFO -- * -# Disable EP. when "Endpoint Disabled" interrupt is received -+ * -# Disable EP. When "Endpoint Disabled" interrupt is received - * re-enable EP. - */ - int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) -@@ -3831,9 +4477,9 @@ int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) - if (pcd->out_ep[i].dwc_ep.active && - pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { - deptsiz.d32 = -- dwc_read_reg32(&dev_if->out_ep_regs[i]->doeptsiz); -+ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz); - depctl.d32 = -- dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); -+ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); - - if (depctl.b.epdis && deptsiz.d32) { - set_current_pkt_info(GET_CORE_IF(pcd), -@@ -3858,7 +4504,7 @@ int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) - } - - dsts.d32 = -- dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> - dev_global_regs->dsts); - dwc_ep->next_frame = dsts.b.soffn; - -@@ -3871,20 +4517,55 @@ int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) - #else - /** @todo implement ISR */ - gintmsk_data_t intr_mask = {.d32 = 0 }; -+ dwc_otg_core_if_t *core_if; -+ deptsiz_data_t deptsiz = {.d32 = 0 }; -+ depctl_data_t depctl = {.d32 = 0 }; -+ dctl_data_t dctl = {.d32 = 0 }; -+ dwc_ep_t *dwc_ep = NULL; -+ int i; -+ core_if = GET_CORE_IF(pcd); - -- DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -- "OUT ISOC Incomplete"); -+ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { -+ dwc_ep = &pcd->out_ep[i].dwc_ep; -+ depctl.d32 = -+ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); -+ if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) { -+ core_if->dev_if->isoc_ep = dwc_ep; -+ deptsiz.d32 = -+ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz); -+ break; -+ } -+ } -+ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); -+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); -+ intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); -+ -+ if (!intr_mask.b.goutnakeff) { -+ /* Unmask it */ -+ intr_mask.b.goutnakeff = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32); -+ } -+ if (!gintsts.b.goutnakeff) { -+ dctl.b.sgoutnak = 1; -+ } -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); - -- intr_mask.b.incomplisoout = 1; -- dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -- intr_mask.d32, 0); -+ depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); -+ if (depctl.b.epena) { -+ depctl.b.epdis = 1; -+ depctl.b.snak = 1; -+ } -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32); - --#endif /* DWC_EN_ISOC */ -+ intr_mask.d32 = 0; -+ intr_mask.b.incomplisoout = 1; -+ -+#endif /* DWC_EN_ISOC */ - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.incomplisoout = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - - return 1; -@@ -3898,34 +4579,35 @@ int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd) - { - dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; - depctl_data_t diepctl = {.d32 = 0 }; -- depctl_data_t diepctl_rd = {.d32 = 0 }; - gintmsk_data_t intr_mask = {.d32 = 0 }; - gintsts_data_t gintsts; -+ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); - int i; - - DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n"); - - /* Disable all active IN EPs */ -- diepctl.b.epdis = 1; -- diepctl.b.snak = 1; -- - for (i = 0; i <= dev_if->num_in_eps; i++) { -- diepctl_rd.d32 = -- dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); -- if (diepctl_rd.b.epena) { -- dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, -- diepctl.d32); -- } -+ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); -+ if (!(diepctl.b.eptype & 1) && diepctl.b.epena) { -+ if (core_if->start_predict > 0) -+ core_if->start_predict++; -+ diepctl.b.epdis = 1; -+ diepctl.b.snak = 1; -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, diepctl.d32); -+ } - } -+ -+ - /* Disable the Global IN NAK Effective Interrupt */ - intr_mask.b.ginnakeff = 1; -- dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, - intr_mask.d32, 0); - - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.ginnakeff = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - - return 1; -@@ -3937,20 +4619,71 @@ int32_t dwc_otg_pcd_handle_in_nak_effective(dwc_otg_pcd_t * pcd) - */ - int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) - { -+ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; - gintmsk_data_t intr_mask = {.d32 = 0 }; - gintsts_data_t gintsts; -+ depctl_data_t doepctl; -+ int i; - -- DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -- "Global IN NAK Effective\n"); -- /* Disable the Global IN NAK Effective Interrupt */ -+ /* Disable the Global OUT NAK Effective Interrupt */ - intr_mask.b.goutnakeff = 1; -- dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -- intr_mask.d32, 0); -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+ /* If DEV OUT NAK enabled*/ -+ if (pcd->core_if->core_params->dev_out_nak) { -+ /* Run over all out endpoints to determine the ep number on -+ * which the timeout has happened -+ */ -+ for (i = 0; i <= dev_if->num_out_eps; i++) { -+ if ( pcd->core_if->ep_xfer_info[i].state == 2 ) -+ break; -+ } -+ if (i > dev_if->num_out_eps) { -+ dctl_data_t dctl; -+ dctl.d32 = DWC_READ_REG32(&dev_if-> -+ dev_global_regs->dctl); -+ dctl.b.cgoutnak = 1; -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, -+ dctl.d32); -+ goto out; -+ } - -+ /* Disable the endpoint */ -+ doepctl.d32 = DWC_READ_REG32(&dev_if-> -+ out_ep_regs[i]->doepctl); -+ if (doepctl.b.epena) { -+ doepctl.b.epdis = 1; -+ doepctl.b.snak = 1; -+ } -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); -+ return 1; -+ } -+ /* We come here from Incomplete ISO OUT handler */ -+ if(dev_if->isoc_ep) -+ { -+ dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep; -+ uint32_t epnum = dwc_ep->num; -+ doepint_data_t doepint; -+ doepint.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint); -+ dev_if->isoc_ep = NULL; -+ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); -+ DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32); -+ if (doepctl.b.epena) { -+ doepctl.b.epdis = 1; -+ doepctl.b.snak = 1; -+ } -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, doepctl.d32); -+ return 1; -+ } else -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "Global OUT NAK Effective\n"); -+ -+out: - /* Clear interrupt */ - gintsts.d32 = 0; - gintsts.b.goutnakeff = 1; -- dwc_write_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, - gintsts.d32); - - return 1; -@@ -3977,11 +4710,15 @@ int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) - gintsts_data_t gintr_status; - int32_t retval = 0; - -+ /* Exit from ISR if core is hibernated */ -+ if (core_if->hibernation_suspend == 1) { -+ return retval; -+ } - #ifdef VERBOSE - DWC_DEBUGPL(DBG_ANY, "%s() gintsts=%08x gintmsk=%08x\n", - __func__, -- dwc_read_reg32(&global_regs->gintsts), -- dwc_read_reg32(&global_regs->gintmsk)); -+ DWC_READ_REG32(&global_regs->gintsts), -+ DWC_READ_REG32(&global_regs->gintmsk)); - #endif - - if (dwc_otg_is_device_mode(core_if)) { -@@ -3989,8 +4726,8 @@ int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) - #ifdef VERBOSE - DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%08x gintmsk=%08x\n", - __func__, -- dwc_read_reg32(&global_regs->gintsts), -- dwc_read_reg32(&global_regs->gintmsk)); -+ DWC_READ_REG32(&global_regs->gintsts), -+ DWC_READ_REG32(&global_regs->gintmsk)); - #endif - - gintr_status.d32 = dwc_otg_read_core_intr(core_if); -@@ -4008,9 +4745,6 @@ int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) - if (gintr_status.b.nptxfempty) { - retval |= dwc_otg_pcd_handle_np_tx_fifo_empty_intr(pcd); - } -- if (gintr_status.b.ginnakeff) { -- retval |= dwc_otg_pcd_handle_in_nak_effective(pcd); -- } - if (gintr_status.b.goutnakeff) { - retval |= dwc_otg_pcd_handle_out_nak_effective(pcd); - } -@@ -4035,9 +4769,6 @@ int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) - retval |= - dwc_otg_pcd_handle_end_periodic_frame_intr(pcd); - } -- if (gintr_status.b.epmismatch) { -- retval |= dwc_otg_pcd_handle_ep_mismatch_intr(core_if); -- } - if (gintr_status.b.inepint) { - if (!core_if->multiproc_int_enable) { - retval |= dwc_otg_pcd_handle_in_ep_intr(pcd); -@@ -4048,6 +4779,15 @@ int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) - retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); - } - } -+ if (gintr_status.b.epmismatch) { -+ retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd); -+ } -+ if (gintr_status.b.fetsusp) { -+ retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd); -+ } -+ if (gintr_status.b.ginnakeff) { -+ retval |= dwc_otg_pcd_handle_in_nak_effective(pcd); -+ } - if (gintr_status.b.incomplisoin) { - retval |= - dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd); -@@ -4057,7 +4797,7 @@ int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) - dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd); - } - -- /* In MPI mode De vice Endpoints intterrupts are asserted -+ /* In MPI mode Device Endpoints interrupts are asserted - * without setting outepintr and inepint bits set, so these - * Interrupt handlers are called without checking these bit-fields - */ -@@ -4067,11 +4807,11 @@ int32_t dwc_otg_pcd_handle_intr(dwc_otg_pcd_t * pcd) - } - #ifdef VERBOSE - DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__, -- dwc_read_reg32(&global_regs->gintsts)); -+ DWC_READ_REG32(&global_regs->gintsts)); - #endif - DWC_SPINUNLOCK(pcd->lock); - } - return retval; - } - --#endif /* DWC_HOST_ONLY */ -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -index 6ce0d97..59a1f33 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ -- * $Revision: #7 $ -- * $Date: 2009/04/03 $ -- * $Change: 1225160 $ -+ * $Revision: #19 $ -+ * $Date: 2011/10/26 $ -+ * $Change: 1873028 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -53,47 +53,9 @@ - * - */ - --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#if defined(LM_INTERFACE) --//# include --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --#include --#else --/* by 2.6.31, at least, the location of some headers has changed --*/ --#include --#endif -- --#elif defined(PLATFORM_INTERFACE) --#include --#endif -- --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) --#include --#include --#include --#else --/* by 2.6.31, at least, the location of some headers has changed --*/ --#include --#include --#include --#endif -- --#include -- -+#include "dwc_otg_os_dep.h" - #include "dwc_otg_pcd_if.h" -+#include "dwc_otg_pcd.h" - #include "dwc_otg_driver.h" - #include "dwc_otg_dbg.h" - -@@ -111,6 +73,26 @@ - - /* Display the contents of the buffer */ - extern void dump_msg(const u8 * buf, unsigned int length); -+/** -+ * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case -+ * if the endpoint is not found -+ */ -+static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) -+{ -+ int i; -+ if (pcd->ep0.priv == handle) { -+ return &pcd->ep0; -+ } -+ -+ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { -+ if (pcd->in_ep[i].priv == handle) -+ return &pcd->in_ep[i]; -+ if (pcd->out_ep[i].priv == handle) -+ return &pcd->out_ep[i]; -+ } -+ -+ return NULL; -+} - - /* USB Endpoint Operations */ - /* -@@ -164,6 +146,13 @@ static int ep_enable(struct usb_ep *usb_ep, - return -ESHUTDOWN; - } - -+ /* Delete after check - MAS */ -+#if 0 -+ nat = (uint32_t) ep_desc->wMaxPacketSize; -+ printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat); -+ nat = (nat >> 11) & 0x03; -+ printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat); -+#endif - retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd, - (const uint8_t *)ep_desc, - (void *)usb_ep); -@@ -227,7 +216,7 @@ static struct usb_request *dwc_otg_pcd_alloc_request(struct usb_ep *ep, - return 0; - } - memset(usb_req, 0, sizeof(*usb_req)); -- usb_req->dma = DWC_INVALID_DMA_ADDR; -+ usb_req->dma = DWC_DMA_ADDR_INVALID; - - return usb_req; - } -@@ -251,7 +240,7 @@ static void dwc_otg_pcd_free_request(struct usb_ep *ep, struct usb_request *req) - kfree(req); - } - --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) - /** - * This function allocates an I/O buffer to be used for a transfer - * to/from the specified endpoint. -@@ -329,7 +318,9 @@ static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, - gfp_t gfp_flags) - { - dwc_otg_pcd_t *pcd; -- int retval; -+ struct dwc_otg_pcd_ep *ep = NULL; -+ int retval = 0, is_isoc_ep = 0; -+ dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID; - - DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n", - __func__, usb_ep, usb_req, gfp_flags); -@@ -359,7 +350,44 @@ static int ep_queue(struct usb_ep *usb_ep, struct usb_request *usb_req, - usb_req->status = -EINPROGRESS; - usb_req->actual = 0; - -- retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, usb_req->dma, -+ ep = ep_from_handle(pcd, usb_ep); -+ if (ep == NULL) -+ is_isoc_ep = 0; -+ else -+ is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) -+ dma_addr = usb_req->dma; -+#else -+ if (GET_CORE_IF(pcd)->dma_enable) { -+ dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev; -+ struct device *dev = NULL; -+ -+ if (otg_dev != NULL) -+ dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep); -+ -+ if (usb_req->length != 0 && -+ usb_req->dma == DWC_DMA_ADDR_INVALID) { -+ dma_addr = dma_map_single(dev, usb_req->buf, -+ usb_req->length, -+ ep->dwc_ep.is_in ? -+ DMA_TO_DEVICE: -+ DMA_FROM_DEVICE); -+ } -+ } -+#endif -+ -+#ifdef DWC_UTE_PER_IO -+ if (is_isoc_ep == 1) { -+ retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, -+ usb_req->length, usb_req->zero, usb_req, -+ gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req); -+ if (retval) -+ return -EINVAL; -+ -+ return 0; -+ } -+#endif -+ retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, - usb_req->length, usb_req->zero, usb_req, - gfp_flags == GFP_ATOMIC ? 1 : 0); - if (retval) { -@@ -568,8 +596,10 @@ static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) - .alloc_request = dwc_otg_pcd_alloc_request, - .free_request = dwc_otg_pcd_free_request, - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) - .alloc_buffer = dwc_otg_pcd_alloc_buffer, - .free_buffer = dwc_otg_pcd_free_buffer, -+#endif - - .queue = ep_queue, - .dequeue = ep_dequeue, -@@ -610,7 +640,7 @@ static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) - .alloc_request = dwc_otg_pcd_alloc_request, - .free_request = dwc_otg_pcd_free_request, - --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) - .alloc_buffer = dwc_otg_pcd_alloc_buffer, - .free_buffer = dwc_otg_pcd_free_buffer, - #else -@@ -627,7 +657,7 @@ static void free_iso_request(struct usb_ep *ep, struct usb_iso_request *req) - - }; - --#endif /* _EN_ISOC_ */ -+#endif /* _EN_ISOC_ */ - /* Gadget Operations */ - /** - * The following gadget operations will be implemented in the DWC_otg -@@ -761,12 +791,78 @@ static int _isoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, - - return 0; - } --#endif /* DWC_EN_ISOC */ -+#endif /* DWC_EN_ISOC */ -+ -+#ifdef DWC_UTE_PER_IO -+/** -+ * Copy the contents of the extended request to the Linux usb_request's -+ * extended part and call the gadget's completion. -+ * -+ * @param pcd Pointer to the pcd structure -+ * @param ep_handle Void pointer to the usb_ep structure -+ * @param req_handle Void pointer to the usb_request structure -+ * @param status Request status returned from the portable logic -+ * @param ereq_port Void pointer to the extended request structure -+ * created in the the portable part that contains the -+ * results of the processed iso packets. -+ */ -+static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, -+ void *req_handle, int32_t status, void *ereq_port) -+{ -+ struct dwc_ute_iso_req_ext *ereqorg = NULL; -+ struct dwc_iso_xreq_port *ereqport = NULL; -+ struct dwc_ute_iso_packet_descriptor *desc_org = NULL; -+ int i; -+ struct usb_request *req; -+ //struct dwc_ute_iso_packet_descriptor * -+ //int status = 0; -+ -+ req = (struct usb_request *)req_handle; -+ ereqorg = &req->ext_req; -+ ereqport = (struct dwc_iso_xreq_port *)ereq_port; -+ desc_org = ereqorg->per_io_frame_descs; -+ -+ if (req && req->complete) { -+ /* Copy the request data from the portable logic to our request */ -+ for (i = 0; i < ereqport->pio_pkt_count; i++) { -+ desc_org[i].actual_length = -+ ereqport->per_io_frame_descs[i].actual_length; -+ desc_org[i].status = -+ ereqport->per_io_frame_descs[i].status; -+ } -+ -+ switch (status) { -+ case -DWC_E_SHUTDOWN: -+ req->status = -ESHUTDOWN; -+ break; -+ case -DWC_E_RESTART: -+ req->status = -ECONNRESET; -+ break; -+ case -DWC_E_INVALID: -+ req->status = -EINVAL; -+ break; -+ case -DWC_E_TIMEOUT: -+ req->status = -ETIMEDOUT; -+ break; -+ default: -+ req->status = status; -+ } -+ -+ /* And call the gadget's completion */ -+ req->complete(ep_handle, req); -+ } -+ -+ return 0; -+} -+#endif /* DWC_UTE_PER_IO */ - - static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle, - void *req_handle, int32_t status, uint32_t actual) - { - struct usb_request *req = (struct usb_request *)req_handle; -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) -+ struct dwc_otg_pcd_ep *ep = NULL; -+#endif - - if (req && req->complete) { - switch (status) { -@@ -786,9 +882,28 @@ static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle, - req->status = status; - - } -+ - req->actual = actual; -+ DWC_SPINUNLOCK(pcd->lock); - req->complete(ep_handle, req); -+ DWC_SPINLOCK(pcd->lock); -+ } -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) -+ ep = ep_from_handle(pcd, ep_handle); -+ if (GET_CORE_IF(pcd)->dma_enable) { -+ if (req->length != 0) { -+ dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev; -+ struct device *dev = NULL; -+ -+ if (otg_dev != NULL) -+ dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep); -+ -+ dma_unmap_single(dev, req->dma, req->length, -+ ep->dwc_ep.is_in ? -+ DMA_TO_DEVICE: DMA_FROM_DEVICE); -+ } - } -+#endif - - return 0; - } -@@ -850,11 +965,9 @@ static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req) - int retval = -DWC_E_INVALID; - if (gadget_wrapper->driver->cfi_feature_setup) { - retval = -- gadget_wrapper->driver->cfi_feature_setup(&gadget_wrapper-> -- gadget, -- (struct -- cfi_usb_ctrlrequest -- *)cfi_req); -+ gadget_wrapper->driver-> -+ cfi_feature_setup(&gadget_wrapper->gadget, -+ (struct cfi_usb_ctrlrequest *)cfi_req); - } - - return retval; -@@ -876,6 +989,9 @@ static int _cfi_setup(dwc_otg_pcd_t * pcd, void *cfi_req) - #ifdef DWC_UTE_CFI - .cfi_setup = _cfi_setup, - #endif -+#ifdef DWC_UTE_PER_IO -+ .xisoc_complete = _xisoc_complete, -+#endif - }; - - /** -@@ -938,6 +1054,7 @@ void gadget_add_eps(struct gadget_wrapper *d) - - int i; - struct usb_ep *ep; -+ int8_t dev_endpoints; - - DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__); - -@@ -968,12 +1085,13 @@ void gadget_add_eps(struct gadget_wrapper *d) - /** - * Initialize the EP structures. - */ -+ dev_endpoints = d->pcd->core_if->dev_if->num_in_eps; - -- for (i = 0; i < 15; i++) { -+ for (i = 0; i < dev_endpoints; i++) { - ep = &d->in_ep[i]; - - /* Init the usb_ep structure. */ -- ep->name = names[i + 1]; -+ ep->name = names[d->pcd->in_ep[i].dwc_ep.num]; - ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; - - /** -@@ -984,11 +1102,13 @@ void gadget_add_eps(struct gadget_wrapper *d) - list_add_tail(&ep->ep_list, &d->gadget.ep_list); - } - -- for (i = 0; i < 15; i++) { -+ dev_endpoints = d->pcd->core_if->dev_if->num_out_eps; -+ -+ for (i = 0; i < dev_endpoints; i++) { - ep = &d->out_ep[i]; - - /* Init the usb_ep structure. */ -- ep->name = names[15 + i + 1]; -+ ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num]; - ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; - - /** -@@ -1017,29 +1137,14 @@ static void dwc_otg_pcd_gadget_release(struct device *dev) - DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev); - } - --static struct gadget_wrapper *alloc_wrapper( --#ifdef LM_INTERFACE -- struct lm_device *_dev --#elif defined(PCI_INTERFACE) -- struct pci_dev *_dev --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *_dev --#endif -- ) -+static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev) - { --#ifdef LM_INTERFACE -- dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); --#endif - static char pcd_name[] = "dwc_otg_pcd"; -- -+ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); - struct gadget_wrapper *d; - int retval; - -- d = dwc_alloc(sizeof(*d)); -+ d = DWC_ALLOC(sizeof(*d)); - if (d == NULL) { - return NULL; - } -@@ -1048,12 +1153,13 @@ static struct gadget_wrapper *alloc_wrapper( - - d->gadget.name = pcd_name; - d->pcd = otg_dev->pcd; --#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) - strcpy(d->gadget.dev.bus_id, "gadget"); - #else -- /*d->gadget.dev.bus = NULL;*/ -- d->gadget.dev.init_name = "gadget"; -+ dev_set_name(&d->gadget.dev, "%s", "gadget"); - #endif -+ - d->gadget.dev.parent = &_dev->dev; - d->gadget.dev.release = dwc_otg_pcd_gadget_release; - d->gadget.ops = &dwc_otg_pcd_ops; -@@ -1065,7 +1171,7 @@ static struct gadget_wrapper *alloc_wrapper( - retval = device_register(&d->gadget.dev); - if (retval != 0) { - DWC_ERROR("device_register failed\n"); -- dwc_free(d); -+ DWC_FREE(d); - return NULL; - } - -@@ -1082,33 +1188,16 @@ static void free_wrapper(struct gadget_wrapper *d) - } - - device_unregister(&d->gadget.dev); -- dwc_free(d); -+ DWC_FREE(d); - } - - /** - * This function initialized the PCD portion of the driver. - * - */ --int pcd_init( --#ifdef LM_INTERFACE -- struct lm_device *_dev --#elif defined(PCI_INTERFACE) -- struct pci_dev *_dev --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *_dev --#endif -- ) -- -+int pcd_init(dwc_bus_dev_t *_dev) - { --#ifdef LM_INTERFACE -- dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); --#endif -- int devirq; -- -+ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); - int retval = 0; - - DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev); -@@ -1120,30 +1209,40 @@ int pcd_init( - return -ENOMEM; - } - -+ otg_dev->pcd->otg_dev = otg_dev; - gadget_wrapper = alloc_wrapper(_dev); - - /* - * Initialize EP structures - */ - gadget_add_eps(gadget_wrapper); -- - /* - * Setup interupt handler - */ - #ifdef PLATFORM_INTERFACE -- devirq = platform_get_irq(_dev, 0); --#else -- devirq = _dev->irq; --#endif -- DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", devirq); -- retval = request_irq(devirq, dwc_otg_pcd_irq, -+ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", -+ platform_get_irq(_dev, 0)); -+ retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq, - IRQF_SHARED, gadget_wrapper->gadget.name, - otg_dev->pcd); - if (retval != 0) { -- DWC_ERROR("request of irq%d failed\n", devirq); -+ DWC_ERROR("request of irq%d failed\n", -+ platform_get_irq(_dev, 0)); - free_wrapper(gadget_wrapper); - return -EBUSY; - } -+#else -+ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", -+ _dev->irq); -+ retval = request_irq(_dev->irq, dwc_otg_pcd_irq, -+ IRQF_SHARED | IRQF_DISABLED, -+ gadget_wrapper->gadget.name, otg_dev->pcd); -+ if (retval != 0) { -+ DWC_ERROR("request of irq%d failed\n", _dev->irq); -+ free_wrapper(gadget_wrapper); -+ return -EBUSY; -+ } -+#endif - - dwc_otg_pcd_start(gadget_wrapper->pcd, &fops); - -@@ -1153,23 +1252,9 @@ int pcd_init( - /** - * Cleanup the PCD. - */ --void pcd_remove( --#ifdef LM_INTERFACE -- struct lm_device *_dev --#elif defined(PCI_INTERFACE) -- struct pci_dev *_dev --#elif defined(PLATFORM_INTERFACE) -- struct platform_device *_dev --#endif -- ) -+void pcd_remove(dwc_bus_dev_t *_dev) - { --#ifdef LM_INTERFACE -- dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); --#elif defined(PCI_INTERFACE) -- dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); --#elif defined(PLATFORM_INTERFACE) -- dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); --#endif -+ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); - dwc_otg_pcd_t *pcd = otg_dev->pcd; - - DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev); -@@ -1196,6 +1281,7 @@ void pcd_remove( - * then a host may connect again, or the driver might get unbound. - * - * @param driver The driver being registered -+ * @param bind The bind function of gadget driver - */ - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) - int usb_gadget_register_driver(struct usb_gadget_driver *driver) -@@ -1213,7 +1299,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) - !driver->bind || - #else -- !bind || -+ !bind || - #endif - !driver->unbind || !driver->disconnect || !driver->setup) { - DWC_DEBUGPL(DBG_PCDV, "EINVAL\n"); -@@ -1249,7 +1335,6 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - driver->driver.name); - return 0; - } -- - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) - EXPORT_SYMBOL(usb_gadget_register_driver); - #else -@@ -1285,4 +1370,4 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) - - EXPORT_SYMBOL(usb_gadget_unregister_driver); - --#endif /* DWC_HOST_ONLY */ -+#endif /* DWC_HOST_ONLY */ -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h -index e8220ad..8dc648b 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_regs.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h -@@ -1,13 +1,13 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $ -- * $Revision: #76 $ -- * $Date: 2009/04/02 $ -- * $Change: 1224216 $ -+ * $Revision: #97 $ -+ * $Date: 2011/10/24 $ -+ * $Change: 1871160 $ - * - * 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 -@@ -17,7 +17,7 @@ - * 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 -@@ -64,7 +64,7 @@ - */ - - /****************************************************************************/ --/** DWC_otg Core registers . -+/** DWC_otg Core registers . - * The dwc_otg_core_global_regs structure defines the size - * and relative field offsets for the Core Global registers. - */ -@@ -132,21 +132,27 @@ - volatile uint32_t ghwcfg3; - /**User HW Config4 Register (Read Only). Offset: 050h*/ - volatile uint32_t ghwcfg4; -- /** Core LPM Configuration register */ -+ /** Core LPM Configuration register Offset: 054h*/ - volatile uint32_t glpmcfg; -- /** Reserved Offset: 058h-0FFh */ -- volatile uint32_t reserved[42]; -+ /** Global PowerDn Register Offset: 058h */ -+ volatile uint32_t gpwrdn; -+ /** Global DFIFO SW Config Register Offset: 05Ch */ -+ volatile uint32_t gdfifocfg; -+ /** ADP Control Register Offset: 060h */ -+ volatile uint32_t adpctl; -+ /** Reserved Offset: 064h-0FFh */ -+ volatile uint32_t reserved39[39]; - /** Host Periodic Transmit FIFO Size Register. Offset: 100h */ - volatile uint32_t hptxfsiz; -- /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, -- otherwise Device Transmit FIFO#n Register. -+ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, -+ otherwise Device Transmit FIFO#n Register. - * Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15). */ -- volatile uint32_t dptxfsiz_dieptxf[15]; -+ volatile uint32_t dtxfsiz[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 -+ * and Status Register (GOTGCTL). Set the bits using the bit - * fields then write the d32 value to the register. - */ - typedef union gotgctl_data { -@@ -156,18 +162,26 @@ - struct { - unsigned sesreqscs:1; - unsigned sesreq:1; -- unsigned reserved2_7:6; -+ unsigned vbvalidoven:1; -+ unsigned vbvalidovval:1; -+ unsigned avalidoven:1; -+ unsigned avalidovval:1; -+ unsigned bvalidoven:1; -+ unsigned bvalidovval:1; - unsigned hstnegscs:1; - unsigned hnpreq:1; - unsigned hstsethnpen:1; - unsigned devhnpen:1; - unsigned reserved12_15:4; - unsigned conidsts:1; -- unsigned reserved17:1; -+ unsigned dbnctime:1; - unsigned asesvld:1; - unsigned bsesvld:1; -- unsigned currmod:1; -- unsigned reserved21_31:11; -+ unsigned otgver:1; -+ unsigned reserved1:1; -+ unsigned multvalidbc:5; -+ unsigned chirpen:1; -+ unsigned reserved28_31:4; - } b; - } gotgctl_data_t; - -@@ -194,7 +208,7 @@ - /** Host Negotiation Success Status Change */ - unsigned hstnegsucstschng:1; - -- unsigned reserver10_16:7; -+ unsigned reserved10_16:7; - - /** Host Negotiation Detected */ - unsigned hstnegdet:1; -@@ -202,15 +216,17 @@ - unsigned adevtoutchng:1; - /** Debounce Done */ - unsigned debdone:1; -+ /** Multi-Valued input changed */ -+ unsigned mvic:1; - -- unsigned reserved31_20:12; -+ unsigned reserved31_21:11; - - } 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 -+ * Register (GAHBCFG). Set/clear the bits using the bit fields then - * write the d32 value to the register. - */ - typedef union gahbcfg_data { -@@ -235,13 +251,17 @@ - unsigned ptxfemplvl:1; - #define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1 - #define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 -- unsigned reserved9_31:23; -+ unsigned reserved9_20:12; -+ unsigned remmemsupp:1; -+ unsigned notialldmawrit:1; -+ unsigned ahbsingle:1; -+ unsigned reserved24_31:8; - } 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 -+ * Register (GUSBCFG). Set the bits using the bit fields then write - * the d32 value to the register. - */ - typedef union gusbcfg_data { -@@ -258,7 +278,7 @@ - unsigned srpcap:1; - unsigned hnpcap:1; - unsigned usbtrdtim:4; -- unsigned nptxfrwnden:1; -+ unsigned reserved1:1; - unsigned phylpwrclksel:1; - unsigned otgutmifssel:1; - unsigned ulpi_fsls:1; -@@ -267,120 +287,19 @@ - unsigned ulpi_ext_vbus_drv:1; - unsigned ulpi_int_vbus_indicator:1; - unsigned term_sel_dl_pulse:1; -- unsigned reserved23_25:3; -+ unsigned indicator_complement:1; -+ unsigned indicator_pass_through:1; -+ unsigned ulpi_int_prot_dis:1; - unsigned ic_usb_cap:1; - unsigned ic_traffic_pull_remove:1; - unsigned tx_end_delay:1; -- unsigned reserved29_31:3; -+ unsigned force_host_mode:1; -+ unsigned force_dev_mode:1; -+ unsigned reserved31:1; - } 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 d32 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 - * d32 value to the register. -@@ -434,7 +353,7 @@ - */ - unsigned hsftrst:1; - /** Host Frame Counter Reset (Host Only)
-- * -+ * - * 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 -@@ -449,27 +368,27 @@ - /** RxFIFO Flush (RxFFlsh) (Device and Host) - * - * The application can flush the entire Receive FIFO -- * using this bit.

The application must first -+ * using this bit. The application must first - * ensure that the core is not in the middle of a -- * transaction.

The application should write into -+ * transaction. 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.

The -+ * is writing the data in to the FIFO. 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). -+ /** TxFIFO Flush (TxFFlsh) (Device and Host). - * - * This bit is used to selectively flush a single or -- * all transmit FIFOs. The application must first -+ * all transmit FIFOs. The application must first - * ensure that the core is not in the middle of a -- * transaction.

The application should write into -+ * transaction. 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.

The -+ * is reading the data out of the FIFO. 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) -@@ -478,7 +397,7 @@ - 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 -@@ -496,7 +415,7 @@ - /** Reserved */ - unsigned reserved11_29:19; - /** DMA Request Signal. Indicated DMA request is in -- * probress. Used for debug purpose. */ -+ * probress. Used for debug purpose. */ - unsigned dmareq:1; - /** AHB Master Idle. Indicates the AHB Master State - * Machine is in IDLE condition. */ -@@ -506,7 +425,7 @@ - - /** - * This union represents the bit fields of the Core Interrupt Mask -- * Register (GINTMSK). Set/clear the bits using the bit fields then -+ * Register (GINTMSK). Set/clear the bits using the bit fields then - * write the d32 value to the register. - */ - typedef union gintmsk_data { -@@ -522,7 +441,7 @@ - unsigned nptxfempty:1; - unsigned ginnakeff:1; - unsigned goutnakeff:1; -- unsigned reserved8:1; -+ unsigned ulpickint:1; - unsigned i2cintr:1; - unsigned erlysuspend:1; - unsigned usbsuspend:1; -@@ -530,13 +449,14 @@ - unsigned enumdone:1; - unsigned isooutdrop:1; - unsigned eopframe:1; -- unsigned reserved16:1; -+ unsigned restoredone:1; - unsigned epmismatch:1; - unsigned inepintr:1; - unsigned outepintr:1; - unsigned incomplisoin:1; - unsigned incomplisoout:1; -- unsigned reserved22_23:2; -+ unsigned fetsusp:1; -+ unsigned resetdet:1; - unsigned portintr:1; - unsigned hcintr:1; - unsigned ptxfempty:1; -@@ -567,7 +487,7 @@ - unsigned nptxfempty:1; - unsigned ginnakeff:1; - unsigned goutnakeff:1; -- unsigned reserved8:1; -+ unsigned ulpickint:1; - unsigned i2cintr:1; - unsigned erlysuspend:1; - unsigned usbsuspend:1; -@@ -575,13 +495,14 @@ - unsigned enumdone:1; - unsigned isooutdrop:1; - unsigned eopframe:1; -- unsigned intokenrx:1; -+ unsigned restoredone:1; - unsigned epmismatch:1; - unsigned inepint:1; - unsigned outepintr:1; - unsigned incomplisoin:1; - unsigned incomplisoout:1; -- unsigned reserved22_23:2; -+ unsigned fetsusp:1; -+ unsigned resetdet:1; - unsigned portintr:1; - unsigned hcintr:1; - unsigned ptxfempty:1; -@@ -594,8 +515,8 @@ - } 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 d32 -+ * This union represents the bit fields in the Device Receive Status Read and -+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 - * element then read out the bits using the bit elements. - */ - typedef union device_grxsts_data { -@@ -615,13 +536,13 @@ - #define DWC_DSTS_SETUP_UPDT 0x6 // SETUP Packet - unsigned pktsts:4; - unsigned fn:4; -- unsigned reserved:7; -+ unsigned reserved25_31: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 d32 -+ * This union represents the bit fields in the Host Receive Status Read and -+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 - * element then read out the bits using the bit elements. - */ - typedef union host_grxsts_data { -@@ -639,14 +560,14 @@ - #define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5 - #define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7 - -- unsigned reserved:11; -+ unsigned reserved21_31: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 d32 element then -- * read out the bits using the bit elements. -+ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the d32 element -+ * then read out the bits using the bit elements. - */ - typedef union fifosize_data { - /** raw register data */ -@@ -671,10 +592,10 @@ - struct { - unsigned nptxfspcavail:16; - unsigned nptxqspcavail:8; -- /** Top of the Non-Periodic Transmit Request Queue -+ /** Top of the Non-Periodic Transmit Request Queue - * - bit 24 - Terminate (Last entry for the selected - * channel/EP) -- * - bits 26:25 - Token Type -+ * - bits 26:25 - Token Type - * - 2'b00 - IN/OUT - * - 2'b01 - Zero Length OUT - * - 2'b10 - PING/Complete Split -@@ -721,13 +642,81 @@ - unsigned ack:1; - unsigned i2csuspctl:1; - unsigned i2cdevaddr:2; -- unsigned reserved:2; -+ unsigned i2cdatse0:1; -+ unsigned reserved:1; - unsigned rw:1; - unsigned bsydne:1; - } b; - } gi2cctl_data_t; - - /** -+ * This union represents the bit fields in the PHY Vendor Control Register -+ * (GPVNDCTL). Read the register into the d32 element then read out the -+ * bits using the bit elements. -+ */ -+typedef union gpvndctl_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ unsigned regdata:8; -+ unsigned vctrl:8; -+ unsigned regaddr16_21:6; -+ unsigned regwr:1; -+ unsigned reserved23_24:2; -+ unsigned newregreq:1; -+ unsigned vstsbsy:1; -+ unsigned vstsdone:1; -+ unsigned reserved28_30:3; -+ unsigned disulpidrvr:1; -+ } b; -+} gpvndctl_data_t; -+ -+/** -+ * This union represents the bit fields in the General Purpose -+ * Input/Output Register (GGPIO). -+ * Read the register into the d32 element then read out the -+ * bits using the bit elements. -+ */ -+typedef union ggpio_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ unsigned gpi:16; -+ unsigned gpo:16; -+ } b; -+} ggpio_data_t; -+ -+/** -+ * This union represents the bit fields in the User ID Register -+ * (GUID). Read the register into the d32 element then read out the -+ * bits using the bit elements. -+ */ -+typedef union guid_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ unsigned rwdata:32; -+ } b; -+} guid_data_t; -+ -+/** -+ * This union represents the bit fields in the Synopsys ID Register -+ * (GSNPSID). Read the register into the d32 element then read out the -+ * bits using the bit elements. -+ */ -+typedef union gsnpsid_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ unsigned rwdata:32; -+ } b; -+} gsnpsid_data_t; -+ -+/** - * This union represents the bit fields in the User HW Config1 - * Register. Read the register into the d32 element then read - * out the bits using the bit elements. -@@ -794,7 +783,7 @@ - unsigned nonperio_tx_q_depth:2; - unsigned host_perio_tx_q_depth:2; - unsigned dev_token_q_depth:5; -- unsigned reserved31:1; -+ unsigned otg_enable_ic_usb:1; - } b; - } hwcfg2_data_t; - -@@ -816,9 +805,9 @@ - unsigned vendor_ctrl_if:1; - unsigned optional_features:1; - unsigned synch_reset_type:1; -- unsigned otg_enable_ic_usb:1; -+ unsigned adp_supp:1; - unsigned otg_enable_hsic:1; -- unsigned reserved14:1; -+ unsigned bc_support:1; - unsigned otg_lpm_en:1; - unsigned dfifo_depth:16; - } b; -@@ -836,7 +825,9 @@ - struct { - unsigned num_dev_perio_in_ep:4; - unsigned power_optimiz:1; -- unsigned min_ahb_freq:9; -+ unsigned min_ahb_freq:1; -+ unsigned part_power_down:1; -+ unsigned reserved:7; - unsigned utmi_phy_data_width:2; - unsigned num_dev_mode_ctrl_ep:4; - unsigned iddig_filt_en:1; -@@ -851,6 +842,229 @@ - } b; - } hwcfg4_data_t; - -+/** -+ * This union represents the bit fields of the Core LPM Configuration -+ * Register (GLPMCFG). Set the bits using bit fields then write -+ * the d32 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 ADP Timer, Control and -+ * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write -+ * the d32 value to the register. -+ */ -+typedef union adpctl_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** Probe Discharge (PRB_DSCHG) -+ * These bits set the times for TADP_DSCHG. -+ * These bits are defined as follows: -+ * 2'b00 - 4 msec -+ * 2'b01 - 8 msec -+ * 2'b10 - 16 msec -+ * 2'b11 - 32 msec -+ */ -+ unsigned prb_dschg:2; -+ /** Probe Delta (PRB_DELTA) -+ * These bits set the resolution for RTIM value. -+ * The bits are defined in units of 32 kHz clock cycles as follows: -+ * 2'b00 - 1 cycles -+ * 2'b01 - 2 cycles -+ * 2'b10 - 3 cycles -+ * 2'b11 - 4 cycles -+ * For example if this value is chosen to 2'b01, it means that RTIM -+ * increments for every 3(three) 32Khz clock cycles. -+ */ -+ unsigned prb_delta:2; -+ /** Probe Period (PRB_PER) -+ * These bits sets the TADP_PRD as shown in Figure 4 as follows: -+ * 2'b00 - 0.625 to 0.925 sec (typical 0.775 sec) -+ * 2'b01 - 1.25 to 1.85 sec (typical 1.55 sec) -+ * 2'b10 - 1.9 to 2.6 sec (typical 2.275 sec) -+ * 2'b11 - Reserved -+ */ -+ unsigned prb_per:2; -+ /** These bits capture the latest time it took for VBUS to ramp from -+ * VADP_SINK to VADP_PRB. -+ * 0x000 - 1 cycles -+ * 0x001 - 2 cycles -+ * 0x002 - 3 cycles -+ * etc -+ * 0x7FF - 2048 cycles -+ * A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec. -+ */ -+ unsigned rtim:11; -+ /** Enable Probe (EnaPrb) -+ * When programmed to 1'b1, the core performs a probe operation. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned enaprb:1; -+ /** Enable Sense (EnaSns) -+ * When programmed to 1'b1, the core performs a Sense operation. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned enasns:1; -+ /** ADP Reset (ADPRes) -+ * When set, ADP controller is reset. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned adpres:1; -+ /** ADP Enable (ADPEn) -+ * When set, the core performs either ADP probing or sensing -+ * based on EnaPrb or EnaSns. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned adpen:1; -+ /** ADP Probe Interrupt (ADP_PRB_INT) -+ * When this bit is set, it means that the VBUS -+ * voltage is greater than VADP_PRB or VADP_PRB is reached. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned adp_prb_int:1; -+ /** -+ * ADP Sense Interrupt (ADP_SNS_INT) -+ * When this bit is set, it means that the VBUS voltage is greater than -+ * VADP_SNS value or VADP_SNS is reached. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned adp_sns_int:1; -+ /** ADP Tomeout Interrupt (ADP_TMOUT_INT) -+ * This bit is relevant only for an ADP probe. -+ * When this bit is set, it means that the ramp time has -+ * completed ie ADPCTL.RTIM has reached its terminal value -+ * of 0x7FF. This is a debug feature that allows software -+ * to read the ramp time after each cycle. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned adp_tmout_int:1; -+ /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK) -+ * When this bit is set, it unmasks the interrupt due to ADP_PRB_INT. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned adp_prb_int_msk:1; -+ /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK) -+ * When this bit is set, it unmasks the interrupt due to ADP_SNS_INT. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned adp_sns_int_msk:1; -+ /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK) -+ * When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT. -+ * This bit is valid only if OTG_Ver = 1'b1. -+ */ -+ unsigned adp_tmout_int_msk:1; -+ /** Access Request -+ * 2'b00 - Read/Write Valid (updated by the core) -+ * 2'b01 - Read -+ * 2'b00 - Write -+ * 2'b00 - Reserved -+ */ -+ unsigned ar:2; -+ /** Reserved */ -+ unsigned reserved29_31:3; -+ } b; -+} adpctl_data_t; -+ - //////////////////////////////////////////// - // Device Registers - /** -@@ -931,7 +1145,7 @@ - unsigned nzstsouthshk:1; - #define DWC_DCFG_SEND_STALL 1 - -- unsigned reserved3:1; -+ unsigned ena32khzs:1; - /** Device Addresses */ - unsigned devaddr:7; - /** Periodic Frame Interval */ -@@ -940,12 +1154,17 @@ - #define DWC_DCFG_FRAME_INTERVAL_85 1 - #define DWC_DCFG_FRAME_INTERVAL_90 2 - #define DWC_DCFG_FRAME_INTERVAL_95 3 -+ -+ /** Enable Device OUT NAK for bulk in DDMA mode */ -+ unsigned endevoutnak:1; - -- unsigned reserved13_17:5; -+ unsigned reserved14_17:4; - /** In Endpoint Mis-match count */ - unsigned epmscnt:5; - /** Enable Descriptor DMA in Device mode */ - unsigned descdma:1; -+ unsigned perschintvl:2; -+ unsigned resvalid:6; - } b; - } dcfg_data_t; - -@@ -977,19 +1196,20 @@ - unsigned sgoutnak:1; - /** Clear Global OUT NAK */ - unsigned cgoutnak:1; -- - /** Power-On Programming Done */ - unsigned pwronprgdone:1; -- /** Global Continue on BNA */ -- unsigned gcontbna:1; -+ /** Reserved */ -+ unsigned reserved:1; - /** Global Multi Count */ - unsigned gmc:2; - /** Ignore Frame Number for ISOC EPs */ - unsigned ifrmnum:1; - /** NAK on Babble */ - unsigned nakonbble:1; -+ /** Enable Continue on BNA */ -+ unsigned encontonbna:1; - -- unsigned reserved17_31:15; -+ unsigned reserved18_31:14; - } b; - } dctl_data_t; - -@@ -1044,9 +1264,9 @@ - unsigned intktxfemp:1; - /** IN Token Received with EP mismatch mask */ - unsigned intknepmis:1; -- /** IN Endpoint HAK Effective mask */ -+ /** IN Endpoint NAK Effective mask */ - unsigned inepnakeff:1; -- /** IN Endpoint HAK Effective mask */ -+ /** Reserved */ - unsigned emptyintr:1; - - unsigned txfifoundrn:1; -@@ -1063,7 +1283,7 @@ - } diepint_data_t; - - /** -- * This union represents the bit fields in the Device IN EP -+ * This union represents the bit fields in the Device IN EP - * Common/Dedicated Interrupt Mask Register. - */ - typedef union diepint_data diepmsk_data_t; -@@ -1116,7 +1336,7 @@ - } doepint_data_t; - - /** -- * This union represents the bit fields in the Device OUT EP -+ * This union represents the bit fields in the Device OUT EP - * Common/Dedicated Interrupt Mask Register. - */ - typedef union doepint_data doepmsk_data_t; -@@ -1221,8 +1441,11 @@ - unsigned rx_thr_en:1; - /** Rx Thr. Length */ - unsigned rx_thr_len:9; -+ unsigned reserved26:1; -+ /** Arbiter Parking Enable*/ -+ unsigned arbprken:1; - /** Reserved */ -- unsigned reserved26_31:6; -+ unsigned reserved28_31:4; - } b; - } dthrctl_data_t; - -@@ -1275,9 +1498,8 @@ - /** Device OUT Endpoint Control Register. Offset:B00h + - * (ep_num * 20h) + 00h */ - volatile uint32_t doepctl; -- /** Device OUT Endpoint Frame number Register. Offset: -- * B00h + (ep_num * 20h) + 04h */ -- volatile uint32_t doepfn; -+ /** Reserved. Offset:B00h + (ep_num * 20h) + 04h */ -+ uint32_t reserved04; - /** Device OUT Endpoint Interrupt Register. Offset:B00h + - * (ep_num * 20h) + 08h */ - volatile uint32_t doepint; -@@ -1306,7 +1528,7 @@ - uint32_t d32; - /** register bits */ - struct { -- /** Maximum Packet Size -+ /** Maximum Packet Size - * IN/OUT EPn - * IN/OUT EP0 - 2 bits - * 2'b00: 64 Bytes -@@ -1319,8 +1541,8 @@ - #define DWC_DEP0CTL_MPS_16 2 - #define DWC_DEP0CTL_MPS_8 3 - -- /** Next Endpoint -- * IN EPn/IN EP0 -+ /** Next Endpoint -+ * IN EPn/IN EP0 - * OUT EPn/OUT EP0 - reserved */ - unsigned nextep:4; - -@@ -1336,7 +1558,7 @@ - * activated. Application use the SetD1PID and - * SetD0PID fields of this register to program either - * D0 or D1 PID. -- * -+ * - * The encoding for this field is - * - 0: D0 - * - 1: D1 -@@ -1346,14 +1568,14 @@ - /** NAK Status */ - unsigned naksts:1; - -- /** Endpoint Type -+ /** Endpoint Type - * 2'b00: Control - * 2'b01: Isochronous - * 2'b10: Bulk - * 2'b11: Interrupt */ - unsigned eptype:2; - -- /** Snoop Mode -+ /** Snoop Mode - * OUT EPn/OUT EP0 - * IN EPn/IN EP0 - reserved */ - unsigned snp:1; -@@ -1361,7 +1583,7 @@ - /** Stall Handshake */ - unsigned stall:1; - -- /** Tx Fifo Number -+ /** Tx Fifo Number - * IN EPn/IN EP0 - * OUT EPn/OUT EP0 - reserved */ - unsigned txfnum:4; -@@ -1407,6 +1629,8 @@ - struct { - /** Transfer size */ - unsigned xfersize:19; -+/** Max packet count for EP (pow(2,10)-1) */ -+#define MAX_PKT_CNT 1023 - /** Packet Count */ - unsigned pktcnt:10; - /** Multi Count - Periodic IN endpoints */ -@@ -1430,9 +1654,9 @@ - /** Reserved */ - unsigned reserved7_18:12; - /** Packet Count */ -- unsigned pktcnt:1; -+ unsigned pktcnt:2; - /** Reserved */ -- unsigned reserved20_28:9; -+ unsigned reserved21_28:8; - /**Setup Packet Count (DOEPTSIZ0 Only) */ - unsigned supcnt:2; - unsigned reserved31; -@@ -1460,7 +1684,7 @@ - /** - * This union represents the bit fields in the DMA Descriptor - * status quadlet. Read the quadlet into the d32 member then -- * set/clear the bits using the bit, b_iso_out and -+ * set/clear the bits using the bit, b_iso_out and - * b_iso_in elements. - */ - typedef union dev_dma_desc_sts { -@@ -1470,8 +1694,9 @@ - struct { - /** Received number of bytes */ - unsigned bytes:16; -- -- unsigned reserved16_22:7; -+ /** NAK bit - only for OUT EPs */ -+ unsigned nak:1; -+ unsigned reserved17_22:6; - /** Multiple Transfer - only for OUT EPs */ - unsigned mtrf:1; - /** Setup Packet received - only for OUT EPs */ -@@ -1488,7 +1713,7 @@ - unsigned bs:2; - } b; - --#ifdef DWC_EN_ISOC -+//#ifdef DWC_EN_ISOC - /** iso out quadlet bits */ - struct { - /** Received number of bytes */ -@@ -1530,11 +1755,11 @@ - /** Buffer Status */ - unsigned bs:2; - } b_iso_in; --#endif /* DWC_EN_ISOC */ -+//#endif /* DWC_EN_ISOC */ - } dev_dma_desc_sts_t; - --/** -- * DMA Descriptor structure -+/** -+ * DMA Descriptor structure - * - * DMA Descriptor structure contains two quadlets: - * Status quadlet and Data buffer pointer. -@@ -1558,8 +1783,8 @@ - dwc_otg_device_global_regs_t *dev_global_regs; - #define DWC_DEV_GLOBAL_REG_OFFSET 0x800 - -- /** -- * Device Logical IN Endpoint-Specific Registers 900h-AFCh -+ /** -+ * Device Logical IN Endpoint-Specific Registers 900h-AFCh - */ - dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS]; - #define DWC_DEV_IN_EP_REG_OFFSET 0x900 -@@ -1613,6 +1838,8 @@ - - /** Setup Packet Detected - if set clear NAK when queueing */ - uint32_t spd; -+ /** Isoc ep pointer on which incomplete happens */ -+ void *isoc_ep; - - } dwc_otg_dev_if_t; - -@@ -1643,20 +1870,17 @@ - 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 d32 member then set/clear the bits using - * the bit elements. Write the d32 member to the hcfg register. - */ --typedef union hcfg_data --{ -+typedef union hcfg_data { - /** raw register data */ - uint32_t d32; - - /** register bits */ -- struct -- { -+ struct { - /** FS/LS Phy Clock Select */ - unsigned fslspclksel:2; - #define DWC_HCFG_30_60_MHZ 0 -@@ -1665,21 +1889,26 @@ - - /** FS/LS Only Support */ - unsigned fslssupp:1; -- unsigned reserved3_22 : 20; -+ unsigned reserved3_6:4; -+ /** Enable 32-KHz Suspend Mode */ -+ unsigned ena32khzs:1; -+ /** Resume Validation Periiod */ -+ unsigned resvalid:8; -+ unsigned reserved16_22:7; - /** Enable Scatter/gather DMA in Host mode */ -- unsigned descdma : 1; -+ unsigned descdma:1; - /** Frame List Entries */ -- unsigned frlisten: 2; -+ unsigned frlisten:2; - /** Enable Periodic Scheduling */ -- unsigned perschedena: 1; -- /** Periodic Scheduling Enabled Status */ -- unsigned perschedstat: 1; -+ unsigned perschedena:1; -+ unsigned reserved27_30:4; -+ unsigned modechtimen:1; - } b; - } hcfg_data_t; - - /** - * This union represents the bit fields in the Host Frame Remaing/Number -- * Register. -+ * Register. - */ - typedef union hfir_data { - /** raw register data */ -@@ -1688,13 +1917,14 @@ - /** register bits */ - struct { - unsigned frint:16; -- unsigned reserved:16; -+ unsigned hfirrldctrl:1; -+ unsigned reserved:15; - } b; - } hfir_data_t; - - /** - * This union represents the bit fields in the Host Frame Remaing/Number -- * Register. -+ * Register. - */ - typedef union hfnum_data { - /** raw register data */ -@@ -1765,8 +1995,8 @@ - } hprt0_data_t; - - /** -- * This union represents the bit fields in the Host All Interrupt -- * Register. -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. - */ - typedef union haint_data { - /** raw register data */ -@@ -1799,8 +2029,8 @@ - } haint_data_t; - - /** -- * This union represents the bit fields in the Host All Interrupt -- * Register. -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. - */ - typedef union haintmsk_data { - /** raw register data */ -@@ -1832,11 +2062,10 @@ - } b2; - } haintmsk_data_t; - --/** -+/** - * Host Channel Specific Registers. 500h-5FCh - */ --typedef struct dwc_otg_hc_regs --{ -+typedef struct dwc_otg_hc_regs { - /** Host Channel 0 Characteristic Register. Offset: 500h + (chan_num * 20h) + 00h */ - volatile uint32_t hcchar; - /** Host Channel 0 Split Control Register. Offset: 500h + (chan_num * 20h) + 04h */ -@@ -1934,16 +2163,14 @@ - } hcsplt_data_t; - - /** -- * This union represents the bit fields in the Host All Interrupt -- * Register. -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. - */ --typedef union hcint_data --{ -+typedef union hcint_data { - /** raw register data */ - uint32_t d32; - /** register bits */ -- struct -- { -+ struct { - /** Transfer Complete */ - unsigned xfercomp:1; - /** Channel Halted */ -@@ -1967,13 +2194,13 @@ - /** Data Toggle Error */ - unsigned datatglerr:1; - /** Buffer Not Available (only for DDMA mode) */ -- unsigned bna : 1; -+ unsigned bna:1; - /** Exessive transaction error (only for DDMA mode) */ -- unsigned xcs_xact : 1; -+ unsigned xcs_xact:1; - /** Frame List Rollover interrupt */ -- unsigned frm_list_roll : 1; -+ unsigned frm_list_roll:1; - /** Reserved */ -- unsigned reserved14_31 : 18; -+ unsigned reserved14_31:18; - } b; - } hcint_data_t; - -@@ -1983,29 +2210,27 @@ - * bits using the bit elements. Write the d32 member to the - * hcintmsk register. - */ --typedef union hcintmsk_data --{ -+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; -+ 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; - -@@ -2016,14 +2241,12 @@ - * hcchar register. - */ - --typedef union hctsiz_data --{ -+typedef union hctsiz_data { - /** raw register data */ - uint32_t d32; - - /** register bits */ -- struct -- { -+ struct { - /** Total transfer size in bytes */ - unsigned xfersize:19; - -@@ -2047,22 +2270,21 @@ - /** Do PING protocol when 1 */ - unsigned dopng:1; - } b; -- -+ - /** register bits */ -- struct -- { -+ struct { - /** Scheduling information */ -- unsigned schinfo : 8; -- -- /** Number of transfer descriptors. -+ unsigned schinfo:8; -+ -+ /** Number of transfer descriptors. - * Max value: -- * 64 in general, -+ * 64 in general, - * 256 only for HS isochronous endpoint. - */ -- unsigned ntd : 8; -+ unsigned ntd:8; - - /** Data packets to transfer */ -- unsigned reserved16_28 : 13; -+ unsigned reserved16_28:13; - - /** - * Packet ID for next data packet -@@ -2071,30 +2293,27 @@ - * 2: DATA1 - * 3: MDATA (non-Control) - */ -- unsigned pid : 2; -+ unsigned pid:2; - - /** Do PING protocol when 1 */ -- unsigned dopng : 1; -+ unsigned dopng:1; - } b_ddma; - } hctsiz_data_t; - -- - /** -- * This union represents the bit fields in the Host DMA Address -+ * This union represents the bit fields in the Host DMA Address - * Register used in Descriptor DMA mode. - */ --typedef union hcdma_data --{ -+typedef union hcdma_data { - /** raw register data */ - uint32_t d32; - /** register bits */ -- struct -- { -- unsigned reserved0_2 : 3; -+ struct { -+ unsigned reserved0_2:3; - /** Current Transfer Descriptor. Not used for ISOC */ -- unsigned ctd : 8; -+ unsigned ctd:8; - /** Start Address of Descriptor List */ -- unsigned dma_addr : 21; -+ unsigned dma_addr:21; - } b; - } hcdma_data_t; - -@@ -2103,8 +2322,7 @@ - * status quadlet for host mode. Read the quadlet into the d32 member then - * set/clear the bits using the bit elements. - */ --typedef union host_dma_desc_sts --{ -+typedef union host_dma_desc_sts { - /** raw register data */ - uint32_t d32; - /** quadlet bits */ -@@ -2112,44 +2330,44 @@ - /* for non-isochronous */ - struct { - /** Number of bytes */ -- unsigned n_bytes : 17; -+ 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 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; -- /** -+ unsigned a_qtd:1; -+ /** - * Setup Packet bit. When set indicates that buffer contains -- * setup packet. -+ * setup packet. - */ -- unsigned sup : 1; -+ unsigned sup:1; - /** Interrupt On Complete */ -- unsigned ioc : 1; -+ unsigned ioc:1; - /** End of List */ -- unsigned eol : 1; -- unsigned reserved27 : 1; -+ unsigned eol:1; -+ unsigned reserved27:1; - /** Rx/Tx Status */ -- unsigned sts : 2; -- #define DMA_DESC_STS_PKTERR 1 -- unsigned reserved30 : 1; -+ unsigned sts:2; -+#define DMA_DESC_STS_PKTERR 1 -+ unsigned reserved30:1; - /** Active Bit */ -- unsigned a : 1; -+ unsigned a:1; - } b; - /* for isochronous */ - struct { - /** Number of bytes */ -- unsigned n_bytes : 12; -- unsigned reserved12_24 : 13; -+ unsigned n_bytes:12; -+ unsigned reserved12_24:13; - /** Interrupt On Complete */ -- unsigned ioc : 1; -- unsigned reserved26_27 : 2; -+ unsigned ioc:1; -+ unsigned reserved26_27:2; - /** Rx/Tx Status */ -- unsigned sts : 2; -- unsigned reserved30 : 1; -+ unsigned sts:2; -+ unsigned reserved30:1; - /** Active Bit */ -- unsigned a : 1; -+ unsigned a:1; - } b_isoc; - } host_dma_desc_sts_t; - -@@ -2157,18 +2375,17 @@ - #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 -+/** -+ * Host-mode DMA Descriptor structure - * - * DMA Descriptor structure contains two quadlets: - * Status quadlet and Data buffer pointer. - */ --typedef struct dwc_otg_host_dma_desc --{ -+typedef struct dwc_otg_host_dma_desc { - /** DMA Descriptor status quadlet */ -- host_dma_desc_sts_t status; -+ host_dma_desc_sts_t status; - /** DMA Descriptor data buffer pointer */ -- uint32_t buf; -+ uint32_t buf; - } dwc_otg_host_dma_desc_t; - - /** OTG Host Interface Structure. -@@ -2205,7 +2422,7 @@ - /** - * This union represents the bit fields in the Power and Clock Gating Control - * Register. Read the register into the d32 member then set/clear the -- * bits using the bit elements. -+ * bits using the bit elements. - */ - typedef union pcgcctl_data { - /** raw register data */ -@@ -2221,17 +2438,108 @@ - unsigned pwrclmp:1; - /** Reset Power Down Modules */ - unsigned rstpdwnmodule:1; -- /** PHY Suspended */ -- unsigned physuspended:1; -+ /** Reserved */ -+ unsigned reserved: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; -+ unsigned resetaftsusp:1; -+ unsigned restoremode:1; -+ unsigned reserved10_12:3; -+ unsigned ess_reg_restored:1; -+ unsigned prt_clk_sel:2; -+ unsigned port_power:1; -+ unsigned max_xcvrselect:2; -+ unsigned max_termsel:1; -+ unsigned mac_dev_addr:7; -+ unsigned p2hd_dev_enum_spd:2; -+ unsigned p2hd_prt_spd:2; -+ unsigned if_dev_mode:1; - } b; - } pcgcctl_data_t; - -+/** -+ * This union represents the bit fields in the Global Data FIFO Software -+ * Configuration Register. Read the register into the d32 member then -+ * set/clear the bits using the bit elements. -+ */ -+typedef union gdfifocfg_data { -+ /* raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** OTG Data FIFO depth */ -+ unsigned gdfifocfg:16; -+ /** Start address of EP info controller */ -+ unsigned epinfobase:16; -+ } b; -+} gdfifocfg_data_t; -+ -+/** -+ * This union represents the bit fields in the Global Power Down Register -+ * Register. Read the register into the d32 member then set/clear the -+ * bits using the bit elements. -+ */ -+typedef union gpwrdn_data { -+ /* raw register data */ -+ uint32_t d32; -+ -+ /** register bits */ -+ struct { -+ /** PMU Interrupt Select */ -+ unsigned pmuintsel:1; -+ /** PMU Active */ -+ unsigned pmuactv:1; -+ /** Restore */ -+ unsigned restore:1; -+ /** Power Down Clamp */ -+ unsigned pwrdnclmp:1; -+ /** Power Down Reset */ -+ unsigned pwrdnrstn:1; -+ /** Power Down Switch */ -+ unsigned pwrdnswtch:1; -+ /** Disable VBUS */ -+ unsigned dis_vbus:1; -+ /** Line State Change */ -+ unsigned lnstschng:1; -+ /** Line state change mask */ -+ unsigned lnstchng_msk:1; -+ /** Reset Detected */ -+ unsigned rst_det:1; -+ /** Reset Detect mask */ -+ unsigned rst_det_msk:1; -+ /** Disconnect Detected */ -+ unsigned disconn_det:1; -+ /** Disconnect Detect mask */ -+ unsigned disconn_det_msk:1; -+ /** Connect Detected*/ -+ unsigned connect_det:1; -+ /** Connect Detected Mask*/ -+ unsigned connect_det_msk:1; -+ /** SRP Detected */ -+ unsigned srp_det:1; -+ /** SRP Detect mask */ -+ unsigned srp_det_msk:1; -+ /** Status Change Interrupt */ -+ unsigned sts_chngint:1; -+ /** Status Change Interrupt Mask */ -+ unsigned sts_chngint_msk:1; -+ /** Line State */ -+ unsigned linestate:2; -+ /** Indicates current mode(status of IDDIG signal) */ -+ unsigned idsts:1; -+ /** B Session Valid signal status*/ -+ unsigned bsessvld:1; -+ /** ADP Event Detected */ -+ unsigned adp_int:1; -+ /** Multi Valued ID pin */ -+ unsigned mult_val_id_bc:5; -+ /** Reserved 24_31 */ -+ unsigned reserved29_31:3; -+ } b; -+} gpwrdn_data_t; -+ - #endif --- -1.8.1.6 - - -From 82ccb28b990ffc2c0a7b6b7179d838054299db84 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sun, 19 Aug 2012 11:58:01 +0100 -Subject: [PATCH 036/102] Merged in microframe scheduler, currently disabled. - Enable with dwc_otg.microframe_schedule=1 - ---- - drivers/usb/host/dwc_otg/dwc_otg_cil.c | 1 - - drivers/usb/host/dwc_otg/dwc_otg_cil.h | 2 - - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 4 + - drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 72 ++++++++- - drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 43 ++--- - drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c | 21 ++- - drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 36 +++-- - drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 226 +++++++++++++++++++++++++-- - 8 files changed, 345 insertions(+), 60 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -index 1b33b66..83545c0 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cil.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -@@ -2403,7 +2403,6 @@ void dwc_otg_hc_halt(dwc_otg_core_if_t * core_if, - dwc_otg_core_global_regs_t *global_regs; - dwc_otg_host_global_regs_t *host_global_regs; - -- DWC_DEBUGPL(DBG_HW2937, " dwc_otg_hc_halt(%d)\n", hc->hc_num); - hc_regs = core_if->host_if->hc_regs[hc->hc_num]; - global_regs = core_if->core_global_regs; - host_global_regs = core_if->host_if->host_global_regs; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -index b76fdd9..9547362 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cil.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -@@ -34,8 +34,6 @@ - #if !defined(__DWC_CIL_H__) - #define __DWC_CIL_H__ - --#define DBG_HW2937 0x400 -- - #include "dwc_list.h" - #include "dwc_otg_dbg.h" - #include "dwc_otg_regs.h" -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -index 8a6e207..d7be7ef 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -60,6 +60,8 @@ - #define DWC_DRIVER_VERSION "2.94b 27-OCT-2011 (rev 01-DEC-2011)" - #define DWC_DRIVER_DESC "HS OTG USB Controller driver" - -+bool microframe_schedule; -+ - static const char dwc_driver_name[] = "dwc_otg"; - - extern int pcd_init( -@@ -1337,6 +1339,8 @@ static void __exit dwc_otg_driver_cleanup(void) - MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled"); - module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444); - MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0"); -+module_param(microframe_schedule, bool, 0444); -+MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler"); - - /** @page "Module Parameters" - * -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -index abe7093..434d0c4 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c -@@ -43,6 +43,16 @@ - #include "dwc_otg_hcd.h" - #include "dwc_otg_regs.h" - -+extern bool microframe_schedule; -+ -+//#define DEBUG_HOST_CHANNELS -+#ifdef DEBUG_HOST_CHANNELS -+static int last_sel_trans_num_per_scheduled = 0; -+static int last_sel_trans_num_nonper_scheduled = 0; -+static int last_sel_trans_num_avail_hc_at_start = 0; -+static int last_sel_trans_num_avail_hc_at_end = 0; -+#endif /* DEBUG_HOST_CHANNELS */ -+ - dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) - { - return DWC_ALLOC(sizeof(dwc_otg_hcd_t)); -@@ -825,6 +835,8 @@ static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd) - DWC_FREE(dwc_otg_hcd); - } - -+int init_hcd_usecs(dwc_otg_hcd_t *_hcd); -+ - int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - { - int retval = 0; -@@ -888,6 +900,10 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) - hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer", - dwc_otg_hcd_connect_timeout, 0); - -+ printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled"); -+ if (microframe_schedule) -+ init_hcd_usecs(hcd); -+ - /* Initialize reset tasklet. */ - hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd); - #ifdef DWC_DEV_SRPCAP -@@ -947,9 +963,12 @@ static void dwc_otg_hcd_reinit(dwc_otg_hcd_t * hcd) - hcd->flags.d32 = 0; - - hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; -- hcd->non_periodic_channels = 0; -- hcd->periodic_channels = 0; -- -+ if (!microframe_schedule) { -+ hcd->non_periodic_channels = 0; -+ hcd->periodic_channels = 0; -+ } else { -+ hcd->available_host_channels = hcd->core_if->core_params->host_channels; -+ } - /* - * Put all channels in the free channel list and clean up channel - * states. -@@ -1225,17 +1244,38 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - dwc_list_link_t *qh_ptr; - dwc_otg_qh_t *qh; - int num_channels; -+ dwc_irqflags_t flags; -+ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); - dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE; - - #ifdef DEBUG_SOF - DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); - #endif - -+#ifdef DEBUG_HOST_CHANNELS -+ last_sel_trans_num_per_scheduled = 0; -+ last_sel_trans_num_nonper_scheduled = 0; -+ last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels; -+#endif /* DEBUG_HOST_CHANNELS */ -+ - /* Process entries in the periodic ready list. */ - qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); - - while (qh_ptr != &hcd->periodic_sched_ready && - !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { -+ if (microframe_schedule) { -+ // Make sure we leave one channel for non periodic transactions. -+ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); -+ if (hcd->available_host_channels <= 1) { -+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); -+ break; -+ } -+ hcd->available_host_channels--; -+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); -+#ifdef DEBUG_HOST_CHANNELS -+ last_sel_trans_num_per_scheduled++; -+#endif /* DEBUG_HOST_CHANNELS */ -+ } - qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); - assign_and_init_hc(hcd, qh); - -@@ -1244,8 +1284,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - * periodic assigned schedule. - */ - qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); - DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, - &qh->qh_list_entry); -+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); - - ret_val = DWC_OTG_TRANSACTION_PERIODIC; - } -@@ -1258,10 +1300,22 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - qh_ptr = hcd->non_periodic_sched_inactive.next; - num_channels = hcd->core_if->core_params->host_channels; - while (qh_ptr != &hcd->non_periodic_sched_inactive && -- (hcd->non_periodic_channels < -+ (microframe_schedule || hcd->non_periodic_channels < - num_channels - hcd->periodic_channels) && - !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { - -+ if (microframe_schedule) { -+ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); -+ if (hcd->available_host_channels < 1) { -+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); -+ break; -+ } -+ hcd->available_host_channels--; -+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); -+#ifdef DEBUG_HOST_CHANNELS -+ last_sel_trans_num_nonper_scheduled++; -+#endif /* DEBUG_HOST_CHANNELS */ -+ } - qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); - - assign_and_init_hc(hcd, qh); -@@ -1271,8 +1325,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - * non-periodic active schedule. - */ - qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); - DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active, - &qh->qh_list_entry); -+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); - - if (ret_val == DWC_OTG_TRANSACTION_NONE) { - ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; -@@ -1280,9 +1336,15 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) - ret_val = DWC_OTG_TRANSACTION_ALL; - } - -- hcd->non_periodic_channels++; -+ if (!microframe_schedule) -+ hcd->non_periodic_channels++; - } - -+#ifdef DEBUG_HOST_CHANNELS -+ last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels; -+#endif /* DEBUG_HOST_CHANNELS */ -+ -+ DWC_SPINLOCK_FREE(channel_lock); - return ret_val; - } - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -index c87cb5b..8075595 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h -@@ -362,20 +362,13 @@ static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, - - /** @} */ - -+ -+ uint16_t speed; -+ uint16_t frame_usecs[8]; - } dwc_otg_qh_t; - - DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); - --#ifdef HW2937_WORKAROUND -- --typedef enum { -- HW2937_XFER_MODE_IDLE, -- HW2937_XFER_MODE_IN, -- HW2937_XFER_MODE_OUT, -- HW2937_XFER_MODE_PAUSEIN /* Transitioning from IN to IDLE */ --} hw2937_xfer_mode_t; --#endif -- - /** - * This structure holds the state of the HCD, including the non-periodic and - * periodic schedules. -@@ -477,6 +470,19 @@ struct dwc_otg_hcd { - uint16_t periodic_usecs; - - /** -+ * Total bandwidth claimed so far for all periodic transfers -+ * in a frame. -+ * This will include a mixture of HS and FS transfers. -+ * Units are microseconds per (micro)frame. -+ * We have a budget per frame and have to schedule -+ * transactions accordingly. -+ * Watch out for the fact that things are actually scheduled for the -+ * "next frame". -+ */ -+ uint16_t frame_usecs[8]; -+ -+ -+ /** - * Frame number read from the core at SOF. The value ranges from 0 to - * DWC_HFNUM_MAX_FRNUM. - */ -@@ -498,12 +504,17 @@ struct dwc_otg_hcd { - * transaction and at least one host channel available for - * non-periodic transactions. - */ -- int periodic_channels; -+ int periodic_channels; /* microframe_schedule==0 */ - - /** - * Number of host channels assigned to non-periodic transfers. - */ -- int non_periodic_channels; -+ int non_periodic_channels; /* microframe_schedule==0 */ -+ -+ /** -+ * Number of host channels assigned to non-periodic transfers. -+ */ -+ int available_host_channels; - - /** - * Array of pointers to the host channel descriptors. Allows accessing -@@ -551,14 +562,6 @@ struct dwc_otg_hcd { - /** Frame List DMA address */ - dma_addr_t frame_list_dma; - --#ifdef HW2937_WORKAROUND -- /** Current transfer mode (IN, OUT, or IDLE) */ -- hw2937_xfer_mode_t hw2937_xfer_mode; -- -- /** Mask of channels assigned to the current mode */ -- uint32_t hw2937_assigned_channels; --#endif -- - #ifdef DEBUG - uint32_t frrem_samples; - uint64_t frrem_accum; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -index e5dfa4c..d0d5fa1 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c -@@ -39,6 +39,8 @@ - #include "dwc_otg_hcd.h" - #include "dwc_otg_regs.h" - -+extern bool microframe_schedule; -+ - static inline uint8_t frame_list_idx(uint16_t frame) - { - return (frame & (MAX_FRLIST_EN_NUM - 1)); -@@ -273,10 +275,18 @@ void dump_frame_list(dwc_otg_hcd_t * hcd) - - static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { -+ dwc_irqflags_t flags; -+ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); -+ - dwc_hc_t *hc = qh->channel; -- if (dwc_qh_is_non_per(qh)) -- hcd->non_periodic_channels--; -- else -+ if (dwc_qh_is_non_per(qh)) { -+ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); -+ if (!microframe_schedule) -+ hcd->non_periodic_channels--; -+ else -+ hcd->available_host_channels++; -+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); -+ } else - update_frame_list(hcd, qh, 0); - - /* -@@ -296,6 +306,7 @@ static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - dwc_memset(qh->desc_list, 0x00, - sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); - } -+ DWC_SPINLOCK_FREE(channel_lock); - } - - /** -@@ -358,7 +369,7 @@ void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - release_channel_ddma(hcd, qh); - - if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) -- && !hcd->periodic_channels && hcd->frame_list) { -+ && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) { - - per_sched_disable(hcd); - frame_list_free(hcd); -@@ -665,7 +676,7 @@ static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - - qtd->in_process = 1; - -- if (qh->ep_type == UE_CONTROL) -+ if (qh->ep_type == UE_CONTROL) - break; - - if (n_desc == MAX_DMA_DESC_NUM_GENERIC) -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -index 130946c..63c1b55 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c -@@ -35,6 +35,8 @@ - #include "dwc_otg_hcd.h" - #include "dwc_otg_regs.h" - -+extern bool microframe_schedule; -+ - /** @file - * This file contains the implementation of the HCD Interrupt handlers. - */ -@@ -794,6 +796,8 @@ static void release_channel(dwc_otg_hcd_t * hcd, - { - dwc_otg_transaction_type_e tr_type; - int free_qtd; -+ dwc_irqflags_t flags; -+ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); - - DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", - __func__, hc->hc_num, halt_status, hc->xfer_len); -@@ -853,19 +857,26 @@ static void release_channel(dwc_otg_hcd_t * hcd, - dwc_otg_hc_cleanup(hcd->core_if, hc); - DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); - -- switch (hc->ep_type) { -- case DWC_OTG_EP_TYPE_CONTROL: -- case DWC_OTG_EP_TYPE_BULK: -- hcd->non_periodic_channels--; -- break; -+ if (!microframe_schedule) { -+ switch (hc->ep_type) { -+ case DWC_OTG_EP_TYPE_CONTROL: -+ case DWC_OTG_EP_TYPE_BULK: -+ hcd->non_periodic_channels--; -+ break; - -- default: -- /* -- * Don't release reservations for periodic channels here. -- * That's done when a periodic transfer is descheduled (i.e. -- * when the QH is removed from the periodic schedule). -- */ -- break; -+ default: -+ /* -+ * Don't release reservations for periodic channels here. -+ * That's done when a periodic transfer is descheduled (i.e. -+ * when the QH is removed from the periodic schedule). -+ */ -+ break; -+ } -+ } else { -+ -+ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); -+ hcd->available_host_channels++; -+ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); - } - - /* Try to queue more transfers now that there's a free channel. */ -@@ -873,6 +884,7 @@ static void release_channel(dwc_otg_hcd_t * hcd, - if (tr_type != DWC_OTG_TRANSACTION_NONE) { - dwc_otg_hcd_queue_transactions(hcd, tr_type); - } -+ DWC_SPINLOCK_FREE(channel_lock); - } - - /** -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -index 903a902..08c1669 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c -@@ -42,6 +42,8 @@ - #include "dwc_otg_hcd.h" - #include "dwc_otg_regs.h" - -+extern bool microframe_schedule; -+ - /** - * Free each QTD in the QH's QTD-list then free the QH. QH should already be - * removed from a list. QTD list should already be empty if called from URB -@@ -176,6 +178,9 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) - - hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port); - qh->do_split = 0; -+ if (microframe_schedule) -+ qh->speed = dev_speed; -+ - - if (((dev_speed == USB_SPEED_LOW) || - (dev_speed == USB_SPEED_FULL)) && -@@ -311,6 +316,8 @@ dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, - return qh; - } - -+/* microframe_schedule=0 start */ -+ - /** - * Checks that a channel is available for a periodic transfer. - * -@@ -379,6 +386,162 @@ static int check_periodic_bandwidth(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - return status; - } - -+/* microframe_schedule=0 end */ -+ -+/** -+ * Microframe scheduler -+ * track the total use in hcd->frame_usecs -+ * keep each qh use in qh->frame_usecs -+ * when surrendering the qh then donate the time back -+ */ -+const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 }; -+ -+/* -+ * called from dwc_otg_hcd.c:dwc_otg_hcd_init -+ */ -+int init_hcd_usecs(dwc_otg_hcd_t *_hcd) -+{ -+ int i; -+ for (i=0; i<8; i++) { -+ _hcd->frame_usecs[i] = max_uframe_usecs[i]; -+ } -+ return 0; -+} -+ -+static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) -+{ -+ int i; -+ unsigned short utime; -+ int t_left; -+ int ret; -+ int done; -+ -+ ret = -1; -+ utime = _qh->usecs; -+ t_left = utime; -+ i = 0; -+ done = 0; -+ while (done == 0) { -+ /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */ -+ if (utime <= _hcd->frame_usecs[i]) { -+ _hcd->frame_usecs[i] -= utime; -+ _qh->frame_usecs[i] += utime; -+ t_left -= utime; -+ ret = i; -+ done = 1; -+ return ret; -+ } else { -+ i++; -+ if (i == 8) { -+ done = 1; -+ ret = -1; -+ } -+ } -+ } -+ return ret; -+ } -+ -+/* -+ * use this for FS apps that can span multiple uframes -+ */ -+static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) -+{ -+ int i; -+ int j; -+ unsigned short utime; -+ int t_left; -+ int ret; -+ int done; -+ unsigned short xtime; -+ -+ ret = -1; -+ utime = _qh->usecs; -+ t_left = utime; -+ i = 0; -+ done = 0; -+loop: -+ while (done == 0) { -+ if(_hcd->frame_usecs[i] <= 0) { -+ i++; -+ if (i == 8) { -+ done = 1; -+ ret = -1; -+ } -+ goto loop; -+ } -+ -+ /* -+ * we need n consecutive slots -+ * so use j as a start slot j plus j+1 must be enough time (for now) -+ */ -+ xtime= _hcd->frame_usecs[i]; -+ for (j = i+1 ; j < 8 ; j++ ) { -+ /* -+ * if we add this frame remaining time to xtime we may -+ * be OK, if not we need to test j for a complete frame -+ */ -+ if ((xtime+_hcd->frame_usecs[j]) < utime) { -+ if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) { -+ j = 8; -+ ret = -1; -+ continue; -+ } -+ } -+ if (xtime >= utime) { -+ ret = i; -+ j = 8; /* stop loop with a good value ret */ -+ continue; -+ } -+ /* add the frame time to x time */ -+ xtime += _hcd->frame_usecs[j]; -+ /* we must have a fully available next frame or break */ -+ if ((xtime < utime) -+ && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) { -+ ret = -1; -+ j = 8; /* stop loop with a bad value ret */ -+ continue; -+ } -+ } -+ if (ret >= 0) { -+ t_left = utime; -+ for (j = i; (t_left>0) && (j < 8); j++ ) { -+ t_left -= _hcd->frame_usecs[j]; -+ if ( t_left <= 0 ) { -+ _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left; -+ _hcd->frame_usecs[j]= -t_left; -+ ret = i; -+ done = 1; -+ } else { -+ _qh->frame_usecs[j] += _hcd->frame_usecs[j]; -+ _hcd->frame_usecs[j] = 0; -+ } -+ } -+ } else { -+ i++; -+ if (i == 8) { -+ done = 1; -+ ret = -1; -+ } -+ } -+ } -+ return ret; -+} -+ -+static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) -+{ -+ int ret; -+ ret = -1; -+ -+ if (_qh->speed == USB_SPEED_HIGH) { -+ /* if this is a hs transaction we need a full frame */ -+ ret = find_single_uframe(_hcd, _qh); -+ } else { -+ /* if this is a fs transaction we may need a sequence of frames */ -+ ret = find_multi_uframe(_hcd, _qh); -+ } -+ return ret; -+} -+ - /** - * Checks that the max transfer size allowed in a host channel is large enough - * to handle the maximum data transfer in a single (micro)frame for a periodic -@@ -422,21 +585,43 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { - int status = 0; - -- status = periodic_channel_available(hcd); -- if (status) { -- DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE -- return status; -- } -+ if (microframe_schedule) { -+ int frame; -+ status = find_uframe(hcd, qh); -+ frame = -1; -+ if (status == 0) { -+ frame = 7; -+ } else { -+ if (status > 0 ) -+ frame = status-1; -+ } -+ -+ /* Set the new frame up */ -+ if (frame > -1) { -+ qh->sched_frame &= ~0x7; -+ qh->sched_frame |= (frame & 7); -+ } - -- status = check_periodic_bandwidth(hcd, qh); -+ if (status != -1) -+ status = 0; -+ } else { -+ status = periodic_channel_available(hcd); -+ if (status) { -+ DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE -+ return status; -+ } -+ -+ status = check_periodic_bandwidth(hcd, qh); -+ } - if (status) { -- DWC_INFO("%s: Insufficient periodic bandwidth for " "periodic transfer.\n", __func__); //NOTICE -+ DWC_INFO("%s: Insufficient periodic bandwidth for " -+ "periodic transfer.\n", __func__); - return status; - } -- - status = check_max_xfer_size(hcd, qh); - if (status) { -- DWC_INFO("%s: Channel max transfer size too small " "for periodic transfer.\n", __func__); //NOTICE -+ DWC_INFO("%s: Channel max transfer size too small " -+ "for periodic transfer.\n", __func__); - return status; - } - -@@ -449,8 +634,10 @@ static int schedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry); - } - -- /* Reserve the periodic channel. */ -- hcd->periodic_channels++; -+ if (!microframe_schedule) { -+ /* Reserve the periodic channel. */ -+ hcd->periodic_channels++; -+ } - - /* Update claimed usecs per (micro)frame. */ - hcd->periodic_usecs += qh->usecs; -@@ -501,13 +688,21 @@ int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - */ - static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) - { -+ int i; - DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); - -- /* Release the periodic channel reservation. */ -- hcd->periodic_channels--; -- - /* Update claimed usecs per (micro)frame. */ - hcd->periodic_usecs -= qh->usecs; -+ -+ if (!microframe_schedule) { -+ /* Release the periodic channel reservation. */ -+ hcd->periodic_channels--; -+ } else { -+ for (i = 0; i < 8; i++) { -+ hcd->frame_usecs[i] += qh->frame_usecs[i]; -+ qh->frame_usecs[i] = 0; -+ } -+ } - } - - /** -@@ -615,7 +810,8 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, - * Remove from periodic_sched_queued and move to - * appropriate queue. - */ -- if (qh->sched_frame == frame_number) { -+ if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) || -+ (!microframe_schedule && qh->sched_frame == frame_number)) { - DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, - &qh->qh_list_entry); - } else { --- -1.8.1.6 - - -From 847ab368ccb35e785427dd260bc52c65edab4cd8 Mon Sep 17 00:00:00 2001 +From eba5eb2eae782a05538df7404ef4dfa00403144e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 21 Aug 2012 18:49:44 +0100 -Subject: [PATCH 037/102] Read memory size for vc_mem through mailbox property +Subject: [PATCH 27/88] Read memory size for vc_mem through mailbox property channel --- @@ -111106,7 +87223,7 @@ index 28ecc15..502c617 100644 -#define VMALLOC_END (0xd8000000) +#define VMALLOC_END (0xe8000000) diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -index 67c10ee..775c213 100644 +index fd9d4be..7a7748e 100644 --- a/arch/arm/mach-bcm2708/vc_mem.c +++ b/arch/arm/mach-bcm2708/vc_mem.c @@ -21,6 +21,7 @@ @@ -111243,2465 +87360,10 @@ index 67c10ee..775c213 100644 1.8.1.6 -From ce3e4f3fa35256e015e95d9459930cf1b6087ecb Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 22 Aug 2012 12:43:36 +0100 -Subject: [PATCH 038/102] Update to dwc_otg 3.00. Seems to be a very minor - update (mostly adding support for a newer version of hardware) - ---- - drivers/usb/host/dwc_otg/doc/doxygen.cfg | 2 +- - drivers/usb/host/dwc_otg/dwc_otg_cil.c | 341 +++++++++++------- - drivers/usb/host/dwc_otg/dwc_otg_cil.h | 15 +- - drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 204 ++++++++++- - drivers/usb/host/dwc_otg/dwc_otg_core_if.h | 6 +- - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 15 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd.c | 216 +++++------ - drivers/usb/host/dwc_otg/dwc_otg_pcd.h | 10 +- - drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 520 ++++++++++++++++++++++----- - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 13 +- - drivers/usb/host/dwc_otg/dwc_otg_regs.h | 19 +- - 11 files changed, 979 insertions(+), 382 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/doc/doxygen.cfg b/drivers/usb/host/dwc_otg/doc/doxygen.cfg -index 2646c88..537c676 100644 ---- a/drivers/usb/host/dwc_otg/doc/doxygen.cfg -+++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg -@@ -4,7 +4,7 @@ - # Project related configuration options - #--------------------------------------------------------------------------- - PROJECT_NAME = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver" --PROJECT_NUMBER = v2.94a -+PROJECT_NUMBER = v3.00a - OUTPUT_DIRECTORY = ./doc/ - CREATE_SUBDIRS = NO - OUTPUT_LANGUAGE = English -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -index 83545c0..9b67537 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cil.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $ -- * $Revision: #189 $ -- * $Date: 2011/10/24 $ -- * $Change: 1871160 $ -+ * $Revision: #191 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -284,12 +284,19 @@ dwc_otg_core_if_t *dwc_otg_cil_init(const uint32_t * reg_base_addr) - */ - void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if) - { -+ dctl_data_t dctl = {.d32 = 0 }; - DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); - - /* Disable all interrupts */ - DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0); - DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); - -+ dctl.b.sftdiscon = 1; -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, -+ dctl.d32); -+ } -+ - if (core_if->wq_otg) { - DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500); - DWC_WORKQ_FREE(core_if->wq_otg); -@@ -942,9 +949,9 @@ int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup) - return -DWC_E_INVALID; - } - -- if (!rem_wakeup) -- { -- DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dr->dctl); -+ if (!rem_wakeup) { -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, -+ dr->dctl); - } - - DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk); -@@ -952,9 +959,9 @@ int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup) - DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk); - - for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -- DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]); - DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]); - DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]); -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]); - } - - return 0; -@@ -1788,58 +1795,60 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - - txfifosize.b.startaddr += txfifosize.b.depth; - } -- /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */ -- gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); -- hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3); -- gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16); -- DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); -- rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); -- nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); -- gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz; -- DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); -+ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { -+ /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */ -+ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); -+ hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3); -+ gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16); -+ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); -+ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); -+ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); -+ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz; -+ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); -+ } - } -- } - -- /* Flush the FIFOs */ -- dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ -- dwc_otg_flush_rx_fifo(core_if); -+ /* Flush the FIFOs */ -+ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ -+ dwc_otg_flush_rx_fifo(core_if); - -- /* Flush the Learning Queue. */ -- resetctl.b.intknqflsh = 1; -- DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); -+ /* Flush the Learning Queue. */ -+ resetctl.b.intknqflsh = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); - -- if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { -- core_if->start_predict = 0; -- for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) { -- core_if->nextep_seq[i] = 0xff; // 0xff - EP not active -- } -- core_if->nextep_seq[0] = 0; -- core_if->first_in_nextep_seq = 0; -- diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); -- diepctl.b.nextep = 0; -- DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); -+ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { -+ core_if->start_predict = 0; -+ for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) { -+ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active -+ } -+ core_if->nextep_seq[0] = 0; -+ core_if->first_in_nextep_seq = 0; -+ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); -+ diepctl.b.nextep = 0; -+ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); - -- /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ -- dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); -- dcfg.b.epmscnt = 2; -- DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); -+ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ -+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); -+ dcfg.b.epmscnt = 2; -+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); - -- DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -- __func__, core_if->first_in_nextep_seq); -- for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -- DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]); -+ DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ __func__, core_if->first_in_nextep_seq); -+ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -+ DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]); -+ } -+ DWC_DEBUGPL(DBG_CILV,"\n"); - } -- DWC_DEBUGPL(DBG_CILV,"\n"); -- } - -- /* Clear all pending Device Interrupts */ -- /** @todo - if the condition needed to be checked -- * or in any case all pending interrutps should be cleared? -- */ -- if (core_if->multiproc_int_enable) { -- for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -- DWC_WRITE_REG32(&dev_if-> -- dev_global_regs->diepeachintmsk[i], 0); -+ /* Clear all pending Device Interrupts */ -+ /** @todo - if the condition needed to be checked -+ * or in any case all pending interrutps should be cleared? -+ */ -+ if (core_if->multiproc_int_enable) { -+ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -+ DWC_WRITE_REG32(&dev_if-> -+ dev_global_regs->diepeachintmsk[i], 0); -+ } - } - - for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { -@@ -1878,9 +1887,35 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - depctl_data_t depctl; - depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); - if (depctl.b.epena) { -+ dctl_data_t dctl = {.d32 = 0 }; -+ gintmsk_data_t gintsts = {.d32 = 0 }; -+ doepint_data_t doepint = {.d32 = 0 }; -+ dctl.b.sgoutnak = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ do { -+ dwc_udelay(10); -+ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); -+ } while (!gintsts.b.goutnakeff); -+ gintsts.d32 = 0; -+ gintsts.b.goutnakeff = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); -+ - depctl.d32 = 0; - depctl.b.epdis = 1; - depctl.b.snak = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32); -+ do { -+ dwc_udelay(10); -+ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[i]->doepint); -+ } while (!doepint.b.epdisabled); -+ -+ doepint.b.epdisabled = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32); -+ -+ dctl.d32 = 0; -+ dctl.b.cgoutnak = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); - } else { - depctl.d32 = 0; - } -@@ -1927,9 +1962,8 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t * core_if) - diepmsk_data_t msk = {.d32 = 0 }; - msk.b.txfifoundrn = 1; - if (core_if->multiproc_int_enable) { -- DWC_MODIFY_REG32(&dev_if-> -- dev_global_regs->diepeachintmsk[0], -- msk.d32, msk.d32); -+ DWC_MODIFY_REG32(&dev_if->dev_global_regs-> -+ diepeachintmsk[0], msk.d32, msk.d32); - } else { - DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, - msk.d32, msk.d32); -@@ -2125,7 +2159,8 @@ void dwc_otg_core_host_init(dwc_otg_core_if_t * core_if) - DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", - DWC_READ_REG32(&global_regs->hptxfsiz)); - -- if (core_if->en_multiple_tx_fifo) { -+ if (core_if->en_multiple_tx_fifo -+ && core_if->snpsid <= OTG_CORE_REV_2_94a) { - /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */ - gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); - rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); -@@ -2624,26 +2659,26 @@ void ep_xfer_timeout(void *ptr) - /* Put the sate to 2 as it was time outed */ - xfer_info->state = 2; - -- dctl.d32 = DWC_READ_REG32(&xfer_info->core_if-> -- dev_if->dev_global_regs->dctl); -- gintsts.d32 = DWC_READ_REG32(&xfer_info->core_if-> -- core_global_regs->gintsts); -- gintmsk.d32 = DWC_READ_REG32(&xfer_info->core_if-> -- core_global_regs->gintmsk); -+ dctl.d32 = -+ DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl); -+ gintsts.d32 = -+ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts); -+ gintmsk.d32 = -+ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk); - - if (!gintmsk.b.goutnakeff) { - /* Unmask it */ - gintmsk.b.goutnakeff = 1; -- DWC_WRITE_REG32(&xfer_info->core_if-> -- core_global_regs->gintmsk, gintmsk.d32); -+ DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk, -+ gintmsk.d32); - - } - - if (!gintsts.b.goutnakeff) { - dctl.b.sgoutnak = 1; - } -- DWC_WRITE_REG32(&xfer_info->core_if->dev_if-> -- dev_global_regs->dctl, dctl.d32); -+ DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl, -+ dctl.d32); - - } - -@@ -3149,11 +3184,20 @@ uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if) - */ - void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest) - { -+ device_grxsts_data_t status; - /* Get the 8 bytes of a setup transaction data */ - - /* Pop 2 DWORDS off the receive data FIFO into memory */ - dest[0] = DWC_READ_REG32(core_if->data_fifo[0]); - dest[1] = DWC_READ_REG32(core_if->data_fifo[0]); -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { -+ status.d32 = -+ DWC_READ_REG32(&core_if->core_global_regs->grxstsp); -+ DWC_DEBUGPL(DBG_ANY, -+ "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n", -+ status.b.epnum, status.b.bcnt, status.b.pktsts, -+ status.b.fn, status.b.fn); -+ } - } - - /** -@@ -3172,6 +3216,7 @@ void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - depctl_data_t doepctl; - dctl_data_t dctl = {.d32 = 0 }; - -+ ep->stp_rollover = 0; - /* Read the Device Status and Endpoint 0 Control registers */ - dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts); - diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); -@@ -3192,9 +3237,10 @@ void dwc_otg_ep0_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); - - /* Enable OUT EP for receive */ -+ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { - doepctl.b.epena = 1; - DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); -- -+ } - #ifdef VERBOSE - DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", - DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); -@@ -3271,10 +3317,12 @@ void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - dcfg.b.epmscnt++; - DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); - -- DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ DWC_DEBUGPL(DBG_PCDV, -+ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", - __func__, core_if->first_in_nextep_seq); - for (i=0; i <= core_if->dev_if->num_in_eps; i++) { -- DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); -+ DWC_DEBUGPL(DBG_PCDV, "%2d\n", -+ core_if->nextep_seq[i]); - } - - } -@@ -3341,8 +3389,7 @@ void dwc_otg_ep_activate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - 0, daintmsk.d32); - } else { - if (ep->type == DWC_OTG_EP_TYPE_ISOC) { -- if (ep->is_in) -- { -+ if (ep->is_in) { - diepmsk_data_t diepmsk = {.d32 = 0 }; - diepmsk.b.nak = 1; - DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32); -@@ -3410,11 +3457,14 @@ void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - core_if->first_in_nextep_seq = i; - core_if->nextep_seq[ep->num] = 0xff; - depctl.b.nextep = 0; -- dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.d32 = -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); - dcfg.b.epmscnt--; -- DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, -+ dcfg.d32); - -- DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ DWC_DEBUGPL(DBG_PCDV, -+ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", - __func__, core_if->first_in_nextep_seq); - for (i=0; i <= core_if->dev_if->num_in_eps; i++) { - DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); -@@ -3429,43 +3479,47 @@ void dwc_otg_ep_deactivate(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - DWC_WRITE_REG32(addr, depctl.d32); - depctl.d32 = DWC_READ_REG32(addr); -- if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC && depctl.b.epena) -- { -+ if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC -+ && depctl.b.epena) { - depctl_data_t depctl = {.d32 = 0}; -- if (ep->is_in) -- { -+ if (ep->is_in) { - diepint_data_t diepint = {.d32 = 0}; - - depctl.b.snak = 1; -- DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepctl, depctl.d32); -- do -- { -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ diepctl, depctl.d32); -+ do { - dwc_udelay(10); -- diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -- in_ep_regs[ep->num]->diepint); -+ diepint.d32 = -+ DWC_READ_REG32(&core_if-> -+ dev_if->in_ep_regs[ep->num]-> -+ diepint); - } while (!diepint.b.inepnakeff); - diepint.b.inepnakeff = 1; -- DWC_WRITE_REG32(&core_if->dev_if-> -- in_ep_regs[ep->num]->diepint, diepint.d32); -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ diepint, diepint.d32); - depctl.d32 = 0; - depctl.b.epdis = 1; -- DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepctl, depctl.d32); -- do -- { -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ diepctl, depctl.d32); -+ do { - dwc_udelay(10); -- diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -- in_ep_regs[ep->num]->diepint); -+ diepint.d32 = -+ DWC_READ_REG32(&core_if-> -+ dev_if->in_ep_regs[ep->num]-> -+ diepint); - } while (!diepint.b.epdisabled); - diepint.b.epdisabled = 1; -- DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->diepint, diepint.d32); -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ diepint, diepint.d32); - } else { - dctl_data_t dctl = {.d32 = 0}; - gintmsk_data_t gintsts = {.d32 = 0}; - doepint_data_t doepint = {.d32 = 0}; - dctl.b.sgoutnak = 1; -- DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); -- do -- { -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> -+ dctl, 0, dctl.d32); -+ do { - dwc_udelay(10); - gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); - } while (!gintsts.b.goutnakeff); -@@ -3552,8 +3606,7 @@ static void init_dma_desc_chain(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - (total_len % maxxfer_local); - } else - xfer_est = ep->desc_cnt * maxxfer_local; -- } -- else -+ } else - xfer_est = total_len; - offset = 0; - for (i = 0; i < ep->desc_cnt; ++i) { -@@ -3626,8 +3679,7 @@ static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep - DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); - - while (txstatus.b.txfspcavail > dwords && -- dwc_ep->xfer_count < dwc_ep->xfer_len && -- dwc_ep->xfer_len != 0) { -+ dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) { - /* Write the FIFO */ - dwc_otg_ep_write_packet(core_if, dwc_ep, 0); - -@@ -3681,8 +3733,7 @@ void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); - - if (core_if->en_multiple_tx_fifo == 0 -- && gtxstatus.b.nptxqspcavail == 0 -- && !core_if->dma_enable) { -+ && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) { - #ifdef DEBUG - DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32); - #endif -@@ -3778,15 +3829,14 @@ void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) - depctl.b.nextep = core_if->nextep_seq[ep->num]; - -- if (ep->type == DWC_OTG_EP_TYPE_ISOC) -- { -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { - dsts_data_t dsts = {.d32 = 0}; - if (ep->bInterval == 1) { - dsts.d32 = -- DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); -+ DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->dsts); - ep->frame_num = dsts.b.soffn + ep->bInterval; -- if (ep->frame_num > 0x3FFF) -- { -+ if (ep->frame_num > 0x3FFF) { - ep->frm_overrun = 1; - ep->frame_num &= 0x3FFF; - } else -@@ -3888,15 +3938,14 @@ void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); - } - -- if (ep->type == DWC_OTG_EP_TYPE_ISOC) -- { -+ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { - dsts_data_t dsts = {.d32 = 0}; - if (ep->bInterval == 1) { - dsts.d32 = -- DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); -+ DWC_READ_REG32(&core_if->dev_if-> -+ dev_global_regs->dsts); - ep->frame_num = dsts.b.soffn + ep->bInterval; -- if (ep->frame_num > 0x3FFF) -- { -+ if (ep->frame_num > 0x3FFF) { - ep->frm_overrun = 1; - ep->frame_num &= 0x3FFF; - } else -@@ -3920,11 +3969,10 @@ void dwc_otg_ep_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - DWC_READ_REG32(&out_regs->doepctl), - DWC_READ_REG32(&out_regs->doeptsiz)); - DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", -- DWC_READ_REG32(&core_if->dev_if-> -- dev_global_regs->daintmsk), -- DWC_READ_REG32(&core_if-> -- core_global_regs->gintmsk)); -- -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> -+ daintmsk), -+ DWC_READ_REG32(&core_if->core_global_regs-> -+ gintmsk)); - - /* Timer is scheduling only for out bulk transfers for - * "Device DDMA OUT NAK Enhancement" feature to inform user -@@ -4075,9 +4123,19 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - gnptxsts_data_t gtxstatus; - -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { -+ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); -+ if (depctl.b.epena) -+ return; -+ } -+ - gtxstatus.d32 = - DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); - -+ /* If dedicated FIFO every time flush fifo before enable ep*/ -+ if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a) -+ dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num); -+ - if (core_if->en_multiple_tx_fifo == 0 - && gtxstatus.b.nptxqspcavail == 0 - && !core_if->dma_enable) { -@@ -4194,6 +4252,8 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - /* Zero Length Packet */ - deptsiz.b.xfersize = ep->maxpacket; - deptsiz.b.pktcnt = 1; -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) -+ deptsiz.b.supcnt = 3; - - DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", - ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt); -@@ -4210,6 +4270,10 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - /** DMA Descriptor Setup */ - dma_desc->status.b.bs = BS_HOST_BUSY; -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { -+ dma_desc->status.b.mtrf = 0; -+ dma_desc->status.b.sr = 0; -+ } - dma_desc->status.b.l = 1; - dma_desc->status.b.ioc = 1; - dma_desc->status.b.bytes = ep->maxpacket; -@@ -4219,8 +4283,8 @@ void dwc_otg_ep0_start_transfer(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - /** DOEPDMA0 Register write */ - DWC_WRITE_REG32(&out_regs->doepdma, -- core_if-> -- dev_if->dma_out_desc_addr); -+ core_if->dev_if-> -+ dma_out_desc_addr); - } - } else { - DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); -@@ -4630,14 +4694,14 @@ void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if) - - DWC_PRINTF("Device Global Registers\n"); - addr = &core_if->dev_if->dev_global_regs->dcfg; -- DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n", (unsigned long) addr, -- DWC_READ_REG32(addr)); -+ DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->dctl; -- DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n", (unsigned long) addr, -- DWC_READ_REG32(addr)); -+ DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->dsts; -- DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n", (unsigned long) addr, -- DWC_READ_REG32(addr)); -+ DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n", -+ (unsigned long)addr, DWC_READ_REG32(addr)); - addr = &core_if->dev_if->dev_global_regs->diepmsk; - DWC_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, - DWC_READ_REG32(addr)); -@@ -4692,8 +4756,8 @@ void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if) - - for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { - addr = -- &core_if->dev_if->dev_global_regs-> -- diepeachintmsk[i]; -+ &core_if->dev_if-> -+ dev_global_regs->diepeachintmsk[i]; - DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", - i, (unsigned long)addr, - DWC_READ_REG32(addr)); -@@ -4701,8 +4765,8 @@ void dwc_otg_dump_dev_registers(dwc_otg_core_if_t * core_if) - - for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { - addr = -- &core_if->dev_if->dev_global_regs-> -- doepeachintmsk[i]; -+ &core_if->dev_if-> -+ dev_global_regs->doepeachintmsk[i]; - DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", - i, (unsigned long)addr, - DWC_READ_REG32(addr)); -@@ -5150,8 +5214,8 @@ void write_isoc_frame_data(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - dwords = (len + 3) / 4; - txstatus.d32 = -- DWC_READ_REG32(&core_if->dev_if-> -- in_ep_regs[ep->num]->dtxfsts); -+ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ dtxfsts); - DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num, - txstatus.d32); - } -@@ -5207,13 +5271,14 @@ void dwc_otg_iso_ep_start_frm_transfer(dwc_otg_core_if_t * core_if, - (ep->xfer_len + (ep->maxpacket - 1)) / ep->maxpacket; - deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; - -- DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> -- doeptsiz, deptsiz.d32); -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ out_ep_regs[ep->num]->doeptsiz, deptsiz.d32); - - if (core_if->dma_enable) { - DWC_WRITE_REG32(& -- (core_if->dev_if->out_ep_regs[ep->num]-> -- doepdma), (uint32_t) ep->dma_addr); -+ (core_if->dev_if-> -+ out_ep_regs[ep->num]->doepdma), -+ (uint32_t) ep->dma_addr); - } - } - -@@ -5715,8 +5780,7 @@ int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t * core_if, - return -DWC_E_INVALID; - } - -- if (val > -- ((core_if->hptxfsiz.d32)>> 16)) { -+ if (val > ((core_if->hptxfsiz.d32) >> 16)) { - if (dwc_otg_param_initialized - (core_if->core_params->host_perio_tx_fifo_size)) { - DWC_ERROR -@@ -6453,8 +6517,10 @@ int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val) - { - int retval = 0; - int valid = 1; -+ hwcfg4_data_t hwcfg4 = {.d32 = 0 }; -+ hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); - -- if (DWC_OTG_PARAM_TEST(val, 0, 2)) { -+ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { - DWC_WARN("`%d' invalid for parameter `power_down'\n", val); - DWC_WARN("power_down must be 0 - 2\n"); - return -DWC_E_INVALID; -@@ -6463,6 +6529,11 @@ int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val) - if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) { - valid = 0; - } -+ if ((val == 3) -+ && ((core_if->snpsid < OTG_CORE_REV_3_00a) -+ || (hwcfg4.b.xhiber == 0))) { -+ valid = 0; -+ } - if (valid == 0) { - if (dwc_otg_param_initialized(core_if->core_params->power_down)) { - DWC_ERROR -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -index 9547362..d367cd1 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cil.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $ -- * $Revision: #122 $ -- * $Date: 2011/10/24 $ -- * $Change: 1871160 $ -+ * $Revision: #123 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -74,6 +74,7 @@ - #define OTG_CORE_REV_2_92a 0x4F54292A - #define OTG_CORE_REV_2_93a 0x4F54293A - #define OTG_CORE_REV_2_94a 0x4F54294A -+#define OTG_CORE_REV_3_00a 0x4F54300A - - /** - * Information for each ISOC packet. -@@ -146,6 +147,9 @@ - /** stall clear flag */ - unsigned stall_clear_flag:1; - -+ /** SETUP pkt cnt rollover flag for EP0 out*/ -+ unsigned stp_rollover; -+ - #ifdef DWC_UTE_CFI - /* The buffer mode */ - data_buffer_mode_e buff_mode; -@@ -764,6 +768,8 @@ struct dwc_otg_global_regs_backup { - uint32_t gdfifocfg_local; - uint32_t dtxfsiz_local[MAX_EPS_CHANNELS]; - uint32_t gpwrdn_local; -+ uint32_t xhib_pcgcctl; -+ uint32_t xhib_gpwrdn; - }; - - struct dwc_otg_host_regs_backup { -@@ -964,6 +970,9 @@ struct dwc_otg_core_if { - /** hibernation/suspend flag */ - int hibernation_suspend; - -+ /** Device mode extended hibernation flag */ -+ int xhib; -+ - /** OTG revision supported */ - uint32_t otg_ver; - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -index edc5c92..21804c4 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ -- * $Revision: #31 $ -- * $Date: 2011/10/24 $ -- * $Change: 1871286 $ -+ * $Revision: #32 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -168,6 +168,10 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t * core_if) - /* Print statements during the HNP interrupt handling - * can cause it to fail.*/ - gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); -+ /* WA for 3.00a- HW is not setting cur_mode, even sometimes -+ * this does not help*/ -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) -+ dwc_udelay(100); - if (gotgctl.b.hstnegscs) { - if (dwc_otg_is_host_mode(core_if)) { - core_if->op_state = B_HOST; -@@ -443,8 +447,8 @@ int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) - if (dwc_otg_is_device_mode(core_if)) { - dctl_data_t dctl = {.d32 = 0 }; - DWC_DEBUGPL(DBG_PCD, "DSTS=0x%0x\n", -- DWC_READ_REG32(&core_if->dev_if-> -- dev_global_regs->dsts)); -+ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> -+ dsts)); - if (core_if->lx_state == DWC_OTG_L2) { - #ifdef PARTIAL_POWER_DOWN - if (core_if->hwcfg4.b.power_optimiz) { -@@ -466,8 +470,8 @@ int32_t dwc_otg_handle_wakeup_detected_intr(dwc_otg_core_if_t * core_if) - #endif - /* Clear the Remote Wakeup Signaling */ - dctl.b.rmtwkupsig = 1; -- DWC_MODIFY_REG32(&core_if->dev_if-> -- dev_global_regs->dctl, dctl.d32, 0); -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> -+ dctl, dctl.d32, 0); - - DWC_SPINUNLOCK(core_if->lock); - if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -@@ -611,8 +615,7 @@ static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev) - - DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); - gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -- if (core_if->power_down == 2) -- { -+ if (core_if->power_down == 2) { - if (!core_if->hibernation_suspend) { - DWC_PRINTF("Already exited from Hibernation\n"); - return 1; -@@ -674,8 +677,7 @@ static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev) - } - } - -- if (core_if->adp_enable) -- { -+ if (core_if->adp_enable) { - uint8_t is_host = 0; - DWC_SPINUNLOCK(core_if->lock); - /* Change the core_if's lock to hcd/pcd lock depend on mode? */ -@@ -978,16 +980,17 @@ int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) - /* Enable Power Down Logic */ - gpwrdn.b.pmuintsel = 1; - gpwrdn.b.pmuactv = 1; -- DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ DWC_MODIFY_REG32(&core_if->core_global_regs-> -+ gpwrdn, 0, gpwrdn.d32); - dwc_otg_adp_probe_start(core_if); - - /* Power off the core */ - if (core_if->power_down == 2) { - gpwrdn.d32 = 0; - gpwrdn.b.pwrdnswtch = 1; -- DWC_MODIFY_REG32(&core_if-> -- core_global_regs-> -- gpwrdn, gpwrdn.d32, 0); -+ DWC_MODIFY_REG32 -+ (&core_if->core_global_regs->gpwrdn, -+ gpwrdn.d32, 0); - } - } - } -@@ -1141,6 +1144,49 @@ int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) - - return 1; - } -+ } else if (core_if->power_down == 3) { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); -+ DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state); -+ DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr); -+ -+ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { -+ DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n"); -+ core_if->xhib = 1; -+ -+ /* Clear interrupt in gintsts */ -+ gintsts.d32 = 0; -+ gintsts.b.usbsuspend = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs-> -+ gintsts, gintsts.d32); -+ -+ dwc_otg_save_global_regs(core_if); -+ dwc_otg_save_dev_regs(core_if); -+ -+ /* Wait for 10 PHY clocks */ -+ dwc_udelay(10); -+ -+ /* Program GPIO register while entering to xHib */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1); -+ -+ pcgcctl.b.enbl_extnd_hiber = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); -+ -+ pcgcctl.d32 = 0; -+ pcgcctl.b.extnd_hiber_pwrclmp = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); -+ -+ pcgcctl.d32 = 0; -+ pcgcctl.b.extnd_hiber_switch = 1; -+ core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); -+ core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32; -+ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); -+ -+ DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n"); -+ -+ return 1; -+ } - } - } else { - if (core_if->op_state == A_PERIPHERAL) { -@@ -1165,6 +1211,70 @@ int32_t dwc_otg_handle_usb_suspend_intr(dwc_otg_core_if_t * core_if) - return 1; - } - -+static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if) -+{ -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ gahbcfg_data_t gahbcfg = {.d32 = 0 }; -+ -+ dwc_udelay(10); -+ -+ /* Program GPIO register while entering to xHib */ -+ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0); -+ -+ pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl; -+ pcgcctl.b.extnd_hiber_pwrclmp = 0; -+ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); -+ dwc_udelay(10); -+ -+ gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn; -+ gpwrdn.b.restore = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32); -+ dwc_udelay(10); -+ -+ restore_lpm_i2c_regs(core_if); -+ -+ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); -+ pcgcctl.b.max_xcvrselect = 1; -+ pcgcctl.b.ess_reg_restored = 0; -+ pcgcctl.b.extnd_hiber_switch = 0; -+ pcgcctl.b.extnd_hiber_pwrclmp = 0; -+ pcgcctl.b.enbl_extnd_hiber = 1; -+ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); -+ -+ gahbcfg.d32 = core_if->gr_backup->gahbcfg_local; -+ gahbcfg.b.glblintrmsk = 1; -+ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); -+ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16); -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, -+ core_if->gr_backup->gusbcfg_local); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, -+ core_if->dr_backup->dcfg); -+ -+ pcgcctl.d32 = 0; -+ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); -+ pcgcctl.b.max_xcvrselect = 1; -+ pcgcctl.d32 |= 0x608; -+ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); -+ dwc_udelay(10); -+ -+ pcgcctl.d32 = 0; -+ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); -+ pcgcctl.b.max_xcvrselect = 1; -+ pcgcctl.b.ess_reg_restored = 1; -+ pcgcctl.b.enbl_extnd_hiber = 1; -+ pcgcctl.b.rstpdwnmodule = 1; -+ pcgcctl.b.restoremode = 1; -+ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); -+ -+ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); -+ -+ return 1; -+} -+ - #ifdef CONFIG_USB_DWC_OTG_LPM - /** - * This function hadles LPM transaction received interrupt. -@@ -1286,6 +1396,16 @@ int32_t dwc_otg_handle_common_intr(void *dev) - if (core_if->lock) - DWC_SPINLOCK(core_if->lock); - -+ if (core_if->power_down == 3 && core_if->xhib == 1) { -+ DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n"); -+ retval |= dwc_otg_handle_xhib_exit_intr(core_if); -+ core_if->xhib = 2; -+ if (core_if->lock) -+ DWC_SPINUNLOCK(core_if->lock); -+ -+ return retval; -+ } -+ - if (core_if->hibernation_suspend <= 0) { - gintsts.d32 = dwc_otg_read_common_intr(core_if); - -@@ -1296,7 +1416,8 @@ int32_t dwc_otg_handle_common_intr(void *dev) - retval |= dwc_otg_handle_otg_intr(core_if); - } - if (gintsts.b.conidstschng) { -- retval |= dwc_otg_handle_conn_id_status_change_intr(core_if); -+ retval |= -+ dwc_otg_handle_conn_id_status_change_intr(core_if); - } - if (gintsts.b.disconnect) { - retval |= dwc_otg_handle_disconnect_intr(core_if); -@@ -1319,6 +1440,57 @@ int32_t dwc_otg_handle_common_intr(void *dev) - gintsts.d32 = 0; - if (core_if->power_down == 2) - core_if->hibernation_suspend = -1; -+ else if (core_if->power_down == 3 && core_if->xhib == 2) { -+ gpwrdn_data_t gpwrdn = {.d32 = 0 }; -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ dctl_data_t dctl = {.d32 = 0 }; -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs-> -+ gintsts, 0xFFFFFFFF); -+ -+ DWC_DEBUGPL(DBG_ANY, -+ "RESTORE DONE generated\n"); -+ -+ gpwrdn.b.restore = 1; -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); -+ dwc_udelay(10); -+ -+ pcgcctl.b.rstpdwnmodule = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); -+ -+ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg); -+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl); -+ dwc_udelay(50); -+ -+ dctl.b.pwronprgdone = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); -+ dwc_udelay(10); -+ -+ dwc_otg_restore_global_regs(core_if); -+ dwc_otg_restore_dev_regs(core_if, 0); -+ -+ dctl.d32 = 0; -+ dctl.b.pwronprgdone = 1; -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); -+ dwc_udelay(10); -+ -+ pcgcctl.d32 = 0; -+ pcgcctl.b.enbl_extnd_hiber = 1; -+ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); -+ -+ /* The core will be in ON STATE */ -+ core_if->lx_state = DWC_OTG_L0; -+ core_if->xhib = 0; -+ -+ DWC_SPINUNLOCK(core_if->lock); -+ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); -+ } -+ DWC_SPINLOCK(core_if->lock); -+ -+ } -+ - gintsts.b.restoredone = 1; - DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); - DWC_PRINTF(" --Restore done interrupt received-- \n"); -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -index 3207cb6..10b68c4 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $ -- * $Revision: #12 $ -- * $Date: 2011/10/24 $ -- * $Change: 1871159 $ -+ * $Revision: #13 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -index d7be7ef..8ddc9ae 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ -- * $Revision: #91 $ -- * $Date: 2011/10/24 $ -- * $Change: 1871159 $ -+ * $Revision: #92 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -57,7 +57,7 @@ - #include "dwc_otg_pcd_if.h" - #include "dwc_otg_hcd_if.h" - --#define DWC_DRIVER_VERSION "2.94b 27-OCT-2011 (rev 01-DEC-2011)" -+#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012" - #define DWC_DRIVER_DESC "HS OTG USB Controller driver" - - bool microframe_schedule; -@@ -836,11 +836,12 @@ static int dwc_otg_driver_probe( - /* - * Attempt to ensure this device is really a DWC_otg Controller. - * Read and verify the SNPSID register contents. The value should be -- * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX". -+ * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3", -+ * as in "OTG version 2.XX" or "OTG version 3.XX". - */ - -- if ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != -- 0x4F542000) { -+ if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) && -+ ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) { - dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n", - dwc_otg_get_gsnpsid(dwc_otg_device->core_if)); - retval = -EINVAL; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -index 2f9642d..c97d65c 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ -- * $Revision: #99 $ -- * $Date: 2011/10/24 $ -- * $Change: 1871160 $ -+ * $Revision: #101 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -453,8 +453,8 @@ void dwc_otg_iso_ep_start_ddma_transfer(dwc_otg_core_if_t * core_if, - fifosize_data_t txfifosize, rxfifosize; - - txfifosize.d32 = -- DWC_READ_REG32(&core_if->dev_if-> -- in_ep_regs[dwc_ep->num]->dtxfsts); -+ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[dwc_ep->num]-> -+ dtxfsts); - rxfifosize.d32 = - DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); - -@@ -574,15 +574,13 @@ void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, - deptsiz.b.xfersize = ep->xfer_len; - deptsiz.b.pktcnt = - (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; -- DWC_WRITE_REG32(&core_if->dev_if-> -- in_ep_regs[ep->num]->dieptsiz, -- deptsiz.d32); -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ dieptsiz, deptsiz.d32); - - /* Write the DMA register */ - DWC_WRITE_REG32(& -- (core_if->dev_if-> -- in_ep_regs[ep->num]->diepdma), -- (uint32_t) ep->dma_addr); -+ (core_if->dev_if->in_ep_regs[ep->num]-> -+ diepdma), (uint32_t) ep->dma_addr); - - } else { - deptsiz.b.pktcnt = -@@ -590,15 +588,13 @@ void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, - ep->maxpacket; - deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; - -- DWC_WRITE_REG32(&core_if->dev_if-> -- out_ep_regs[ep->num]->doeptsiz, -- deptsiz.d32); -+ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> -+ doeptsiz, deptsiz.d32); - - /* Write the DMA register */ - DWC_WRITE_REG32(& -- (core_if->dev_if-> -- out_ep_regs[ep->num]->doepdma), -- (uint32_t) ep->dma_addr); -+ (core_if->dev_if->out_ep_regs[ep->num]-> -+ doepdma), (uint32_t) ep->dma_addr); - - } - /** Enable endpoint, clear nak */ -@@ -636,11 +632,11 @@ static void dwc_otg_iso_ep_start_transfer(dwc_otg_core_if_t * core_if, - dwc_otg_iso_ep_start_buf_transfer(core_if, ep); - } else { - ep->cur_pkt_addr = -- (ep->proc_buf_num) ? ep-> -- xfer_buff1 : ep->xfer_buff0; -+ (ep->proc_buf_num) ? ep->xfer_buff1 : ep-> -+ xfer_buff0; - ep->cur_pkt_dma_addr = -- (ep->proc_buf_num) ? ep-> -- dma_addr1 : ep->dma_addr0; -+ (ep->proc_buf_num) ? ep->dma_addr1 : ep-> -+ dma_addr0; - dwc_otg_iso_ep_start_frm_transfer(core_if, ep); - } - } -@@ -1014,14 +1010,16 @@ static void srp_timeout(void *ptr) - /* Power off the core */ - if (core_if->power_down == 2) { - gpwrdn.b.pwrdnswtch = 1; -- DWC_MODIFY_REG32(&core_if->core_global_regs-> -- gpwrdn, gpwrdn.d32, 0); -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs->gpwrdn, -+ gpwrdn.d32, 0); - } - - gpwrdn.d32 = 0; - gpwrdn.b.pmuintsel = 1; - gpwrdn.b.pmuactv = 1; -- DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); -+ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, -+ gpwrdn.d32); - dwc_otg_adp_probe_start(core_if); - } else { - DWC_PRINTF("SRP Timeout BSESSVLD = 1\n"); -@@ -1180,19 +1178,18 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - - if (GET_CORE_IF(pcd)->dma_desc_enable) { - dev_if->setup_desc_addr[0] = -- dwc_otg_ep_alloc_desc_chain(&dev_if-> -- dma_setup_desc_addr[0], -- 1); -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_setup_desc_addr[0], 1); - dev_if->setup_desc_addr[1] = -- dwc_otg_ep_alloc_desc_chain(&dev_if-> -- dma_setup_desc_addr[1], -- 1); -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_setup_desc_addr[1], 1); - dev_if->in_desc_addr = -- dwc_otg_ep_alloc_desc_chain(&dev_if-> -- dma_in_desc_addr, 1); -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_in_desc_addr, 1); - dev_if->out_desc_addr = -- dwc_otg_ep_alloc_desc_chain(&dev_if-> -- dma_out_desc_addr, 1); -+ dwc_otg_ep_alloc_desc_chain -+ (&dev_if->dma_out_desc_addr, 1); -+ pcd->data_terminated = 0; - - if (dev_if->setup_desc_addr[0] == 0 - || dev_if->setup_desc_addr[1] == 0 -@@ -1200,31 +1197,21 @@ dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) - || dev_if->out_desc_addr == 0) { - - if (dev_if->out_desc_addr) -- dwc_otg_ep_free_desc_chain(dev_if-> -- out_desc_addr, -- dev_if-> -- dma_out_desc_addr, -- 1); -+ dwc_otg_ep_free_desc_chain -+ (dev_if->out_desc_addr, -+ dev_if->dma_out_desc_addr, 1); - if (dev_if->in_desc_addr) -- dwc_otg_ep_free_desc_chain(dev_if-> -- in_desc_addr, -- dev_if-> -- dma_in_desc_addr, -- 1); -+ dwc_otg_ep_free_desc_chain -+ (dev_if->in_desc_addr, -+ dev_if->dma_in_desc_addr, 1); - if (dev_if->setup_desc_addr[1]) -- dwc_otg_ep_free_desc_chain(dev_if-> -- setup_desc_addr -- [1], -- dev_if-> -- dma_setup_desc_addr -- [1], 1); -+ dwc_otg_ep_free_desc_chain -+ (dev_if->setup_desc_addr[1], -+ dev_if->dma_setup_desc_addr[1], 1); - if (dev_if->setup_desc_addr[0]) -- dwc_otg_ep_free_desc_chain(dev_if-> -- setup_desc_addr -- [0], -- dev_if-> -- dma_setup_desc_addr -- [0], 1); -+ dwc_otg_ep_free_desc_chain -+ (dev_if->setup_desc_addr[0], -+ dev_if->dma_setup_desc_addr[0], 1); - - DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, - pcd->setup_pkt, -@@ -1550,20 +1537,23 @@ int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, - } - - /* Calculating EP info controller base address */ -- if (ep->dwc_ep.tx_fifo_num && GET_CORE_IF(pcd)->en_multiple_tx_fifo) { -+ if (ep->dwc_ep.tx_fifo_num -+ && GET_CORE_IF(pcd)->en_multiple_tx_fifo) { - gdfifocfg.d32 = -- DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs-> -- gdfifocfg); -+ DWC_READ_REG32(&GET_CORE_IF(pcd)-> -+ core_global_regs->gdfifocfg); - gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; - dptxfsiz.d32 = - (DWC_READ_REG32 -- (&GET_CORE_IF(pcd)-> -- core_global_regs->dtxfsiz[ep->dwc_ep. -- tx_fifo_num-1]) >> 16); -+ (&GET_CORE_IF(pcd)->core_global_regs-> -+ dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16); - gdfifocfg.b.epinfobase = - gdfifocfgbase.d32 + dptxfsiz.d32; -- DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs-> -- gdfifocfg, gdfifocfg.d32); -+ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> -+ core_global_regs->gdfifocfg, -+ gdfifocfg.d32); -+ } - } - } - /* Set initial data PID. */ -@@ -1643,8 +1633,7 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - dwc_otg_request_nuke(ep); - - dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep); -- if (pcd->core_if->core_params->dev_out_nak) -- { -+ if (pcd->core_if->core_params->dev_out_nak) { - DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]); - pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0; - } -@@ -1658,7 +1647,8 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - if (ep->dwc_ep.is_in) { - if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { - /* Flush the Tx FIFO */ -- dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); -+ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), -+ ep->dwc_ep.tx_fifo_num); - } - release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); - release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); -@@ -1669,8 +1659,10 @@ int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) - (&GET_CORE_IF(pcd)-> - core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16); - gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32; -- DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg, -+ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg, - gdfifocfg.d32); -+ } - } - } - -@@ -1756,7 +1748,8 @@ int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd, - for (i = 0; i < ereq->pio_pkt_count; i++) { - //if ((i % (nat + 1)) == 0) - if ( i > 0 ) -- dwcep->xiso_frame_num = (dwcep->xiso_bInterval + -+ dwcep->xiso_frame_num = -+ (dwcep->xiso_bInterval + - dwcep->xiso_frame_num) & 0x3FFF; - dwcep->desc_addr[i].buf = - req->dma + ddesc_iso[i].offset; -@@ -1823,15 +1816,15 @@ int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd, - - /* Setup and start the transfer for this endpoint */ - dwcep->xiso_active_xfers++; -- DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if-> -- out_ep_regs[dwcep->num]->doepdma, -- dwcep->dma_desc_addr); -+ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> -+ dev_if->out_ep_regs[dwcep->num]-> -+ doepdma, dwcep->dma_desc_addr); - diepctl.d32 = 0; - diepctl.b.epena = 1; - diepctl.b.cnak = 1; -- DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> -- out_ep_regs[dwcep->num]->doepctl, 0, -- diepctl.d32); -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> -+ dev_if->out_ep_regs[dwcep->num]-> -+ doepctl, 0, diepctl.d32); - } - - } else { -@@ -2128,17 +2121,20 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - * Received when EP is disabled interrupt to obtain starting microframe - * (odd/even) start transfer - */ -- if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -- { -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { - if (req != 0) { -- depctl_data_t depctl = {.d32 = DWC_READ_REG32(&pcd->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->diepctl)}; -+ depctl_data_t depctl = {.d32 = -+ DWC_READ_REG32(&pcd->core_if->dev_if-> -+ in_ep_regs[ep->dwc_ep.num]-> -+ diepctl) }; - ++pcd->request_pending; - - DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); -- if (ep->dwc_ep.is_in) -- { -+ if (ep->dwc_ep.is_in) { - depctl.b.cnak = 1; -- DWC_WRITE_REG32(&pcd->core_if->dev_if->in_ep_regs[ep->dwc_ep.num]->diepctl, depctl.d32); -+ DWC_WRITE_REG32(&pcd->core_if->dev_if-> -+ in_ep_regs[ep->dwc_ep.num]-> -+ diepctl, depctl.d32); - } - - DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); -@@ -2219,16 +2215,20 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - } else { - #endif - max_transfer = -- GET_CORE_IF(ep->pcd)-> -- core_params->max_transfer_size; -+ GET_CORE_IF(ep->pcd)->core_params-> -+ max_transfer_size; - - /* Setup and start the Transfer */ - if (req->dw_align_buf){ - if (ep->dwc_ep.is_in) -- dwc_memcpy(req->dw_align_buf, buf, buflen); -- ep->dwc_ep.dma_addr = req->dw_align_buf_dma; -- ep->dwc_ep.start_xfer_buff = req->dw_align_buf; -- ep->dwc_ep.xfer_buff = req->dw_align_buf; -+ dwc_memcpy(req->dw_align_buf, -+ buf, buflen); -+ ep->dwc_ep.dma_addr = -+ req->dw_align_buf_dma; -+ ep->dwc_ep.start_xfer_buff = -+ req->dw_align_buf; -+ ep->dwc_ep.xfer_buff = -+ req->dw_align_buf; - } else { - ep->dwc_ep.dma_addr = dma_buf; - ep->dwc_ep.start_xfer_buff = buf; -@@ -2288,14 +2288,14 @@ int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, - diepmsk_data_t diepmsk = {.d32 = 0 }; - diepmsk.b.intktxfemp = 1; - if (GET_CORE_IF(pcd)->multiproc_int_enable) { -- DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> -- dev_global_regs-> -- diepeachintmsk[ep->dwc_ep.num], -- 0, diepmsk.d32); -- } else { -- DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> -- dev_global_regs->diepmsk, 0, -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> -+ dev_if->dev_global_regs->diepeachintmsk -+ [ep->dwc_ep.num], 0, - diepmsk.d32); -+ } else { -+ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> -+ dev_if->dev_global_regs-> -+ diepmsk, 0, diepmsk.d32); - } - - } -@@ -2379,11 +2379,13 @@ int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle) - fifosize_data_t txfifosize; - - txfifosize.d32 = -- DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs-> -- dtxfsiz[ep->dwc_ep.tx_fifo_num]); -+ DWC_READ_REG32(&GET_CORE_IF(pcd)-> -+ core_global_regs->dtxfsiz[ep->dwc_ep. -+ tx_fifo_num]); - txstatus.d32 = -- DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> -- in_ep_regs[ep->dwc_ep.num]->dtxfsts); -+ DWC_READ_REG32(&GET_CORE_IF(pcd)-> -+ dev_if->in_ep_regs[ep->dwc_ep.num]-> -+ dtxfsts); - - if (txstatus.b.txfspcavail < txfifosize.b.depth) { - DWC_WARN("%s() Data In Tx Fifo\n", __func__); -@@ -2501,14 +2503,16 @@ void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set) - /* Mask SRP detected interrupt from Power Down Logic */ - gpwrdn.d32 = 0; - gpwrdn.b.srp_det_msk = 1; -- DWC_MODIFY_REG32(&core_if->core_global_regs-> -- gpwrdn, gpwrdn.d32, 0); -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs->gpwrdn, -+ gpwrdn.d32, 0); - - /* Disable Power Down Logic */ - gpwrdn.d32 = 0; - gpwrdn.b.pmuactv = 1; -- DWC_MODIFY_REG32(&core_if->core_global_regs-> -- gpwrdn, gpwrdn.d32, 0); -+ DWC_MODIFY_REG32(&core_if-> -+ core_global_regs->gpwrdn, -+ gpwrdn.d32, 0); - - /* - * Initialize the Core for Device mode. -@@ -2522,13 +2526,13 @@ void dwc_otg_pcd_rem_wkup_from_suspend(dwc_otg_pcd_t * pcd, int set) - } - - dctl.b.rmtwkupsig = 1; -- DWC_MODIFY_REG32(&core_if->dev_if-> -- dev_global_regs->dctl, 0, dctl.d32); -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> -+ dctl, 0, dctl.d32); - DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); - - dwc_mdelay(2); -- DWC_MODIFY_REG32(&core_if->dev_if-> -- dev_global_regs->dctl, dctl.d32, 0); -+ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> -+ dctl, dctl.d32, 0); - DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); - } - } else { -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -index 4b2dde9..8ef7ba6 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ -- * $Revision: #46 $ -- * $Date: 2011/10/20 $ -- * $Change: 1870124 $ -+ * $Revision: #48 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -215,6 +215,10 @@ struct dwc_otg_pcd { - - dwc_dma_t setup_pkt_dma_handle; - -+ /* Additional buffer and flag for CTRL_WR premature case */ -+ uint8_t *backup_buf; -+ unsigned data_terminated; -+ - /** 2-byte dma buffer used to return status from GET_STATUS */ - uint16_t *status_buf; - dwc_dma_t status_buf_dma_handle; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -index 4a6520f..27061d3 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ -- * $Revision: #113 $ -- * $Date: 2011/10/24 $ -- * $Change: 1871160 $ -+ * $Revision: #116 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -741,6 +741,12 @@ static inline void ep0_out_start(dwc_otg_core_if_t * core_if, - DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__, - DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); - #endif -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { -+ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); -+ if (doepctl.b.epena) { -+ return; -+ } -+ } - - doeptsize0.b.supcnt = 3; - doeptsize0.b.pktcnt = 1; -@@ -763,6 +769,10 @@ static inline void ep0_out_start(dwc_otg_core_if_t * core_if, - - /** DMA Descriptor Setup */ - dma_desc->status.b.bs = BS_HOST_BUSY; -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { -+ dma_desc->status.b.sr = 0; -+ dma_desc->status.b.mtrf = 0; -+ } - dma_desc->status.b.l = 1; - dma_desc->status.b.ioc = 1; - dma_desc->status.b.bytes = pcd->ep0.dwc_ep.maxpacket; -@@ -772,8 +782,7 @@ static inline void ep0_out_start(dwc_otg_core_if_t * core_if, - - /** DOEPDMA0 Register write */ - DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, -- dev_if-> -- dma_setup_desc_addr -+ dev_if->dma_setup_desc_addr - [dev_if->setup_desc_index]); - } - -@@ -783,10 +792,15 @@ static inline void ep0_out_start(dwc_otg_core_if_t * core_if, - doeptsize0.d32); - } - -- /** DOEPCTL0 Register write */ -+ /** DOEPCTL0 Register write cnak will be set after setup interrupt */ -+ doepctl.d32 = 0; - doepctl.b.epena = 1; -+ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { - doepctl.b.cnak = 1; - DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); -+ } else { -+ DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32); -+ } - - #ifdef VERBOSE - DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", -@@ -898,7 +912,8 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - dcfg.b.epmscnt = 2; - DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); - -- DWC_DEBUGPL(DBG_PCDV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", -+ DWC_DEBUGPL(DBG_PCDV, -+ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", - __func__, core_if->first_in_nextep_seq); - for (i=0; i <= core_if->dev_if->num_in_eps; i++) { - DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); -@@ -916,10 +931,13 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - doepmsk.b.ahberr = 1; - doepmsk.b.epdisabled = 1; - -- if (core_if->dma_desc_enable) { -+ if ((core_if->dma_desc_enable) || -+ (core_if->dma_enable -+ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { - doepmsk.b.stsphsercvd = 1; -- doepmsk.b.bna = 1; - } -+ if (core_if->dma_desc_enable) -+ doepmsk.b.bna = 1; - /* - doepmsk.b.babble = 1; - doepmsk.b.nyet = 1; -@@ -961,10 +979,13 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - doepmsk.b.ahberr = 1; - doepmsk.b.epdisabled = 1; - -- if (core_if->dma_desc_enable) { -+ if ((core_if->dma_desc_enable) || -+ (core_if->dma_enable -+ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { - doepmsk.b.stsphsercvd = 1; -- doepmsk.b.bna = 1; - } -+ if (core_if->dma_desc_enable) -+ doepmsk.b.bna = 1; - DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); - - diepmsk.b.xfercompl = 1; -@@ -988,7 +1009,8 @@ int32_t dwc_otg_pcd_handle_usb_reset_intr(dwc_otg_pcd_t * pcd) - DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); - - /* setup EP0 to receive SETUP packets */ -- ep0_out_start(core_if, pcd); -+ if (core_if->snpsid <= OTG_CORE_REV_2_94a) -+ ep0_out_start(core_if, pcd); - - /* Clear interrupt */ - gintsts.d32 = 0; -@@ -1051,6 +1073,9 @@ int32_t dwc_otg_pcd_handle_enum_done_intr(dwc_otg_pcd_t * pcd) - utmi8b = 8; - } - dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep); -+ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) { -+ ep0_out_start(GET_CORE_IF(pcd), pcd); -+ } - - #ifdef DEBUG_EP0 - print_ep0_state(pcd); -@@ -1341,6 +1366,14 @@ static inline void do_setup_in_status_phase(dwc_otg_pcd_t * pcd) - - /* Prepare for more SETUP Packets */ - DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n"); -+ if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) -+ && (pcd->core_if->dma_desc_enable) -+ && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) { -+ DWC_DEBUGPL(DBG_PCDV, -+ "Data terminated wait next packet in out_desc_addr\n"); -+ pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr); -+ pcd->data_terminated = 1; -+ } - ep0->dwc_ep.xfer_len = 0; - ep0->dwc_ep.xfer_count = 0; - ep0->dwc_ep.is_in = 1; -@@ -1478,20 +1511,25 @@ static inline void do_get_status(dwc_otg_pcd_t * pcd) - if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */ - DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex)); - DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver); -- DWC_PRINTF("OTG CAP - %d, %d\n", core_if->core_params->otg_cap, -+ DWC_PRINTF("OTG CAP - %d, %d\n", -+ core_if->core_params->otg_cap, - DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); -- if(core_if->otg_ver == 1 && -- core_if->core_params->otg_cap == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { -+ if (core_if->otg_ver == 1 -+ && core_if->core_params->otg_cap == -+ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { - uint8_t *otgsts = (uint8_t*)pcd->status_buf; - *otgsts = (core_if->otg_sts & 0x1); - pcd->ep0_pending = 1; -- ep0->dwc_ep.start_xfer_buff = (uint8_t *) otgsts; -+ ep0->dwc_ep.start_xfer_buff = -+ (uint8_t *) otgsts; - ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts; -- ep0->dwc_ep.dma_addr = pcd->status_buf_dma_handle; -+ ep0->dwc_ep.dma_addr = -+ pcd->status_buf_dma_handle; - ep0->dwc_ep.xfer_len = 1; - ep0->dwc_ep.xfer_count = 0; - ep0->dwc_ep.total_len = ep0->dwc_ep.xfer_len; -- dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), &ep0->dwc_ep); -+ dwc_otg_ep0_start_transfer(GET_CORE_IF(pcd), -+ &ep0->dwc_ep); - return; - } else { - ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); -@@ -1767,22 +1805,28 @@ static inline void pcd_setup(dwc_otg_pcd_t * pcd) - struct cfi_usb_ctrlrequest cfi_req; - #endif - --#ifdef DEBUG_EP0 -- DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", -- ctrl.bmRequestType, ctrl.bRequest, -- UGETW(ctrl.wValue), UGETW(ctrl.wIndex), -- UGETW(ctrl.wLength)); --#endif -- - doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz); - -- /** @todo handle > 1 setup packet , assert error for now */ -- -+ /** In BDMA more then 1 setup packet is not supported till 3.00a */ - if (core_if->dma_enable && core_if->dma_desc_enable == 0 -- && (doeptsize0.b.supcnt < 2)) { -+ && (doeptsize0.b.supcnt < 2) -+ && (core_if->snpsid < OTG_CORE_REV_2_94a)) { - DWC_ERROR - ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n"); - } -+ if ((core_if->snpsid >= OTG_CORE_REV_3_00a) -+ && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) { -+ ctrl = -+ (pcd->setup_pkt + -+ (3 - doeptsize0.b.supcnt - 1 + -+ ep0->dwc_ep.stp_rollover))->req; -+ } -+#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", -+ ctrl.bmRequestType, ctrl.bRequest, -+ UGETW(ctrl.wValue), UGETW(ctrl.wIndex), -+ UGETW(ctrl.wLength)); -+#endif - - /* Clean up the request queue */ - dwc_otg_request_nuke(ep0); -@@ -2028,8 +2072,18 @@ static int32_t ep0_complete_request(dwc_otg_pcd_ep_t * ep) - #endif - req->sent_zlp = 0; - } -- if (core_if->dma_desc_enable == 0) -+ /* For older cores do setup in status phase in Slave/BDMA modes, -+ * starting from 3.00 do that only in slave, and for DMA modes -+ * just re-enable ep 0 OUT here*/ -+ if (core_if->dma_enable == 0 -+ || (core_if->dma_desc_enable == 0 -+ && core_if->snpsid <= OTG_CORE_REV_2_94a)) { - do_setup_in_status_phase(pcd); -+ } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) { -+ DWC_DEBUGPL(DBG_PCDV, -+ "Enable out ep before in status phase\n"); -+ ep0_out_start(core_if, pcd); -+ } - } - - /* Complete the request */ -@@ -2169,8 +2223,8 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - is_last = 1; - } - } else { -- if(ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -- { -+ if (ep->dwc_ep.type == -+ DWC_OTG_EP_TYPE_ISOC) { - req->actual = 0; - dwc_otg_request_done(ep, req, 0); - -@@ -2306,25 +2360,34 @@ static void complete_ep(dwc_otg_pcd_ep_t * ep) - */ - if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR && - (ep->dwc_ep.maxpacket%4)) { -- ep->dwc_ep.xfer_count = ep->dwc_ep.total_len - byte_count; -- if ((ep->dwc_ep.xfer_len % ep->dwc_ep.maxpacket) && -- (ep->dwc_ep.xfer_len/ep->dwc_ep.maxpacket < MAX_DMA_DESC_CNT)) -+ ep->dwc_ep.xfer_count = -+ ep->dwc_ep.total_len - byte_count; -+ if ((ep->dwc_ep.xfer_len % -+ ep->dwc_ep.maxpacket) -+ && (ep->dwc_ep.xfer_len / -+ ep->dwc_ep.maxpacket < -+ MAX_DMA_DESC_CNT)) - ep->dwc_ep.xfer_len -= -- (ep->dwc_ep.desc_cnt - 1) * ep->dwc_ep.maxpacket + -- ep->dwc_ep.xfer_len % ep->dwc_ep.maxpacket; -+ (ep->dwc_ep.desc_cnt - -+ 1) * ep->dwc_ep.maxpacket + -+ ep->dwc_ep.xfer_len % -+ ep->dwc_ep.maxpacket; - else - ep->dwc_ep.xfer_len -= -- ep->dwc_ep.desc_cnt * ep->dwc_ep.maxpacket; -+ ep->dwc_ep.desc_cnt * -+ ep->dwc_ep.maxpacket; - if (ep->dwc_ep.xfer_len > 0) { -- dwc_otg_ep_start_transfer(core_if, -- &ep->dwc_ep); -+ dwc_otg_ep_start_transfer -+ (core_if, &ep->dwc_ep); - } else { - is_last = 1; - } - } else { -- ep->dwc_ep.xfer_count = ep->dwc_ep.total_len -- - byte_count + -- ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3); -+ ep->dwc_ep.xfer_count = -+ ep->dwc_ep.total_len - byte_count + -+ ((4 - -+ (ep->dwc_ep. -+ total_len & 0x3)) & 0x3); - is_last = 1; - } - } else { -@@ -2924,12 +2987,12 @@ static uint32_t set_iso_pkts_info(dwc_otg_core_if_t * core_if, dwc_ep_t * ep) - - if (ep->is_in) { - deptsiz.d32 = -- DWC_READ_REG32(&core_if->dev_if-> -- in_ep_regs[ep->num]->dieptsiz); -+ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ dieptsiz); - } else { - deptsiz.d32 = -- DWC_READ_REG32(&core_if->dev_if-> -- out_ep_regs[ep->num]->doeptsiz); -+ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> -+ doeptsiz); - } - - if (!deptsiz.b.xfersize) { -@@ -3068,7 +3131,8 @@ static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep) - int i, start; - - if (!dwc_ep->desc_cnt) -- DWC_WARN("Descriptor count = %d\n", dwc_ep->desc_cnt); -+ DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num, -+ (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt); - - if (core_if->core_params->cont_on_bna && !dwc_ep->is_in - && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) { -@@ -3092,8 +3156,8 @@ static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep) - - if (dwc_ep->is_in == 0) { - addr = -- &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep-> -- num]->doepctl; -+ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]-> -+ doepctl; - } else { - addr = - &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; -@@ -3106,7 +3170,7 @@ static void dwc_otg_pcd_handle_noniso_bna(dwc_otg_pcd_ep_t * ep) - /** - * This function handles EP0 Control transfers. - * -- * The state of the control tranfers are tracked in -+ * The state of the control transfers are tracked in - * ep0state. - */ - static void handle_ep0(dwc_otg_pcd_t * pcd) -@@ -3174,7 +3238,7 @@ static void handle_ep0(dwc_otg_pcd_t * pcd) - dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), - &ep0->dwc_ep); - ep0->dwc_ep.sent_zlp = 0; -- DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); -+ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); - } else { - ep0_complete_request(ep0); - DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); -@@ -3212,7 +3276,7 @@ static void handle_ep0(dwc_otg_pcd_t * pcd) - dwc_otg_ep0_continue_transfer(GET_CORE_IF(pcd), - &ep0->dwc_ep); - ep0->dwc_ep.sent_zlp = 0; -- DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); -+ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); - } else { - ep0_complete_request(ep0); - DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); -@@ -3365,22 +3429,26 @@ void predict_nextep_seq( dwc_otg_core_if_t * core_if) - if (TOKEN_Q_DEPTH > 6) { - /* Fill intkn_seq[] from in_tkn_epnums[1] */ - for (i=6; i < 14; i++) -- intkn_seq[i] = (in_tkn_epnums[1] >> ((7-(i-6)) * 4)) & 0xf; -+ intkn_seq[i] = -+ (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf; - } - - if (TOKEN_Q_DEPTH > 14) { - /* Fill intkn_seq[] from in_tkn_epnums[1] */ - for (i=14; i < 22; i++) -- intkn_seq[i] = (in_tkn_epnums[2] >> ((7-(i-14)) * 4)) & 0xf; -+ intkn_seq[i] = -+ (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf; - } - - if (TOKEN_Q_DEPTH > 22) { - /* Fill intkn_seq[] from in_tkn_epnums[1] */ - for (i=22; i < 30; i++) -- intkn_seq[i] = (in_tkn_epnums[3] >> ((7-(i-22)) * 4)) & 0xf; -+ intkn_seq[i] = -+ (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf; - } - -- DWC_DEBUGPL(DBG_PCDV,"%s start=%d end=%d intkn_seq[]:\n", __func__, start, end); -+ DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__, -+ start, end); - for (i=0; idev_if->num_in_eps; i++) { -- depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); -+ depctl.d32 = -+ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); - if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP - depctl.b.nextep = core_if->nextep_seq[i]; - DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); -@@ -3729,7 +3798,7 @@ static inline int32_t handle_out_ep_nak_intr(dwc_otg_pcd_t * pcd, - dwc_otg_core_if_t *core_if; - doepmsk_data_t intr_mask = {.d32 = 0 }; - -- DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); -+ DWC_DEBUGPL(DBG_ANY, "INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); - core_if = GET_CORE_IF(pcd); - intr_mask.b.nak = 1; - -@@ -3842,7 +3911,7 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - /* Transfer complete */ - if (diepint.b.xfercompl) { - /* Disable the NP Tx FIFO Empty -- * Interrrupt */ -+ * Interrupt */ - if (core_if->en_multiple_tx_fifo == 0) { - intr_mask.b.nptxfempty = 1; - DWC_MODIFY_REG32 -@@ -4013,14 +4082,11 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - if (diepint.b.nak) { - DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n", - epnum); -- if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -- { -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { - depctl_data_t depctl; -- if (ep->dwc_ep.frame_num == 0xFFFFFFFF) -- { -+ if (ep->dwc_ep.frame_num == 0xFFFFFFFF) { - ep->dwc_ep.frame_num = core_if->frame_num; -- if (ep->dwc_ep.bInterval > 1) -- { -+ if (ep->dwc_ep.bInterval > 1) { - depctl.d32 = 0; - depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); - if (ep->dwc_ep.frame_num & 0x1) { -@@ -4035,8 +4101,7 @@ static int32_t dwc_otg_pcd_handle_in_ep_intr(dwc_otg_pcd_t * pcd) - start_next_request(ep); - } - ep->dwc_ep.frame_num += ep->dwc_ep.bInterval; -- if (dwc_ep->frame_num > 0x3FFF) -- { -+ if (dwc_ep->frame_num > 0x3FFF) { - dwc_ep->frm_overrun = 1; - dwc_ep->frame_num &= 0x3FFF; - } else -@@ -4106,17 +4171,290 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - #endif - doepint.d32 = - dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep); -- -+ /* Moved this interrupt upper due to core deffect of asserting -+ * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */ -+ if (doepint.b.stsphsercvd) { -+ deptsiz0_data_t deptsiz; -+ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); -+ deptsiz.d32 = -+ DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[0]->doeptsiz); -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a -+ && core_if->dma_enable -+ && core_if->dma_desc_enable == 0 -+ && doepint.b.xfercompl -+ && deptsiz.b.xfersize == 24) { -+ CLEAR_OUT_EP_INTR(core_if, epnum, -+ xfercompl); -+ doepint.b.xfercompl = 0; -+ ep0_out_start(core_if, pcd); -+ } -+ if ((core_if->dma_desc_enable) || -+ (core_if->dma_enable -+ && core_if->snpsid >= -+ OTG_CORE_REV_3_00a)) { -+ do_setup_in_status_phase(pcd); -+ } -+ } - /* Transfer complete */ - if (doepint.b.xfercompl) { - - if (epnum == 0) { - /* Clear the bit in DOEPINTn for this interrupt */ -- CLEAR_OUT_EP_INTR(core_if, epnum, -- xfercompl); -+ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { -+ DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n", -+ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint), -+ doepint.d32); -+ DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n", -+ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl)); -+ -+ if (core_if->snpsid >= OTG_CORE_REV_3_00a -+ && core_if->dma_enable == 0) { -+ doepint_data_t doepint; -+ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[0]->doepint); -+ if (pcd->ep0state == EP0_IDLE && doepint.b.sr) { -+ CLEAR_OUT_EP_INTR(core_if, epnum, sr); -+ goto exit_xfercompl; -+ } -+ } -+ /* In case of DDMA look at SR bit to go to the Data Stage */ -+ if (core_if->dma_desc_enable) { -+ dev_dma_desc_sts_t status = {.d32 = 0}; -+ if (pcd->ep0state == EP0_IDLE) { -+ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> -+ dev_if->setup_desc_index]->status.d32; -+ if(pcd->data_terminated) { -+ pcd->data_terminated = 0; -+ status.d32 = core_if->dev_if->out_desc_addr->status.d32; -+ dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8); -+ } -+ if (status.b.sr) { -+ if (doepint.b.setup) { -+ DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n"); -+ /* Already started data stage, clear setup */ -+ CLEAR_OUT_EP_INTR(core_if, epnum, setup); -+ doepint.b.setup = 0; -+ handle_ep0(pcd); -+ /* Prepare for more setup packets */ -+ if (pcd->ep0state == EP0_IN_STATUS_PHASE || -+ pcd->ep0state == EP0_IN_DATA_PHASE) { -+ ep0_out_start(core_if, pcd); -+ } -+ -+ goto exit_xfercompl; -+ } else { -+ /* Prepare for more setup packets */ -+ DWC_DEBUGPL(DBG_PCDV, -+ "EP0_IDLE SR=1 setup=0 new setup comes\n"); -+ ep0_out_start(core_if, pcd); -+ } -+ } -+ } else { -+ dwc_otg_pcd_request_t *req; -+ dev_dma_desc_sts_t status = {.d32 = 0}; -+ diepint_data_t diepint0; -+ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepint); -+ -+ if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) { -+ DWC_ERROR("EP0 is stalled/disconnected\n"); -+ } -+ -+ /* Clear IN xfercompl if set */ -+ if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE -+ || pcd->ep0state == EP0_IN_DATA_PHASE)) { -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepint, diepint0.d32); -+ } -+ -+ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> -+ dev_if->setup_desc_index]->status.d32; -+ -+ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len -+ && (pcd->ep0state == EP0_OUT_DATA_PHASE)) -+ status.d32 = core_if->dev_if->out_desc_addr->status.d32; -+ if (pcd->ep0state == EP0_OUT_STATUS_PHASE) -+ status.d32 = status.d32 = core_if->dev_if-> -+ out_desc_addr->status.d32; -+ -+ if (status.b.sr) { -+ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); -+ } else { -+ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && -+ pcd->ep0state == EP0_OUT_DATA_PHASE) { -+ /* Read arrived setup packet from req->buf */ -+ dwc_memcpy(&pcd->setup_pkt->req, -+ req->buf + ep->dwc_ep.xfer_count, 8); -+ } -+ req->actual = ep->dwc_ep.xfer_count; -+ dwc_otg_request_done(ep, req, -ECONNRESET); -+ ep->dwc_ep.start_xfer_buff = 0; -+ ep->dwc_ep.xfer_buff = 0; -+ ep->dwc_ep.xfer_len = 0; -+ } -+ pcd->ep0state = EP0_IDLE; -+ if (doepint.b.setup) { -+ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); -+ /* Data stage started, clear setup */ -+ CLEAR_OUT_EP_INTR(core_if, epnum, setup); -+ doepint.b.setup = 0; -+ handle_ep0(pcd); -+ /* Prepare for setup packets if ep0in was enabled*/ -+ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { -+ ep0_out_start(core_if, pcd); -+ } -+ -+ goto exit_xfercompl; -+ } else { -+ /* Prepare for more setup packets */ -+ DWC_DEBUGPL(DBG_PCDV, -+ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); -+ ep0_out_start(core_if, pcd); -+ } -+ } -+ } -+ } -+ if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable -+ && core_if->dma_desc_enable == 0) { -+ doepint_data_t doepint_temp = {.d32 = 0}; -+ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; -+ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[ep->dwc_ep.num]->doepint); -+ doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[ep->dwc_ep.num]->doeptsiz); -+ if (pcd->ep0state == EP0_IDLE) { -+ if (doepint_temp.b.sr) { -+ CLEAR_OUT_EP_INTR(core_if, epnum, sr); -+ } -+ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[0]->doepint); -+ if (doeptsize0.b.supcnt == 3) { -+ DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n"); -+ ep->dwc_ep.stp_rollover = 1; -+ } -+ if (doepint.b.setup) { -+retry: -+ /* Already started data stage, clear setup */ -+ CLEAR_OUT_EP_INTR(core_if, epnum, setup); -+ doepint.b.setup = 0; -+ handle_ep0(pcd); -+ ep->dwc_ep.stp_rollover = 0; -+ /* Prepare for more setup packets */ -+ if (pcd->ep0state == EP0_IN_STATUS_PHASE || -+ pcd->ep0state == EP0_IN_DATA_PHASE) { -+ ep0_out_start(core_if, pcd); -+ } -+ goto exit_xfercompl; -+ } else { -+ /* Prepare for more setup packets */ -+ DWC_DEBUGPL(DBG_ANY, -+ "EP0_IDLE SR=1 setup=0 new setup comes\n"); -+ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[0]->doepint); -+ if(doepint.b.setup) -+ goto retry; -+ ep0_out_start(core_if, pcd); -+ } -+ } else { -+ dwc_otg_pcd_request_t *req; -+ diepint_data_t diepint0 = {.d32 = 0}; -+ doepint_data_t doepint_temp = {.d32 = 0}; -+ depctl_data_t diepctl0; -+ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepint); -+ diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepctl); -+ -+ if (pcd->ep0state == EP0_IN_DATA_PHASE -+ || pcd->ep0state == EP0_IN_STATUS_PHASE) { -+ if (diepint0.b.xfercompl) { -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepint, diepint0.d32); -+ } -+ if (diepctl0.b.epena) { -+ diepint_data_t diepint = {.d32 = 0}; -+ diepctl0.b.snak = 1; -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepctl, diepctl0.d32); -+ do { -+ dwc_udelay(10); -+ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepint); -+ } while (!diepint.b.inepnakeff); -+ diepint.b.inepnakeff = 1; -+ DWC_WRITE_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepint, diepint.d32); -+ diepctl0.d32 = 0; -+ diepctl0.b.epdis = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl, -+ diepctl0.d32); -+ do { -+ dwc_udelay(10); -+ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ in_ep_regs[0]->diepint); -+ } while (!diepint.b.epdisabled); -+ diepint.b.epdisabled = 1; -+ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint, -+ diepint.d32); -+ } -+ } -+ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> -+ out_ep_regs[ep->dwc_ep.num]->doepint); -+ if (doepint_temp.b.sr) { -+ CLEAR_OUT_EP_INTR(core_if, epnum, sr); -+ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { -+ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); -+ } else { -+ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); -+ req = DWC_CIRCLEQ_FIRST(&ep->queue); -+ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && -+ pcd->ep0state == EP0_OUT_DATA_PHASE) { -+ /* Read arrived setup packet from req->buf */ -+ dwc_memcpy(&pcd->setup_pkt->req, -+ req->buf + ep->dwc_ep.xfer_count, 8); -+ } -+ req->actual = ep->dwc_ep.xfer_count; -+ dwc_otg_request_done(ep, req, -ECONNRESET); -+ ep->dwc_ep.start_xfer_buff = 0; -+ ep->dwc_ep.xfer_buff = 0; -+ ep->dwc_ep.xfer_len = 0; -+ } -+ pcd->ep0state = EP0_IDLE; -+ if (doepint.b.setup) { -+ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); -+ /* Data stage started, clear setup */ -+ CLEAR_OUT_EP_INTR(core_if, epnum, setup); -+ doepint.b.setup = 0; -+ handle_ep0(pcd); -+ /* Prepare for setup packets if ep0in was enabled*/ -+ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { -+ ep0_out_start(core_if, pcd); -+ } -+ goto exit_xfercompl; -+ } else { -+ /* Prepare for more setup packets */ -+ DWC_DEBUGPL(DBG_PCDV, -+ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); -+ ep0_out_start(core_if, pcd); -+ } -+ } -+ } -+ } -+ if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE) -+ handle_ep0(pcd); -+exit_xfercompl: -+ DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n", -+ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32); -+ } else { - if (core_if->dma_desc_enable == 0 - || pcd->ep0state != EP0_IDLE) - handle_ep0(pcd); -+ } - #ifdef DWC_EN_ISOC - } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { - if (doepint.b.pktdrpsts == 0) { -@@ -4228,8 +4566,7 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - /* Setup Phase Done (contorl EPs) */ - if (doepint.b.setup) { - #ifdef DEBUG_EP0 -- DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", -- epnum); -+ DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum); - #endif - CLEAR_OUT_EP_INTR(core_if, epnum, setup); - -@@ -4257,13 +4594,7 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - } - } - } -- if (doepint.b.stsphsercvd) { -- CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); -- if (core_if->dma_desc_enable) { -- do_setup_in_status_phase(pcd); -- } -- } -- /* Babble Interrutp */ -+ /* Babble Interrupt */ - if (doepint.b.babble) { - DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n", - epnum); -@@ -4271,16 +4602,13 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) - - CLEAR_OUT_EP_INTR(core_if, epnum, babble); - } -- if (doepint.b.outtknepdis) -- { -+ if (doepint.b.outtknepdis) { - DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \ - disabled\n",epnum); -- if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) -- { -+ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { - doepmsk_data_t doepmsk = {.d32 = 0}; - ep->dwc_ep.frame_num = core_if->frame_num; -- if (ep->dwc_ep.bInterval > 1) -- { -+ if (ep->dwc_ep.bInterval > 1) { - depctl_data_t depctl; - depctl.d32 = DWC_READ_REG32(&core_if->dev_if-> - out_ep_regs[epnum]->doepctl); -@@ -4331,7 +4659,8 @@ static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun - int retval = 0; - if(!frm_overrun && curr_fr >= trgt_fr) - retval = 1; -- else if (frm_overrun && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF/2))) -+ else if (frm_overrun -+ && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2))) - retval = 1; - return retval; - } -@@ -4641,8 +4970,8 @@ int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) - } - if (i > dev_if->num_out_eps) { - dctl_data_t dctl; -- dctl.d32 = DWC_READ_REG32(&dev_if-> -- dev_global_regs->dctl); -+ dctl.d32 = -+ DWC_READ_REG32(&dev_if->dev_global_regs->dctl); - dctl.b.cgoutnak = 1; - DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, - dctl.d32); -@@ -4650,8 +4979,7 @@ int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) - } - - /* Disable the endpoint */ -- doepctl.d32 = DWC_READ_REG32(&dev_if-> -- out_ep_regs[i]->doepctl); -+ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); - if (doepctl.b.epena) { - doepctl.b.epdis = 1; - doepctl.b.snak = 1; -@@ -4660,20 +4988,22 @@ int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) - return 1; - } - /* We come here from Incomplete ISO OUT handler */ -- if(dev_if->isoc_ep) -- { -+ if (dev_if->isoc_ep) { - dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep; - uint32_t epnum = dwc_ep->num; - doepint_data_t doepint; -- doepint.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint); -+ doepint.d32 = -+ DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint); - dev_if->isoc_ep = NULL; -- doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); -+ doepctl.d32 = -+ DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); - DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32); - if (doepctl.b.epena) { - doepctl.b.epdis = 1; - doepctl.b.snak = 1; - } -- DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, doepctl.d32); -+ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, -+ doepctl.d32); - return 1; - } else - DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -index 59a1f33..903e670 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ -- * $Revision: #19 $ -- * $Date: 2011/10/26 $ -- * $Change: 1873028 $ -+ * $Revision: #21 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -525,9 +525,10 @@ static int iso_ep_start(struct usb_ep *usb_ep, struct usb_iso_request *req, - req->buf1, req->dma0, req->dma1, - req->sync_frame, req->data_pattern_frame, - req->data_per_frame, -- req->flags & USB_REQ_ISO_ASAP ? -1 : req-> -- start_frame, req->buf_proc_intrvl, req, -- gfp_flags == GFP_ATOMIC ? 1 : 0); -+ req-> -+ flags & USB_REQ_ISO_ASAP ? -1 : -+ req->start_frame, req->buf_proc_intrvl, -+ req, gfp_flags == GFP_ATOMIC ? 1 : 0); - - if (retval) { - return -EINVAL; -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h -index 8dc648b..0572642 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_regs.h -+++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h -@@ -1,8 +1,8 @@ - /* ========================================================================== - * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $ -- * $Revision: #97 $ -- * $Date: 2011/10/24 $ -- * $Change: 1871160 $ -+ * $Revision: #98 $ -+ * $Date: 2012/08/10 $ -+ * $Change: 2047372 $ - * - * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, - * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless -@@ -826,8 +826,9 @@ - unsigned num_dev_perio_in_ep:4; - unsigned power_optimiz:1; - unsigned min_ahb_freq:1; -- unsigned part_power_down:1; -- unsigned reserved:7; -+ unsigned hiber:1; -+ unsigned xhiber:1; -+ unsigned reserved:6; - unsigned utmi_phy_data_width:2; - unsigned num_dev_mode_ctrl_ep:4; - unsigned iddig_filt_en:1; -@@ -1330,8 +1331,10 @@ - unsigned nak:1; - /** NYET Interrupt */ - unsigned nyet:1; -+ /** Bit indicating setup packet received */ -+ unsigned sr:1; - -- unsigned reserved15_31:17; -+ unsigned reserved16_31:16; - } b; - } doepint_data_t; - -@@ -2448,7 +2451,9 @@ - unsigned deep_sleep:1; - unsigned resetaftsusp:1; - unsigned restoremode:1; -- unsigned reserved10_12:3; -+ unsigned enbl_extnd_hiber:1; -+ unsigned extnd_hiber_pwrclmp:1; -+ unsigned extnd_hiber_switch:1; - unsigned ess_reg_restored:1; - unsigned prt_clk_sel:2; - unsigned port_power:1; --- -1.8.1.6 - - -From cd4017094ab361490285e9de25e00803d154d2d0 Mon Sep 17 00:00:00 2001 +From 23effc5826fd97a33418646601e5aea1cef1143d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 039/102] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 28/88] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) --- @@ -113764,37 +87426,10 @@ index 510be0b..d61e747 100644 1.8.1.6 -From 92e29a8c527fedab65aa73a087dd549178e53cbb Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 24 Aug 2012 23:25:13 +0100 -Subject: [PATCH 040/102] Turn on microframe_schedule by default. Can still be - disabled on command line - ---- - drivers/usb/host/dwc_otg/dwc_otg_driver.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -index 8ddc9ae..e7f99e1 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c -@@ -60,7 +60,7 @@ - #define DWC_DRIVER_VERSION "3.00a 10-AUG-2012" - #define DWC_DRIVER_DESC "HS OTG USB Controller driver" - --bool microframe_schedule; -+bool microframe_schedule=true; - - static const char dwc_driver_name[] = "dwc_otg"; - --- -1.8.1.6 - - -From 8cda847966ef2785fa41df07445df21ec712a1f0 Mon Sep 17 00:00:00 2001 +From 6bfb747cf6be7dd680c15753d78ffcc9117fabb2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:27:48 +0100 -Subject: [PATCH 041/102] Add low-latency mode to sdcard driver. Disable with +Subject: [PATCH 29/88] Add low-latency mode to sdcard driver. Disable with sdhci-bcm2708.enable_llm=0. Thanks ddv2005. --- @@ -113885,7 +87520,7 @@ index 7a703c2..7ce2829 100644 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c -index 71e2696..c9dcd22 100644 +index 179e83e..470860b 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -124,6 +124,91 @@ static void sdhci_dumpregs(struct sdhci_host *host) @@ -114082,7 +87717,7 @@ index 71e2696..c9dcd22 100644 } static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -@@ -1600,7 +1689,7 @@ static int sdhci_check_ro(struct sdhci_host *host) +@@ -1631,7 +1720,7 @@ static int sdhci_check_ro(struct sdhci_host *host) unsigned long flags; int is_readonly; @@ -114091,7 +87726,7 @@ index 71e2696..c9dcd22 100644 if (host->flags & SDHCI_DEVICE_DEAD) is_readonly = 0; -@@ -1610,7 +1699,7 @@ static int sdhci_check_ro(struct sdhci_host *host) +@@ -1641,7 +1730,7 @@ static int sdhci_check_ro(struct sdhci_host *host) is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_WRITE_PROTECT); @@ -114100,7 +87735,7 @@ index 71e2696..c9dcd22 100644 /* This quirk needs to be replaced by a callback-function later */ return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? -@@ -1683,9 +1772,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) +@@ -1714,9 +1803,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) struct sdhci_host *host = mmc_priv(mmc); unsigned long flags; @@ -114112,7 +87747,7 @@ index 71e2696..c9dcd22 100644 } static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, -@@ -2029,7 +2118,7 @@ static void sdhci_card_event(struct mmc_host *mmc) +@@ -2060,7 +2149,7 @@ static void sdhci_card_event(struct mmc_host *mmc) struct sdhci_host *host = mmc_priv(mmc); unsigned long flags; @@ -114121,7 +87756,7 @@ index 71e2696..c9dcd22 100644 /* Check host->mrq first in case we are runtime suspended */ if (host->mrq && -@@ -2046,7 +2135,7 @@ static void sdhci_card_event(struct mmc_host *mmc) +@@ -2077,7 +2166,7 @@ static void sdhci_card_event(struct mmc_host *mmc) tasklet_schedule(&host->finish_tasklet); } @@ -114130,7 +87765,7 @@ index 71e2696..c9dcd22 100644 } static const struct mmc_host_ops sdhci_ops = { -@@ -2084,14 +2173,14 @@ static void sdhci_tasklet_finish(unsigned long param) +@@ -2116,14 +2205,14 @@ static void sdhci_tasklet_finish(unsigned long param) host = (struct sdhci_host*)param; @@ -114147,7 +87782,7 @@ index 71e2696..c9dcd22 100644 return; } -@@ -2129,7 +2218,7 @@ static void sdhci_tasklet_finish(unsigned long param) +@@ -2161,7 +2250,7 @@ static void sdhci_tasklet_finish(unsigned long param) #endif mmiowb(); @@ -114156,7 +87791,7 @@ index 71e2696..c9dcd22 100644 mmc_request_done(host->mmc, mrq); sdhci_runtime_pm_put(host); -@@ -2142,7 +2231,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2174,7 +2263,7 @@ static void sdhci_timeout_timer(unsigned long data) host = (struct sdhci_host*)data; @@ -114165,7 +87800,7 @@ index 71e2696..c9dcd22 100644 if (host->mrq) { pr_err("%s: Timeout waiting for hardware " -@@ -2163,7 +2252,7 @@ static void sdhci_timeout_timer(unsigned long data) +@@ -2195,7 +2284,7 @@ static void sdhci_timeout_timer(unsigned long data) } mmiowb(); @@ -114174,7 +87809,7 @@ index 71e2696..c9dcd22 100644 } static void sdhci_tuning_timer(unsigned long data) -@@ -2173,11 +2262,11 @@ static void sdhci_tuning_timer(unsigned long data) +@@ -2205,11 +2294,11 @@ static void sdhci_tuning_timer(unsigned long data) host = (struct sdhci_host *)data; @@ -114188,7 +87823,7 @@ index 71e2696..c9dcd22 100644 } /*****************************************************************************\ -@@ -2401,10 +2490,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2433,10 +2522,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) u32 intmask, unexpected = 0; int cardint = 0, max_loops = 16; @@ -114201,7 +87836,7 @@ index 71e2696..c9dcd22 100644 pr_warning("%s: got irq while runtime suspended\n", mmc_hostname(host->mmc)); return IRQ_HANDLED; -@@ -2508,7 +2597,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) +@@ -2540,7 +2629,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) if (intmask && --max_loops) goto again; out: @@ -114210,7 +87845,7 @@ index 71e2696..c9dcd22 100644 if (unexpected) { pr_err("%s: Unexpected interrupt 0x%08x.\n", -@@ -2670,15 +2759,15 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) +@@ -2702,15 +2791,15 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) host->flags &= ~SDHCI_NEEDS_RETUNING; } @@ -114230,7 +87865,7 @@ index 71e2696..c9dcd22 100644 return ret; } -@@ -2704,16 +2793,16 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) +@@ -2736,16 +2825,16 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) sdhci_do_start_signal_voltage_switch(host, &host->mmc->ios); if ((host_flags & SDHCI_PV_ENABLED) && !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { @@ -114250,7 +87885,7 @@ index 71e2696..c9dcd22 100644 host->runtime_suspended = false; -@@ -2724,7 +2813,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) +@@ -2756,7 +2845,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) /* Enable Card Detection */ sdhci_enable_card_detection(host); @@ -114259,7 +87894,7 @@ index 71e2696..c9dcd22 100644 return ret; } -@@ -3211,7 +3300,7 @@ int sdhci_add_host(struct sdhci_host *host) +@@ -3248,7 +3337,7 @@ int sdhci_add_host(struct sdhci_host *host) host->tuning_timer.function = sdhci_tuning_timer; } @@ -114268,7 +87903,7 @@ index 71e2696..c9dcd22 100644 mmc_hostname(mmc), host); if (ret) { pr_err("%s: Failed to request IRQ %d: %d\n", -@@ -3275,7 +3364,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) +@@ -3312,7 +3401,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) unsigned long flags; if (dead) { @@ -114277,7 +87912,7 @@ index 71e2696..c9dcd22 100644 host->flags |= SDHCI_DEVICE_DEAD; -@@ -3287,7 +3376,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) +@@ -3324,7 +3413,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) tasklet_schedule(&host->finish_tasklet); } @@ -114317,10 +87952,10 @@ index f3a39c1..58bfab0 100644 1.8.1.6 -From 8e789d81c4df6fb7d643c2f2126347146b42cadd Mon Sep 17 00:00:00 2001 +From 56b675fceebb97e27686cdfaa918591d28e6f1bb Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Wed, 8 May 2013 12:02:03 +0100 -Subject: [PATCH 042/102] Add FIQ patch to dwc_otg driver. Enable with +Date: Wed, 3 Jul 2013 00:46:42 +0100 +Subject: [PATCH 30/88] Add FIQ patch to dwc_otg driver. Enable with dwc_otg.fiq_fix_enable=1. Should give about 10% more ARM performance. Thanks to Gordon and Costas @@ -114351,7 +87986,7 @@ Subject: [PATCH 042/102] Add FIQ patch to dwc_otg driver. Enable with create mode 100755 drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 448f328..d33eb79 100644 +index edae05e..0cafe24 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -373,6 +373,7 @@ config ARCH_BCM2708 @@ -115480,10 +89115,10 @@ index a7e9076..bb1c42d 100644 1.8.1.6 -From 38caf84cdb0d6b6d743e9d5fba24878622df7528 Mon Sep 17 00:00:00 2001 +From d2c50dbe9f75e1b89aadfb87eafea7874ec0fe63 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 12 Apr 2013 23:58:47 +0100 -Subject: [PATCH 045/102] Add verious user config requests. +Subject: [PATCH 33/88] Add verious user config requests. CONFIG_DEVTMPFS_MOUNT, CONFIG_NFS_V4_1=y CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y, drbd and IPSEC modules @@ -115893,42 +89528,11 @@ index 31f5afaa..ef43466 100644 1.8.1.6 -From eb7e6a2dc12d923e6deab50e2280c7b5d0b38800 Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Sat, 8 Sep 2012 14:49:16 +0100 -Subject: [PATCH 046/102] Don't believe KDIR is required when building as part - of kernel - ---- - drivers/usb/host/dwc_common_port/Makefile | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/drivers/usb/host/dwc_common_port/Makefile b/drivers/usb/host/dwc_common_port/Makefile -index 203c7ea..63e3485 100644 ---- a/drivers/usb/host/dwc_common_port/Makefile -+++ b/drivers/usb/host/dwc_common_port/Makefile -@@ -30,9 +30,9 @@ endif - - else - --ifeq ($(KDIR),) --$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) --endif -+#ifeq ($(KDIR),) -+#$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) -+#endif - - ifeq ($(ARCH),) - $(error Must give "ARCH=" on command line or in environment. Also, if \ --- -1.8.1.6 - - -From 59c7f023529bf96df69c8241a0455c21b9b153f0 Mon Sep 17 00:00:00 2001 +From 41886846d6954160e12a8a615670aa75c008f74c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 8 Sep 2012 15:17:53 +0100 -Subject: [PATCH 047/102] Avoid dynamic memory allocation for channel lock in - USB driver. Thanks ddv2005. +Subject: [PATCH 34/88] Avoid dynamic memory allocation for channel lock in USB + driver. Thanks ddv2005. --- drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 6 +++--- @@ -116034,10 +89638,10 @@ index f1658fa..21e8f09 100644 1.8.1.6 -From 2a5ffee873590b0eafba48448de435576c8ec3c4 Mon Sep 17 00:00:00 2001 +From f7ac5d29e294fd756c952b0a58fba1ede77221e5 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Wed, 8 May 2013 12:04:44 +0100 -Subject: [PATCH 048/102] Add cpufreq driver +Date: Wed, 3 Jul 2013 00:49:20 +0100 +Subject: [PATCH 35/88] Add cpufreq driver --- arch/arm/Kconfig | 1 + @@ -116045,14 +89649,14 @@ Subject: [PATCH 048/102] Add cpufreq driver arch/arm/mach-bcm2708/include/mach/vcio.h | 81 +++++++++- arch/arm/mach-bcm2708/vc_mem.c | 47 +++--- arch/arm/mach-bcm2708/vcio.c | 34 +++++ - drivers/cpufreq/Kconfig.arm | 9 ++ + drivers/cpufreq/Kconfig.arm | 8 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/bcm2835-cpufreq.c | 239 ++++++++++++++++++++++++++++++ - 8 files changed, 381 insertions(+), 37 deletions(-) + 8 files changed, 380 insertions(+), 37 deletions(-) create mode 100755 drivers/cpufreq/bcm2835-cpufreq.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index d33eb79..7845052 100644 +index 0cafe24..ee597ef 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -369,6 +369,7 @@ config ARCH_BCM2708 @@ -116176,7 +89780,7 @@ index ace4ea4..7dfd14e 100644 #endif diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -index 775c213..ae1810c 100644 +index 7a7748e..5ef68b3 100644 --- a/arch/arm/mach-bcm2708/vc_mem.c +++ b/arch/arm/mach-bcm2708/vc_mem.c @@ -128,44 +128,33 @@ struct vc_set_msg { @@ -116288,13 +89892,13 @@ index 3874051..468fdef 100644 * Platform Device for Mailbox * -------------------------------------------------------------------- */ diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm -index 030ddf6..48a1ba1 100644 +index 6e57543..bf40783 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm -@@ -113,3 +113,12 @@ config ARM_HIGHBANK_CPUFREQ - based boards. - - If in doubt, say N. +@@ -150,3 +150,11 @@ config ARM_SPEAR_CPUFREQ + default y + help + This adds the CPUFreq driver support for SPEAr SOCs. + +config ARM_BCM2835_CPUFREQ + bool "BCM2835 Driver" @@ -116303,15 +89907,14 @@ index 030ddf6..48a1ba1 100644 + This adds the CPUFreq driver for BCM2835 + + If in doubt, say N. -+ diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile -index 863fd18..6c6eccb 100644 +index 315b923..52bdd64 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile -@@ -57,6 +57,7 @@ obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o +@@ -72,6 +72,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o + obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o - obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o - obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o + obj-$(CONFIG_ARCH_TEGRA) += tegra-cpufreq.o +obj-$(CONFIG_ARM_BCM2835_CPUFREQ) += bcm2835-cpufreq.o ################################################################################## @@ -116565,10 +90168,10 @@ index 0000000..aa6fc66 1.8.1.6 -From cbd42608997dff6ea3ff9fe88b4e38305f101e84 Mon Sep 17 00:00:00 2001 +From 9a13f810caf54c783f29731af4a50da242bca676 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 8 Apr 2013 21:12:48 +0100 -Subject: [PATCH 049/102] Add NAK holdoff scheme. Enabled by default, disable +Subject: [PATCH 36/88] Add NAK holdoff scheme. Enabled by default, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh --- @@ -116778,10 +90381,10 @@ index ac10323..e6b2a7b 100644 1.8.1.6 -From 9f95a6a09d5b545208dcffe96cba4a95bb9e89f4 Mon Sep 17 00:00:00 2001 +From 8a29d2cd7f9c46ad76010620b3fca8082dd34f1f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 050/102] Added hwmon/thermal driver for reporting core +Subject: [PATCH 37/88] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian --- @@ -116826,10 +90429,10 @@ index f5f262c..2875cd2 100644 { extern void vc_mem_connected_init(void); diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 89ac1cb..845e902 100644 +index 0428e8a..dd3a6e0 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig -@@ -1462,6 +1462,15 @@ config SENSORS_MC13783_ADC +@@ -1528,6 +1528,15 @@ config SENSORS_MC13783_ADC help Support for the A/D converter on MC13783 and MC13892 PMIC. @@ -116846,10 +90449,10 @@ index 89ac1cb..845e902 100644 comment "ACPI drivers" diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile -index 8d6d97e..5bfd723 100644 +index d17d3e6..a922c03 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile -@@ -134,6 +134,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o +@@ -140,6 +140,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o @@ -117075,10 +90678,10 @@ index 0000000..4976387 + +module_platform_driver(bcm2835_hwmon_driver); diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig -index a764f16..768722f 100644 +index 5e3c025..5f16fc0 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig -@@ -165,4 +165,11 @@ config INTEL_POWERCLAMP +@@ -169,4 +169,11 @@ config INTEL_POWERCLAMP enforce idle time which results in more package C-state residency. The user interface is exposed via generic thermal framework. @@ -117091,11 +90694,11 @@ index a764f16..768722f 100644 endif + diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile -index d3a2b38..3e3e44a 100644 +index c054d41..7893ed1 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile -@@ -21,4 +21,5 @@ obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o - obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o +@@ -23,4 +23,5 @@ obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o + obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o +obj-$(CONFIG_THERMAL_BCM2835) += bcm2835-thermal.o @@ -117305,10 +90908,10 @@ index 0000000..f1ecdb2 1.8.1.6 -From 45024257f048c1f12acde326b70e10606d3316e2 Mon Sep 17 00:00:00 2001 +From f10623b14323b7fd230da611043b7098b0353cba Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 12 Apr 2013 23:59:27 +0100 -Subject: [PATCH 051/102] Add config options for thermal sensor, L2TP, +Subject: [PATCH 38/88] Add config options for thermal sensor, L2TP, RT2800USB_UNKNOWN, and various I2C and SPI RTCs. Tidy of thermal driver. --- @@ -117384,10 +90987,10 @@ index 5b0a171..d11f688 100644 CONFIG_UIO_PDRV=m CONFIG_UIO_PDRV_GENIRQ=m diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig -index 845e902..8c5ad5a 100644 +index dd3a6e0..760940b 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig -@@ -1463,6 +1463,7 @@ config SENSORS_MC13783_ADC +@@ -1529,6 +1529,7 @@ config SENSORS_MC13783_ADC Support for the A/D converter on MC13783 and MC13892 PMIC. config SENSORS_BCM2835 @@ -117476,10 +91079,10 @@ index f1ecdb2..3f9a733 100644 1.8.1.6 -From d7a418269d4af6c9408d0cd609655c275422dcc7 Mon Sep 17 00:00:00 2001 +From d7c871a20faf02c4a9e4fa9434f7109c870de68a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 28 Mar 2013 01:19:54 +0000 -Subject: [PATCH 052/102] 2708fb: Remove some unnecessary dmesg output. +Subject: [PATCH 39/88] 2708fb: Remove some unnecessary dmesg output. --- drivers/video/bcm2708_fb.c | 34 +++++++++++++++++++--------------- @@ -117606,10 +91209,10 @@ index c82dd90..08d9238 100644 1.8.1.6 -From b1fccfaee08a3429c2ba6a0cd34355e244f46f5d Mon Sep 17 00:00:00 2001 +From 80027aa78529bb27b8b368eecdc73ddb99b87dca Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 28 Mar 2013 01:20:34 +0000 -Subject: [PATCH 053/102] cpufreq: Remove some unnecessary dmesg output. +Subject: [PATCH 40/88] cpufreq: Remove some unnecessary dmesg output. --- drivers/cpufreq/bcm2835-cpufreq.c | 2 +- @@ -117632,11 +91235,11 @@ index aa6fc66..6ff1edb 100755 1.8.1.6 -From db9f960f9af8aa7ba07da5b058c82287885b7339 Mon Sep 17 00:00:00 2001 +From c1d625a495bda54a60b56a5bd0f5449b7ac53d49 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 17 Sep 2012 22:57:29 +0100 -Subject: [PATCH 054/102] Switch to powersave governor. We'll enable ondemand - in the distribution +Subject: [PATCH 41/88] Switch to powersave governor. We'll enable ondemand in + the distribution --- arch/arm/configs/bcmrpi_defconfig | 5 +++-- @@ -117663,10 +91266,10 @@ index d11f688..c1afa47 100644 1.8.1.6 -From c3d251350f4777171a2dbb3552b6d56567837639 Mon Sep 17 00:00:00 2001 +From c33b7bcc3a6de49b94381096f6a0c2e4879682af Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Apr 2013 12:16:36 +0100 -Subject: [PATCH 055/102] Enable multiple ALSA channels +Subject: [PATCH 42/88] Enable multiple ALSA channels --- arch/arm/mach-bcm2708/bcm2708.c | 54 ++++++++++++++++++++++++++++++++++++----- @@ -117741,10 +91344,10 @@ index 2875cd2..27e9553 100644 1.8.1.6 -From cea02ff976cab64a7a6e6ad86446090f472a349f Mon Sep 17 00:00:00 2001 +From 86cd9547f7bc2f8c427e34527be3d8e27a44f298 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Oct 2012 20:08:19 +0100 -Subject: [PATCH 056/102] set i2c speed via module-parameter or menuconfig. +Subject: [PATCH 43/88] set i2c speed via module-parameter or menuconfig. Thanks FrankBoesing --- @@ -117753,7 +91356,7 @@ Subject: [PATCH 056/102] set i2c speed via module-parameter or menuconfig. 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index f1b55eb..f57cd6b 100644 +index 62ff7ac..8885e4a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -351,6 +351,17 @@ config I2C_BCM2708 @@ -117819,10 +91422,10 @@ index 7cae615..3391889 100644 1.8.1.6 -From 2afa47626e59af70b14349135bc6fe577148be5b Mon Sep 17 00:00:00 2001 +From dc1c709396bd2711af5c4e285a223bb0f026244f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Oct 2012 21:31:48 +0100 -Subject: [PATCH 057/102] Allow the number of cycles delay between sdcard +Subject: [PATCH 44/88] Allow the number of cycles delay between sdcard peripheral writes to be specified on command line with sdhci-bcm2708.cycle_delay @@ -117864,10 +91467,10 @@ index 7ce2829..ffd7310 100644 1.8.1.6 -From 9ebd07a58d6215678afd84b27cf858a6006302ce Mon Sep 17 00:00:00 2001 +From c372f2d12122085d55d03268a0cb4c2d670a7064 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Apr 2013 14:37:25 +0100 -Subject: [PATCH 058/102] Fix vc-mem by using module parameters +Subject: [PATCH 45/88] Fix vc-mem by using module parameters --- arch/arm/mach-bcm2708/bcm2708.c | 12 ++--- @@ -117918,7 +91521,7 @@ index 27e9553..e010515 100644 module_param(serial, uint, 0644); +module_param(uart_clock, uint, 0644); diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -index ae1810c..5c56b31 100644 +index 5ef68b3..057f74f 100644 --- a/arch/arm/mach-bcm2708/vc_mem.c +++ b/arch/arm/mach-bcm2708/vc_mem.c @@ -36,7 +36,7 @@ @@ -118055,8 +91658,8 @@ index ae1810c..5c56b31 100644 if ((rc = alloc_chrdev_region(&vc_mem_devnum, 0, 1, DRIVER_NAME)) < 0) { LOG_ERR("%s: alloc_chrdev_region failed (rc=%d)", __func__, rc); -@@ -438,7 +394,7 @@ static void vc_mem_update(void) - vc_mem_proc_entry->write_proc = vc_mem_proc_write; +@@ -440,7 +396,7 @@ static void vc_mem_update(void) + #endif vc_mem_inited = 1; - return; @@ -118064,7 +91667,7 @@ index ae1810c..5c56b31 100644 out_device_destroy: device_destroy(vc_mem_class, vc_mem_devnum); -@@ -454,23 +410,7 @@ static void vc_mem_update(void) +@@ -456,23 +412,7 @@ static void vc_mem_update(void) unregister_chrdev_region(vc_mem_devnum, 1); out_err: @@ -118089,7 +91692,7 @@ index ae1810c..5c56b31 100644 } /**************************************************************************** -@@ -497,3 +437,8 @@ static void vc_mem_update(void) +@@ -501,3 +441,8 @@ static void vc_mem_update(void) module_exit(vc_mem_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Broadcom Corporation"); @@ -118102,10 +91705,10 @@ index ae1810c..5c56b31 100644 1.8.1.6 -From 656bb407ea0f8538d2297f99d4e979c3d763f979 Mon Sep 17 00:00:00 2001 +From 9578fd3da96819661e04f6d856c3fd0cb4d4dcdf Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 5 Oct 2012 22:44:47 +0100 -Subject: [PATCH 059/102] Support dummy vc-mem ioctl used by vcdbg +Subject: [PATCH 46/88] Support dummy vc-mem ioctl used by vcdbg --- arch/arm/mach-bcm2708/include/mach/vc_mem.h | 1 + @@ -118125,7 +91728,7 @@ index 9d41c3a..d29125b 100644 #if defined( __KERNEL__ ) #define VC_MEM_TO_ARM_ADDR_MASK 0x3FFFFFFF diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c -index 5c56b31..f12cb49 100644 +index 057f74f..aeae4d5 100644 --- a/arch/arm/mach-bcm2708/vc_mem.c +++ b/arch/arm/mach-bcm2708/vc_mem.c @@ -208,6 +208,20 @@ @@ -118153,11 +91756,11 @@ index 5c56b31..f12cb49 100644 1.8.1.6 -From 58cbc811cc291d9a1e086d1223d7a5cd293e8ecb Mon Sep 17 00:00:00 2001 +From 321f91d1c01a6dfb91ccc3a05d01f487ddb67c5e Mon Sep 17 00:00:00 2001 From: dero Date: Mon, 19 Nov 2012 12:46:06 +0100 -Subject: [PATCH 060/102] Lazy CRC quirk: Implemented retrying mechanisms for - SD SSR and SCR, disabled missing_status and spurious CRC ACMD51 quirks by +Subject: [PATCH 47/88] Lazy CRC quirk: Implemented retrying mechanisms for SD + SSR and SCR, disabled missing_status and spurious CRC ACMD51 quirks by default (should be fixed by the retrying-mechanishm) --- @@ -118388,10 +91991,10 @@ index ffd7310..3556ed3 100644 1.8.1.6 -From f34b0d96d02bb0d83ff4fc6920e03635194494c2 Mon Sep 17 00:00:00 2001 +From 5fd69f8d1c8b53b52319bb712c9d925b429caa5e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 28 Mar 2013 00:10:32 +0000 -Subject: [PATCH 061/102] bcm2708: Add vc_cma driver to enable use of CMA +Subject: [PATCH 48/88] bcm2708: Add vc_cma driver to enable use of CMA --- arch/arm/mach-bcm2708/bcm2708.c | 18 ++++++++++++++++++ @@ -118452,10 +92055,10 @@ index e010515..9d38d40 100644 1.8.1.6 -From 7ebb3a6a0ebee2a33e3ba7457af37f1500b96ccd Mon Sep 17 00:00:00 2001 +From b243d68cd0e3e1ac8fe4d9313e44a6c94886ee5a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 24 Oct 2012 22:00:43 +0100 -Subject: [PATCH 062/102] Fix reboot with new restart method of machine driver +Subject: [PATCH 49/88] Fix reboot with new restart method of machine driver --- arch/arm/mach-bcm2708/bcm2708.c | 18 +++++++++++++++++- @@ -118533,10 +92136,10 @@ index bc9d458..2d0b821 100644 1.8.1.6 -From 7483b1f17a23eeefabda099d1e2b06c83736caeb Mon Sep 17 00:00:00 2001 +From dafd5e9e557ffa7494f6a5c11ab62b5c2dab6139 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Sun, 4 Nov 2012 15:55:01 +0000 -Subject: [PATCH 063/102] Make sure we wait for the reset to finish +Subject: [PATCH 50/88] Make sure we wait for the reset to finish --- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2 ++ @@ -118559,10 +92162,10 @@ index 3e762e2..e8c91e7 100644 1.8.1.6 -From 485f8faa6d463bf3c687de0a2c0b1aa4a6b74272 Mon Sep 17 00:00:00 2001 +From cf9d13622e80e613716a03de85045247d7382bfd Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 19 Nov 2012 18:27:05 +0000 -Subject: [PATCH 064/102] Add Simon Hall's dma helper module, useful in future +Subject: [PATCH 51/88] Add Simon Hall's dma helper module, useful in future for X acceleration --- @@ -119900,10 +93503,10 @@ index 0000000..5cb1335 1.8.1.6 -From 35a681ff75b9543fe27417b38ee07113794f228b Mon Sep 17 00:00:00 2001 +From 6ffd27277fcf553852d92aa961714aef6104d98e Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 065/102] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 52/88] lirc: added support for RaspberryPi GPIO --- drivers/staging/media/lirc/Kconfig | 6 + @@ -120638,11 +94241,11 @@ index 0000000..96acab0 1.8.1.6 -From 9d605813990813476803efc68efa443bcd62a50a Mon Sep 17 00:00:00 2001 +From bcf9c84e3c30f79d9beae9bad42f7a18ccd15c3c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 25 Nov 2012 18:28:09 +0000 -Subject: [PATCH 066/102] Allow mailbox driver to be called from user code - though ioctl +Subject: [PATCH 53/88] Allow mailbox driver to be called from user code though + ioctl --- arch/arm/mach-bcm2708/include/mach/vcio.h | 33 +++++++ @@ -120878,10 +94481,10 @@ index 468fdef..09b78b5 100644 1.8.1.6 -From 213114b2ae2c23fd2ea96fd3f11cf9cd6776859f Mon Sep 17 00:00:00 2001 +From f7048aa2a847de942629ce21d11345a57c2e66e4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 11 Dec 2012 18:23:03 +0000 -Subject: [PATCH 067/102] Default to dwc_otp.lpm_enable=0 +Subject: [PATCH 54/88] Default to dwc_otp.lpm_enable=0 --- drivers/usb/host/dwc_otg/dwc_otg_driver.c | 2 +- @@ -120904,10 +94507,10 @@ index d353a9a..cea8fcb 100644 1.8.1.6 -From b16bb40731b409faf11da8197388a7ab26a0e50b Mon Sep 17 00:00:00 2001 +From a49eddff6d55578a3caa1d2e5cd11c92df4f278a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 11 Dec 2012 19:04:27 +0000 -Subject: [PATCH 068/102] Increase default coherent pool so vchiq starts up +Subject: [PATCH 55/88] Increase default coherent pool so vchiq starts up --- arch/arm/mach-bcm2708/bcm2708.c | 4 +--- @@ -120932,10 +94535,10 @@ index 9f456e9..87fd348 100644 1.8.1.6 -From 10f835d7c46e4694e056ab67d3f9682d1d65a5dd Mon Sep 17 00:00:00 2001 +From f5adca2359cd6b7bb40d41ddc66e290141e05a58 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 7 Jan 2013 21:34:59 +0000 -Subject: [PATCH 069/102] Add mutex around bcm_mailbox_property function +Subject: [PATCH 56/88] Add mutex around bcm_mailbox_property function --- arch/arm/mach-bcm2708/vcio.c | 5 ++++- @@ -120975,10 +94578,10 @@ index 09b78b5..599eb63 100644 1.8.1.6 -From 6325da467151a62fcf5d0981762912468cc3fade Mon Sep 17 00:00:00 2001 +From de86ee42fc5f624a9879bce5b2603c0555741016 Mon Sep 17 00:00:00 2001 From: P33M Date: Wed, 9 Jan 2013 16:12:04 +0000 -Subject: [PATCH 070/102] dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent +Subject: [PATCH 57/88] dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent kernel memory corruption, escalating to OOPS under high USB load. --- @@ -121015,10 +94618,10 @@ index e6b2a7b..b337e1b 100644 1.8.1.6 -From 4990e3b6f96934ce29a371eca430e4a5fea023e4 Mon Sep 17 00:00:00 2001 +From f6156c223969196d360586d6e09d81a1fe85e8de Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 21 Jan 2013 23:03:53 +0000 -Subject: [PATCH 071/102] Return error value from bcm2708_setup_state. Thanks +Subject: [PATCH 58/88] Return error value from bcm2708_setup_state. Thanks notro --- @@ -121041,10 +94644,10 @@ index 9f1580e..8513704 100644 1.8.1.6 -From 5151d746e52d02a7c399ec863f0330a16a4327e4 Mon Sep 17 00:00:00 2001 +From 3c635bdecfe28dbbaabaf0f7afc9f70066d470ab Mon Sep 17 00:00:00 2001 From: Kamal Mostafa Date: Mon, 22 Oct 2012 15:52:44 -0700 -Subject: [PATCH 072/102] spi/spi-bcm2708: respect per-transfer SPI clock +Subject: [PATCH 59/88] spi/spi-bcm2708: respect per-transfer SPI clock speed_hz value The bcm2708 SPI driver's bcm2708_process_transfer() was ignoring the @@ -121089,18 +94692,17 @@ index 8513704..b74aa32 100644 1.8.1.6 -From 94c3e025769b2661bcd5286923a9456ea32e9966 Mon Sep 17 00:00:00 2001 +From 43d6cf5febd600a9ef11ba7b8656519d2c356346 Mon Sep 17 00:00:00 2001 From: popcornmix -Date: Tue, 26 Mar 2013 22:29:01 +0000 -Subject: [PATCH 073/102] Add hwrng (hardware random number generator) driver +Date: Wed, 3 Jul 2013 00:51:55 +0100 +Subject: [PATCH 60/88] Add hwrng (hardware random number generator) driver -Conflicts: --- arch/arm/mach-bcm2708/include/mach/platform.h | 1 + drivers/char/hw_random/Kconfig | 12 +++ - drivers/char/hw_random/Makefile | 2 + + drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/bcm2708-rng.c | 117 ++++++++++++++++++++++++++ - 4 files changed, 132 insertions(+) + 4 files changed, 131 insertions(+) create mode 100755 drivers/char/hw_random/bcm2708-rng.c diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h @@ -121116,10 +94718,10 @@ index 89e72d1..992a630 100644 #define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */ #define MMCI0_BASE (BCM2708_PERI_BASE + 0x202000) /* MMC interface */ diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig -index c5a0262..229f430 100644 +index 2f9dbf7..d725a53 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig -@@ -302,3 +302,15 @@ config HW_RANDOM_TPM +@@ -314,3 +314,15 @@ config HW_RANDOM_TPM module will be called tpm-rng. If unsure, say Y. @@ -121136,15 +94738,14 @@ index c5a0262..229f430 100644 + If unsure, say N. + diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile -index 1fd7eec..1974a07 100644 +index bed467c..18fc4d4 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile -@@ -26,3 +26,5 @@ obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o - obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o +@@ -27,3 +27,4 @@ obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o + obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o +obj-$(CONFIG_HW_RANDOM_BCM2708) += bcm2708-rng.o -+ diff --git a/drivers/char/hw_random/bcm2708-rng.c b/drivers/char/hw_random/bcm2708-rng.c new file mode 100755 index 0000000..1ffa7d7 @@ -121272,10 +94873,10 @@ index 0000000..1ffa7d7 1.8.1.6 -From abac2d03dee9f46c72b30c140af6932c47dc587a Mon Sep 17 00:00:00 2001 +From ee3463d963f75ec8d1b13d81d7ab583255e1d890 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 7 Feb 2013 17:04:13 +0000 -Subject: [PATCH 074/102] Add missing newlines to log messages +Subject: [PATCH 61/88] Add missing newlines to log messages --- drivers/cpufreq/bcm2835-cpufreq.c | 20 ++++++++++---------- @@ -121374,10 +94975,10 @@ index 6ff1edb..5a19212 100755 1.8.1.6 -From 400b7e9b953cc6a852a2f855d8ead3a17233baf8 Mon Sep 17 00:00:00 2001 +From 9f3f17339f5165e1060883db422398a7f165c2be Mon Sep 17 00:00:00 2001 From: Technion Date: Mon, 11 Feb 2013 22:08:53 +1100 -Subject: [PATCH 075/102] Changed wording on logging. Previously, we received +Subject: [PATCH 62/88] Changed wording on logging. Previously, we received errors like this: mmc0: could read SD Status register (SSR) at the 3th attempt A more sensible response is now returned. A typo also fixed in comments. @@ -121412,10 +95013,10 @@ index 1ee6cf3..90228f9 100644 1.8.1.6 -From 2a4d22b3c85caecc3fcd38d2fa466205a5da44fe Mon Sep 17 00:00:00 2001 +From bbdfaf49aa05257794d7ddc19717e3e1f035285a Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 15 Feb 2013 22:36:47 +0000 -Subject: [PATCH 076/102] dwc_otg: Fix unsafe access of QTD during URB enqueue +Subject: [PATCH 63/88] dwc_otg: Fix unsafe access of QTD during URB enqueue In dwc_otg_hcd_urb_enqueue during qtd creation, it was possible that the transaction could complete almost immediately after the qtd was assigned @@ -121502,10 +95103,10 @@ index b337e1b..b3e6e52 100644 1.8.1.6 -From 3d68c8d67e5160831187b05ba56c9a86b6682381 Mon Sep 17 00:00:00 2001 +From f385db71cd990d3e6d5e7020127357afabe0b4e4 Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 15 Feb 2013 22:38:40 +0000 -Subject: [PATCH 077/102] dwc_otg: Fix incorrect URB allocation error handling +Subject: [PATCH 64/88] dwc_otg: Fix incorrect URB allocation error handling If the memory allocation for a dwc_otg_urb failed, the kernel would OOPS because for some reason a member of the *unallocated* struct was set to @@ -121546,10 +95147,10 @@ index e653d84..fcec97f 100644 1.8.1.6 -From f89498db7dced4b21c51158ad4000759acfbf335 Mon Sep 17 00:00:00 2001 +From 9cb0f13eb3ffc4f82a8756f6b79e3653406f529b Mon Sep 17 00:00:00 2001 From: pjennings Date: Wed, 20 Feb 2013 17:51:43 -0600 -Subject: [PATCH 078/102] Added inverted transmitter support +Subject: [PATCH 65/88] Added inverted transmitter support --- drivers/staging/media/lirc/lirc_rpi.c | 17 +++++++++++------ @@ -121630,10 +95231,10 @@ index 96acab0..5bb0dfe 100644 1.8.1.6 -From 09874e5468560c13b84514d5accae43f7275a5a6 Mon Sep 17 00:00:00 2001 +From c332df8c672e573f6ba42e011fa9d2a6fc5ce527 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 24 Feb 2013 16:30:57 +0000 -Subject: [PATCH 079/102] Add retry on error and tidy of temperature driver +Subject: [PATCH 66/88] Add retry on error and tidy of temperature driver --- drivers/thermal/bcm2835-thermal.c | 78 ++++++++++++++------------------------- @@ -121760,11 +95361,11 @@ index 3f9a733..85fceb5 100644 1.8.1.6 -From 3b16c1cb79430b57ff077a407fd89001d20384ef Mon Sep 17 00:00:00 2001 +From 01690a39d2700286bb67bed762b88b4895a40c76 Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 28 Feb 2013 16:52:51 +0000 -Subject: [PATCH 080/102] dwc_otg: fix potential use-after-free case in - interrupt handler +Subject: [PATCH 67/88] dwc_otg: fix potential use-after-free case in interrupt + handler If a transaction had previously aborted, certain interrupts are enabled to track error counts and reset where necessary. On IN @@ -121795,11 +95396,11 @@ index e8c91e7..0c81a64 100644 1.8.1.6 -From 14c24823f532747029189f0e5155d85e6bb7fb4b Mon Sep 17 00:00:00 2001 +From d3ebe68a2b7629d107b31ae0644ebce63ccee58a Mon Sep 17 00:00:00 2001 From: P33M Date: Sun, 3 Mar 2013 14:45:53 +0000 -Subject: [PATCH 081/102] dwc_otg: add handling of SPLIT transaction data - toggle errors +Subject: [PATCH 68/88] dwc_otg: add handling of SPLIT transaction data toggle + errors Previously a data toggle error on packets from a USB1.1 device behind a TT would result in the Pi locking up as the driver never handled @@ -121853,10 +95454,10 @@ index 0c81a64..16e8c6c 100644 1.8.1.6 -From 1c33862335784d4e65b94cb5818b8ec3cfa71d9b Mon Sep 17 00:00:00 2001 +From 56cbbf3c61827a1a3e795ba0d2e8ecaa9e3e73da Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 21:14:28 +0100 -Subject: [PATCH 082/102] Add bitbanging pullups, use them for w1-gpio +Subject: [PATCH 69/88] Add bitbanging pullups, use them for w1-gpio Allows parasite power to work, uses module option pullup=1 --- @@ -121995,10 +95596,10 @@ index e10acc2..667fdd5 100644 1.8.1.6 -From 961c937bb67b44d351f31a1ab9ac8639957fff43 Mon Sep 17 00:00:00 2001 +From 8af17a0ad8e286c71468d15076f9209791971149 Mon Sep 17 00:00:00 2001 From: notro Date: Sat, 26 Jan 2013 20:38:03 +0100 -Subject: [PATCH 083/102] spi-bcm2708: add 9-bit support using LoSSI mode +Subject: [PATCH 70/88] spi-bcm2708: add 9-bit support using LoSSI mode --- drivers/spi/spi-bcm2708.c | 30 ++++++++++++++++++++++++++++-- @@ -122068,10 +95669,10 @@ index b74aa32..abaa5a6 100644 1.8.1.6 -From ef3bb13257937de845843ebbec4c5ec35cea496d Mon Sep 17 00:00:00 2001 +From ddd6ba1219a97ec27e002ecc6bc8d41bc0b8e591 Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 21 Mar 2013 19:36:17 +0000 -Subject: [PATCH 084/102] dwc_otg: implement tasklet for returning URBs to +Subject: [PATCH 71/88] dwc_otg: implement tasklet for returning URBs to usbcore hcd layer The dwc_otg driver interrupt handler for transfer completion will spend @@ -122313,1713 +95914,11 @@ index 9702f81..7bb133a 100644 1.8.1.6 -From 61711e38ec9920f03605b22f23f63e2a0919905e Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Wed, 27 Mar 2013 20:23:39 +0000 -Subject: [PATCH 085/102] dwc_otg: Fix build issue with usb_gadget_probe_driver - ---- - drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c | 22 +++------------------- - 1 file changed, 3 insertions(+), 19 deletions(-) - -diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -index 903e670..a591d89 100644 ---- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -+++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c -@@ -1284,12 +1284,8 @@ void pcd_remove(dwc_bus_dev_t *_dev) - * @param driver The driver being registered - * @param bind The bind function of gadget driver - */ --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) --int usb_gadget_register_driver(struct usb_gadget_driver *driver) --#else --int usb_gadget_probe_driver(struct usb_gadget_driver *driver, -- int (*bind)(struct usb_gadget *)) --#endif -+ -+int usb_gadget_probe_driver(struct usb_gadget_driver *driver) - { - int retval; - -@@ -1297,11 +1293,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - driver->driver.name); - - if (!driver || driver->max_speed == USB_SPEED_UNKNOWN || --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) - !driver->bind || --#else -- !bind || --#endif - !driver->unbind || !driver->disconnect || !driver->setup) { - DWC_DEBUGPL(DBG_PCDV, "EINVAL\n"); - return -EINVAL; -@@ -1320,11 +1312,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - gadget_wrapper->gadget.dev.driver = &driver->driver; - - DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -- retval = driver->bind(&gadget_wrapper->gadget); --#else -- retval = bind(&gadget_wrapper->gadget); --#endif -+ retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver); - if (retval) { - DWC_ERROR("bind to driver %s --> error %d\n", - driver->driver.name, retval); -@@ -1336,11 +1324,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - driver->driver.name); - return 0; - } --#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) --EXPORT_SYMBOL(usb_gadget_register_driver); --#else - EXPORT_SYMBOL(usb_gadget_probe_driver); --#endif - - /** - * This function unregisters a gadget driver --- -1.8.1.6 - - -From b1525056e02d418047515c7eb29ba11a6a8a90aa Mon Sep 17 00:00:00 2001 -From: popcornmix -Date: Fri, 27 Apr 2012 00:31:37 +0100 -Subject: [PATCH 086/102] Update config files for f2fs and 3.8 kernel - ---- - arch/arm/configs/bcmrpi_cutdown_defconfig | 504 ---------------------------- - arch/arm/configs/bcmrpi_defconfig | 378 ++++++++++++++------- - arch/arm/configs/bcmrpi_emergency_defconfig | 1 + - arch/arm/configs/bcmrpi_quick_defconfig | 298 ++++++++++++++++ - 4 files changed, 560 insertions(+), 621 deletions(-) - create mode 100644 arch/arm/configs/bcmrpi_quick_defconfig - -diff --git a/arch/arm/configs/bcmrpi_cutdown_defconfig b/arch/arm/configs/bcmrpi_cutdown_defconfig -index a61a915..e69de29 100644 ---- a/arch/arm/configs/bcmrpi_cutdown_defconfig -+++ b/arch/arm/configs/bcmrpi_cutdown_defconfig -@@ -1,504 +0,0 @@ --CONFIG_EXPERIMENTAL=y --# CONFIG_LOCALVERSION_AUTO is not set --CONFIG_SYSVIPC=y --CONFIG_POSIX_MQUEUE=y --CONFIG_IKCONFIG=y --CONFIG_IKCONFIG_PROC=y --# CONFIG_UID16 is not set --# CONFIG_KALLSYMS is not set --CONFIG_EMBEDDED=y --# CONFIG_VM_EVENT_COUNTERS is not set --# CONFIG_COMPAT_BRK is not set --CONFIG_SLAB=y --CONFIG_MODULES=y --CONFIG_MODULE_UNLOAD=y --CONFIG_MODVERSIONS=y --CONFIG_MODULE_SRCVERSION_ALL=y --# CONFIG_BLK_DEV_BSG is not set --CONFIG_ARCH_BCM2708=y --CONFIG_NO_HZ=y --CONFIG_HIGH_RES_TIMERS=y --CONFIG_AEABI=y --CONFIG_ZBOOT_ROM_TEXT=0x0 --CONFIG_ZBOOT_ROM_BSS=0x0 --CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait" --CONFIG_CPU_IDLE=y --CONFIG_VFP=y --CONFIG_BINFMT_MISC=m --CONFIG_NET=y --CONFIG_PACKET=y --CONFIG_UNIX=y --CONFIG_XFRM_USER=y --CONFIG_NET_KEY=m --CONFIG_INET=y --CONFIG_IP_MULTICAST=y --CONFIG_IP_PNP=y --CONFIG_IP_PNP_DHCP=y --CONFIG_IP_PNP_RARP=y --CONFIG_SYN_COOKIES=y --# CONFIG_INET_XFRM_MODE_TRANSPORT is not set --# CONFIG_INET_XFRM_MODE_TUNNEL is not set --# CONFIG_INET_XFRM_MODE_BEET is not set --# CONFIG_INET_LRO is not set --# CONFIG_INET_DIAG is not set --# CONFIG_IPV6 is not set --CONFIG_NET_PKTGEN=m --CONFIG_IRDA=m --CONFIG_IRLAN=m --CONFIG_IRCOMM=m --CONFIG_IRDA_ULTRA=y --CONFIG_IRDA_CACHE_LAST_LSAP=y --CONFIG_IRDA_FAST_RR=y --CONFIG_IRTTY_SIR=m --CONFIG_KINGSUN_DONGLE=m --CONFIG_KSDAZZLE_DONGLE=m --CONFIG_KS959_DONGLE=m --CONFIG_USB_IRDA=m --CONFIG_SIGMATEL_FIR=m --CONFIG_MCS_FIR=m --CONFIG_BT=m --CONFIG_BT_L2CAP=y --CONFIG_BT_SCO=y --CONFIG_BT_RFCOMM=m --CONFIG_BT_RFCOMM_TTY=y --CONFIG_BT_BNEP=m --CONFIG_BT_BNEP_MC_FILTER=y --CONFIG_BT_BNEP_PROTO_FILTER=y --CONFIG_BT_HIDP=m --CONFIG_BT_HCIBTUSB=m --CONFIG_BT_HCIBCM203X=m --CONFIG_BT_HCIBPA10X=m --CONFIG_BT_HCIBFUSB=m --CONFIG_BT_HCIVHCI=m --CONFIG_BT_MRVL=m --CONFIG_BT_MRVL_SDIO=m --CONFIG_BT_ATH3K=m --CONFIG_CFG80211=m --CONFIG_MAC80211=m --CONFIG_MAC80211_RC_PID=y --CONFIG_MAC80211_MESH=y --CONFIG_WIMAX=m --CONFIG_NET_9P=m --CONFIG_NFC=m --CONFIG_NFC_PN533=m --CONFIG_DEVTMPFS=y --CONFIG_BLK_DEV_LOOP=y --CONFIG_BLK_DEV_CRYPTOLOOP=m --CONFIG_BLK_DEV_NBD=m --CONFIG_BLK_DEV_RAM=y --CONFIG_CDROM_PKTCDVD=m --CONFIG_MISC_DEVICES=y --CONFIG_SCSI=y --# CONFIG_SCSI_PROC_FS is not set --CONFIG_BLK_DEV_SD=m --CONFIG_BLK_DEV_SR=m --CONFIG_SCSI_MULTI_LUN=y --# CONFIG_SCSI_LOWLEVEL is not set --CONFIG_NETDEVICES=y --CONFIG_TUN=m --CONFIG_PHYLIB=m --CONFIG_MDIO_BITBANG=m --CONFIG_NET_ETHERNET=y --# CONFIG_NETDEV_1000 is not set --# CONFIG_NETDEV_10000 is not set --CONFIG_LIBERTAS_THINFIRM=m --CONFIG_LIBERTAS_THINFIRM_USB=m --CONFIG_AT76C50X_USB=m --CONFIG_USB_ZD1201=m --CONFIG_USB_NET_RNDIS_WLAN=m --CONFIG_RTL8187=m --CONFIG_MAC80211_HWSIM=m --CONFIG_ATH_COMMON=m --CONFIG_ATH9K=m --CONFIG_ATH9K_HTC=m --CONFIG_CARL9170=m --CONFIG_B43=m --CONFIG_B43LEGACY=m --CONFIG_HOSTAP=m --CONFIG_IWM=m --CONFIG_LIBERTAS=m --CONFIG_LIBERTAS_USB=m --CONFIG_LIBERTAS_SDIO=m --CONFIG_P54_COMMON=m --CONFIG_P54_USB=m --CONFIG_RT2X00=m --CONFIG_RT2500USB=m --CONFIG_RT73USB=m --CONFIG_RT2800USB=m --CONFIG_RT2800USB_RT53XX=y --CONFIG_RTL8192CU=m --CONFIG_WL1251=m --CONFIG_WL12XX_MENU=m --CONFIG_ZD1211RW=m --CONFIG_MWIFIEX=m --CONFIG_MWIFIEX_SDIO=m --CONFIG_WIMAX_I2400M_USB=m --CONFIG_USB_CATC=m --CONFIG_USB_KAWETH=m --CONFIG_USB_PEGASUS=m --CONFIG_USB_RTL8150=m --CONFIG_USB_USBNET=y --CONFIG_USB_NET_AX8817X=m --CONFIG_USB_NET_CDCETHER=m --CONFIG_USB_NET_CDC_EEM=m --CONFIG_USB_NET_DM9601=m --CONFIG_USB_NET_SMSC75XX=m --CONFIG_USB_NET_SMSC95XX=y --CONFIG_USB_NET_GL620A=m --CONFIG_USB_NET_NET1080=m --CONFIG_USB_NET_PLUSB=m --CONFIG_USB_NET_MCS7830=m --CONFIG_USB_NET_CDC_SUBSET=m --CONFIG_USB_ALI_M5632=y --CONFIG_USB_AN2720=y --CONFIG_USB_KC2190=y --# CONFIG_USB_NET_ZAURUS is not set --CONFIG_USB_NET_CX82310_ETH=m --CONFIG_USB_NET_KALMIA=m --CONFIG_USB_NET_INT51X1=m --CONFIG_USB_IPHETH=m --CONFIG_USB_SIERRA_NET=m --CONFIG_USB_VL600=m --CONFIG_PPP=m --CONFIG_PPP_ASYNC=m --CONFIG_PPP_SYNC_TTY=m --CONFIG_PPP_DEFLATE=m --CONFIG_PPP_BSDCOMP=m --CONFIG_SLIP=m --CONFIG_SLIP_COMPRESSED=y --CONFIG_NETCONSOLE=m --CONFIG_INPUT_POLLDEV=m --# CONFIG_INPUT_MOUSEDEV_PSAUX is not set --CONFIG_INPUT_JOYDEV=m --CONFIG_INPUT_EVDEV=m --# CONFIG_INPUT_KEYBOARD is not set --# CONFIG_INPUT_MOUSE is not set --CONFIG_INPUT_MISC=y --CONFIG_INPUT_AD714X=m --CONFIG_INPUT_ATI_REMOTE=m --CONFIG_INPUT_ATI_REMOTE2=m --CONFIG_INPUT_KEYSPAN_REMOTE=m --CONFIG_INPUT_POWERMATE=m --CONFIG_INPUT_YEALINK=m --CONFIG_INPUT_CM109=m --CONFIG_INPUT_UINPUT=m --CONFIG_INPUT_GPIO_ROTARY_ENCODER=m --CONFIG_INPUT_ADXL34X=m --CONFIG_INPUT_CMA3000=m --CONFIG_SERIO=m --CONFIG_SERIO_RAW=m --CONFIG_GAMEPORT=m --CONFIG_GAMEPORT_NS558=m --CONFIG_GAMEPORT_L4=m --CONFIG_VT_HW_CONSOLE_BINDING=y --# CONFIG_LEGACY_PTYS is not set --# CONFIG_DEVKMEM is not set --CONFIG_SERIAL_AMBA_PL011=y --CONFIG_SERIAL_AMBA_PL011_CONSOLE=y --# CONFIG_HW_RANDOM is not set --CONFIG_RAW_DRIVER=y --CONFIG_GPIO_SYSFS=y --# CONFIG_HWMON is not set --CONFIG_WATCHDOG=y --CONFIG_BCM2708_WDT=m --# CONFIG_MFD_SUPPORT is not set --CONFIG_FB=y --CONFIG_FB_BCM2708=y --CONFIG_FRAMEBUFFER_CONSOLE=y --CONFIG_LOGO=y --# CONFIG_LOGO_LINUX_MONO is not set --# CONFIG_LOGO_LINUX_VGA16 is not set --CONFIG_SOUND=y --CONFIG_SND=m --CONFIG_SND_SEQUENCER=m --CONFIG_SND_SEQ_DUMMY=m --CONFIG_SND_MIXER_OSS=m --CONFIG_SND_PCM_OSS=m --CONFIG_SND_SEQUENCER_OSS=y --CONFIG_SND_HRTIMER=m --CONFIG_SND_DUMMY=m --CONFIG_SND_ALOOP=m --CONFIG_SND_VIRMIDI=m --CONFIG_SND_MTPAV=m --CONFIG_SND_SERIAL_U16550=m --CONFIG_SND_MPU401=m --CONFIG_SND_BCM2835=m --CONFIG_SND_USB_AUDIO=m --CONFIG_SND_USB_UA101=m --CONFIG_SND_USB_CAIAQ=m --CONFIG_SND_USB_6FIRE=m --CONFIG_SOUND_PRIME=m --CONFIG_HID_PID=y --CONFIG_USB_HIDDEV=y --CONFIG_HID_A4TECH=m --CONFIG_HID_ACRUX=m --CONFIG_HID_APPLE=m --CONFIG_HID_BELKIN=m --CONFIG_HID_CHERRY=m --CONFIG_HID_CHICONY=m --CONFIG_HID_CYPRESS=m --CONFIG_HID_DRAGONRISE=m --CONFIG_HID_EMS_FF=m --CONFIG_HID_ELECOM=m --CONFIG_HID_EZKEY=m --CONFIG_HID_HOLTEK=m --CONFIG_HID_KEYTOUCH=m --CONFIG_HID_KYE=m --CONFIG_HID_UCLOGIC=m --CONFIG_HID_WALTOP=m --CONFIG_HID_GYRATION=m --CONFIG_HID_TWINHAN=m --CONFIG_HID_KENSINGTON=m --CONFIG_HID_LCPOWER=m --CONFIG_HID_LOGITECH=m --CONFIG_HID_MAGICMOUSE=m --CONFIG_HID_MICROSOFT=m --CONFIG_HID_MONTEREY=m --CONFIG_HID_MULTITOUCH=m --CONFIG_HID_NTRIG=m --CONFIG_HID_ORTEK=m --CONFIG_HID_PANTHERLORD=m --CONFIG_HID_PETALYNX=m --CONFIG_HID_PICOLCD=m --CONFIG_HID_QUANTA=m --CONFIG_HID_ROCCAT=m --CONFIG_HID_SAMSUNG=m --CONFIG_HID_SONY=m --CONFIG_HID_SPEEDLINK=m --CONFIG_HID_SUNPLUS=m --CONFIG_HID_GREENASIA=m --CONFIG_HID_SMARTJOYPLUS=m --CONFIG_HID_TOPSEED=m --CONFIG_HID_THRUSTMASTER=m --CONFIG_HID_WACOM=m --CONFIG_HID_WIIMOTE=m --CONFIG_HID_ZEROPLUS=m --CONFIG_HID_ZYDACRON=m --CONFIG_USB=y --CONFIG_USB_ANNOUNCE_NEW_DEVICES=y --CONFIG_USB_MON=m --CONFIG_USB_DWCOTG=y --CONFIG_USB_STORAGE=y --CONFIG_USB_STORAGE_REALTEK=m --CONFIG_USB_STORAGE_DATAFAB=m --CONFIG_USB_STORAGE_FREECOM=m --CONFIG_USB_STORAGE_ISD200=m --CONFIG_USB_STORAGE_USBAT=m --CONFIG_USB_STORAGE_SDDR09=m --CONFIG_USB_STORAGE_SDDR55=m --CONFIG_USB_STORAGE_JUMPSHOT=m --CONFIG_USB_STORAGE_ALAUDA=m --CONFIG_USB_STORAGE_ONETOUCH=m --CONFIG_USB_STORAGE_KARMA=m --CONFIG_USB_STORAGE_CYPRESS_ATACB=m --CONFIG_USB_STORAGE_ENE_UB6250=m --CONFIG_USB_UAS=m --CONFIG_USB_LIBUSUAL=y --CONFIG_USB_MDC800=m --CONFIG_USB_MICROTEK=m --CONFIG_USB_SERIAL=m --CONFIG_USB_SERIAL_GENERIC=y --CONFIG_USB_SERIAL_AIRCABLE=m --CONFIG_USB_SERIAL_ARK3116=m --CONFIG_USB_SERIAL_BELKIN=m --CONFIG_USB_SERIAL_CH341=m --CONFIG_USB_SERIAL_WHITEHEAT=m --CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m --CONFIG_USB_SERIAL_CP210X=m --CONFIG_USB_SERIAL_CYPRESS_M8=m --CONFIG_USB_SERIAL_EMPEG=m --CONFIG_USB_SERIAL_FTDI_SIO=m --CONFIG_USB_SERIAL_FUNSOFT=m --CONFIG_USB_SERIAL_VISOR=m --CONFIG_USB_SERIAL_IPAQ=m --CONFIG_USB_SERIAL_IR=m --CONFIG_USB_SERIAL_EDGEPORT=m --CONFIG_USB_SERIAL_EDGEPORT_TI=m --CONFIG_USB_SERIAL_GARMIN=m --CONFIG_USB_SERIAL_IPW=m --CONFIG_USB_SERIAL_IUU=m --CONFIG_USB_SERIAL_KEYSPAN_PDA=m --CONFIG_USB_SERIAL_KEYSPAN=m --CONFIG_USB_SERIAL_KLSI=m --CONFIG_USB_SERIAL_KOBIL_SCT=m --CONFIG_USB_SERIAL_MCT_U232=m --CONFIG_USB_SERIAL_MOS7720=m --CONFIG_USB_SERIAL_MOS7840=m --CONFIG_USB_SERIAL_MOTOROLA=m --CONFIG_USB_SERIAL_NAVMAN=m --CONFIG_USB_SERIAL_PL2303=m --CONFIG_USB_SERIAL_OTI6858=m --CONFIG_USB_SERIAL_QCAUX=m --CONFIG_USB_SERIAL_QUALCOMM=m --CONFIG_USB_SERIAL_SPCP8X5=m --CONFIG_USB_SERIAL_HP4X=m --CONFIG_USB_SERIAL_SAFE=m --CONFIG_USB_SERIAL_SIEMENS_MPI=m --CONFIG_USB_SERIAL_SIERRAWIRELESS=m --CONFIG_USB_SERIAL_SYMBOL=m --CONFIG_USB_SERIAL_TI=m --CONFIG_USB_SERIAL_CYBERJACK=m --CONFIG_USB_SERIAL_XIRCOM=m --CONFIG_USB_SERIAL_OPTION=m --CONFIG_USB_SERIAL_OMNINET=m --CONFIG_USB_SERIAL_OPTICON=m --CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m --CONFIG_USB_SERIAL_ZIO=m --CONFIG_USB_SERIAL_SSU100=m --CONFIG_USB_SERIAL_DEBUG=m --CONFIG_USB_EMI62=m --CONFIG_USB_EMI26=m --CONFIG_USB_ADUTUX=m --CONFIG_USB_SEVSEG=m --CONFIG_USB_RIO500=m --CONFIG_USB_LEGOTOWER=m --CONFIG_USB_LCD=m --CONFIG_USB_LED=m --CONFIG_USB_CYPRESS_CY7C63=m --CONFIG_USB_CYTHERM=m --CONFIG_USB_IDMOUSE=m --CONFIG_USB_FTDI_ELAN=m --CONFIG_USB_APPLEDISPLAY=m --CONFIG_USB_LD=m --CONFIG_USB_TRANCEVIBRATOR=m --CONFIG_USB_IOWARRIOR=m --CONFIG_USB_TEST=m --CONFIG_USB_ISIGHTFW=m --CONFIG_USB_YUREX=m --CONFIG_MMC=y --CONFIG_MMC_SDHCI=y --CONFIG_MMC_SDHCI_PLTFM=y --CONFIG_MMC_SDHCI_BCM2708=y --CONFIG_MMC_SDHCI_BCM2708_DMA=y --CONFIG_LEDS_GPIO=y --CONFIG_LEDS_TRIGGER_TIMER=m --CONFIG_LEDS_TRIGGER_HEARTBEAT=m --CONFIG_LEDS_TRIGGER_DEFAULT_ON=m --CONFIG_UIO=m --CONFIG_UIO_PDRV=m --CONFIG_UIO_PDRV_GENIRQ=m --# CONFIG_IOMMU_SUPPORT is not set --CONFIG_EXT4_FS=y --CONFIG_EXT4_FS_POSIX_ACL=y --CONFIG_EXT4_FS_SECURITY=y --CONFIG_REISERFS_FS=m --CONFIG_REISERFS_FS_XATTR=y --CONFIG_REISERFS_FS_POSIX_ACL=y --CONFIG_REISERFS_FS_SECURITY=y --CONFIG_JFS_FS=m --CONFIG_JFS_POSIX_ACL=y --CONFIG_JFS_SECURITY=y --CONFIG_XFS_FS=m --CONFIG_XFS_QUOTA=y --CONFIG_XFS_POSIX_ACL=y --CONFIG_XFS_RT=y --CONFIG_GFS2_FS=m --CONFIG_OCFS2_FS=m --CONFIG_BTRFS_FS=m --CONFIG_BTRFS_FS_POSIX_ACL=y --CONFIG_NILFS2_FS=m --CONFIG_AUTOFS4_FS=y --CONFIG_FUSE_FS=m --CONFIG_CUSE=m --CONFIG_FSCACHE=y --CONFIG_CACHEFILES=y --CONFIG_ISO9660_FS=m --CONFIG_JOLIET=y --CONFIG_ZISOFS=y --CONFIG_UDF_FS=m --CONFIG_MSDOS_FS=y --CONFIG_VFAT_FS=y --CONFIG_FAT_DEFAULT_IOCHARSET="ascii" --CONFIG_NTFS_FS=m --CONFIG_TMPFS=y --CONFIG_TMPFS_POSIX_ACL=y --CONFIG_CONFIGFS_FS=y --CONFIG_SQUASHFS=m --CONFIG_SQUASHFS_XATTR=y --CONFIG_SQUASHFS_LZO=y --CONFIG_SQUASHFS_XZ=y --CONFIG_NFS_FS=y --CONFIG_NFS_V3=y --CONFIG_NFS_V3_ACL=y --CONFIG_NFS_V4=y --CONFIG_ROOT_NFS=y --CONFIG_NFS_FSCACHE=y --CONFIG_CIFS=m --CONFIG_CIFS_WEAK_PW_HASH=y --CONFIG_CIFS_XATTR=y --CONFIG_CIFS_POSIX=y --CONFIG_9P_FS=m --CONFIG_PARTITION_ADVANCED=y --CONFIG_MAC_PARTITION=y --CONFIG_EFI_PARTITION=y --CONFIG_NLS_DEFAULT="utf8" --CONFIG_NLS_CODEPAGE_437=y --CONFIG_NLS_CODEPAGE_737=m --CONFIG_NLS_CODEPAGE_775=m --CONFIG_NLS_CODEPAGE_850=m --CONFIG_NLS_CODEPAGE_852=m --CONFIG_NLS_CODEPAGE_855=m --CONFIG_NLS_CODEPAGE_857=m --CONFIG_NLS_CODEPAGE_860=m --CONFIG_NLS_CODEPAGE_861=m --CONFIG_NLS_CODEPAGE_862=m --CONFIG_NLS_CODEPAGE_863=m --CONFIG_NLS_CODEPAGE_864=m --CONFIG_NLS_CODEPAGE_865=m --CONFIG_NLS_CODEPAGE_866=m --CONFIG_NLS_CODEPAGE_869=m --CONFIG_NLS_CODEPAGE_936=m --CONFIG_NLS_CODEPAGE_950=m --CONFIG_NLS_CODEPAGE_932=m --CONFIG_NLS_CODEPAGE_949=m --CONFIG_NLS_CODEPAGE_874=m --CONFIG_NLS_ISO8859_8=m --CONFIG_NLS_CODEPAGE_1250=m --CONFIG_NLS_CODEPAGE_1251=m --CONFIG_NLS_ASCII=y --CONFIG_NLS_ISO8859_1=m --CONFIG_NLS_ISO8859_2=m --CONFIG_NLS_ISO8859_3=m --CONFIG_NLS_ISO8859_4=m --CONFIG_NLS_ISO8859_5=m --CONFIG_NLS_ISO8859_6=m --CONFIG_NLS_ISO8859_7=m --CONFIG_NLS_ISO8859_9=m --CONFIG_NLS_ISO8859_13=m --CONFIG_NLS_ISO8859_14=m --CONFIG_NLS_ISO8859_15=m --CONFIG_NLS_KOI8_R=m --CONFIG_NLS_KOI8_U=m --CONFIG_NLS_UTF8=m --# CONFIG_SCHED_DEBUG is not set --# CONFIG_DEBUG_BUGVERBOSE is not set --# CONFIG_FTRACE is not set --# CONFIG_ARM_UNWIND is not set --CONFIG_CRYPTO_AUTHENC=m --CONFIG_CRYPTO_SEQIV=m --CONFIG_CRYPTO_CBC=y --CONFIG_CRYPTO_HMAC=y --CONFIG_CRYPTO_XCBC=m --CONFIG_CRYPTO_MD5=y --CONFIG_CRYPTO_SHA1=y --CONFIG_CRYPTO_SHA256=m --CONFIG_CRYPTO_SHA512=m --CONFIG_CRYPTO_TGR192=m --CONFIG_CRYPTO_WP512=m --CONFIG_CRYPTO_CAST5=m --CONFIG_CRYPTO_DES=y --CONFIG_CRYPTO_DEFLATE=m --# CONFIG_CRYPTO_ANSI_CPRNG is not set --# CONFIG_CRYPTO_HW is not set --CONFIG_CRC_ITU_T=y --CONFIG_LIBCRC32C=y --CONFIG_I2C=y --CONFIG_I2C_BOARDINFO=y --CONFIG_I2C_COMPAT=y --CONFIG_I2C_CHARDEV=m --CONFIG_I2C_HELPER_AUTO=y --CONFIG_I2C_BCM2708=m --CONFIG_SPI=y --CONFIG_SPI_MASTER=y --CONFIG_SPI_BCM2708=m -- -diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig -index c1afa47..f1ada24 100644 ---- a/arch/arm/configs/bcmrpi_defconfig -+++ b/arch/arm/configs/bcmrpi_defconfig -@@ -3,10 +3,16 @@ CONFIG_EXPERIMENTAL=y - # CONFIG_LOCALVERSION_AUTO is not set - CONFIG_SYSVIPC=y - CONFIG_POSIX_MQUEUE=y --CONFIG_BSD_PROCESS_ACCT=y --CONFIG_BSD_PROCESS_ACCT_V3=y - CONFIG_FHANDLE=y - CONFIG_AUDIT=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y - CONFIG_IKCONFIG=y - CONFIG_IKCONFIG_PROC=y - CONFIG_CGROUP_FREEZER=y -@@ -16,6 +22,7 @@ CONFIG_RESOURCE_COUNTERS=y - CONFIG_BLK_CGROUP=y - CONFIG_NAMESPACES=y - CONFIG_SCHED_AUTOGROUP=y -+CONFIG_RELAY=y - CONFIG_EMBEDDED=y - # CONFIG_COMPAT_BRK is not set - CONFIG_SLAB=y -@@ -26,18 +33,22 @@ CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y - CONFIG_MODULE_SRCVERSION_ALL=y --# CONFIG_BLK_DEV_BSG is not set - CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y - CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_BCM2708=y --CONFIG_NO_HZ=y --CONFIG_HIGH_RES_TIMERS=y -+CONFIG_BCM2708_DMAER=m -+CONFIG_PREEMPT=y - CONFIG_AEABI=y -+CONFIG_CLEANCACHE=y -+CONFIG_FRONTSWAP=y -+CONFIG_UACCESS_WITH_MEMCPY=y - CONFIG_SECCOMP=y - CONFIG_CC_STACKPROTECTOR=y - CONFIG_ZBOOT_ROM_TEXT=0x0 - CONFIG_ZBOOT_ROM_BSS=0x0 --CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext3 rootwait" -+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" - CONFIG_KEXEC=y - CONFIG_CPU_FREQ=y - CONFIG_CPU_FREQ_STAT=m -@@ -56,9 +67,17 @@ CONFIG_XFRM_USER=y - CONFIG_NET_KEY=m - CONFIG_INET=y - CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y - CONFIG_IP_PNP=y - CONFIG_IP_PNP_DHCP=y - CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_NET_IPGRE_DEMUX=m -+CONFIG_NET_IPGRE=m -+CONFIG_ARPD=y - CONFIG_SYN_COOKIES=y - CONFIG_INET_AH=m - CONFIG_INET_ESP=m -@@ -79,7 +98,6 @@ CONFIG_NF_CONNTRACK_ZONES=y - CONFIG_NF_CONNTRACK_EVENTS=y - CONFIG_NF_CONNTRACK_TIMESTAMP=y - CONFIG_NF_CT_PROTO_DCCP=m --CONFIG_NF_CT_PROTO_SCTP=m - CONFIG_NF_CT_PROTO_UDPLITE=m - CONFIG_NF_CONNTRACK_AMANDA=m - CONFIG_NF_CONNTRACK_FTP=m -@@ -98,10 +116,11 @@ CONFIG_NETFILTER_XT_TARGET_AUDIT=m - CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m - CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m - CONFIG_NETFILTER_XT_TARGET_CONNMARK=m --CONFIG_NETFILTER_XT_TARGET_CT=m - CONFIG_NETFILTER_XT_TARGET_DSCP=m -+CONFIG_NETFILTER_XT_TARGET_HMARK=m - CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m - CONFIG_NETFILTER_XT_TARGET_LED=m -+CONFIG_NETFILTER_XT_TARGET_LOG=m - CONFIG_NETFILTER_XT_TARGET_MARK=m - CONFIG_NETFILTER_XT_TARGET_NFLOG=m - CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -@@ -126,11 +145,13 @@ CONFIG_NETFILTER_XT_MATCH_ESP=m - CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m - CONFIG_NETFILTER_XT_MATCH_HELPER=m - CONFIG_NETFILTER_XT_MATCH_IPRANGE=m -+CONFIG_NETFILTER_XT_MATCH_IPVS=m - CONFIG_NETFILTER_XT_MATCH_LENGTH=m - CONFIG_NETFILTER_XT_MATCH_LIMIT=m - CONFIG_NETFILTER_XT_MATCH_MAC=m - CONFIG_NETFILTER_XT_MATCH_MARK=m - CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -+CONFIG_NETFILTER_XT_MATCH_NFACCT=m - CONFIG_NETFILTER_XT_MATCH_OSF=m - CONFIG_NETFILTER_XT_MATCH_OWNER=m - CONFIG_NETFILTER_XT_MATCH_POLICY=m -@@ -140,7 +161,6 @@ CONFIG_NETFILTER_XT_MATCH_QUOTA=m - CONFIG_NETFILTER_XT_MATCH_RATEEST=m - CONFIG_NETFILTER_XT_MATCH_REALM=m - CONFIG_NETFILTER_XT_MATCH_RECENT=m --CONFIG_NETFILTER_XT_MATCH_SCTP=m - CONFIG_NETFILTER_XT_MATCH_SOCKET=m - CONFIG_NETFILTER_XT_MATCH_STATE=m - CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -@@ -160,20 +180,41 @@ CONFIG_IP_SET_HASH_NET=m - CONFIG_IP_SET_HASH_NETPORT=m - CONFIG_IP_SET_HASH_NETIFACE=m - CONFIG_IP_SET_LIST_SET=m -+CONFIG_IP_VS=m -+CONFIG_IP_VS_IPV6=y -+CONFIG_IP_VS_PROTO_TCP=y -+CONFIG_IP_VS_PROTO_UDP=y -+CONFIG_IP_VS_PROTO_ESP=y -+CONFIG_IP_VS_PROTO_AH=y -+CONFIG_IP_VS_PROTO_SCTP=y -+CONFIG_IP_VS_RR=m -+CONFIG_IP_VS_WRR=m -+CONFIG_IP_VS_LC=m -+CONFIG_IP_VS_WLC=m -+CONFIG_IP_VS_LBLC=m -+CONFIG_IP_VS_LBLCR=m -+CONFIG_IP_VS_DH=m -+CONFIG_IP_VS_SH=m -+CONFIG_IP_VS_SED=m -+CONFIG_IP_VS_NQ=m -+CONFIG_IP_VS_FTP=m -+CONFIG_IP_VS_PE_SIP=m - CONFIG_NF_CONNTRACK_IPV4=m -+CONFIG_IP_NF_QUEUE=m - CONFIG_IP_NF_IPTABLES=m - CONFIG_IP_NF_MATCH_AH=m - CONFIG_IP_NF_MATCH_ECN=m -+CONFIG_IP_NF_MATCH_RPFILTER=m - CONFIG_IP_NF_MATCH_TTL=m - CONFIG_IP_NF_FILTER=m - CONFIG_IP_NF_TARGET_REJECT=m --CONFIG_IP_NF_TARGET_LOG=m - CONFIG_IP_NF_TARGET_ULOG=m --CONFIG_NF_NAT=m -+CONFIG_NF_NAT_IPV4=m - CONFIG_IP_NF_TARGET_MASQUERADE=m - CONFIG_IP_NF_TARGET_NETMAP=m - CONFIG_IP_NF_TARGET_REDIRECT=m - CONFIG_IP_NF_MANGLE=m -+CONFIG_IP_NF_TARGET_CLUSTERIP=m - CONFIG_IP_NF_TARGET_ECN=m - CONFIG_IP_NF_TARGET_TTL=m - CONFIG_IP_NF_RAW=m -@@ -181,7 +222,6 @@ CONFIG_IP_NF_ARPTABLES=m - CONFIG_IP_NF_ARPFILTER=m - CONFIG_IP_NF_ARP_MANGLE=m - CONFIG_NF_CONNTRACK_IPV6=m --CONFIG_IP6_NF_IPTABLES=m - CONFIG_IP6_NF_MATCH_AH=m - CONFIG_IP6_NF_MATCH_EUI64=m - CONFIG_IP6_NF_MATCH_FRAG=m -@@ -189,13 +229,16 @@ CONFIG_IP6_NF_MATCH_OPTS=m - CONFIG_IP6_NF_MATCH_HL=m - CONFIG_IP6_NF_MATCH_IPV6HEADER=m - CONFIG_IP6_NF_MATCH_MH=m -+CONFIG_IP6_NF_MATCH_RPFILTER=m - CONFIG_IP6_NF_MATCH_RT=m - CONFIG_IP6_NF_TARGET_HL=m --CONFIG_IP6_NF_TARGET_LOG=m - CONFIG_IP6_NF_FILTER=m - CONFIG_IP6_NF_TARGET_REJECT=m - CONFIG_IP6_NF_MANGLE=m - CONFIG_IP6_NF_RAW=m -+CONFIG_NF_NAT_IPV6=m -+CONFIG_IP6_NF_TARGET_MASQUERADE=m -+CONFIG_IP6_NF_TARGET_NPT=m - CONFIG_BRIDGE_NF_EBTABLES=m - CONFIG_BRIDGE_EBT_BROUTE=m - CONFIG_BRIDGE_EBT_T_FILTER=m -@@ -240,6 +283,10 @@ CONFIG_NET_SCH_DRR=m - CONFIG_NET_SCH_MQPRIO=m - CONFIG_NET_SCH_CHOKE=m - CONFIG_NET_SCH_QFQ=m -+CONFIG_NET_SCH_CODEL=m -+CONFIG_NET_SCH_FQ_CODEL=m -+CONFIG_NET_SCH_INGRESS=m -+CONFIG_NET_SCH_PLUG=m - CONFIG_NET_CLS_BASIC=m - CONFIG_NET_CLS_TCINDEX=m - CONFIG_NET_CLS_ROUTE4=m -@@ -256,6 +303,7 @@ CONFIG_NET_EMATCH_NBYTE=m - CONFIG_NET_EMATCH_U32=m - CONFIG_NET_EMATCH_META=m - CONFIG_NET_EMATCH_TEXT=m -+CONFIG_NET_EMATCH_IPSET=m - CONFIG_NET_CLS_ACT=y - CONFIG_NET_ACT_POLICE=m - CONFIG_NET_ACT_GACT=m -@@ -267,9 +315,21 @@ CONFIG_NET_ACT_PEDIT=m - CONFIG_NET_ACT_SIMP=m - CONFIG_NET_ACT_SKBEDIT=m - CONFIG_NET_ACT_CSUM=m -+CONFIG_BATMAN_ADV=m - CONFIG_NET_PKTGEN=m -+CONFIG_HAMRADIO=y -+CONFIG_AX25=m -+CONFIG_NETROM=m -+CONFIG_ROSE=m -+CONFIG_MKISS=m -+CONFIG_6PACK=m -+CONFIG_BPQETHER=m -+CONFIG_BAYCOM_SER_FDX=m -+CONFIG_BAYCOM_SER_HDX=m -+CONFIG_YAM=m - CONFIG_IRDA=m - CONFIG_IRLAN=m -+CONFIG_IRNET=m - CONFIG_IRCOMM=m - CONFIG_IRDA_ULTRA=y - CONFIG_IRDA_CACHE_LAST_LSAP=y -@@ -282,8 +342,6 @@ CONFIG_USB_IRDA=m - CONFIG_SIGMATEL_FIR=m - CONFIG_MCS_FIR=m - CONFIG_BT=m --CONFIG_BT_L2CAP=y --CONFIG_BT_SCO=y - CONFIG_BT_RFCOMM=m - CONFIG_BT_RFCOMM_TTY=y - CONFIG_BT_BNEP=m -@@ -291,6 +349,8 @@ CONFIG_BT_BNEP_MC_FILTER=y - CONFIG_BT_BNEP_PROTO_FILTER=y - CONFIG_BT_HIDP=m - CONFIG_BT_HCIBTUSB=m -+CONFIG_BT_HCIBTSDIO=m -+CONFIG_BT_HCIUART=m - CONFIG_BT_HCIBCM203X=m - CONFIG_BT_HCIBPA10X=m - CONFIG_BT_HCIBFUSB=m -@@ -298,71 +358,66 @@ CONFIG_BT_HCIVHCI=m - CONFIG_BT_MRVL=m - CONFIG_BT_MRVL_SDIO=m - CONFIG_BT_ATH3K=m -+CONFIG_BT_WILINK=m -+CONFIG_AF_RXRPC=m -+CONFIG_RXKAD=m - CONFIG_CFG80211=m -+CONFIG_CFG80211_WEXT=y - CONFIG_MAC80211=m - CONFIG_MAC80211_RC_PID=y - CONFIG_MAC80211_MESH=y - CONFIG_WIMAX=m -+CONFIG_RFKILL=m -+CONFIG_RFKILL_INPUT=y - CONFIG_NET_9P=m - CONFIG_NFC=m - CONFIG_NFC_PN533=m --CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" - CONFIG_DEVTMPFS=y - CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_CMA=y - CONFIG_BLK_DEV_LOOP=y - CONFIG_BLK_DEV_CRYPTOLOOP=m - CONFIG_BLK_DEV_DRBD=m - CONFIG_BLK_DEV_NBD=m - CONFIG_BLK_DEV_RAM=y - CONFIG_CDROM_PKTCDVD=m --CONFIG_MISC_DEVICES=y - CONFIG_SCSI=y - # CONFIG_SCSI_PROC_FS is not set --CONFIG_BLK_DEV_SD=m -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m - CONFIG_BLK_DEV_SR=m - CONFIG_SCSI_MULTI_LUN=y --# CONFIG_SCSI_LOWLEVEL is not set -+CONFIG_SCSI_ISCSI_ATTRS=y -+CONFIG_ISCSI_TCP=m - CONFIG_MD=y -+CONFIG_MD_RAID0=m -+CONFIG_BLK_DEV_DM=m -+CONFIG_DM_CRYPT=m -+CONFIG_DM_SNAPSHOT=m -+CONFIG_DM_MIRROR=m -+CONFIG_DM_RAID=m -+CONFIG_DM_LOG_USERSPACE=m -+CONFIG_DM_ZERO=m -+CONFIG_DM_DELAY=m - CONFIG_NETDEVICES=y -+CONFIG_BONDING=m -+CONFIG_MACVLAN=m -+CONFIG_NETCONSOLE=m - CONFIG_TUN=m --CONFIG_PHYLIB=m - CONFIG_MDIO_BITBANG=m --CONFIG_NET_ETHERNET=y --# CONFIG_NETDEV_1000 is not set --# CONFIG_NETDEV_10000 is not set --CONFIG_LIBERTAS_THINFIRM=m --CONFIG_LIBERTAS_THINFIRM_USB=m --CONFIG_AT76C50X_USB=m --CONFIG_USB_ZD1201=m --CONFIG_USB_NET_RNDIS_WLAN=m --CONFIG_RTL8187=m --CONFIG_MAC80211_HWSIM=m --CONFIG_ATH_COMMON=m --CONFIG_ATH9K=m --CONFIG_ATH9K_HTC=m --CONFIG_CARL9170=m --CONFIG_B43=m --CONFIG_B43LEGACY=m --CONFIG_HOSTAP=m --CONFIG_IWM=m --CONFIG_LIBERTAS=m --CONFIG_LIBERTAS_USB=m --CONFIG_LIBERTAS_SDIO=m --CONFIG_P54_COMMON=m --CONFIG_P54_USB=m --CONFIG_RT2X00=m --CONFIG_RT2500USB=m --CONFIG_RT73USB=m --CONFIG_RT2800USB=m --CONFIG_RT2800USB_RT53XX=y --CONFIG_RT2800USB_UNKNOWN=y --CONFIG_WL1251=m --CONFIG_WL12XX_MENU=m --CONFIG_ZD1211RW=m --CONFIG_MWIFIEX=m --CONFIG_MWIFIEX_SDIO=m --CONFIG_RTL8192CU=m --CONFIG_WIMAX_I2400M_USB=m -+CONFIG_PPP=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_FILTER=y -+CONFIG_PPP_MPPE=m -+CONFIG_PPP_MULTILINK=y -+CONFIG_PPPOE=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_SLIP_SMART=y - CONFIG_USB_CATC=m - CONFIG_USB_KAWETH=m - CONFIG_USB_PEGASUS=m -@@ -371,6 +426,8 @@ CONFIG_USB_USBNET=y - CONFIG_USB_NET_AX8817X=m - CONFIG_USB_NET_CDCETHER=m - CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_CDC_NCM=m -+CONFIG_USB_NET_CDC_MBIM=m - CONFIG_USB_NET_DM9601=m - CONFIG_USB_NET_SMSC75XX=m - CONFIG_USB_NET_SMSC95XX=y -@@ -382,21 +439,42 @@ CONFIG_USB_NET_CDC_SUBSET=m - CONFIG_USB_ALI_M5632=y - CONFIG_USB_AN2720=y - CONFIG_USB_KC2190=y --# CONFIG_USB_NET_ZAURUS is not set -+CONFIG_USB_NET_ZAURUS=m - CONFIG_USB_NET_CX82310_ETH=m - CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_QMI_WWAN=m -+CONFIG_USB_HSO=m - CONFIG_USB_NET_INT51X1=m - CONFIG_USB_IPHETH=m - CONFIG_USB_SIERRA_NET=m - CONFIG_USB_VL600=m --CONFIG_PPP=m --CONFIG_PPP_ASYNC=m --CONFIG_PPP_SYNC_TTY=m --CONFIG_PPP_DEFLATE=m --CONFIG_PPP_BSDCOMP=m --CONFIG_SLIP=m --CONFIG_SLIP_COMPRESSED=y --CONFIG_NETCONSOLE=m -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_AT76C50X_USB=m -+CONFIG_USB_ZD1201=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_RTL8187=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_ATH_CARDS=m -+CONFIG_CARL9170=m -+CONFIG_AR5523=m -+CONFIG_HOSTAP=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RT2800USB_UNKNOWN=y -+CONFIG_ZD1211RW=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_RTL8192CU=m -+CONFIG_WIMAX_I2400M_USB=m - CONFIG_INPUT_POLLDEV=m - # CONFIG_INPUT_MOUSEDEV_PSAUX is not set - CONFIG_INPUT_JOYDEV=m -@@ -405,7 +483,6 @@ CONFIG_INPUT_EVDEV=m - # CONFIG_INPUT_MOUSE is not set - CONFIG_INPUT_MISC=y - CONFIG_INPUT_AD714X=m --CONFIG_INPUT_ATI_REMOTE=m - CONFIG_INPUT_ATI_REMOTE2=m - CONFIG_INPUT_KEYSPAN_REMOTE=m - CONFIG_INPUT_POWERMATE=m -@@ -425,8 +502,11 @@ CONFIG_VT_HW_CONSOLE_BINDING=y - # CONFIG_DEVKMEM is not set - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y --# CONFIG_HW_RANDOM is not set -+CONFIG_TTY_PRINTK=y -+CONFIG_HW_RANDOM_BCM2708=m - CONFIG_RAW_DRIVER=y -+CONFIG_BRCM_CHAR_DRIVERS=y -+CONFIG_BCM_VC_CMA=y - CONFIG_I2C=y - CONFIG_I2C_CHARDEV=m - CONFIG_I2C_BCM2708=m -@@ -434,21 +514,45 @@ CONFIG_SPI=y - CONFIG_SPI_BCM2708=m - CONFIG_SPI_SPIDEV=m - CONFIG_GPIO_SYSFS=y -+CONFIG_W1=m -+CONFIG_W1_MASTER_DS2490=m -+CONFIG_W1_MASTER_DS2482=m -+CONFIG_W1_MASTER_DS1WM=m -+CONFIG_W1_MASTER_GPIO=m -+CONFIG_W1_SLAVE_THERM=m -+CONFIG_W1_SLAVE_SMEM=m -+CONFIG_W1_SLAVE_DS2408=m -+CONFIG_W1_SLAVE_DS2423=m -+CONFIG_W1_SLAVE_DS2431=m -+CONFIG_W1_SLAVE_DS2433=m -+CONFIG_W1_SLAVE_DS2760=m -+CONFIG_W1_SLAVE_DS2780=m -+CONFIG_W1_SLAVE_BQ27000=m - # CONFIG_HWMON is not set - CONFIG_THERMAL=y - CONFIG_THERMAL_BCM2835=y - CONFIG_WATCHDOG=y - CONFIG_BCM2708_WDT=m -+CONFIG_UCB1400_CORE=m - CONFIG_MEDIA_SUPPORT=m --CONFIG_VIDEO_DEV=m --CONFIG_DVB_CORE=m -+CONFIG_MEDIA_CAMERA_SUPPORT=y -+CONFIG_MEDIA_ANALOG_TV_SUPPORT=y -+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y -+CONFIG_MEDIA_RADIO_SUPPORT=y -+CONFIG_MEDIA_RC_SUPPORT=y -+CONFIG_MEDIA_CONTROLLER=y -+CONFIG_LIRC=m -+CONFIG_RC_DEVICES=y - CONFIG_RC_ATI_REMOTE=m - CONFIG_IR_IMON=m - CONFIG_IR_MCEUSB=m - CONFIG_IR_REDRAT3=m - CONFIG_IR_STREAMZAP=m -+CONFIG_IR_IGUANA=m -+CONFIG_IR_TTUSBIR=m - CONFIG_RC_LOOPBACK=m --CONFIG_MEDIA_ATTACH=y -+CONFIG_IR_GPIO_CIR=m -+CONFIG_MEDIA_USB_SUPPORT=y - CONFIG_USB_VIDEO_CLASS=m - CONFIG_USB_M5602=m - CONFIG_USB_STV06XX=m -@@ -459,6 +563,7 @@ CONFIG_USB_GSPCA_CPIA1=m - CONFIG_USB_GSPCA_ETOMS=m - CONFIG_USB_GSPCA_FINEPIX=m - CONFIG_USB_GSPCA_JEILINJ=m -+CONFIG_USB_GSPCA_JL2005BCD=m - CONFIG_USB_GSPCA_KINECT=m - CONFIG_USB_GSPCA_KONICA=m - CONFIG_USB_GSPCA_MARS=m -@@ -489,31 +594,32 @@ CONFIG_USB_GSPCA_STK014=m - CONFIG_USB_GSPCA_STV0680=m - CONFIG_USB_GSPCA_SUNPLUS=m - CONFIG_USB_GSPCA_T613=m -+CONFIG_USB_GSPCA_TOPRO=m - CONFIG_USB_GSPCA_TV8532=m - CONFIG_USB_GSPCA_VC032X=m - CONFIG_USB_GSPCA_VICAM=m - CONFIG_USB_GSPCA_XIRLINK_CIT=m - CONFIG_USB_GSPCA_ZC3XX=m -+CONFIG_USB_PWC=m -+CONFIG_VIDEO_CPIA2=m -+CONFIG_USB_ZR364XX=m -+CONFIG_USB_STKWEBCAM=m -+CONFIG_USB_S2255=m -+CONFIG_USB_SN9C102=m -+CONFIG_VIDEO_AU0828=m - CONFIG_VIDEO_PVRUSB2=m -+CONFIG_VIDEO_PVRUSB2_DEBUGIFC=y - CONFIG_VIDEO_HDPVR=m --CONFIG_VIDEO_EM28XX=m --CONFIG_VIDEO_EM28XX_ALSA=m --CONFIG_VIDEO_EM28XX_DVB=m - CONFIG_VIDEO_TLG2300=m -+CONFIG_VIDEO_USBVISION=m -+CONFIG_VIDEO_STK1160=m -+CONFIG_VIDEO_STK1160_AC97=y - CONFIG_VIDEO_CX231XX=m - CONFIG_VIDEO_CX231XX_ALSA=m - CONFIG_VIDEO_CX231XX_DVB=m --CONFIG_VIDEO_USBVISION=m --CONFIG_USB_ET61X251=m --CONFIG_USB_SN9C102=m --CONFIG_USB_PWC=m --CONFIG_USB_ZR364XX=m --CONFIG_USB_STKWEBCAM=m --CONFIG_USB_S2255=m --CONFIG_USB_DSBR=m --CONFIG_RADIO_SI470X=y --CONFIG_USB_SI470X=m --CONFIG_USB_MR800=m -+CONFIG_VIDEO_TM6000=m -+CONFIG_VIDEO_TM6000_ALSA=m -+CONFIG_VIDEO_TM6000_DVB=m - CONFIG_DVB_USB=m - CONFIG_DVB_USB_A800=m - CONFIG_DVB_USB_DIBUSB_MB=m -@@ -522,8 +628,6 @@ CONFIG_DVB_USB_DIB0700=m - CONFIG_DVB_USB_UMT_010=m - CONFIG_DVB_USB_CXUSB=m - CONFIG_DVB_USB_M920X=m --CONFIG_DVB_USB_GL861=m --CONFIG_DVB_USB_AU6610=m - CONFIG_DVB_USB_DIGITV=m - CONFIG_DVB_USB_VP7045=m - CONFIG_DVB_USB_VP702X=m -@@ -536,21 +640,44 @@ CONFIG_DVB_USB_AF9005=m - CONFIG_DVB_USB_AF9005_REMOTE=m - CONFIG_DVB_USB_DW2102=m - CONFIG_DVB_USB_CINERGY_T2=m --CONFIG_DVB_USB_ANYSEE=m - CONFIG_DVB_USB_DTV5100=m -+CONFIG_DVB_USB_FRIIO=m -+CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_TECHNISAT_USB2=m -+CONFIG_DVB_USB_V2=m - CONFIG_DVB_USB_AF9015=m -+CONFIG_DVB_USB_AF9035=m -+CONFIG_DVB_USB_ANYSEE=m -+CONFIG_DVB_USB_AU6610=m -+CONFIG_DVB_USB_AZ6007=m - CONFIG_DVB_USB_CE6230=m --CONFIG_DVB_USB_FRIIO=m - CONFIG_DVB_USB_EC168=m --CONFIG_DVB_USB_AZ6027=m -+CONFIG_DVB_USB_GL861=m -+CONFIG_DVB_USB_IT913X=m - CONFIG_DVB_USB_LME2510=m --CONFIG_DVB_USB_TECHNISAT_USB2=m --CONFIG_SMS_SIANO_MDTV=m -+CONFIG_DVB_USB_MXL111SF=m -+CONFIG_DVB_USB_RTL28XXU=m - CONFIG_SMS_USB_DRV=m --CONFIG_DVB_B2C2_FLEXCOP=m - CONFIG_DVB_B2C2_FLEXCOP_USB=m -+CONFIG_VIDEO_EM28XX=m -+CONFIG_VIDEO_EM28XX_ALSA=m -+CONFIG_VIDEO_EM28XX_DVB=m -+CONFIG_SMS_SDIO_DRV=m -+CONFIG_USB_MR800=m -+CONFIG_USB_DSBR=m -+CONFIG_RADIO_SHARK=m -+CONFIG_RADIO_SHARK2=m -+CONFIG_RADIO_SI4713=m -+CONFIG_USB_KEENE=m -+CONFIG_RADIO_TEA5764=m -+CONFIG_RADIO_SAA7706H=m -+CONFIG_RADIO_TEF6862=m -+CONFIG_RADIO_WL1273=m -+CONFIG_RADIO_WL128X=m -+CONFIG_MEDIA_ATTACH=y - CONFIG_FB=y - CONFIG_FB_BCM2708=y -+# CONFIG_BACKLIGHT_GENERIC is not set - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_LOGO=y - # CONFIG_LOGO_LINUX_MONO is not set -@@ -573,10 +700,10 @@ CONFIG_SND_BCM2835=m - CONFIG_SND_USB_AUDIO=m - CONFIG_SND_USB_UA101=m - CONFIG_SND_USB_CAIAQ=m -+CONFIG_SND_USB_CAIAQ_INPUT=y - CONFIG_SND_USB_6FIRE=m - CONFIG_SOUND_PRIME=m --CONFIG_HID_PID=y --CONFIG_USB_HIDDEV=y -+CONFIG_HIDRAW=y - CONFIG_HID_A4TECH=m - CONFIG_HID_ACRUX=m - CONFIG_HID_APPLE=m -@@ -607,7 +734,6 @@ CONFIG_HID_ORTEK=m - CONFIG_HID_PANTHERLORD=m - CONFIG_HID_PETALYNX=m - CONFIG_HID_PICOLCD=m --CONFIG_HID_QUANTA=m - CONFIG_HID_ROCCAT=m - CONFIG_HID_SAMSUNG=m - CONFIG_HID_SONY=m -@@ -617,14 +743,16 @@ CONFIG_HID_GREENASIA=m - CONFIG_HID_SMARTJOYPLUS=m - CONFIG_HID_TOPSEED=m - CONFIG_HID_THRUSTMASTER=m --CONFIG_HID_WACOM=m --CONFIG_HID_WIIMOTE=m - CONFIG_HID_ZEROPLUS=m - CONFIG_HID_ZYDACRON=m -+CONFIG_HID_PID=y -+CONFIG_USB_HIDDEV=y - CONFIG_USB=y - CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - CONFIG_USB_MON=m - CONFIG_USB_DWCOTG=y -+CONFIG_USB_PRINTER=m -+CONFIG_USB_TMC=m - CONFIG_USB_STORAGE=y - CONFIG_USB_STORAGE_REALTEK=m - CONFIG_USB_STORAGE_DATAFAB=m -@@ -639,8 +767,6 @@ CONFIG_USB_STORAGE_ONETOUCH=m - CONFIG_USB_STORAGE_KARMA=m - CONFIG_USB_STORAGE_CYPRESS_ATACB=m - CONFIG_USB_STORAGE_ENE_UB6250=m --CONFIG_USB_UAS=m --CONFIG_USB_LIBUSUAL=y - CONFIG_USB_MDC800=m - CONFIG_USB_MICROTEK=m - CONFIG_USB_SERIAL=m -@@ -661,6 +787,7 @@ CONFIG_USB_SERIAL_IPAQ=m - CONFIG_USB_SERIAL_IR=m - CONFIG_USB_SERIAL_EDGEPORT=m - CONFIG_USB_SERIAL_EDGEPORT_TI=m -+CONFIG_USB_SERIAL_F81232=m - CONFIG_USB_SERIAL_GARMIN=m - CONFIG_USB_SERIAL_IPW=m - CONFIG_USB_SERIAL_IUU=m -@@ -669,6 +796,7 @@ CONFIG_USB_SERIAL_KEYSPAN=m - CONFIG_USB_SERIAL_KLSI=m - CONFIG_USB_SERIAL_KOBIL_SCT=m - CONFIG_USB_SERIAL_MCT_U232=m -+CONFIG_USB_SERIAL_METRO=m - CONFIG_USB_SERIAL_MOS7720=m - CONFIG_USB_SERIAL_MOS7840=m - CONFIG_USB_SERIAL_MOTOROLA=m -@@ -691,7 +819,9 @@ CONFIG_USB_SERIAL_OMNINET=m - CONFIG_USB_SERIAL_OPTICON=m - CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m - CONFIG_USB_SERIAL_ZIO=m -+CONFIG_USB_SERIAL_ZTE=m - CONFIG_USB_SERIAL_SSU100=m -+CONFIG_USB_SERIAL_QT2=m - CONFIG_USB_SERIAL_DEBUG=m - CONFIG_USB_EMI62=m - CONFIG_USB_EMI26=m -@@ -717,11 +847,10 @@ CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SDHCI_BCM2708=y - CONFIG_MMC_SDHCI_BCM2708_DMA=y --CONFIG_LEDS_GPIO=y --CONFIG_LEDS_TRIGGER_TIMER=m --CONFIG_LEDS_TRIGGER_HEARTBEAT=m --CONFIG_LEDS_TRIGGER_DEFAULT_ON=m -+CONFIG_MMC_SPI=m -+CONFIG_LEDS_GPIO=m - CONFIG_RTC_CLASS=y -+# CONFIG_RTC_HCTOSYS is not set - CONFIG_RTC_DRV_DS1307=m - CONFIG_RTC_DRV_DS1374=m - CONFIG_RTC_DRV_DS1672=m -@@ -753,6 +882,23 @@ CONFIG_RTC_DRV_PCF2123=m - CONFIG_UIO=m - CONFIG_UIO_PDRV=m - CONFIG_UIO_PDRV_GENIRQ=m -+CONFIG_STAGING=y -+CONFIG_W35UND=m -+CONFIG_PRISM2_USB=m -+CONFIG_R8712U=m -+CONFIG_VT6656=m -+CONFIG_ZRAM=m -+CONFIG_ZSMALLOC=m -+CONFIG_SPEAKUP=m -+CONFIG_SPEAKUP_SYNTH_SOFT=m -+CONFIG_STAGING_MEDIA=y -+CONFIG_DVB_AS102=m -+CONFIG_LIRC_STAGING=y -+CONFIG_LIRC_IGORPLUGUSB=m -+CONFIG_LIRC_IMON=m -+CONFIG_LIRC_RPI=m -+CONFIG_LIRC_SASEM=m -+CONFIG_LIRC_SERIAL=m - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXT4_FS=y - CONFIG_EXT4_FS_POSIX_ACL=y -@@ -770,6 +916,7 @@ CONFIG_XFS_QUOTA=y - CONFIG_XFS_POSIX_ACL=y - CONFIG_XFS_RT=y - CONFIG_GFS2_FS=m -+CONFIG_GFS2_FS_LOCKING_DLM=y - CONFIG_OCFS2_FS=m - CONFIG_BTRFS_FS=m - CONFIG_BTRFS_FS_POSIX_ACL=y -@@ -790,15 +937,19 @@ CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y - CONFIG_FAT_DEFAULT_IOCHARSET="ascii" - CONFIG_NTFS_FS=m -+CONFIG_NTFS_RW=y - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y - CONFIG_CONFIGFS_FS=y -+CONFIG_ECRYPT_FS=m -+CONFIG_HFS_FS=m -+CONFIG_HFSPLUS_FS=m - CONFIG_SQUASHFS=m - CONFIG_SQUASHFS_XATTR=y - CONFIG_SQUASHFS_LZO=y - CONFIG_SQUASHFS_XZ=y -+CONFIG_F2FS_FS=y - CONFIG_NFS_FS=y --CONFIG_NFS_V3=y - CONFIG_NFS_V3_ACL=y - CONFIG_NFS_V4=y - CONFIG_ROOT_NFS=y -@@ -812,9 +963,6 @@ CONFIG_CIFS_XATTR=y - CONFIG_CIFS_POSIX=y - CONFIG_9P_FS=m - CONFIG_9P_FS_POSIX_ACL=y --CONFIG_PARTITION_ADVANCED=y --CONFIG_MAC_PARTITION=y --CONFIG_EFI_PARTITION=y - CONFIG_NLS_DEFAULT="utf8" - CONFIG_NLS_CODEPAGE_437=y - CONFIG_NLS_CODEPAGE_737=m -@@ -853,32 +1001,28 @@ CONFIG_NLS_ISO8859_14=m - CONFIG_NLS_ISO8859_15=m - CONFIG_NLS_KOI8_R=m - CONFIG_NLS_KOI8_U=m --CONFIG_NLS_UTF8=m -+CONFIG_DLM=m - CONFIG_PRINTK_TIME=y -+CONFIG_DEBUG_FS=y - CONFIG_DETECT_HUNG_TASK=y - CONFIG_TIMER_STATS=y --CONFIG_DEBUG_STACK_USAGE=y --CONFIG_DEBUG_INFO=y -+# CONFIG_DEBUG_PREEMPT is not set - CONFIG_DEBUG_MEMORY_INIT=y - CONFIG_BOOT_PRINTK_DELAY=y - CONFIG_LATENCYTOP=y --CONFIG_SYSCTL_SYSCALL_CHECK=y --CONFIG_IRQSOFF_TRACER=y --CONFIG_SCHED_TRACER=y --CONFIG_STACK_TRACER=y --CONFIG_BLK_DEV_IO_TRACE=y --CONFIG_FUNCTION_PROFILER=y -+# CONFIG_KPROBE_EVENT is not set - CONFIG_KGDB=y - CONFIG_KGDB_KDB=y - CONFIG_KDB_KEYBOARD=y - CONFIG_STRICT_DEVMEM=y -+CONFIG_CRYPTO_NULL=m - CONFIG_CRYPTO_SEQIV=m - CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_XTS=m - CONFIG_CRYPTO_HMAC=y - CONFIG_CRYPTO_XCBC=m - CONFIG_CRYPTO_MD5=y - CONFIG_CRYPTO_SHA1=y --CONFIG_CRYPTO_SHA256=m - CONFIG_CRYPTO_SHA512=m - CONFIG_CRYPTO_TGR192=m - CONFIG_CRYPTO_WP512=m -diff --git a/arch/arm/configs/bcmrpi_emergency_defconfig b/arch/arm/configs/bcmrpi_emergency_defconfig -index 3b40c49..ab1b8d9 100644 ---- a/arch/arm/configs/bcmrpi_emergency_defconfig -+++ b/arch/arm/configs/bcmrpi_emergency_defconfig -@@ -530,3 +530,4 @@ CONFIG_CRYPTO_DEFLATE=m - # CONFIG_CRYPTO_HW is not set - CONFIG_CRC_ITU_T=y - CONFIG_LIBCRC32C=y -+CONFIG_F2FS=y -diff --git a/arch/arm/configs/bcmrpi_quick_defconfig b/arch/arm/configs/bcmrpi_quick_defconfig -new file mode 100644 -index 0000000..10b84df ---- /dev/null -+++ b/arch/arm/configs/bcmrpi_quick_defconfig -@@ -0,0 +1,298 @@ -+# CONFIG_ARM_PATCH_PHYS_VIRT is not set -+CONFIG_EXPERIMENTAL=y -+CONFIG_LOCALVERSION="-quick" -+# CONFIG_LOCALVERSION_AUTO is not set -+CONFIG_SYSVIPC=y -+CONFIG_POSIX_MQUEUE=y -+CONFIG_BSD_PROCESS_ACCT=y -+CONFIG_BSD_PROCESS_ACCT_V3=y -+CONFIG_FHANDLE=y -+CONFIG_TASKSTATS=y -+CONFIG_TASK_DELAY_ACCT=y -+CONFIG_TASK_XACCT=y -+CONFIG_TASK_IO_ACCOUNTING=y -+CONFIG_AUDIT=y -+CONFIG_NO_HZ=y -+CONFIG_HIGH_RES_TIMERS=y -+CONFIG_IKCONFIG=y -+CONFIG_IKCONFIG_PROC=y -+CONFIG_CGROUP_FREEZER=y -+CONFIG_CGROUP_DEVICE=y -+CONFIG_CGROUP_CPUACCT=y -+CONFIG_RESOURCE_COUNTERS=y -+CONFIG_BLK_CGROUP=y -+CONFIG_NAMESPACES=y -+CONFIG_SCHED_AUTOGROUP=y -+CONFIG_RELAY=y -+CONFIG_EMBEDDED=y -+# CONFIG_COMPAT_BRK is not set -+CONFIG_SLAB=y -+CONFIG_PROFILING=y -+CONFIG_OPROFILE=m -+CONFIG_KPROBES=y -+CONFIG_MODULES=y -+CONFIG_MODULE_UNLOAD=y -+CONFIG_MODVERSIONS=y -+CONFIG_MODULE_SRCVERSION_ALL=y -+# CONFIG_BLK_DEV_BSG is not set -+CONFIG_BLK_DEV_THROTTLING=y -+CONFIG_PARTITION_ADVANCED=y -+CONFIG_MAC_PARTITION=y -+CONFIG_EFI_PARTITION=y -+CONFIG_CFQ_GROUP_IOSCHED=y -+CONFIG_ARCH_BCM2708=y -+# CONFIG_BCM2708_GPIO is not set -+# CONFIG_BCM2708_VCMEM is not set -+CONFIG_PREEMPT=y -+CONFIG_AEABI=y -+CONFIG_UACCESS_WITH_MEMCPY=y -+CONFIG_SECCOMP=y -+CONFIG_CC_STACKPROTECTOR=y -+CONFIG_ZBOOT_ROM_TEXT=0x0 -+CONFIG_ZBOOT_ROM_BSS=0x0 -+CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" -+CONFIG_KEXEC=y -+CONFIG_CPU_FREQ=y -+CONFIG_CPU_FREQ_STAT=m -+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y -+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -+CONFIG_CPU_FREQ_GOV_USERSPACE=y -+CONFIG_CPU_FREQ_GOV_ONDEMAND=y -+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -+# CONFIG_ARM_BCM2835_CPUFREQ is not set -+CONFIG_CPU_IDLE=y -+CONFIG_VFP=y -+CONFIG_BINFMT_MISC=m -+CONFIG_NET=y -+CONFIG_PACKET=y -+CONFIG_UNIX=y -+CONFIG_XFRM_USER=y -+CONFIG_NET_KEY=m -+CONFIG_INET=y -+CONFIG_IP_MULTICAST=y -+CONFIG_IP_ADVANCED_ROUTER=y -+CONFIG_IP_MULTIPLE_TABLES=y -+CONFIG_IP_ROUTE_MULTIPATH=y -+CONFIG_IP_ROUTE_VERBOSE=y -+CONFIG_IP_PNP=y -+CONFIG_IP_PNP_DHCP=y -+CONFIG_IP_PNP_RARP=y -+CONFIG_NET_IPIP=m -+CONFIG_SYN_COOKIES=y -+CONFIG_INET_AH=m -+CONFIG_INET_ESP=m -+CONFIG_INET_IPCOMP=m -+CONFIG_INET_XFRM_MODE_TRANSPORT=m -+CONFIG_INET_XFRM_MODE_TUNNEL=m -+CONFIG_INET_XFRM_MODE_BEET=m -+CONFIG_INET_LRO=m -+CONFIG_INET_DIAG=m -+# CONFIG_IPV6 is not set -+CONFIG_L2TP=m -+CONFIG_NET_PKTGEN=m -+# CONFIG_WIRELESS is not set -+CONFIG_WIMAX=m -+CONFIG_NET_9P=m -+CONFIG_NFC=m -+CONFIG_NFC_PN533=m -+CONFIG_DEVTMPFS=y -+CONFIG_DEVTMPFS_MOUNT=y -+CONFIG_BLK_DEV_LOOP=y -+CONFIG_BLK_DEV_CRYPTOLOOP=m -+CONFIG_BLK_DEV_NBD=m -+CONFIG_BLK_DEV_RAM=y -+CONFIG_CDROM_PKTCDVD=m -+CONFIG_EEPROM_93CX6=m -+# CONFIG_BCM2708_VCHIQ is not set -+CONFIG_SCSI=y -+# CONFIG_SCSI_PROC_FS is not set -+CONFIG_BLK_DEV_SD=y -+CONFIG_CHR_DEV_ST=m -+CONFIG_CHR_DEV_OSST=m -+CONFIG_BLK_DEV_SR=m -+CONFIG_SCSI_MULTI_LUN=y -+# CONFIG_SCSI_LOWLEVEL is not set -+CONFIG_NETDEVICES=y -+CONFIG_MII=y -+CONFIG_NETCONSOLE=m -+CONFIG_TUN=m -+CONFIG_PHYLIB=m -+CONFIG_MDIO_BITBANG=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+# CONFIG_WLAN is not set -+CONFIG_INPUT_FF_MEMLESS=m -+CONFIG_INPUT_POLLDEV=m -+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -+CONFIG_INPUT_EVDEV=m -+# CONFIG_INPUT_KEYBOARD is not set -+# CONFIG_INPUT_MOUSE is not set -+# CONFIG_SERIO is not set -+CONFIG_VT_HW_CONSOLE_BINDING=y -+# CONFIG_LEGACY_PTYS is not set -+# CONFIG_DEVKMEM is not set -+CONFIG_SERIAL_AMBA_PL011=y -+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y -+CONFIG_TTY_PRINTK=y -+# CONFIG_HW_RANDOM is not set -+CONFIG_RAW_DRIVER=y -+# CONFIG_HWMON is not set -+CONFIG_FB=y -+CONFIG_FB_BCM2708=y -+CONFIG_BACKLIGHT_LCD_SUPPORT=y -+CONFIG_FRAMEBUFFER_CONSOLE=y -+CONFIG_LOGO=y -+# CONFIG_LOGO_LINUX_MONO is not set -+# CONFIG_LOGO_LINUX_VGA16 is not set -+CONFIG_SOUND=y -+# CONFIG_USB_HID is not set -+CONFIG_USB=y -+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y -+CONFIG_USB_DWCOTG=y -+CONFIG_USB_ACM=m -+CONFIG_USB_MDC800=m -+CONFIG_USB_MICROTEK=m -+CONFIG_MMC=y -+CONFIG_MMC_SDHCI=y -+CONFIG_MMC_SDHCI_PLTFM=y -+CONFIG_MMC_SDHCI_BCM2708=y -+CONFIG_MMC_SDHCI_BCM2708_DMA=y -+CONFIG_NEW_LEDS=y -+CONFIG_LEDS_CLASS=m -+CONFIG_LEDS_TRIGGERS=y -+CONFIG_LEDS_TRIGGER_TIMER=m -+CONFIG_LEDS_TRIGGER_HEARTBEAT=m -+CONFIG_LEDS_TRIGGER_DEFAULT_ON=m -+CONFIG_UIO=m -+CONFIG_UIO_PDRV=m -+CONFIG_UIO_PDRV_GENIRQ=m -+# CONFIG_IOMMU_SUPPORT is not set -+CONFIG_EXT4_FS=y -+CONFIG_EXT4_FS_POSIX_ACL=y -+CONFIG_EXT4_FS_SECURITY=y -+CONFIG_REISERFS_FS=m -+CONFIG_REISERFS_FS_XATTR=y -+CONFIG_REISERFS_FS_POSIX_ACL=y -+CONFIG_REISERFS_FS_SECURITY=y -+CONFIG_JFS_FS=m -+CONFIG_JFS_POSIX_ACL=y -+CONFIG_JFS_SECURITY=y -+CONFIG_XFS_FS=m -+CONFIG_XFS_QUOTA=y -+CONFIG_XFS_POSIX_ACL=y -+CONFIG_XFS_RT=y -+CONFIG_GFS2_FS=m -+CONFIG_OCFS2_FS=m -+CONFIG_BTRFS_FS=m -+CONFIG_BTRFS_FS_POSIX_ACL=y -+CONFIG_NILFS2_FS=m -+CONFIG_AUTOFS4_FS=y -+CONFIG_FUSE_FS=m -+CONFIG_CUSE=m -+CONFIG_FSCACHE=y -+CONFIG_CACHEFILES=y -+CONFIG_ISO9660_FS=m -+CONFIG_JOLIET=y -+CONFIG_ZISOFS=y -+CONFIG_UDF_FS=m -+CONFIG_MSDOS_FS=y -+CONFIG_VFAT_FS=y -+CONFIG_FAT_DEFAULT_IOCHARSET="ascii" -+CONFIG_NTFS_FS=m -+CONFIG_TMPFS=y -+CONFIG_TMPFS_POSIX_ACL=y -+CONFIG_CONFIGFS_FS=y -+CONFIG_SQUASHFS=m -+CONFIG_SQUASHFS_XATTR=y -+CONFIG_SQUASHFS_LZO=y -+CONFIG_SQUASHFS_XZ=y -+CONFIG_NFS_FS=y -+CONFIG_NFS_V3_ACL=y -+CONFIG_NFS_V4=y -+CONFIG_ROOT_NFS=y -+CONFIG_NFS_FSCACHE=y -+CONFIG_NFSD=m -+CONFIG_NFSD_V3_ACL=y -+CONFIG_NFSD_V4=y -+CONFIG_CIFS=m -+CONFIG_CIFS_WEAK_PW_HASH=y -+CONFIG_CIFS_XATTR=y -+CONFIG_CIFS_POSIX=y -+CONFIG_9P_FS=m -+CONFIG_9P_FS_POSIX_ACL=y -+CONFIG_NLS_DEFAULT="utf8" -+CONFIG_NLS_CODEPAGE_437=y -+CONFIG_NLS_CODEPAGE_737=m -+CONFIG_NLS_CODEPAGE_775=m -+CONFIG_NLS_CODEPAGE_850=m -+CONFIG_NLS_CODEPAGE_852=m -+CONFIG_NLS_CODEPAGE_855=m -+CONFIG_NLS_CODEPAGE_857=m -+CONFIG_NLS_CODEPAGE_860=m -+CONFIG_NLS_CODEPAGE_861=m -+CONFIG_NLS_CODEPAGE_862=m -+CONFIG_NLS_CODEPAGE_863=m -+CONFIG_NLS_CODEPAGE_864=m -+CONFIG_NLS_CODEPAGE_865=m -+CONFIG_NLS_CODEPAGE_866=m -+CONFIG_NLS_CODEPAGE_869=m -+CONFIG_NLS_CODEPAGE_936=m -+CONFIG_NLS_CODEPAGE_950=m -+CONFIG_NLS_CODEPAGE_932=m -+CONFIG_NLS_CODEPAGE_949=m -+CONFIG_NLS_CODEPAGE_874=m -+CONFIG_NLS_ISO8859_8=m -+CONFIG_NLS_CODEPAGE_1250=m -+CONFIG_NLS_CODEPAGE_1251=m -+CONFIG_NLS_ASCII=y -+CONFIG_NLS_ISO8859_1=m -+CONFIG_NLS_ISO8859_2=m -+CONFIG_NLS_ISO8859_3=m -+CONFIG_NLS_ISO8859_4=m -+CONFIG_NLS_ISO8859_5=m -+CONFIG_NLS_ISO8859_6=m -+CONFIG_NLS_ISO8859_7=m -+CONFIG_NLS_ISO8859_9=m -+CONFIG_NLS_ISO8859_13=m -+CONFIG_NLS_ISO8859_14=m -+CONFIG_NLS_ISO8859_15=m -+CONFIG_NLS_KOI8_R=m -+CONFIG_NLS_KOI8_U=m -+CONFIG_PRINTK_TIME=y -+CONFIG_DEBUG_FS=y -+CONFIG_DETECT_HUNG_TASK=y -+CONFIG_TIMER_STATS=y -+# CONFIG_DEBUG_PREEMPT is not set -+CONFIG_DEBUG_MEMORY_INIT=y -+CONFIG_BOOT_PRINTK_DELAY=y -+CONFIG_LATENCYTOP=y -+# CONFIG_KPROBE_EVENT is not set -+CONFIG_KGDB=y -+CONFIG_KGDB_KDB=y -+CONFIG_KDB_KEYBOARD=y -+CONFIG_STRICT_DEVMEM=y -+CONFIG_DEBUG_LL=y -+CONFIG_DEBUG_BCM2708_UART0=y -+CONFIG_EARLY_PRINTK=y -+CONFIG_CRYPTO_SEQIV=m -+CONFIG_CRYPTO_CBC=y -+CONFIG_CRYPTO_XTS=m -+CONFIG_CRYPTO_HMAC=y -+CONFIG_CRYPTO_XCBC=m -+CONFIG_CRYPTO_MD5=y -+CONFIG_CRYPTO_MICHAEL_MIC=m -+CONFIG_CRYPTO_SHA1=y -+CONFIG_CRYPTO_SHA256=m -+CONFIG_CRYPTO_SHA512=m -+CONFIG_CRYPTO_TGR192=m -+CONFIG_CRYPTO_WP512=m -+CONFIG_CRYPTO_AES=m -+CONFIG_CRYPTO_CAST5=m -+CONFIG_CRYPTO_DES=y -+# CONFIG_CRYPTO_ANSI_CPRNG is not set -+# CONFIG_CRYPTO_HW is not set -+CONFIG_CRC_CCITT=m -+CONFIG_CRC_ITU_T=y -+CONFIG_CRC7=m -+CONFIG_LIBCRC32C=y -+CONFIG_AVERAGE=y --- -1.8.1.6 - - -From 137a908e0b40dcdbc630808b96fc3dca3ed91b50 Mon Sep 17 00:00:00 2001 +From f33f65ca756725be996e508fba215f7d5457341b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 16 Apr 2013 15:36:01 +0100 -Subject: [PATCH 088/102] Add v6wbi_flush_kern_tlb_range to allow zsmalloc to - be built as a module +Subject: [PATCH 73/88] Add v6wbi_flush_kern_tlb_range to allow zsmalloc to be + built as a module --- arch/arm/kernel/armksyms.c | 4 ++++ @@ -124041,10 +95940,10 @@ index 60d3b73..cba4d28 100644 1.8.1.6 -From 6b029ab6b6035e2d85658a5381546c1020354660 Mon Sep 17 00:00:00 2001 +From f79f0fd16fe7e180db35b21566fbb9adf9ff9978 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 22 Apr 2013 00:08:36 +0100 -Subject: [PATCH 089/102] dwc_otg: fix NAK holdoff and allow on split +Subject: [PATCH 74/88] dwc_otg: fix NAK holdoff and allow on split transactions only This corrects a bug where if a single active non-periodic endpoint @@ -124114,10 +96013,10 @@ index 91eefecd..eaa8f38 100644 1.8.1.6 -From fe1160bb7b53ca48e199d920ccfb262706ac1e14 Mon Sep 17 00:00:00 2001 +From 4de35edee9be469614d1632a198cfd800ae5b25e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 26 Apr 2013 10:08:31 -0700 -Subject: [PATCH 090/102] Merge pull request #286 from +Subject: [PATCH 75/88] Merge pull request #286 from martinezjavier/rpi-3.6.y-dev add mmap support and some cleanups to bcm2835 ALSA driver @@ -124598,153 +96497,84 @@ index b966e28..08c763d 100755 1.8.1.6 -From c5541458c100f0090a4ee388a7729684a2942144 Mon Sep 17 00:00:00 2001 +From 911b47b068b6e7e15f1abbc918b28b294856870b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 7 May 2013 22:20:24 +0100 -Subject: [PATCH 091/102] Add quick config. +Subject: [PATCH 76/88] Add quick config. This is designed for quick compiling when developing. No modules are needed and it includes all Pi specific drivers --- - arch/arm/configs/bcmrpi_quick_defconfig | 265 ++++++++++---------------------- - 1 file changed, 82 insertions(+), 183 deletions(-) + arch/arm/configs/bcmrpi_quick_defconfig | 197 ++++++++++++++++++++++++++++++++ + 1 file changed, 197 insertions(+) + create mode 100644 arch/arm/configs/bcmrpi_quick_defconfig diff --git a/arch/arm/configs/bcmrpi_quick_defconfig b/arch/arm/configs/bcmrpi_quick_defconfig -index 10b84df..e5efe75 100644 ---- a/arch/arm/configs/bcmrpi_quick_defconfig +new file mode 100644 +index 0000000..e5efe75 +--- /dev/null +++ b/arch/arm/configs/bcmrpi_quick_defconfig -@@ -1,130 +1,84 @@ - # CONFIG_ARM_PATCH_PHYS_VIRT is not set --CONFIG_EXPERIMENTAL=y - CONFIG_LOCALVERSION="-quick" - # CONFIG_LOCALVERSION_AUTO is not set +@@ -0,0 +1,197 @@ ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_LOCALVERSION="-quick" ++# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set - CONFIG_SYSVIPC=y - CONFIG_POSIX_MQUEUE=y --CONFIG_BSD_PROCESS_ACCT=y --CONFIG_BSD_PROCESS_ACCT_V3=y --CONFIG_FHANDLE=y --CONFIG_TASKSTATS=y --CONFIG_TASK_DELAY_ACCT=y --CONFIG_TASK_XACCT=y --CONFIG_TASK_IO_ACCOUNTING=y --CONFIG_AUDIT=y - CONFIG_NO_HZ=y - CONFIG_HIGH_RES_TIMERS=y - CONFIG_IKCONFIG=y - CONFIG_IKCONFIG_PROC=y --CONFIG_CGROUP_FREEZER=y --CONFIG_CGROUP_DEVICE=y --CONFIG_CGROUP_CPUACCT=y --CONFIG_RESOURCE_COUNTERS=y --CONFIG_BLK_CGROUP=y --CONFIG_NAMESPACES=y --CONFIG_SCHED_AUTOGROUP=y --CONFIG_RELAY=y ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y +CONFIG_KALLSYMS_ALL=y - CONFIG_EMBEDDED=y ++CONFIG_EMBEDDED=y +CONFIG_PERF_EVENTS=y - # CONFIG_COMPAT_BRK is not set - CONFIG_SLAB=y --CONFIG_PROFILING=y --CONFIG_OPROFILE=m --CONFIG_KPROBES=y - CONFIG_MODULES=y - CONFIG_MODULE_UNLOAD=y - CONFIG_MODVERSIONS=y - CONFIG_MODULE_SRCVERSION_ALL=y - # CONFIG_BLK_DEV_BSG is not set --CONFIG_BLK_DEV_THROTTLING=y --CONFIG_PARTITION_ADVANCED=y --CONFIG_MAC_PARTITION=y --CONFIG_EFI_PARTITION=y --CONFIG_CFQ_GROUP_IOSCHED=y - CONFIG_ARCH_BCM2708=y --# CONFIG_BCM2708_GPIO is not set --# CONFIG_BCM2708_VCMEM is not set - CONFIG_PREEMPT=y - CONFIG_AEABI=y - CONFIG_UACCESS_WITH_MEMCPY=y --CONFIG_SECCOMP=y --CONFIG_CC_STACKPROTECTOR=y - CONFIG_ZBOOT_ROM_TEXT=0x0 - CONFIG_ZBOOT_ROM_BSS=0x0 - CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" --CONFIG_KEXEC=y - CONFIG_CPU_FREQ=y --CONFIG_CPU_FREQ_STAT=m - CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y - CONFIG_CPU_FREQ_GOV_PERFORMANCE=y - CONFIG_CPU_FREQ_GOV_USERSPACE=y - CONFIG_CPU_FREQ_GOV_ONDEMAND=y - CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y --# CONFIG_ARM_BCM2835_CPUFREQ is not set - CONFIG_CPU_IDLE=y - CONFIG_VFP=y --CONFIG_BINFMT_MISC=m ++# CONFIG_COMPAT_BRK is not set ++CONFIG_SLAB=y ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODVERSIONS=y ++CONFIG_MODULE_SRCVERSION_ALL=y ++# CONFIG_BLK_DEV_BSG is not set ++CONFIG_ARCH_BCM2708=y ++CONFIG_PREEMPT=y ++CONFIG_AEABI=y ++CONFIG_UACCESS_WITH_MEMCPY=y ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait" ++CONFIG_CPU_FREQ=y ++CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE=y ++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y ++CONFIG_CPU_FREQ_GOV_USERSPACE=y ++CONFIG_CPU_FREQ_GOV_ONDEMAND=y ++CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y ++CONFIG_CPU_IDLE=y ++CONFIG_VFP=y +CONFIG_BINFMT_MISC=y - CONFIG_NET=y - CONFIG_PACKET=y - CONFIG_UNIX=y --CONFIG_XFRM_USER=y --CONFIG_NET_KEY=m - CONFIG_INET=y - CONFIG_IP_MULTICAST=y --CONFIG_IP_ADVANCED_ROUTER=y --CONFIG_IP_MULTIPLE_TABLES=y --CONFIG_IP_ROUTE_MULTIPATH=y --CONFIG_IP_ROUTE_VERBOSE=y - CONFIG_IP_PNP=y - CONFIG_IP_PNP_DHCP=y - CONFIG_IP_PNP_RARP=y --CONFIG_NET_IPIP=m - CONFIG_SYN_COOKIES=y --CONFIG_INET_AH=m --CONFIG_INET_ESP=m --CONFIG_INET_IPCOMP=m --CONFIG_INET_XFRM_MODE_TRANSPORT=m --CONFIG_INET_XFRM_MODE_TUNNEL=m --CONFIG_INET_XFRM_MODE_BEET=m --CONFIG_INET_LRO=m --CONFIG_INET_DIAG=m ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_RARP=y ++CONFIG_SYN_COOKIES=y +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set - # CONFIG_IPV6 is not set --CONFIG_L2TP=m --CONFIG_NET_PKTGEN=m - # CONFIG_WIRELESS is not set --CONFIG_WIMAX=m --CONFIG_NET_9P=m --CONFIG_NFC=m --CONFIG_NFC_PN533=m - CONFIG_DEVTMPFS=y - CONFIG_DEVTMPFS_MOUNT=y - CONFIG_BLK_DEV_LOOP=y --CONFIG_BLK_DEV_CRYPTOLOOP=m --CONFIG_BLK_DEV_NBD=m - CONFIG_BLK_DEV_RAM=y --CONFIG_CDROM_PKTCDVD=m --CONFIG_EEPROM_93CX6=m --# CONFIG_BCM2708_VCHIQ is not set - CONFIG_SCSI=y - # CONFIG_SCSI_PROC_FS is not set --CONFIG_BLK_DEV_SD=y --CONFIG_CHR_DEV_ST=m --CONFIG_CHR_DEV_OSST=m --CONFIG_BLK_DEV_SR=m --CONFIG_SCSI_MULTI_LUN=y - # CONFIG_SCSI_LOWLEVEL is not set - CONFIG_NETDEVICES=y --CONFIG_MII=y --CONFIG_NETCONSOLE=m --CONFIG_TUN=m --CONFIG_PHYLIB=m --CONFIG_MDIO_BITBANG=m --CONFIG_SLIP=m --CONFIG_SLIP_COMPRESSED=y ++# CONFIG_IPV6 is not set ++# CONFIG_WIRELESS is not set ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y ++CONFIG_BLK_DEV_LOOP=y ++CONFIG_BLK_DEV_RAM=y ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_FARADAY is not set @@ -124763,25 +96593,21 @@ index 10b84df..e5efe75 100644 +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set - # CONFIG_WLAN is not set --CONFIG_INPUT_FF_MEMLESS=m --CONFIG_INPUT_POLLDEV=m --# CONFIG_INPUT_MOUSEDEV_PSAUX is not set --CONFIG_INPUT_EVDEV=m ++# CONFIG_WLAN is not set +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_EVDEV=y - # CONFIG_INPUT_KEYBOARD is not set - # CONFIG_INPUT_MOUSE is not set - # CONFIG_SERIO is not set -@@ -134,165 +88,110 @@ CONFIG_VT_HW_CONSOLE_BINDING=y - CONFIG_SERIAL_AMBA_PL011=y - CONFIG_SERIAL_AMBA_PL011_CONSOLE=y - CONFIG_TTY_PRINTK=y --# CONFIG_HW_RANDOM is not set ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_SERIO is not set ++CONFIG_VT_HW_CONSOLE_BINDING=y ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_AMBA_PL011=y ++CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_TTY_PRINTK=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_BCM2708=y - CONFIG_RAW_DRIVER=y --# CONFIG_HWMON is not set ++CONFIG_RAW_DRIVER=y +CONFIG_THERMAL=y +CONFIG_THERMAL_BCM2835=y +CONFIG_WATCHDOG=y @@ -124791,118 +96617,48 @@ index 10b84df..e5efe75 100644 +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_VIRTUAL_CONSUMER=y +CONFIG_REGULATOR_USERSPACE_CONSUMER=y - CONFIG_FB=y - CONFIG_FB_BCM2708=y --CONFIG_BACKLIGHT_LCD_SUPPORT=y - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_LOGO=y - # CONFIG_LOGO_LINUX_MONO is not set - # CONFIG_LOGO_LINUX_VGA16 is not set - CONFIG_SOUND=y --# CONFIG_USB_HID is not set ++CONFIG_FB=y ++CONFIG_FB_BCM2708=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_BCM2835=y +# CONFIG_SND_USB is not set - CONFIG_USB=y - CONFIG_USB_ANNOUNCE_NEW_DEVICES=y - CONFIG_USB_DWCOTG=y --CONFIG_USB_ACM=m --CONFIG_USB_MDC800=m --CONFIG_USB_MICROTEK=m - CONFIG_MMC=y - CONFIG_MMC_SDHCI=y - CONFIG_MMC_SDHCI_PLTFM=y - CONFIG_MMC_SDHCI_BCM2708=y - CONFIG_MMC_SDHCI_BCM2708_DMA=y - CONFIG_NEW_LEDS=y --CONFIG_LEDS_CLASS=m ++CONFIG_USB=y ++CONFIG_USB_ANNOUNCE_NEW_DEVICES=y ++CONFIG_USB_DWCOTG=y ++CONFIG_MMC=y ++CONFIG_MMC_SDHCI=y ++CONFIG_MMC_SDHCI_PLTFM=y ++CONFIG_MMC_SDHCI_BCM2708=y ++CONFIG_MMC_SDHCI_BCM2708_DMA=y ++CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y - CONFIG_LEDS_TRIGGERS=y --CONFIG_LEDS_TRIGGER_TIMER=m --CONFIG_LEDS_TRIGGER_HEARTBEAT=m --CONFIG_LEDS_TRIGGER_DEFAULT_ON=m --CONFIG_UIO=m --CONFIG_UIO_PDRV=m --CONFIG_UIO_PDRV_GENIRQ=m - # CONFIG_IOMMU_SUPPORT is not set - CONFIG_EXT4_FS=y - CONFIG_EXT4_FS_POSIX_ACL=y - CONFIG_EXT4_FS_SECURITY=y --CONFIG_REISERFS_FS=m --CONFIG_REISERFS_FS_XATTR=y --CONFIG_REISERFS_FS_POSIX_ACL=y --CONFIG_REISERFS_FS_SECURITY=y --CONFIG_JFS_FS=m --CONFIG_JFS_POSIX_ACL=y --CONFIG_JFS_SECURITY=y --CONFIG_XFS_FS=m --CONFIG_XFS_QUOTA=y --CONFIG_XFS_POSIX_ACL=y --CONFIG_XFS_RT=y --CONFIG_GFS2_FS=m --CONFIG_OCFS2_FS=m --CONFIG_BTRFS_FS=m --CONFIG_BTRFS_FS_POSIX_ACL=y --CONFIG_NILFS2_FS=m - CONFIG_AUTOFS4_FS=y --CONFIG_FUSE_FS=m --CONFIG_CUSE=m - CONFIG_FSCACHE=y - CONFIG_CACHEFILES=y --CONFIG_ISO9660_FS=m --CONFIG_JOLIET=y --CONFIG_ZISOFS=y --CONFIG_UDF_FS=m - CONFIG_MSDOS_FS=y - CONFIG_VFAT_FS=y - CONFIG_FAT_DEFAULT_IOCHARSET="ascii" --CONFIG_NTFS_FS=m - CONFIG_TMPFS=y - CONFIG_TMPFS_POSIX_ACL=y - CONFIG_CONFIGFS_FS=y --CONFIG_SQUASHFS=m --CONFIG_SQUASHFS_XATTR=y --CONFIG_SQUASHFS_LZO=y --CONFIG_SQUASHFS_XZ=y ++CONFIG_LEDS_TRIGGERS=y ++# CONFIG_IOMMU_SUPPORT is not set ++CONFIG_EXT4_FS=y ++CONFIG_EXT4_FS_POSIX_ACL=y ++CONFIG_EXT4_FS_SECURITY=y ++CONFIG_AUTOFS4_FS=y ++CONFIG_FSCACHE=y ++CONFIG_CACHEFILES=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_IOCHARSET="ascii" ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++CONFIG_CONFIGFS_FS=y +# CONFIG_MISC_FILESYSTEMS is not set - CONFIG_NFS_FS=y - CONFIG_NFS_V3_ACL=y - CONFIG_NFS_V4=y - CONFIG_ROOT_NFS=y - CONFIG_NFS_FSCACHE=y --CONFIG_NFSD=m --CONFIG_NFSD_V3_ACL=y --CONFIG_NFSD_V4=y --CONFIG_CIFS=m --CONFIG_CIFS_WEAK_PW_HASH=y --CONFIG_CIFS_XATTR=y --CONFIG_CIFS_POSIX=y --CONFIG_9P_FS=m --CONFIG_9P_FS_POSIX_ACL=y - CONFIG_NLS_DEFAULT="utf8" - CONFIG_NLS_CODEPAGE_437=y --CONFIG_NLS_CODEPAGE_737=m --CONFIG_NLS_CODEPAGE_775=m --CONFIG_NLS_CODEPAGE_850=m --CONFIG_NLS_CODEPAGE_852=m --CONFIG_NLS_CODEPAGE_855=m --CONFIG_NLS_CODEPAGE_857=m --CONFIG_NLS_CODEPAGE_860=m --CONFIG_NLS_CODEPAGE_861=m --CONFIG_NLS_CODEPAGE_862=m --CONFIG_NLS_CODEPAGE_863=m --CONFIG_NLS_CODEPAGE_864=m --CONFIG_NLS_CODEPAGE_865=m --CONFIG_NLS_CODEPAGE_866=m --CONFIG_NLS_CODEPAGE_869=m --CONFIG_NLS_CODEPAGE_936=m --CONFIG_NLS_CODEPAGE_950=m --CONFIG_NLS_CODEPAGE_932=m --CONFIG_NLS_CODEPAGE_949=m --CONFIG_NLS_CODEPAGE_874=m --CONFIG_NLS_ISO8859_8=m --CONFIG_NLS_CODEPAGE_1250=m --CONFIG_NLS_CODEPAGE_1251=m ++CONFIG_NFS_FS=y ++CONFIG_NFS_V3_ACL=y ++CONFIG_NFS_V4=y ++CONFIG_ROOT_NFS=y ++CONFIG_NFS_FSCACHE=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y @@ -124925,20 +96681,7 @@ index 10b84df..e5efe75 100644 +CONFIG_NLS_ISO8859_8=y +CONFIG_NLS_CODEPAGE_1250=y +CONFIG_NLS_CODEPAGE_1251=y - CONFIG_NLS_ASCII=y --CONFIG_NLS_ISO8859_1=m --CONFIG_NLS_ISO8859_2=m --CONFIG_NLS_ISO8859_3=m --CONFIG_NLS_ISO8859_4=m --CONFIG_NLS_ISO8859_5=m --CONFIG_NLS_ISO8859_6=m --CONFIG_NLS_ISO8859_7=m --CONFIG_NLS_ISO8859_9=m --CONFIG_NLS_ISO8859_13=m --CONFIG_NLS_ISO8859_14=m --CONFIG_NLS_ISO8859_15=m --CONFIG_NLS_KOI8_R=m --CONFIG_NLS_KOI8_U=m ++CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y @@ -124951,55 +96694,32 @@ index 10b84df..e5efe75 100644 +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_UTF8=y - CONFIG_PRINTK_TIME=y - CONFIG_DEBUG_FS=y - CONFIG_DETECT_HUNG_TASK=y --CONFIG_TIMER_STATS=y - # CONFIG_DEBUG_PREEMPT is not set --CONFIG_DEBUG_MEMORY_INIT=y --CONFIG_BOOT_PRINTK_DELAY=y --CONFIG_LATENCYTOP=y --# CONFIG_KPROBE_EVENT is not set ++CONFIG_PRINTK_TIME=y ++CONFIG_DEBUG_FS=y ++CONFIG_DETECT_HUNG_TASK=y ++# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_FTRACE is not set - CONFIG_KGDB=y - CONFIG_KGDB_KDB=y --CONFIG_KDB_KEYBOARD=y --CONFIG_STRICT_DEVMEM=y --CONFIG_DEBUG_LL=y --CONFIG_DEBUG_BCM2708_UART0=y --CONFIG_EARLY_PRINTK=y --CONFIG_CRYPTO_SEQIV=m ++CONFIG_KGDB=y ++CONFIG_KGDB_KDB=y +# CONFIG_ARM_UNWIND is not set - CONFIG_CRYPTO_CBC=y --CONFIG_CRYPTO_XTS=m - CONFIG_CRYPTO_HMAC=y --CONFIG_CRYPTO_XCBC=m - CONFIG_CRYPTO_MD5=y --CONFIG_CRYPTO_MICHAEL_MIC=m - CONFIG_CRYPTO_SHA1=y --CONFIG_CRYPTO_SHA256=m --CONFIG_CRYPTO_SHA512=m --CONFIG_CRYPTO_TGR192=m --CONFIG_CRYPTO_WP512=m --CONFIG_CRYPTO_AES=m --CONFIG_CRYPTO_CAST5=m - CONFIG_CRYPTO_DES=y - # CONFIG_CRYPTO_ANSI_CPRNG is not set - # CONFIG_CRYPTO_HW is not set --CONFIG_CRC_CCITT=m - CONFIG_CRC_ITU_T=y --CONFIG_CRC7=m - CONFIG_LIBCRC32C=y --CONFIG_AVERAGE=y ++CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_HMAC=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_SHA1=y ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_HW is not set ++CONFIG_CRC_ITU_T=y ++CONFIG_LIBCRC32C=y -- 1.8.1.6 -From 8d029af692c6d824f77c97e040a1192b55745542 Mon Sep 17 00:00:00 2001 +From aacfe85df55f02c51b405a01f4391a2eb790fdff Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 10 May 2013 19:42:38 +0100 -Subject: [PATCH 092/102] mmc: suppress sdcard warnings we are happy about by +Subject: [PATCH 77/88] mmc: suppress sdcard warnings we are happy about by default --- @@ -125065,10 +96785,10 @@ index 3556ed3..c2409b9 100644 1.8.1.6 -From 7e99dfcf3a71453db52eb04a0efdcb978c5e1faa Mon Sep 17 00:00:00 2001 +From 84d80662cd68320b63ed25cfa4f611b96f2e6f82 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 14 May 2013 11:42:25 +0100 -Subject: [PATCH 093/102] Allow reboot=q on command line to set a flag that +Subject: [PATCH 78/88] Allow reboot=q on command line to set a flag that bootcode.bin can use to boot from alternate partition --- @@ -125099,10 +96819,10 @@ index 87fd348..1ed4d73 100644 1.8.1.6 -From 640b5a8e828d424955b350ae1561df8ec378cd7e Mon Sep 17 00:00:00 2001 +From d88ada9ddccea359ee02e044f86cd9e33aecc02f Mon Sep 17 00:00:00 2001 From: hutorny Date: Mon, 13 May 2013 10:26:14 +0300 -Subject: [PATCH 095/102] Update bcm2708.c to use CONFIG_BCM2708_SPIDEV rather +Subject: [PATCH 80/88] Update bcm2708.c to use CONFIG_BCM2708_SPIDEV rather than CONFIG_SPI --- @@ -125152,10 +96872,10 @@ index 1ed4d73..68c577a 100644 1.8.1.6 -From 7e5b9f6d6977853567deeb275d9987475b91d231 Mon Sep 17 00:00:00 2001 +From 8b2532eaea9f27d74973aa563c209e95a6436377 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 8 Jun 2013 22:14:13 +0100 -Subject: [PATCH 097/102] Only init gpio pins of selected i2c bus +Subject: [PATCH 82/88] Only init gpio pins of selected i2c bus --- drivers/i2c/busses/i2c-bcm2708.c | 8 +++++--- @@ -125199,10 +96919,10 @@ index 3391889..edc90c0 100644 1.8.1.6 -From 0db53cd1f9963d363514a7ee2a953804c8aba920 Mon Sep 17 00:00:00 2001 +From b87736ed6ed5d4d5cc534f679ab8b832e693d452 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 13 Jun 2013 16:46:54 +0100 -Subject: [PATCH 098/102] Avoid responding to unexpected I2C interrupts +Subject: [PATCH 83/88] Avoid responding to unexpected I2C interrupts --- drivers/i2c/busses/i2c-bcm2708.c | 6 ++++++ @@ -125236,10 +96956,10 @@ index edc90c0..33f4e7d 100644 1.8.1.6 -From 28b9be88b84415a562665bfc2309cc261a161518 Mon Sep 17 00:00:00 2001 +From c9e3680fe3d1b66ec5e8947b52cf582001d39690 Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 099/102] Speed up console framebuffer imageblit function +Subject: [PATCH 84/88] Speed up console framebuffer imageblit function Especially on platforms with a slower CPU but a relatively high framebuffer fill bandwidth, like current ARM devices, the existing @@ -125451,10 +97171,10 @@ index baed57d..ce91bf2 100644 1.8.1.6 -From c097503eedbb5e19038bb712e969e12336159dfe Mon Sep 17 00:00:00 2001 +From 37fa288e60b2f5cdfde5a392504bf1097699c0d8 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 100/102] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 85/88] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -125469,7 +97189,7 @@ Signed-off-by: Siarhei Siamashka 2 files changed, 35 insertions(+) diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c -index 86291dc..b488ff9 100644 +index 098bfc6..da8e53b 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1074,6 +1074,25 @@ static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, @@ -125550,10 +97270,10 @@ index fb795c3..fa72af0 100644 1.8.1.6 -From 538323c20a09c68e6b62d300f2355b34d8e47915 Mon Sep 17 00:00:00 2001 +From 511c5dd60c2023b810e0f419fd37b2bc3f078cdc Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 16:00:25 +0300 -Subject: [PATCH 101/102] bcm2708_fb: DMA acceleration for fb_copyarea +Subject: [PATCH 86/88] bcm2708_fb: DMA acceleration for fb_copyarea Based on http://www.raspberrypi.org/phpBB3/viewtopic.php?p=62425#p62425 Also used Simon's dmaer_master module as a reference for tweaking DMA @@ -125797,11 +97517,11 @@ index 08d9238..c10c5ee 100644 1.8.1.6 -From 5eb73fa33a2d58ecc7857e07ddfa573287b0f59b Mon Sep 17 00:00:00 2001 +From 44aa1f6534dbd06e3529d8496a1dd494be5f9b98 Mon Sep 17 00:00:00 2001 From: Mike Bradley Date: Mon, 17 Jun 2013 11:31:42 -0700 -Subject: [PATCH 102/102] dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock - held in completion handler +Subject: [PATCH 87/88] dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held + in completion handler usb_hcd_unlink_urb_from_ep must be called with the HCD lock held. Calling it asynchronously in the tasklet was not safe (regression in @@ -125886,3 +97606,1425 @@ index 7bb133a..fef557d 100644 -- 1.8.1.6 + +From 1fdd347791b4e01e811427ab5974b3659b805982 Mon Sep 17 00:00:00 2001 +From: Gordon Hollingworth +Date: Thu, 4 Apr 2013 11:05:21 +0100 +Subject: [PATCH 88/88] USB fix using a FIQ to implement split transactions + +This commit adds a FIQ implementaion that schedules +the split transactions using a FIQ so we don't get +held off by the interrupt latency of Linux +--- + .../usb/host/dwc_common_port/dwc_common_linux.c | 7 +- + drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 37 +- + drivers/usb/host/dwc_otg/dwc_otg_driver.c | 6 +- + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 125 ++++- + drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 20 +- + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 538 ++++++++++++++++++--- + drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 18 +- + drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 31 +- + drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h | 26 +- + drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 2 +- + 10 files changed, 696 insertions(+), 114 deletions(-) + +diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c +index 6814e51..0812d3a 100644 +--- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c ++++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c +@@ -580,7 +580,12 @@ void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value) + + void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) + { ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ local_fiq_disable(); + writel((readl(reg) & ~clear_mask) | set_mask, reg); ++ local_irq_restore(flags); + } + + #if 0 +@@ -1301,7 +1306,7 @@ int DWC_WORKQ_PENDING(dwc_workq_t *wq) + EXPORT_SYMBOL(__DWC_DEBUG); + #endif + +-EXPORT_SYMBOL(__DWC_DMA_ALLOC); ++EXPORT_SYMBOL(__DWC_DMA_ALLOC); + EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); + EXPORT_SYMBOL(__DWC_DMA_FREE); + EXPORT_SYMBOL(__DWC_ALLOC); +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +index b861b55..b5a007d 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +@@ -47,8 +47,6 @@ + #include "dwc_otg_hcd.h" + #include "dwc_otg_mphi_fix.h" + +-extern bool fiq_fix_enable; +- + #ifdef DEBUG + inline const char *op_state_str(dwc_otg_core_if_t * core_if) + { +@@ -1321,7 +1319,7 @@ static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) + /** + * This function returns the Core Interrupt register. + */ +-static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) ++static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk) + { + gahbcfg_data_t gahbcfg = {.d32 = 0 }; + gintsts_data_t gintsts; +@@ -1338,19 +1336,33 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) + gintmsk_common.b.lpmtranrcvd = 1; + #endif + gintmsk_common.b.restoredone = 1; +- /** @todo: The port interrupt occurs while in device +- * mode. Added code to CIL to clear the interrupt for now! +- */ +- gintmsk_common.b.portintr = 1; +- ++ if(dwc_otg_is_device_mode(core_if)) ++ { ++ /** @todo: The port interrupt occurs while in device ++ * mode. Added code to CIL to clear the interrupt for now! ++ */ ++ gintmsk_common.b.portintr = 1; ++ } + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); + gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ { ++ unsigned long flags; ++ ++ // Re-enable the saved interrupts ++ local_irq_save(flags); ++ local_fiq_disable(); ++ gintmsk.d32 |= gintmsk_common.d32; ++ gintsts_saved.d32 &= ~gintmsk_common.d32; ++ reenable_gintmsk->d32 = gintmsk.d32; ++ local_irq_restore(flags); ++ } ++ + gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); + + #ifdef DEBUG + /* if any common interrupts set */ + if (gintsts.d32 & gintmsk_common.d32) { +- DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", ++ DWC_DEBUGPL(DBG_ANY, "common_intr: gintsts=%08x gintmsk=%08x\n", + gintsts.d32, gintmsk.d32); + } + #endif +@@ -1394,6 +1406,7 @@ int32_t dwc_otg_handle_common_intr(void *dev) + { + int retval = 0; + gintsts_data_t gintsts; ++ gintmsk_data_t reenable_gintmsk; + gpwrdn_data_t gpwrdn = {.d32 = 0 }; + dwc_otg_device_t *otg_dev = dev; + dwc_otg_core_if_t *core_if = otg_dev->core_if; +@@ -1415,7 +1428,7 @@ int32_t dwc_otg_handle_common_intr(void *dev) + } + + if (core_if->hibernation_suspend <= 0) { +- gintsts.d32 = dwc_otg_read_common_intr(core_if); ++ gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk); + + if (gintsts.b.modemismatch) { + retval |= dwc_otg_handle_mode_mismatch_intr(core_if); +@@ -1512,8 +1525,12 @@ int32_t dwc_otg_handle_common_intr(void *dev) + gintsts.b.portintr = 1; + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); + retval |= 1; ++ reenable_gintmsk.b.portintr = 1; + + } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32); ++ + } else { + DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); + +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c +index cea8fcb..6c89a69 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c +@@ -242,7 +242,8 @@ struct dwc_otg_driver_module_params { + + //Global variable to switch the fiq fix on or off (declared in bcm2708.c) + extern bool fiq_fix_enable; +- ++// Global variable to enable the split transaction fix ++bool fiq_split_enable = true; + //Global variable to switch the nak holdoff on or off + bool nak_holdoff_enable = true; + +@@ -1090,6 +1091,7 @@ static int __init dwc_otg_driver_init(void) + } + printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled"); + printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled"); ++ printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled"); + + error = driver_create_file(drv, &driver_attr_version); + #ifdef DEBUG +@@ -1374,6 +1376,8 @@ static void __exit dwc_otg_driver_cleanup(void) + MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix"); + module_param(nak_holdoff_enable, bool, 0444); + MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff"); ++module_param(fiq_split_enable, bool, 0444); ++MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions"); + + /** @page "Module Parameters" + * +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +index 9c2e71a..af9108c 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -45,6 +45,7 @@ + + #include "dwc_otg_hcd.h" + #include "dwc_otg_regs.h" ++#include "dwc_otg_mphi_fix.h" + + extern bool microframe_schedule, nak_holdoff_enable; + +@@ -581,6 +582,8 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, + */ + dwc_otg_hc_halt(hcd->core_if, qh->channel, + DWC_OTG_HC_XFER_URB_DEQUEUE); ++ ++ dwc_otg_hcd_release_port(hcd, qh); + } + } + +@@ -716,6 +719,8 @@ static void completion_tasklet_func(void *ptr) + + usb_hcd_giveback_urb(hcd->priv, urb, urb->status); + ++ fiq_print(FIQDBG_PORTHUB, "COMPLETE"); ++ + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); + } + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); +@@ -979,6 +984,10 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) + hcd->frame_list = NULL; + hcd->frame_list_dma = 0; + hcd->periodic_qh_count = 0; ++ ++ DWC_MEMSET(hcd->hub_port, 0, sizeof(hcd->hub_port)); ++ DWC_MEMSET(hcd->hub_port_alloc, -1, sizeof(hcd->hub_port_alloc)); ++ + out: + return retval; + } +@@ -1124,7 +1133,12 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) + uint32_t hub_addr, port_addr; + hc->do_split = 1; + hc->xact_pos = qtd->isoc_split_pos; +- hc->complete_split = qtd->complete_split; ++ /* We don't need to do complete splits anymore */ ++ if(fiq_split_enable) ++ hc->complete_split = qtd->complete_split = 0; ++ else ++ hc->complete_split = qtd->complete_split; ++ + hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr); + hc->hub_addr = (uint8_t) hub_addr; + hc->port_addr = (uint8_t) port_addr; +@@ -1271,6 +1285,62 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) + hc->qh = qh; + } + ++/* ++** Check the transaction to see if the port / hub has already been assigned for ++** a split transaction ++** ++** Return 0 - Port is already in use ++*/ ++int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) ++{ ++ uint32_t hub_addr, port_addr; ++ ++ if(!fiq_split_enable) ++ return 0; ++ ++ hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr); ++ ++ if(hcd->hub_port[hub_addr] & (1 << port_addr)) ++ { ++ fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count); ++ ++ qh->skip_count++; ++ ++ if(qh->skip_count > 40000) ++ { ++ printk_once(KERN_ERR "Error: Having to skip port allocation"); ++ local_fiq_disable(); ++ BUG(); ++ return 0; ++ } ++ return 1; ++ } ++ else ++ { ++ qh->skip_count = 0; ++ hcd->hub_port[hub_addr] |= 1 << port_addr; ++ fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num); ++ hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd); ++ return 0; ++ } ++} ++void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) ++{ ++ uint32_t hub_addr, port_addr; ++ ++ if(!fiq_split_enable) ++ return; ++ ++ hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr); ++ ++ hcd->hub_port[hub_addr] &= ~(1 << port_addr); ++ hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1; ++ ++ fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num); ++ ++} ++ ++ + /** + * This function selects transactions from the HCD transfer schedule and + * assigns them to available host channels. It is called from HCD interrupt +@@ -1304,11 +1374,22 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) + + while (qh_ptr != &hcd->periodic_sched_ready && + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ ++ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); ++ ++ if(qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh)) ++ { ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1); ++ continue; ++ } ++ + if (microframe_schedule) { + // Make sure we leave one channel for non periodic transactions. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + if (hcd->available_host_channels <= 1) { + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh); + break; + } + hcd->available_host_channels--; +@@ -1329,8 +1410,6 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, + &qh->qh_list_entry); + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); +- +- ret_val = DWC_OTG_TRANSACTION_PERIODIC; + } + + /* +@@ -1369,10 +1448,19 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) + qh->nak_frame = 0xffff; + } + } ++ ++ if (qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh)) ++ { ++ g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1); ++ qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ continue; ++ } ++ + if (microframe_schedule) { + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + if (hcd->available_host_channels < 1) { + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh); + break; + } + hcd->available_host_channels--; +@@ -1396,16 +1484,17 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) + + g_np_sent++; + +- if (ret_val == DWC_OTG_TRANSACTION_NONE) { +- ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; +- } else { +- ret_val = DWC_OTG_TRANSACTION_ALL; +- } +- + if (!microframe_schedule) + hcd->non_periodic_channels++; + } + ++ if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) ++ ret_val |= DWC_OTG_TRANSACTION_PERIODIC; ++ ++ if(!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) ++ ret_val |= DWC_OTG_TRANSACTION_NON_PERIODIC; ++ ++ + #ifdef DEBUG_HOST_CHANNELS + last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels; + #endif /* DEBUG_HOST_CHANNELS */ +@@ -1522,6 +1611,15 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd) + + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); + ++ // Do not send a split start transaction any later than frame .6 ++ // Note, we have to schedule a periodic in .5 to make it go in .6 ++ if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6) ++ { ++ qh_ptr = qh_ptr->next; ++ g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7; ++ continue; ++ } ++ + /* + * Set a flag if we're queuing high-bandwidth in slave mode. + * The flag prevents any halts to get into the request queue in +@@ -1651,6 +1749,15 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) + + qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t, + qh_list_entry); ++ ++ // Do not send a split start transaction any later than frame .5 ++ // non periodic transactions will start immediately in this uframe ++ if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6) ++ { ++ g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7; ++ break; ++ } ++ + status = + queue_transaction(hcd, qh->channel, + tx_status.b.nptxfspcavail); +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +index 0493dbf..d3d6e997 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +@@ -168,10 +168,10 @@ static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, + + /** Transaction types. */ + typedef enum dwc_otg_transaction_type { +- DWC_OTG_TRANSACTION_NONE, +- DWC_OTG_TRANSACTION_PERIODIC, +- DWC_OTG_TRANSACTION_NON_PERIODIC, +- DWC_OTG_TRANSACTION_ALL ++ DWC_OTG_TRANSACTION_NONE = 0, ++ DWC_OTG_TRANSACTION_PERIODIC = 1, ++ DWC_OTG_TRANSACTION_NON_PERIODIC = 2, ++ DWC_OTG_TRANSACTION_ALL = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC + } dwc_otg_transaction_type_e; + + struct dwc_otg_qh; +@@ -370,6 +370,8 @@ static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, + + uint16_t speed; + uint16_t frame_usecs[8]; ++ ++ uint32_t skip_count; + } dwc_otg_qh_t; + + DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); +@@ -574,6 +576,10 @@ struct dwc_otg_hcd { + /** Frame List */ + uint32_t *frame_list; + ++ /** Hub - Port assignment */ ++ int hub_port[16]; ++ int hub_port_alloc[256]; ++ + /** Frame List DMA address */ + dma_addr_t frame_list_dma; + +@@ -604,12 +610,16 @@ extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t + extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, + dwc_otg_transaction_type_e tr_type); + ++int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh); ++void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh); ++ ++ + /** @} */ + + /** @name Interrupt Handler Functions */ + /** @{ */ + extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); +-extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd, int32_t); ++extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd); + extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * + dwc_otg_hcd); + extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +index 16e8c6c..e8b4d35 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -38,6 +38,7 @@ + + #include + #include ++#include + + + extern bool microframe_schedule; +@@ -52,21 +53,295 @@ + + void * dummy_send; + mphi_regs_t c_mphi_regs; ++volatile void *dwc_regs_base; + int fiq_done, int_done; +-int g_next_sched_frame, g_np_count, g_np_sent, g_work_expected; +-static int mphi_int_count = 0 ; + +-extern bool fiq_fix_enable, nak_holdoff_enable; ++gintsts_data_t gintsts_saved = {.d32 = 0}; ++hcint_data_t hcint_saved[MAX_EPS_CHANNELS]; ++hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS]; ++int split_out_xfersize[MAX_EPS_CHANNELS]; ++haint_data_t haint_saved; ++ ++int g_next_sched_frame, g_np_count, g_np_sent; ++static int mphi_int_count = 0 ; + + hcchar_data_t nak_hcchar; + hctsiz_data_t nak_hctsiz; + hcsplt_data_t nak_hcsplt; + int nak_count; + ++int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; ++int split_start_frame[MAX_EPS_CHANNELS]; ++int queued_port[MAX_EPS_CHANNELS]; ++ ++#ifdef FIQ_DEBUG ++char buffer[1000*16]; ++int wptr; ++void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...) ++{ ++ FIQDBG_T dbg_lvl_req = FIQDBG_PORTHUB; ++ va_list args; ++ char text[17]; ++ hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) }; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ local_fiq_disable(); ++ if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR) ++ { ++ snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937); ++ va_start(args, fmt); ++ vsnprintf(text+8, 9, fmt, args); ++ va_end(args); ++ ++ memcpy(buffer + wptr, text, 16); ++ wptr = (wptr + 16) % sizeof(buffer); ++ } ++ local_irq_restore(flags); ++} ++#endif ++ ++void fiq_queue_request(int channel, int odd_frame) ++{ ++ hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) }; ++ hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) }; ++ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) }; ++ ++ if(hcsplt.b.spltena == 0) ++ { ++ fiq_print(FIQDBG_ERR, "SPLTENA "); ++ BUG(); ++ } ++ ++ if(hcchar.b.epdir == 1) ++ { ++ fiq_print(FIQDBG_SCHED, "IN Ch %d", channel); ++ } ++ else ++ { ++ hctsiz.b.xfersize = 0; ++ fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel); ++ } ++ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32); ++ ++ hcsplt.b.compsplt = 1; ++ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32); ++ ++ // Send the Split complete ++ hcchar.b.chen = 1; ++ hcchar.b.oddfrm = odd_frame ? 1 : 0; ++ ++ // Post this for transmit on the next frame for periodic or this frame for non-periodic ++ fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN"); ++ ++ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32); ++} ++ ++static int last_sof = -1; ++ ++/* ++** Function to handle the start of frame interrupt, choose whether we need to do anything and ++** therefore trigger the main interrupt ++** ++** returns int != 0 - interrupt has been handled ++*/ ++int diff; ++ ++int fiq_sof_handle(hfnum_data_t hfnum) ++{ ++ int handled = 0; ++ int i; ++ ++ // Just check that once we're running we don't miss a SOF ++ /*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff))) ++ { ++ fiq_print(FIQDBG_ERR, "LASTSOF "); ++ fiq_print(FIQDBG_ERR, "%4d%d ", last_sof / 8, last_sof & 7); ++ fiq_print(FIQDBG_ERR, "%4d%d ", hfnum.b.frnum / 8, hfnum.b.frnum & 7); ++ BUG(); ++ }*/ ++ ++ // Only start remembering the last sof when the interrupt has been ++ // enabled (we don't check the mask to come in here...) ++ if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3)) ++ last_sof = hfnum.b.frnum; ++ ++ for(i = 0; i < MAX_EPS_CHANNELS; i++) ++ { ++ if(complete_sched[i] != -1) ++ { ++ if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0)) ++ { ++ fiq_queue_request(i, hfnum.b.frnum & 1); ++ complete_sched[i] = -1; ++ } ++ } ++ ++ if(complete_sched[i] != -1) ++ { ++ // This is because we've seen a split complete occur with no start... ++ // most likely because missed the complete 0x3fff frames ago! ++ ++ diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ; ++ if(diff > 32 && diff < 0x3f00) ++ { ++ fiq_print(FIQDBG_ERR, "SPLTMISS"); ++ BUG(); ++ } ++ } ++ } ++ ++ if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) ++ { ++ /* ++ * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet ++ * g_next_sched_frame is the next frame we have periodic packets for ++ * ++ * if neither of these are required for this frame then just clear the interrupt ++ */ ++ handled = 1; ++ ++ } ++ ++ return handled; ++} ++ ++int port_id(hcsplt_data_t hcsplt) ++{ ++ return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8); ++} ++ ++int fiq_hcintr_handle(int channel, hfnum_data_t hfnum) ++{ ++ hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) }; ++ hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) }; ++ hcint_data_t hcint = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) }; ++ hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) }; ++ hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)}; ++ ++ hcint_saved[channel].d32 |= hcint.d32; ++ hcintmsk_saved[channel].d32 = hcintmsk.d32; ++ ++ if(hcsplt.b.spltena) ++ { ++ fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt)); ++ if(hcint.b.chhltd) ++ { ++ fiq_print(FIQDBG_SCHED, "CH HLT %d", channel); ++ fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]); ++ } ++ if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr) ++ { ++ queued_port[channel] = 0; ++ fiq_print(FIQDBG_ERR, "CHAN ERR"); ++ } ++ if(hcint.b.xfercomp) ++ { ++ // Clear the port allocation and transmit anything also on this port ++ queued_port[channel] = 0; ++ fiq_print(FIQDBG_SCHED, "XFERCOMP"); ++ } ++ if(hcint.b.nak) ++ { ++ queued_port[channel] = 0; ++ fiq_print(FIQDBG_SCHED, "NAK"); ++ } ++ if(hcint.b.ack && !hcsplt.b.compsplt) ++ { ++ int i; ++ ++ // Do not complete isochronous out transactions ++ if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0) ++ { ++ queued_port[channel] = 0; ++ fiq_print(FIQDBG_SCHED, "ISOC_OUT"); ++ } ++ else ++ { ++ // Make sure we check the port / hub combination that we sent this split on. ++ // Do not queue a second request to the same port ++ for(i = 0; i < MAX_EPS_CHANNELS; i++) ++ { ++ if(port_id(hcsplt) == queued_port[i]) ++ { ++ fiq_print(FIQDBG_ERR, "PORTERR "); ++ //BUG(); ++ } ++ } ++ ++ split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7; ++ ++ // Note, the size of an OUT is in the start split phase, not ++ // the complete split ++ split_out_xfersize[channel] = hctsiz.b.xfersize; ++ ++ hcint_saved[channel].b.chhltd = 0; ++ hcint_saved[channel].b.ack = 0; ++ ++ queued_port[channel] = port_id(hcsplt); ++ ++ if(hcchar.b.eptype & 1) ++ { ++ // Send the periodic complete in the same oddness frame as the ACK went... ++ fiq_queue_request(channel, !(hfnum.b.frnum & 1)); ++ // complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1); ++ } ++ else ++ { ++ // Schedule the split complete to occur later ++ complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2); ++ fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8); ++ } ++ } ++ } ++ if(hcint.b.nyet) ++ { ++ fiq_print(FIQDBG_ERR, "NYETERR1"); ++ //BUG(); ++ // Can transmit a split complete up to uframe .0 of the next frame ++ if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8)) ++ { ++ // Send it next frame ++ if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc ++ { ++ fiq_print(FIQDBG_SCHED, "NYT:SEND"); ++ fiq_queue_request(channel, !(hfnum.b.frnum & 1)); ++ } ++ else ++ { ++ // Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP) ++ complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1); ++ fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8); ++ } ++ hcint_saved[channel].b.chhltd = 0; ++ hcint_saved[channel].b.nyet = 0; ++ } ++ else ++ { ++ queued_port[channel] = 0; ++ fiq_print(FIQDBG_ERR, "NYETERR2"); ++ //BUG(); ++ } ++ } ++ } ++ ++ // Clear the interrupt, this will also clear the HAINT bit ++ FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32); ++ return hcint_saved[channel].d32 == 0; ++} ++ ++gintsts_data_t gintsts; ++gintmsk_data_t gintmsk; ++// triggered: The set of interrupts that were triggered ++// handled: The set of interrupts that have been handled (no IRQ is ++// required) ++// keep: The set of interrupts we want to keep unmasked even though we ++// want to trigger an IRQ to handle it (SOF and HCINTR) ++gintsts_data_t triggered, handled, keep; ++hfnum_data_t hfnum; ++ + void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void) + { +- gintsts_data_t gintsts; +- hfnum_data_t hfnum; + + /* entry takes care to store registers we will be treading on here */ + asm __volatile__ ( +@@ -74,43 +349,112 @@ void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void) + /* stash FIQ and normal regs */ + "stmdb sp!, {r0-r12, lr};" + /* !! THIS SETS THE FRAME, adjust to > sizeof locals */ +- "sub fp, ip, #256 ;" ++ "sub fp, ip, #512 ;" + ); + +- fiq_done++; +- gintsts.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x14) & FIQ_READ_IO_ADDRESS(USB_BASE + 0x18); +- hfnum.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x408); +- +- if(gintsts.d32) ++ // Cannot put local variables at the beginning of the function ++ // because otherwise 'C' will play with the stack pointer. any locals ++ // need to be inside the following block ++ do + { +- if(gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) ++ fiq_done++; ++ gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14); ++ gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18); ++ hfnum.d32 = FIQ_READ(dwc_regs_base + 0x408); ++ triggered.d32 = gintsts.d32 & gintmsk.d32; ++ handled.d32 = 0; ++ keep.d32 = 0; ++ fiq_print(FIQDBG_INT, "FIQ "); ++ fiq_print(FIQDBG_INT, "%08x", gintsts.d32); ++ fiq_print(FIQDBG_INT, "%08x", gintmsk.d32); ++ if(gintsts.d32) + { +- /* +- * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet +- * g_next_sched_frame is the next frame we have periodic packets for +- * +- * if neither of these are required for this frame then just clear the interrupt +- */ +- gintsts.d32 = 0; +- gintsts.b.sofintr = 1; +- FIQ_WRITE_IO_ADDRESS((USB_BASE + 0x14), gintsts.d32); ++ // If port enabled ++ if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5) ++ { ++ if(gintsts.b.sofintr) ++ { ++ if(fiq_sof_handle(hfnum)) ++ { ++ handled.b.sofintr = 1; /* Handled in FIQ */ ++ } ++ else ++ { ++ /* Keer interrupt unmasked */ ++ keep.b.sofintr = 1; ++ } ++ { ++ // Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing ++ // a start of frame interrupt ++ gintsts_data_t gintsts = { .b.sofintr = 1 }; ++ FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32); ++ } ++ } ++ ++ if(fiq_split_enable && gintsts.b.hcintr) ++ { ++ int i; ++ haint_data_t haint; ++ haintmsk_data_t haintmsk; ++ ++ haint.d32 = FIQ_READ(dwc_regs_base + 0x414); ++ haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418); ++ haint.d32 &= haintmsk.d32; ++ haint_saved.d32 |= haint.d32; ++ ++ fiq_print(FIQDBG_INT, "hcintr"); ++ fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414)); ++ ++ // Go through each channel that has an enabled interrupt ++ for(i = 0; i < 16; i++) ++ if((haint.d32 >> i) & 1) ++ if(fiq_hcintr_handle(i, hfnum)) ++ haint_saved.d32 &= ~(1 << i); /* this was handled */ ++ ++ /* If we've handled all host channel interrupts then don't trigger the interrupt */ ++ if(haint_saved.d32 == 0) ++ { ++ handled.b.hcintr = 1; ++ } ++ else ++ { ++ /* Make sure we keep the channel interrupt unmasked when triggering the IRQ */ ++ keep.b.hcintr = 1; ++ } + +- g_work_expected = 0; ++ { ++ gintsts_data_t gintsts = { .b.hcintr = 1 }; ++ ++ // Always clear the channel interrupt ++ FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32); ++ } ++ } ++ } ++ else ++ { ++ last_sof = -1; ++ } + } +- else ++ ++ // Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep ++ gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32)); ++ // Save those that were triggered but not handled ++ gintsts_saved.d32 |= triggered.d32 & ~handled.d32; ++ FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32); ++ ++ // Clear and save any unhandled interrupts and trigger the interrupt ++ if(gintsts_saved.d32) + { +- g_work_expected = 1; + /* To enable the MPHI interrupt (INT 32) + */ +- FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send); ++ FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send); + FIQ_WRITE( c_mphi_regs.outddb, (1 << 29)); + + mphi_int_count++; +- /* Clear the USB global interrupt so we don't just sit in the FIQ */ +- FIQ_MODIFY_IO_ADDRESS((USB_BASE + 0x8),1,0); +- + } + } ++ while(0); ++ + mb(); + + /* exit back to normal mode restoring everything */ +@@ -133,6 +477,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; + gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk; + hfnum_data_t hfnum; + + #ifdef DEBUG +@@ -140,6 +485,9 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + + #endif + ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ + /* Exit from ISR if core is hibernated */ + if (core_if->hibernation_suspend == 1) { + goto exit_handler_routine; +@@ -147,11 +495,18 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + DWC_SPINLOCK(dwc_otg_hcd->lock); + /* Check if HOST Mode */ + if (dwc_otg_is_host_mode(core_if)) { +- gintsts.d32 = dwc_otg_read_core_intr(core_if); ++ local_fiq_disable(); ++ gintmsk.d32 |= gintsts_saved.d32; ++ gintsts.d32 |= gintsts_saved.d32; ++ gintsts_saved.d32 = 0; ++ local_fiq_enable(); + if (!gintsts.d32) { + goto exit_handler_routine; + } ++ gintsts.d32 &= gintmsk.d32; ++ + #ifdef DEBUG ++ // We should be OK doing this because the common interrupts should already have been serviced + /* Don't print debug message in the interrupt handler on SOF */ + #ifndef DEBUG_SOF + if (gintsts.d32 != DWC_SOF_INTR_MASK) +@@ -171,11 +526,12 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) + { + /* Note, we should never get here if the FIQ is doing it's job properly*/ +- retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected); ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); + } + else if (gintsts.b.sofintr) { +- retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected); ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); + } ++ + if (gintsts.b.rxstsqlvl) { + retval |= + dwc_otg_hcd_handle_rx_status_q_level_intr +@@ -190,7 +546,10 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + /** @todo Implement i2cintr handler. */ + } + if (gintsts.b.portintr) { ++ ++ gintmsk_data_t gintmsk = { .b.portintr = 1}; + retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); + } + if (gintsts.b.hcintr) { + retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); +@@ -227,26 +586,35 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + + if (fiq_fix_enable) + { +- /* Clear the MPHI interrupt */ +- DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16)); +- if (mphi_int_count >= 60) ++ local_fiq_disable(); ++ // Make sure that we don't clear the interrupt if we've still got pending work to do ++ if(gintsts_saved.d32 == 0) + { +- DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16))); +- while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17))) +- ; +- DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31)); +- mphi_int_count = 0; ++ /* Clear the MPHI interrupt */ ++ DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16)); ++ if (mphi_int_count >= 60) ++ { ++ DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16))); ++ while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17))) ++ ; ++ DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31)); ++ mphi_int_count = 0; ++ } ++ int_done++; + } +- int_done++; ++ ++ // Unmask handled interrupts ++ FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32); ++ //DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1); ++ ++ local_fiq_enable(); ++ + if((jiffies / HZ) > last_time) + { + /* Once a second output the fiq and irq numbers, useful for debug */ + last_time = jiffies / HZ; + DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done); + } +- +- /* Re-Enable FIQ interrupt from USB peripheral */ +- DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1); + } + + DWC_SPINUNLOCK(dwc_otg_hcd->lock); +@@ -294,13 +662,12 @@ static inline void track_missed_sofs(uint16_t curr_frame_number) + * (micro)frame. Periodic transactions may be queued to the controller for the + * next (micro)frame. + */ +-int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected) ++int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) + { + hfnum_data_t hfnum; + dwc_list_link_t *qh_entry; + dwc_otg_qh_t *qh; + dwc_otg_transaction_type_e tr_type; +- gintsts_data_t gintsts = {.d32 = 0 }; + int did_something = 0; + int32_t next_sched_frame = -1; + +@@ -326,6 +693,7 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected) + qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry); + qh_entry = qh_entry->next; + if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { ++ + /* + * Move QH to the ready list to be executed next + * (micro)frame. +@@ -351,15 +719,10 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected) + dwc_otg_hcd_queue_transactions(hcd, tr_type); + did_something = 1; + } +- if(work_expected && !did_something) +- DWC_DEBUGPL(DBG_USER, "Nothing to do !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame); +- if(!work_expected && did_something) +- DWC_DEBUGPL(DBG_USER, "Unexpected work done !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame); +- + + /* Clear interrupt */ +- gintsts.b.sofintr = 1; +- DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); ++ //gintsts.b.sofintr = 1; ++ //DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); + + return 1; + } +@@ -643,6 +1006,15 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) + + haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); + ++ // Overwrite with saved interrupts from fiq handler ++ if(fiq_split_enable) ++ { ++ local_fiq_disable(); ++ haint.d32 = haint_saved.d32; ++ haint_saved.d32 = 0; ++ local_fiq_enable(); ++ } ++ + for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { + if (haint.b2.chint & (1 << i)) { + retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); +@@ -683,7 +1055,10 @@ static uint32_t get_actual_xfer_length(dwc_hc_t * hc, + *short_read = (hctsiz.b.xfersize != 0); + } + } else if (hc->qh->do_split) { +- length = qtd->ssplit_out_xfer_count; ++ if(fiq_split_enable) ++ length = split_out_xfersize[hc->hc_num]; ++ else ++ length = qtd->ssplit_out_xfer_count; + } else { + length = hc->xfer_len; + } +@@ -727,7 +1102,6 @@ static int update_urb_state_xfer_comp(dwc_hc_t * hc, + DWC_OTG_HC_XFER_COMPLETE, + &short_read); + +- + /* non DWORD-aligned buffer case handling. */ + if (hc->align_buff && xfer_length && hc->ep_is_in) { + dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, +@@ -930,6 +1304,9 @@ static void release_channel(dwc_otg_hcd_t * hcd, + int free_qtd; + dwc_irqflags_t flags; + dwc_spinlock_t *channel_lock = hcd->channel_lock; ++#ifdef FIQ_DEBUG ++ int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0; ++#endif + + DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", + __func__, hc->hc_num, halt_status, hc->xfer_len); +@@ -1008,9 +1385,24 @@ static void release_channel(dwc_otg_hcd_t * hcd, + + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + hcd->available_host_channels++; ++ fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels); + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); + } + ++ if(fiq_split_enable && hc->do_split) ++ { ++ if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr))) ++ { ++ fiq_print(FIQDBG_ERR, "PRTNOTAL"); ++ //BUG(); ++ } ++ ++ hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr); ++ hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1; ++ ++ fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp); ++ } ++ + /* Try to queue more transfers now that there's a free channel. */ + tr_type = dwc_otg_hcd_select_transactions(hcd); + if (tr_type != DWC_OTG_TRANSACTION_NONE) { +@@ -1633,8 +2025,10 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { + int frnum = dwc_otg_hcd_get_frame_number(hcd); + ++ // With the FIQ running we only ever see the failed NYET + if (dwc_full_frame_num(frnum) != +- dwc_full_frame_num(hc->qh->sched_frame)) { ++ dwc_full_frame_num(hc->qh->sched_frame) || ++ fiq_split_enable) { + /* + * No longer in the same full speed frame. + * Treat this as a transaction error. +@@ -2012,10 +2406,10 @@ static inline int halt_status_ok(dwc_otg_hcd_t * hcd, + static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, + dwc_hc_t * hc, + dwc_otg_hc_regs_t * hc_regs, +- dwc_otg_qtd_t * qtd) ++ dwc_otg_qtd_t * qtd, ++ hcint_data_t hcint, ++ hcintmsk_data_t hcintmsk) + { +- hcint_data_t hcint; +- hcintmsk_data_t hcintmsk; + int out_nak_enh = 0; + + /* For core with OUT NAK enhancement, the flow for high- +@@ -2047,8 +2441,11 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, + } + + /* Read the HCINTn register to determine the cause for the halt. */ +- hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); +- hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ if(!fiq_split_enable) ++ { ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); ++ } + + if (hcint.b.xfercomp) { + /** @todo This is here because of a possible hardware bug. Spec +@@ -2161,13 +2558,15 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, + static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, + dwc_hc_t * hc, + dwc_otg_hc_regs_t * hc_regs, +- dwc_otg_qtd_t * qtd) ++ dwc_otg_qtd_t * qtd, ++ hcint_data_t hcint, ++ hcintmsk_data_t hcintmsk) + { + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Channel Halted--\n", hc->hc_num); + + if (hcd->core_if->dma_enable) { +- handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); ++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk); + } else { + #ifdef DEBUG + if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { +@@ -2184,7 +2583,7 @@ static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, + int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) + { + int retval = 0; +- hcint_data_t hcint; ++ hcint_data_t hcint, hcint_orig; + hcintmsk_data_t hcintmsk; + dwc_hc_t *hc; + dwc_otg_hc_regs_t *hc_regs; +@@ -2197,12 +2596,23 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) + qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); + + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcint_orig = hcint; + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); + DWC_DEBUGPL(DBG_HCDV, + " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", + hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); + hcint.d32 = hcint.d32 & hcintmsk.d32; + ++ if(fiq_split_enable) ++ { ++ // replace with the saved interrupts from the fiq handler ++ local_fiq_disable(); ++ hcint_orig.d32 = hcint_saved[num].d32; ++ hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32; ++ hcint_saved[num].d32 = 0; ++ local_fiq_enable(); ++ } ++ + if (!dwc_otg_hcd->core_if->dma_enable) { + if (hcint.b.chhltd && hcint.d32 != 0x2) { + hcint.b.chhltd = 0; +@@ -2220,7 +2630,7 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) + hcint.b.nyet = 0; + } + if (hcint.b.chhltd) { +- retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); ++ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]); + } + if (hcint.b.ahberr) { + retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +index fef557d..0d6f5f4 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +@@ -392,7 +392,11 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, + static struct fiq_handler fh = { + .name = "usb_fiq", + }; +-static uint8_t fiqStack[1024]; ++struct fiq_stack_s { ++ int magic1; ++ uint8_t stack[2048]; ++ int magic2; ++} fiq_stack; + + extern mphi_regs_t c_mphi_regs; + /** +@@ -434,9 +438,11 @@ int hcd_init(dwc_bus_dev_t *_dev) + memset(®s,0,sizeof(regs)); + regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq; + regs.ARM_r9 = (long)0; +- regs.ARM_sp = (long)fiqStack + sizeof(fiqStack) - 4; ++ regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4; + set_fiq_regs(®s); +- } ++ fiq_stack.magic1 = 0xdeadbeef; ++ fiq_stack.magic2 = 0xaa995566; ++ } + + /* + * Allocate memory for the base HCD plus the DWC OTG HCD. +@@ -459,6 +465,8 @@ int hcd_init(dwc_bus_dev_t *_dev) + + if (fiq_fix_enable) + { ++ volatile extern void *dwc_regs_base; ++ + //Set the mphi periph to the required registers + c_mphi_regs.base = otg_dev->os_dep.mphi_base; + c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c; +@@ -466,6 +474,8 @@ int hcd_init(dwc_bus_dev_t *_dev) + c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c; + c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50; + ++ dwc_regs_base = otg_dev->os_dep.base; ++ + //Enable mphi peripheral + writel((1<<31),c_mphi_regs.ctrl); + #ifdef DEBUG +@@ -839,6 +849,8 @@ static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + usb_hcd_unlink_urb_from_ep(hcd, urb); + #endif + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++ ++ + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + usb_hcd_giveback_urb(hcd, urb); + #else +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +index b3e6e52..8125307 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +@@ -41,6 +41,7 @@ + + #include "dwc_otg_hcd.h" + #include "dwc_otg_regs.h" ++#include "dwc_otg_mphi_fix.h" + + extern bool microframe_schedule; + +@@ -191,6 +192,7 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) + dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, + hub_port); + qh->do_split = 1; ++ qh->skip_count = 0; + } + + if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) { +@@ -737,6 +739,9 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) + hcd->non_periodic_qh_ptr->next; + } + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); ++ ++ // If we've removed the last non-periodic entry then there are none left! ++ g_np_count = g_np_sent; + } else { + deschedule_periodic(hcd, qh); + hcd->periodic_qh_count--; +@@ -766,21 +771,21 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, + { + if (dwc_qh_is_non_per(qh)) { + +- dwc_otg_qh_t *qh_tmp; +- dwc_list_link_t *qh_list; +- DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive) +- { +- qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry); +- if(qh_tmp == qh) ++ dwc_otg_qh_t *qh_tmp; ++ dwc_list_link_t *qh_list; ++ DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive) + { +- /* +- * FIQ is being disabled because this one nevers gets a np_count increment +- * This is still not absolutely correct, but it should fix itself with +- * just an unnecessary extra interrupt +- */ +- g_np_sent = g_np_count; ++ qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry); ++ if(qh_tmp == qh) ++ { ++ /* ++ * FIQ is being disabled because this one nevers gets a np_count increment ++ * This is still not absolutely correct, but it should fix itself with ++ * just an unnecessary extra interrupt ++ */ ++ g_np_sent = g_np_count; ++ } + } +- } + + + dwc_otg_hcd_qh_remove(hcd, qh); +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h +index 22f28e1..ca17379 100755 +--- a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h +@@ -1,10 +1,7 @@ + #ifndef __DWC_OTG_MPHI_FIX_H__ + #define __DWC_OTG_MPHI_FIX_H__ +- +-#define FIQ_WRITE_IO_ADDRESS(_addr_,_data_) *(volatile uint32_t *) IO_ADDRESS(_addr_) = _data_ +-#define FIQ_READ_IO_ADDRESS(_addr_) *(volatile uint32_t *) IO_ADDRESS(_addr_) +-#define FIQ_MODIFY_IO_ADDRESS(_addr_,_clear_,_set_) FIQ_WRITE_IO_ADDRESS(_addr_ , (FIQ_READ_IO_ADDRESS(_addr_)&~_clear_)|_set_) +-#define FIQ_WRITE(_addr_,_data_) *(volatile uint32_t *) _addr_ = _data_ ++#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_)) ++#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_)) + + typedef struct { + volatile void* base; +@@ -12,13 +9,13 @@ + volatile void* outdda; + volatile void* outddb; + volatile void* intstat; +-} mphi_regs_t; ++} mphi_regs_t; + + void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name); + void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name); + void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name); + +- ++extern gintsts_data_t gintsts_saved; + + #ifdef DEBUG + #define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__) +@@ -30,7 +27,22 @@ + #define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) + #define DWC_DBG_PRINT_OTG_INT(_arg_) + ++#endif ++ ++typedef enum { ++ FIQDBG_SCHED = (1 << 0), ++ FIQDBG_INT = (1 << 1), ++ FIQDBG_ERR = (1 << 2), ++ FIQDBG_PORTHUB = (1 << 3), ++} FIQDBG_T; + ++void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...); ++#ifdef FIQ_DEBUG ++#define fiq_print _fiq_print ++#else ++#define fiq_print(x, y, ...) + #endif + ++extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable; ++ + #endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +index 27061d3..9720937 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +@@ -4276,7 +4276,7 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) + && (pcd->ep0state == EP0_OUT_DATA_PHASE)) + status.d32 = core_if->dev_if->out_desc_addr->status.d32; + if (pcd->ep0state == EP0_OUT_STATUS_PHASE) +- status.d32 = status.d32 = core_if->dev_if-> ++ status.d32 = core_if->dev_if-> + out_desc_addr->status.d32; + + if (status.b.sr) { +-- +1.8.1.6 + From 4d3757bb5ff804ab1e9c8cc64648f41bc5642682 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 14:23:31 +0200 Subject: [PATCH 20/61] linux: remove kernel 3.9 patches Signed-off-by: Stephan Raue --- packages/linux/meta | 4 - .../3.9.8/linux-003-no_dev_console.patch | 20 - .../3.9.8/linux-010-perf_crosscompiling.patch | 17 - .../3.9.8/linux-052-XBOX_remote_support.patch | 1029 -- .../linux-053-spinelplus-remote-0.2.patch | 161 - ...1056c5564eec8a1b169c6e84ff3.6.114c13.patch | 12 - ...-add_Formosa_eHome_Infrared_Receiver.patch | 11 - ...-add_Adaptec_eHome_Infrared_Receiver.patch | 20 - ...tomer-code-restriction-in-rc6-decode.patch | 22 - ..._Manufacturing_Inc_Infrared_Receiver.patch | 13 - ...nux-058.01-HID-Sony-upstream_patches.patch | 860 - ..._sony-add_autorepeat_for_PS3_remotes.patch | 61 - .../linux-059-remove_some_xpad_pids-0.2.patch | 11 - .../3.9.8/linux-060-add_AUGUST_DVB-T205.patch | 12 - ...x-203-stb0899_enable_low_symbol_rate.patch | 12 - .../patches/3.9.8/linux-210-dvbsky.patch | 6161 -------- ...linux-212-mantis_stb0899_faster_lock.patch | 138 - .../3.9.8/linux-213-cinergy_s2_usb_r2.patch | 53 - .../3.9.8/linux-221-ngene-octopus.patch | 12735 --------------- .../linux-222-stb0899_signal_quality.patch | 62 - ...-video-artifacts-with-tt-3600-s2-usb.patch | 17 - .../3.9.8/linux-700-jmicron_1_0_8_5.patch | 1603 -- .../3.9.8/linux-900-hide_tsc_error.patch | 12 - ...x-950-saa716x_PCIe_interface_chipset.patch | 12914 ---------------- ...ting-HDMI-audio-before-prepare-.patch.todo | 76 - .../linux-995-CX24120-13Z_frontend.patch | 1577 -- .../linux-996-macmini2012-ethernet.patch | 11 - ...x-997-disable-rc6-on-sandybridge-gt1.patch | 13 - 28 files changed, 37637 deletions(-) delete mode 100644 packages/linux/patches/3.9.8/linux-003-no_dev_console.patch delete mode 100644 packages/linux/patches/3.9.8/linux-010-perf_crosscompiling.patch delete mode 100644 packages/linux/patches/3.9.8/linux-052-XBOX_remote_support.patch delete mode 100644 packages/linux/patches/3.9.8/linux-053-spinelplus-remote-0.2.patch delete mode 100644 packages/linux/patches/3.9.8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch delete mode 100644 packages/linux/patches/3.9.8/linux-055-add_Formosa_eHome_Infrared_Receiver.patch delete mode 100644 packages/linux/patches/3.9.8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch delete mode 100644 packages/linux/patches/3.9.8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch delete mode 100644 packages/linux/patches/3.9.8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch delete mode 100644 packages/linux/patches/3.9.8/linux-058.01-HID-Sony-upstream_patches.patch delete mode 100644 packages/linux/patches/3.9.8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch delete mode 100644 packages/linux/patches/3.9.8/linux-059-remove_some_xpad_pids-0.2.patch delete mode 100644 packages/linux/patches/3.9.8/linux-060-add_AUGUST_DVB-T205.patch delete mode 100644 packages/linux/patches/3.9.8/linux-203-stb0899_enable_low_symbol_rate.patch delete mode 100644 packages/linux/patches/3.9.8/linux-210-dvbsky.patch delete mode 100644 packages/linux/patches/3.9.8/linux-212-mantis_stb0899_faster_lock.patch delete mode 100644 packages/linux/patches/3.9.8/linux-213-cinergy_s2_usb_r2.patch delete mode 100644 packages/linux/patches/3.9.8/linux-221-ngene-octopus.patch delete mode 100644 packages/linux/patches/3.9.8/linux-222-stb0899_signal_quality.patch delete mode 100644 packages/linux/patches/3.9.8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch delete mode 100644 packages/linux/patches/3.9.8/linux-700-jmicron_1_0_8_5.patch delete mode 100644 packages/linux/patches/3.9.8/linux-900-hide_tsc_error.patch delete mode 100644 packages/linux/patches/3.9.8/linux-950-saa716x_PCIe_interface_chipset.patch delete mode 100644 packages/linux/patches/3.9.8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch.todo delete mode 100755 packages/linux/patches/3.9.8/linux-995-CX24120-13Z_frontend.patch delete mode 100644 packages/linux/patches/3.9.8/linux-996-macmini2012-ethernet.patch delete mode 100644 packages/linux/patches/3.9.8/linux-997-disable-rc6-on-sandybridge-gt1.patch diff --git a/packages/linux/meta b/packages/linux/meta index 6121a85d53..8dfb627c70 100644 --- a/packages/linux/meta +++ b/packages/linux/meta @@ -33,10 +33,6 @@ case "$LINUX" in PKG_VERSION="2.6.38-ti-omap4" PKG_URL="$DISTRO_SRC/$PKG_NAME-$PKG_VERSION.tar.bz2" ;; - 3.9) - PKG_VERSION="3.9.8" - PKG_URL="http://www.kernel.org/pub/linux/kernel/v3.x/$PKG_NAME-$PKG_VERSION.tar.xz" - ;; *) PKG_VERSION="3.10" PKG_URL="http://www.kernel.org/pub/linux/kernel/v3.x/$PKG_NAME-$PKG_VERSION.tar.xz" diff --git a/packages/linux/patches/3.9.8/linux-003-no_dev_console.patch b/packages/linux/patches/3.9.8/linux-003-no_dev_console.patch deleted file mode 100644 index 9b5e51437d..0000000000 --- a/packages/linux/patches/3.9.8/linux-003-no_dev_console.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff -Naur linux-2.6.34-rc7/init/main.c linux-2.6.34-rc7.patch/init/main.c ---- linux-2.6.34-rc7/init/main.c 2010-05-10 03:36:28.000000000 +0200 -+++ linux-2.6.34-rc7.patch/init/main.c 2010-05-15 12:28:34.767241760 +0200 -@@ -886,8 +886,14 @@ - do_basic_setup(); - - /* Open the /dev/console on the rootfs, this should never fail */ -- if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) -- printk(KERN_WARNING "Warning: unable to open an initial console.\n"); -+ char *console = "/dev_console"; -+ -+ if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) { -+ sys_mknod(console, S_IFCHR|0600, (TTYAUX_MAJOR<<8)|1); -+ if (sys_open(console, O_RDWR, 0) < 0) -+ printk(KERN_WARNING "Warning: unable to open an initial console.\n"); -+ sys_unlink(console); -+ } - - (void) sys_dup(0); - (void) sys_dup(0); diff --git a/packages/linux/patches/3.9.8/linux-010-perf_crosscompiling.patch b/packages/linux/patches/3.9.8/linux-010-perf_crosscompiling.patch deleted file mode 100644 index aeea6963f4..0000000000 --- a/packages/linux/patches/3.9.8/linux-010-perf_crosscompiling.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff -Naur linux-3.9.4/tools/perf/Makefile linux-3.9.4.patch/tools/perf/Makefile ---- linux-3.9.4/tools/perf/Makefile 2013-05-24 20:45:59.000000000 +0200 -+++ linux-3.9.4.patch/tools/perf/Makefile 2013-05-30 23:57:04.135031372 +0200 -@@ -668,12 +668,10 @@ - endif - - ifndef NO_NEWT -- FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt -+ FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt -lslang - ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT),libnewt),y) - msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); - else -- # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h -- BASIC_CFLAGS += -I/usr/include/slang - BASIC_CFLAGS += -DNEWT_SUPPORT - EXTLIBS += -lnewt -lslang - LIB_OBJS += $(OUTPUT)ui/browser.o diff --git a/packages/linux/patches/3.9.8/linux-052-XBOX_remote_support.patch b/packages/linux/patches/3.9.8/linux-052-XBOX_remote_support.patch deleted file mode 100644 index 6b43f9b315..0000000000 --- a/packages/linux/patches/3.9.8/linux-052-XBOX_remote_support.patch +++ /dev/null @@ -1,1029 +0,0 @@ -diff -Naur linux-3.9.4/drivers/staging/media/lirc/Kconfig linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig ---- linux-3.9.4/drivers/staging/media/lirc/Kconfig 2013-05-24 20:45:59.000000000 +0200 -+++ linux-3.9.4.patch/drivers/staging/media/lirc/Kconfig 2013-05-30 18:18:57.238957100 +0200 -@@ -63,10 +63,17 @@ - help - Driver for the SIR IrDA port - -+config LIRC_XBOX -+ tristate "XBOX USB IR Remote" -+ depends on LIRC && USB -+ help -+ Driver for the Microsoft XBOX USB IR Remote -+ - config LIRC_ZILOG - tristate "Zilog/Hauppauge IR Transmitter" - depends on LIRC && I2C - help - Driver for the Zilog/Hauppauge IR Transmitter, found on - PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards -+ - endif -diff -Naur linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c ---- linux-3.9.4/drivers/staging/media/lirc/lirc_xbox.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.9.4.patch/drivers/staging/media/lirc/lirc_xbox.c 2013-05-30 18:40:22.523775446 +0200 -@@ -0,0 +1,995 @@ -+/* -+ * lirc_xbox - USB remote support for LIRC -+ * (supports Microsoft XBOX DVD Dongle) -+ * -+ * Copyright (C) 2003-2004 Paul Miller -+ * -+ * This driver was derived from: -+ * Vladimir Dergachev 's 2002 -+ * "USB ATI Remote support" (input device) -+ * Adrian Dewhurst 's 2002 -+ * "USB StreamZap remote driver" (LIRC) -+ * Artur Lipowski 's 2002 -+ * "lirc_dev" and "lirc_gpio" LIRC modules -+ * Michael Wojciechowski -+ * initial xbox support -+ * Vassilis Virvilis 2006 -+ * reworked the patch for lirc submission -+ * Paul Miller's 2004 -+ * lirc_atiusb - removed all ati remote support -+ * $Id: lirc_xbox.c,v 1.88 2011/06/03 11:11:11 jmartin Exp $ -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#include -+ -+//#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) -+//#include -+//#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+//#include "drivers/kcompat.h" -+//#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) -+#include -+#include -+//#else -+//#include "drivers/lirc.h" -+//#include "drivers/lirc_dev/lirc_dev.h" -+//#endif -+ -+#define DRIVER_VERSION "$Revision: 0.01 $" -+#define DRIVER_AUTHOR "Jason Martin " -+#define DRIVER_DESC "XBOX DVD Dongle USB remote driver for LIRC" -+#define DRIVER_NAME "lirc_xbox" -+ -+#define CODE_LENGTH 6 -+#define CODE_MIN_LENGTH 6 -+#define DECODE_LENGTH 1 -+ -+#ifndef URB_ASYNC_UNLINK -+#define URB_ASYNC_UNLINK 0 -+#endif -+ -+/* module parameters */ -+#ifdef CONFIG_USB_DEBUG -+static int debug = 1; -+#else -+static int debug; -+#endif -+ -+#define dprintk(fmt, args...) \ -+ do { \ -+ if (debug) \ -+ printk(KERN_DEBUG fmt, ## args); \ -+ } while (0) -+ -+/* -+ * USB_BUFF_LEN must be the maximum value of the code_length array. -+ * It is used for static arrays. -+ */ -+#define USB_BUFF_LEN 6 -+ -+static int mask = 0xFFFF; /* channel acceptance bit mask */ -+static int unique; /* enable channel-specific codes */ -+static int repeat = 10; /* repeat time in 1/100 sec */ -+static unsigned long repeat_jiffies; /* repeat timeout */ -+ -+/* get hi and low bytes of a 16-bits int */ -+#define HI(a) ((unsigned char)((a) >> 8)) -+#define LO(a) ((unsigned char)((a) & 0xff)) -+ -+/* general constants */ -+#define SEND_FLAG_IN_PROGRESS 1 -+#define SEND_FLAG_COMPLETE 2 -+#define FREE_ALL 0xFF -+ -+/* endpoints */ -+#define EP_KEYS 0 -+#define EP_MOUSE 1 -+#define EP_MOUSE_ADDR 0x81 -+#define EP_KEYS_ADDR 0x82 -+ -+/* USB vendor ids for XBOX DVD Dongles */ -+#define VENDOR_MS1 0x040b -+#define VENDOR_MS2 0x045e -+#define VENDOR_MS3 0xFFFF -+ -+static struct usb_device_id usb_remote_table[] = { -+ /* Gamester Xbox DVD Movie Playback Kit IR */ -+ { USB_DEVICE(VENDOR_MS1, 0x6521) }, -+ -+ /* Microsoft Xbox DVD Movie Playback Kit IR */ -+ { USB_DEVICE(VENDOR_MS2, 0x0284) }, -+ -+ /* -+ * Some Chinese manufacturer -- conflicts with the joystick from the -+ * same manufacturer -+ */ -+ { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, -+ -+ /* Terminating entry */ -+ { } -+}; -+ -+/* init strings */ -+#define USB_OUTLEN 7 -+ -+static char init1[] = {0x01, 0x00, 0x20, 0x14}; -+static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; -+ -+struct in_endpt { -+ /* inner link in list of endpoints for the remote specified by ir */ -+ struct list_head iep_list_link; -+ struct xbox_dev *ir; -+ struct urb *urb; -+ struct usb_endpoint_descriptor *ep; -+ -+ /* buffers and dma */ -+ unsigned char *buf; -+ unsigned int len; -+ dma_addr_t dma; -+ -+ /* handle repeats */ -+ unsigned char old[USB_BUFF_LEN]; -+ unsigned long old_jiffies; -+}; -+ -+struct out_endpt { -+ struct xbox_dev *ir; -+ struct urb *urb; -+ struct usb_endpoint_descriptor *ep; -+ -+ /* buffers and dma */ -+ unsigned char *buf; -+ dma_addr_t dma; -+ -+ /* handle sending (init strings) */ -+ int send_flags; -+ wait_queue_head_t wait; -+}; -+ -+ -+/* data structure for each usb remote */ -+struct xbox_dev { -+ /* inner link in list of all remotes managed by this module */ -+ struct list_head remote_list_link; -+ /* Number of usb interfaces associated with this device */ -+ int dev_refcount; -+ -+ /* usb */ -+ struct usb_device *usbdev; -+ /* Head link to list of all inbound endpoints in this remote */ -+ struct list_head iep_listhead; -+ struct out_endpt *out_init; -+ int devnum; -+ -+ /* lirc */ -+ struct lirc_driver *d; -+ int connected; -+ -+ /* locking */ -+ struct mutex lock; -+}; -+ -+/* list of all registered devices via the remote_list_link in xbox_dev */ -+static struct list_head remote_list; -+ -+/* -+ * Convenience macros to retrieve a pointer to the surrounding struct from -+ * the given list_head reference within, pointed at by link. -+ */ -+#define get_iep_from_link(link) \ -+ list_entry((link), struct in_endpt, iep_list_link); -+#define get_irctl_from_link(link) \ -+ list_entry((link), struct xbox_dev, remote_list_link); -+ -+/* send packet - used to initialize remote */ -+static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) -+{ -+ struct xbox_dev *ir = oep->ir; -+ DECLARE_WAITQUEUE(wait, current); -+ int timeout = HZ; /* 1 second */ -+ unsigned char buf[USB_OUTLEN]; -+ -+ dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); -+ -+ mutex_lock(&ir->lock); -+ oep->urb->transfer_buffer_length = LO(cmd) + 1; -+ oep->urb->dev = oep->ir->usbdev; -+ oep->send_flags = SEND_FLAG_IN_PROGRESS; -+ -+ memcpy(buf+1, data, LO(cmd)); -+ buf[0] = HI(cmd); -+ memcpy(oep->buf, buf, LO(cmd)+1); -+ -+ set_current_state(TASK_INTERRUPTIBLE); -+ add_wait_queue(&oep->wait, &wait); -+ -+ if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&oep->wait, &wait); -+ mutex_unlock(&ir->lock); -+ return; -+ } -+ mutex_unlock(&ir->lock); -+ -+ while (timeout && (oep->urb->status == -EINPROGRESS) -+ && !(oep->send_flags & SEND_FLAG_COMPLETE)) { -+ timeout = schedule_timeout(timeout); -+ rmb(); -+ } -+ -+ dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); -+ -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&oep->wait, &wait); -+ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(oep->urb); -+} -+ -+static int unregister_from_lirc(struct xbox_dev *ir) -+{ -+ struct lirc_driver *d = ir->d; -+ int devnum; -+ -+ devnum = ir->devnum; -+ dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); -+ -+ lirc_unregister_driver(d->minor); -+ -+ printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); -+ return 0; -+} -+ -+static int set_use_inc(void *data) -+{ -+ struct xbox_dev *ir = data; -+ struct list_head *pos, *n; -+ struct in_endpt *iep; -+ int rtn; -+ -+ if (!ir) { -+ printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); -+ return -EIO; -+ } -+ dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); -+ -+ mutex_lock(&ir->lock); -+ if (!ir->connected) { -+ if (!ir->usbdev) { -+ mutex_unlock(&ir->lock); -+ dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); -+ return -ENOENT; -+ } -+ -+ /* Iterate through the inbound endpoints */ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ /* extract the current in_endpt */ -+ iep = get_iep_from_link(pos); -+ iep->urb->dev = ir->usbdev; -+ dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", -+ ir->devnum, iep->ep->bEndpointAddress, iep); -+ rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); -+ if (rtn) { -+ printk(DRIVER_NAME "[%d]: open result = %d " -+ "error submitting urb\n", -+ ir->devnum, rtn); -+ mutex_unlock(&ir->lock); -+ return -EIO; -+ } -+ } -+ ir->connected = 1; -+ } -+ mutex_unlock(&ir->lock); -+ -+ return 0; -+} -+ -+static void set_use_dec(void *data) -+{ -+ struct xbox_dev *ir = data; -+ struct list_head *pos, *n; -+ struct in_endpt *iep; -+ -+ if (!ir) { -+ printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); -+ return; -+ } -+ dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); -+ -+ mutex_lock(&ir->lock); -+ if (ir->connected) { -+ /* Free inbound usb urbs */ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ iep = get_iep_from_link(pos); -+ dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", -+ ir->devnum, iep->ep->bEndpointAddress, iep); -+ usb_kill_urb(iep->urb); -+ } -+ ir->connected = 0; -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static void print_data(struct in_endpt *iep, char *buf, int len) -+{ -+ const int clen = CODE_LENGTH; -+ char codes[clen * 3 + 1]; -+ int i; -+ -+ if (len <= 0) -+ return; -+ -+ for (i = 0; i < len && i < clen; i++) -+ snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); -+ printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", -+ iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); -+} -+ -+static int code_check_xbox(struct in_endpt *iep, int len) -+{ -+ // struct xbox_dev *ir = iep->ir; -+ const int clen = CODE_LENGTH; -+ -+ if (len != clen) { -+ dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " -+ "ir.. ?\n", len, clen); -+ return -1; -+ } -+ -+ /* check for repeats */ -+ if (memcmp(iep->old, iep->buf, len) == 0) { -+ if (iep->old_jiffies + repeat_jiffies > jiffies) -+ return -1; -+ } else { -+ /* -+ * the third byte of xbox ir packet seems to contain key info -+ * the last two bytes are.. some kind of clock? -+ */ -+ iep->buf[0] = iep->buf[2]; -+ memset(iep->buf + 1, 0, len - 1); -+ memcpy(iep->old, iep->buf, len); -+ } -+ iep->old_jiffies = jiffies; -+ -+ return 0; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) -+#else -+static void usb_remote_recv(struct urb *urb) -+#endif -+{ -+ struct in_endpt *iep; -+ int len, result = -1; -+ -+ if (!urb) -+ return; -+ iep = urb->context; -+ if (!iep) { -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ } -+ if (!iep->ir->usbdev) -+ return; -+ -+ len = urb->actual_length; -+ if (debug) -+ print_data(iep, urb->transfer_buffer, len); -+ -+ switch (urb->status) { -+ -+ case 0: -+ result = code_check_xbox(iep, len); -+ -+ if (result < 0) -+ break; -+ -+ lirc_buffer_write(iep->ir->d->rbuf, iep->buf); -+ wake_up(&iep->ir->d->rbuf->wait_poll); -+ break; -+ -+ case -ECONNRESET: -+ case -ENOENT: -+ case -ESHUTDOWN: -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ -+ case -EPIPE: -+ default: -+ break; -+ } -+ -+ usb_submit_urb(urb, GFP_ATOMIC); -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+static void usb_remote_send(struct urb *urb, struct pt_regs *regs) -+#else -+static void usb_remote_send(struct urb *urb) -+#endif -+{ -+ struct out_endpt *oep; -+ -+ if (!urb) -+ return; -+ oep = urb->context; -+ if (!oep) { -+ urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(urb); -+ return; -+ } -+ if (!oep->ir->usbdev) -+ return; -+ -+ dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); -+ -+ if (urb->status) -+ return; -+ -+ oep->send_flags |= SEND_FLAG_COMPLETE; -+ wmb(); -+ if (waitqueue_active(&oep->wait)) -+ wake_up(&oep->wait); -+} -+ -+ -+/* -+ * Initialization and removal -+ */ -+ -+/* -+ * Free iep according to mem_failure which specifies a checkpoint into the -+ * initialization sequence for rollback recovery. -+ */ -+static void free_in_endpt(struct in_endpt *iep, int mem_failure) -+{ -+ struct xbox_dev *ir; -+ dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); -+ if (!iep) -+ return; -+ -+ ir = iep->ir; -+ if (!ir) { -+ dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); -+ return; -+ } -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 5: -+ list_del(&iep->iep_list_link); -+ dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " -+ "from list\n", ir->devnum, iep->ep->bEndpointAddress); -+ case 4: -+ if (iep->urb) { -+ iep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(iep->urb); -+ usb_free_urb(iep->urb); -+ iep->urb = 0; -+ } else -+ dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", -+ ir->devnum); -+ case 3: -+ usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); -+ iep->buf = 0; -+ case 2: -+ kfree(iep); -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+/* -+ * Construct a new inbound endpoint for this remote, and add it to the list of -+ * in_epts in ir. -+ */ -+static struct in_endpt *new_in_endpt(struct xbox_dev *ir, -+ struct usb_endpoint_descriptor *ep) -+{ -+ struct usb_device *dev = ir->usbdev; -+ struct in_endpt *iep; -+ int pipe, maxp, len, addr; -+ int mem_failure; -+ -+ addr = ep->bEndpointAddress; -+ pipe = usb_rcvintpipe(dev, addr); -+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); -+ -+/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; -+ * len -= (len % CODE_LENGTH); */ -+ len = CODE_LENGTH; -+ -+ dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " -+ "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); -+ -+ mem_failure = 0; -+ iep = kzalloc(sizeof(*iep), GFP_KERNEL); -+ if (!iep) { -+ mem_failure = 1; -+ goto new_in_endpt_failure_check; -+ } -+ iep->ir = ir; -+ iep->ep = ep; -+ iep->len = len; -+ -+ iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); -+ if (!iep->buf) { -+ mem_failure = 2; -+ goto new_in_endpt_failure_check; -+ } -+ -+ iep->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!iep->urb) -+ mem_failure = 3; -+ -+new_in_endpt_failure_check: -+ -+ if (mem_failure) { -+ free_in_endpt(iep, mem_failure); -+ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", -+ ir->devnum, addr, mem_failure); -+ return NULL; -+ } -+ list_add_tail(&iep->iep_list_link, &ir->iep_listhead); -+ dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", -+ ir->devnum, iep->ep->bEndpointAddress); -+ return iep; -+} -+ -+static void free_out_endpt(struct out_endpt *oep, int mem_failure) -+{ -+ struct xbox_dev *ir; -+ dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); -+ if (!oep) -+ return; -+ -+ wake_up_all(&oep->wait); -+ -+ ir = oep->ir; -+ if (!ir) { -+ dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); -+ return; -+ } -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 4: -+ if (oep->urb) { -+ oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -+ usb_unlink_urb(oep->urb); -+ usb_free_urb(oep->urb); -+ oep->urb = 0; -+ } else { -+ dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", -+ ir->devnum); -+ } -+ case 3: -+ usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, -+ oep->buf, oep->dma); -+ oep->buf = 0; -+ case 2: -+ kfree(oep); -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static struct out_endpt *new_out_endpt(struct xbox_dev *ir, -+ struct usb_endpoint_descriptor *ep) -+{ -+ struct usb_device *dev = ir->usbdev; -+ struct out_endpt *oep; -+ int mem_failure; -+ -+ dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", -+ ir->devnum, ep->bEndpointAddress); -+ -+ mem_failure = 0; -+ oep = kzalloc(sizeof(*oep), GFP_KERNEL); -+ if (!oep) -+ mem_failure = 1; -+ else { -+ oep->ir = ir; -+ oep->ep = ep; -+ init_waitqueue_head(&oep->wait); -+ -+ oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, -+ GFP_ATOMIC, &oep->dma); -+ if (!oep->buf) -+ mem_failure = 2; -+ else { -+ oep->urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!oep->urb) -+ mem_failure = 3; -+ } -+ } -+ if (mem_failure) { -+ free_out_endpt(oep, mem_failure); -+ printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", -+ ir->devnum, ep->bEndpointAddress, mem_failure); -+ return NULL; -+ } -+ return oep; -+} -+ -+static void free_irctl(struct xbox_dev *ir, int mem_failure) -+{ -+ struct list_head *pos, *n; -+ struct in_endpt *in; -+ dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); -+ -+ if (!ir) -+ return; -+ -+ list_for_each_safe(pos, n, &ir->iep_listhead) { -+ in = get_iep_from_link(pos); -+ free_in_endpt(in, FREE_ALL); -+ } -+ if (ir->out_init) { -+ free_out_endpt(ir->out_init, FREE_ALL); -+ ir->out_init = NULL; -+ } -+ -+ mutex_lock(&ir->lock); -+ switch (mem_failure) { -+ case FREE_ALL: -+ case 6: -+ if (!--ir->dev_refcount) { -+ list_del(&ir->remote_list_link); -+ dprintk(DRIVER_NAME "[%d]: free_irctl: removing " -+ "remote from list\n", ir->devnum); -+ } else { -+ dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," -+ "aborting free_irctl\n", -+ ir->devnum, ir->dev_refcount); -+ mutex_unlock(&ir->lock); -+ return; -+ } -+ case 5: -+ case 4: -+ case 3: -+ if (ir->d) { -+ switch (mem_failure) { -+ case 5: -+ lirc_buffer_free(ir->d->rbuf); -+ case 4: -+ kfree(ir->d->rbuf); -+ case 3: -+ kfree(ir->d); -+ } -+ } else -+ printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n", -+ ir->devnum); -+ case 2: -+ mutex_unlock(&ir->lock); -+ kfree(ir); -+ return; -+ } -+ mutex_unlock(&ir->lock); -+} -+ -+static struct xbox_dev *new_irctl(struct usb_interface *intf) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct xbox_dev *ir; -+ struct lirc_driver *driver; -+ int devnum, dclen; -+ int mem_failure; -+ -+ devnum = dev->devnum; -+ -+ dprintk(DRIVER_NAME "[%d]: remote type = XBOX DVD Dongle\n", devnum); -+ -+ mem_failure = 0; -+ ir = kzalloc(sizeof(*ir), GFP_KERNEL); -+ if (!ir) { -+ mem_failure = 1; -+ goto new_irctl_failure_check; -+ } -+ -+ dclen = DECODE_LENGTH; -+ -+ /* -+ * add this infrared remote struct to remote_list, keeping track -+ * of the number of drivers registered. -+ */ -+ dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); -+ list_add_tail(&ir->remote_list_link, &remote_list); -+ ir->dev_refcount = 1; -+ -+ driver = kzalloc(sizeof(*driver), GFP_KERNEL); -+ if (!driver) { -+ mem_failure = 2; -+ goto new_irctl_failure_check; -+ } -+ -+ ir->d = driver; -+ driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL); -+ if (!driver->rbuf) { -+ mem_failure = 3; -+ goto new_irctl_failure_check; -+ } -+ -+ if (lirc_buffer_init(driver->rbuf, dclen, 2)) { -+ mem_failure = 4; -+ goto new_irctl_failure_check; -+ } -+ -+ strcpy(driver->name, DRIVER_NAME " "); -+ driver->minor = -1; -+ driver->code_length = dclen * 8; -+ driver->features = LIRC_CAN_REC_LIRCCODE; -+ driver->data = ir; -+ driver->set_use_inc = &set_use_inc; -+ driver->set_use_dec = &set_use_dec; -+ driver->dev = &intf->dev; -+ driver->owner = THIS_MODULE; -+ ir->usbdev = dev; -+ ir->devnum = devnum; -+ -+ mutex_init(&ir->lock); -+ INIT_LIST_HEAD(&ir->iep_listhead); -+ -+new_irctl_failure_check: -+ -+ if (mem_failure) { -+ free_irctl(ir, mem_failure); -+ printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", -+ devnum, mem_failure); -+ return NULL; -+ } -+ return ir; -+} -+ -+/* -+ * Scan the global list of remotes to see if the device listed is one of them. -+ * If it is, the corresponding xbox_dev is returned, with its dev_refcount -+ * incremented. Otherwise, returns null. -+ */ -+static struct xbox_dev *get_prior_reg_ir(struct usb_device *dev) -+{ -+ struct list_head *pos; -+ struct xbox_dev *ir = NULL; -+ -+ dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); -+ list_for_each(pos, &remote_list) { -+ ir = get_irctl_from_link(pos); -+ if (ir->usbdev != dev) { -+ dprintk(DRIVER_NAME "[%d]: device %d isn't it...", -+ dev->devnum, ir->devnum); -+ ir = NULL; -+ } else { -+ dprintk(DRIVER_NAME "[%d]: prior instance found.\n", -+ dev->devnum); -+ ir->dev_refcount++; -+ break; -+ } -+ } -+ return ir; -+} -+ -+/* -+ * If the USB interface has an out endpoint for control. -+ */ -+static void send_outbound_init(struct xbox_dev *ir) -+{ -+ if (ir->out_init) { -+ struct out_endpt *oep = ir->out_init; -+ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " -+ "outbound ep\n", ir->devnum); -+ usb_fill_int_urb(oep->urb, ir->usbdev, -+ usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), -+ oep->buf, USB_OUTLEN, usb_remote_send, -+ oep, oep->ep->bInterval); -+ oep->urb->transfer_dma = oep->dma; -+ oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -+ -+ send_packet(oep, 0x8004, init1); -+ send_packet(oep, 0x8007, init2); -+ } -+} -+ -+/* Log driver and usb info */ -+static void log_usb_dev_info(struct usb_device *dev) -+{ -+ char buf[63], name[128] = ""; -+ -+ if (dev->descriptor.iManufacturer -+ && usb_string(dev, dev->descriptor.iManufacturer, -+ buf, sizeof(buf)) > 0) -+ strlcpy(name, buf, sizeof(name)); -+ if (dev->descriptor.iProduct -+ && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) -+ snprintf(name + strlen(name), sizeof(name) - strlen(name), -+ " %s", buf); -+ printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, -+ dev->bus->busnum, dev->devnum); -+} -+ -+ -+static int usb_remote_probe(struct usb_interface *intf, -+ const struct usb_device_id *id) -+{ -+ struct usb_device *dev = interface_to_usbdev(intf); -+ struct usb_host_interface *idesc; -+ struct usb_endpoint_descriptor *ep; -+ struct in_endpt *iep; -+ struct xbox_dev *ir; -+ int i; -+ -+ dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", -+ dev->devnum, dev, intf, id); -+ -+ idesc = intf->cur_altsetting; -+ -+ /* Check if a usb remote has already been registered for this device */ -+ ir = get_prior_reg_ir(dev); -+ -+ if (!ir) { -+ ir = new_irctl(intf); -+ if (!ir) -+ return -ENOMEM; -+ } -+ -+ /* -+ * step through the endpoints to find first in and first out endpoint -+ * of type interrupt transfer -+ */ -+ for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { -+ ep = &idesc->endpoint[i].desc; -+ dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", -+ dev->devnum, i); -+ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == -+ USB_DIR_IN) && -+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT)) { -+ -+ iep = new_in_endpt(ir, ep); -+ if (iep) -+ { -+ usb_fill_int_urb(iep->urb, dev, -+ usb_rcvintpipe(dev, -+ iep->ep->bEndpointAddress), -+ iep->buf, iep->len, usb_remote_recv, -+ iep, iep->ep->bInterval); -+ iep->urb->transfer_dma = iep->dma; -+ iep->urb->transfer_flags |= -+ URB_NO_TRANSFER_DMA_MAP; -+ } -+ } -+ -+ if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == -+ USB_DIR_OUT) && -+ ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == -+ USB_ENDPOINT_XFER_INT) && -+ (ir->out_init == NULL)) -+ ir->out_init = new_out_endpt(ir, ep); -+ } -+ if (list_empty(&ir->iep_listhead)) { -+ printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", -+ ir->devnum); -+ free_irctl(ir, FREE_ALL); -+ return -ENODEV; -+ } -+ if (ir->dev_refcount == 1) { -+ ir->d->minor = lirc_register_driver(ir->d); -+ if (ir->d->minor < 0) { -+ free_irctl(ir, FREE_ALL); -+ return -ENODEV; -+ } -+ -+ /* Note new driver registration in kernel logs */ -+ log_usb_dev_info(dev); -+ -+ /* outbound data (initialization) */ -+ send_outbound_init(ir); -+ } -+ -+ usb_set_intfdata(intf, ir); -+ return 0; -+} -+ -+static void usb_remote_disconnect(struct usb_interface *intf) -+{ -+ /* struct usb_device *dev = interface_to_usbdev(intf); */ -+ struct xbox_dev *ir = usb_get_intfdata(intf); -+ usb_set_intfdata(intf, NULL); -+ -+ dprintk(DRIVER_NAME ": disconnecting remote %d:\n", -+ (ir ? ir->devnum : -1)); -+ if (!ir || !ir->d) -+ return; -+ -+ if (ir->usbdev) { -+ /* Only unregister once */ -+ ir->usbdev = NULL; -+ unregister_from_lirc(ir); -+ } -+ -+ /* This also removes the current remote from remote_list */ -+ free_irctl(ir, FREE_ALL); -+} -+ -+static struct usb_driver usb_remote_driver = { -+ .name = DRIVER_NAME, -+ .probe = usb_remote_probe, -+ .disconnect = usb_remote_disconnect, -+ .id_table = usb_remote_table -+}; -+ -+static int __init usb_remote_init(void) -+{ -+ int i; -+ -+ INIT_LIST_HEAD(&remote_list); -+ -+ printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " -+ DRIVER_VERSION "\n"); -+ printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); -+ dprintk(DRIVER_NAME ": debug mode enabled: " -+ "$Id: lirc_xbox.c,v 1.88 2011/06/05 11:11:11 jmartin Exp $\n"); -+ -+ repeat_jiffies = repeat*HZ/100; -+ -+ i = usb_register(&usb_remote_driver); -+ if (i) { -+ printk(DRIVER_NAME ": usb register failed, result = %d\n", i); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+static void __exit usb_remote_exit(void) -+{ -+ usb_deregister(&usb_remote_driver); -+} -+ -+module_init(usb_remote_init); -+module_exit(usb_remote_exit); -+ -+MODULE_DESCRIPTION(DRIVER_DESC); -+MODULE_AUTHOR(DRIVER_AUTHOR); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(usb, usb_remote_table); -+ -+module_param(debug, bool, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); -+ -+module_param(mask, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); -+ -+module_param(unique, bool, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); -+ -+module_param(repeat, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); -diff -Naur linux-3.9.4/drivers/staging/media/lirc/Makefile linux-3.9.4.patch/drivers/staging/media/lirc/Makefile ---- linux-3.9.4/drivers/staging/media/lirc/Makefile 2013-05-24 20:45:59.000000000 +0200 -+++ linux-3.9.4.patch/drivers/staging/media/lirc/Makefile 2013-05-30 18:17:39.163634834 +0200 -@@ -10,4 +10,5 @@ - obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o - obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o - obj-$(CONFIG_LIRC_SIR) += lirc_sir.o -+obj-$(CONFIG_LIRC_XBOX) += lirc_xbox.o - obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o diff --git a/packages/linux/patches/3.9.8/linux-053-spinelplus-remote-0.2.patch b/packages/linux/patches/3.9.8/linux-053-spinelplus-remote-0.2.patch deleted file mode 100644 index f110183d85..0000000000 --- a/packages/linux/patches/3.9.8/linux-053-spinelplus-remote-0.2.patch +++ /dev/null @@ -1,161 +0,0 @@ -diff -Naur linux-3.9/drivers/hid/hid-core.c linux-3.9.patch/drivers/hid/hid-core.c ---- linux-3.9/drivers/hid/hid-core.c 2013-04-29 02:36:01.000000000 +0200 -+++ linux-3.9.patch/drivers/hid/hid-core.c 2013-04-29 17:08:40.528324010 +0200 -@@ -1681,6 +1681,9 @@ - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) }, - { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, - { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, - #if IS_ENABLED(CONFIG_HID_ROCCAT) - { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) }, -diff -Naur linux-3.9/drivers/hid/hid-ids.h linux-3.9.patch/drivers/hid/hid-ids.h ---- linux-3.9/drivers/hid/hid-ids.h 2013-04-29 02:36:01.000000000 +0200 -+++ linux-3.9.patch/drivers/hid/hid-ids.h 2013-04-29 17:08:40.537323981 +0200 -@@ -663,6 +663,9 @@ - - #define USB_VENDOR_ID_PHILIPS 0x0471 - #define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617 -+#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1 0x206c -+#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2 0x20cc -+#define USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3 0x0613 - - #define USB_VENDOR_ID_PI_ENGINEERING 0x05f3 - #define USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL 0xff -diff -Naur linux-3.9/drivers/hid/hid-spinelplus.c linux-3.9.patch/drivers/hid/hid-spinelplus.c ---- linux-3.9/drivers/hid/hid-spinelplus.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.9.patch/drivers/hid/hid-spinelplus.c 2013-04-29 17:08:40.537323981 +0200 -@@ -0,0 +1,104 @@ -+/* -+ * HID driver for "PHILIPS MCE USB IR Receiver- Spinel plus" remotes -+ * -+ * Copyright (c) 2010 Panagiotis Skintzos -+ * -+ * Renamed to Spinel, cleanup and modified to also support -+ * Spinel Plus 0471:20CC by Stephan Raue 2012. -+ */ -+ -+/* -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License as published by the Free -+ * Software Foundation; either version 2 of the License, or (at your option) -+ * any later version. -+ */ -+ -+#include -+#include -+#include -+#include -+ -+#include "hid-ids.h" -+ -+#define spinelplus_map_key(c) set_bit(EV_REP, hi->input->evbit); \ -+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) -+ -+static int spinelplus_input_mapping(struct hid_device *hdev, -+ struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, -+ unsigned long **bit, int *max) -+{ -+ switch (usage->hid) { -+ case 0xffbc000d: spinelplus_map_key(KEY_MEDIA); break; -+ case 0xffbc0024: spinelplus_map_key(KEY_MEDIA); break; -+ case 0xffbc0027: spinelplus_map_key(KEY_ZOOM); break; -+ case 0xffbc0033: spinelplus_map_key(KEY_HOME); break; -+ case 0xffbc0035: spinelplus_map_key(KEY_CAMERA); break; -+ case 0xffbc0036: spinelplus_map_key(KEY_EPG); break; -+ case 0xffbc0037: spinelplus_map_key(KEY_DVD); break; -+ case 0xffbc0038: spinelplus_map_key(KEY_HOME); break; -+ case 0xffbc0039: spinelplus_map_key(KEY_MP3); break; -+ case 0xffbc003a: spinelplus_map_key(KEY_VIDEO); break; -+ case 0xffbc005a: spinelplus_map_key(KEY_TEXT); break; -+ case 0xffbc005b: spinelplus_map_key(KEY_RED); break; -+ case 0xffbc005c: spinelplus_map_key(KEY_GREEN); break; -+ case 0xffbc005d: spinelplus_map_key(KEY_YELLOW); break; -+ case 0xffbc005e: spinelplus_map_key(KEY_BLUE); break; -+ default: -+ return 0; -+ } -+ return 1; -+} -+ -+static int spinelplus_probe(struct hid_device *hdev, -+ const struct hid_device_id *id) -+{ -+ int ret; -+ /* Connect only to hid input (not hiddev & hidraw)*/ -+ unsigned int cmask = HID_CONNECT_HIDINPUT; -+ -+ ret = hid_parse(hdev); -+ if (ret) { -+ dev_err(&hdev->dev, "parse failed\n"); -+ goto err_free; -+ } -+ -+ ret = hid_hw_start(hdev, cmask); -+ if (ret) { -+ dev_err(&hdev->dev, "hw start failed\n"); -+ goto err_free; -+ } -+ -+ return 0; -+err_free: -+ return ret; -+} -+ -+static const struct hid_device_id spinelplus_devices[] = { -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_1) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_2) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS,USB_DEVICE_ID_PHILIPS_SPINEL_PLUS_3) }, -+ { } -+}; -+MODULE_DEVICE_TABLE(hid, spinelplus_devices); -+ -+static struct hid_driver spinelplus_driver = { -+ .name = "SpinelPlus", -+ .id_table = spinelplus_devices, -+ .input_mapping = spinelplus_input_mapping, -+ .probe = spinelplus_probe, -+}; -+ -+static int __init spinelplus_init(void) -+{ -+ return hid_register_driver(&spinelplus_driver); -+} -+ -+static void __exit spinelplus_exit(void) -+{ -+ hid_unregister_driver(&spinelplus_driver); -+} -+ -+module_init(spinelplus_init); -+module_exit(spinelplus_exit); -+MODULE_LICENSE("GPL"); -diff -Naur linux-3.9/drivers/hid/Kconfig linux-3.9.patch/drivers/hid/Kconfig ---- linux-3.9/drivers/hid/Kconfig 2013-04-29 02:36:01.000000000 +0200 -+++ linux-3.9.patch/drivers/hid/Kconfig 2013-04-29 17:08:40.538323977 +0200 -@@ -602,6 +602,12 @@ - ---help--- - Support for Steelseries SRW-S1 steering wheel - -+config HID_SPINELPLUS -+ tristate "Spinel Plus remote control" -+ depends on USB_HID -+ ---help--- -+ Say Y here if you have a Spinel Plus (0471:206c/20cc/0613) remote -+ - config HID_SUNPLUS - tristate "Sunplus wireless desktop" - depends on USB_HID -diff -Naur linux-3.9/drivers/hid/Makefile linux-3.9.patch/drivers/hid/Makefile ---- linux-3.9/drivers/hid/Makefile 2013-04-29 02:36:01.000000000 +0200 -+++ linux-3.9.patch/drivers/hid/Makefile 2013-04-29 17:09:26.744173841 +0200 -@@ -101,6 +101,7 @@ - obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o - obj-$(CONFIG_HID_SONY) += hid-sony.o - obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o -+obj-$(CONFIG_HID_SPINELPLUS) += hid-spinelplus.o - obj-$(CONFIG_HID_STEELSERIES) += hid-steelseries.o - obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o - obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o diff --git a/packages/linux/patches/3.9.8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch b/packages/linux/patches/3.9.8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch deleted file mode 100644 index 08566d1f13..0000000000 --- a/packages/linux/patches/3.9.8/linux-054-nuvoton_revert_d7b290a1056c5564eec8a1b169c6e84ff3.6.114c13.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur linux-3.0/drivers/media/rc/nuvoton-cir.c linux-3.0.patch/drivers/media/rc/nuvoton-cir.c ---- linux-3.0/drivers/media/rc/nuvoton-cir.c 2011-07-22 04:17:23.000000000 +0200 -+++ linux-3.0.patch/drivers/media/rc/nuvoton-cir.c 2011-07-22 21:30:48.374591146 +0200 -@@ -1110,7 +1110,7 @@ - rdev->dev.parent = &pdev->dev; - rdev->driver_name = NVT_DRIVER_NAME; - rdev->map_name = RC_MAP_RC6_MCE; -- rdev->timeout = MS_TO_NS(100); -+ rdev->timeout = US_TO_NS(1000); - /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ - rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD); - #if 0 diff --git a/packages/linux/patches/3.9.8/linux-055-add_Formosa_eHome_Infrared_Receiver.patch b/packages/linux/patches/3.9.8/linux-055-add_Formosa_eHome_Infrared_Receiver.patch deleted file mode 100644 index e2afb63e3d..0000000000 --- a/packages/linux/patches/3.9.8/linux-055-add_Formosa_eHome_Infrared_Receiver.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-3.2.2.orig/drivers/media/rc/mceusb.c 2012-01-30 23:37:12.374473509 +0100 -+++ linux-3.2.2/drivers/media/rc/mceusb.c 2012-01-30 23:40:57.989652931 +0100 -@@ -350,6 +350,8 @@ - { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, - /* Formosa21 / eHome Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, -+ /* Formosa21 / eHome Infrared Receiver */ -+ { USB_DEVICE(VENDOR_FORMOSA, 0xe042) }, - /* Formosa aim / Trust MCE Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe017), - .driver_info = MCE_GEN2_NO_TX }, diff --git a/packages/linux/patches/3.9.8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch b/packages/linux/patches/3.9.8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch deleted file mode 100644 index 461a82e4d5..0000000000 --- a/packages/linux/patches/3.9.8/linux-056-add_Adaptec_eHome_Infrared_Receiver.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff -Naur linux-3.6.7/drivers/media/rc/mceusb.c linux-3.6.7.patch/drivers/media/rc/mceusb.c ---- linux-3.6.7/drivers/media/rc/mceusb.c 2012-11-29 04:45:51.142129739 +0100 -+++ linux-3.6.7.patch/drivers/media/rc/mceusb.c 2012-11-29 04:51:30.982828558 +0100 -@@ -200,6 +200,7 @@ - #define VENDOR_TIVO 0x105a - #define VENDOR_CONEXANT 0x0572 - #define VENDOR_TWISTEDMELON 0x2596 -+#define VENDOR_ADAPTEC 0x03f3 - - enum mceusb_model_type { - MCE_GEN2 = 0, /* Most boards */ -@@ -400,6 +401,8 @@ - { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8016) }, - /* Twisted Melon Inc. - Manta Transceiver */ - { USB_DEVICE(VENDOR_TWISTEDMELON, 0x8042) }, -+ /* Adaptec / HP eHome Receiver */ -+ { USB_DEVICE(VENDOR_ADAPTEC, 0x0094) }, - /* Terminating entry */ - { } - }; diff --git a/packages/linux/patches/3.9.8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch b/packages/linux/patches/3.9.8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch deleted file mode 100644 index 9f84e6659f..0000000000 --- a/packages/linux/patches/3.9.8/linux-057-Removed-MCE-customer-code-restriction-in-rc6-decode.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- linux/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:08:13.148418669 -0800 -+++ linux.patch/drivers/media/rc/ir-rc6-decoder.c 2012-11-25 22:07:48.864417975 -0800 -@@ -39,7 +39,6 @@ - #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ - #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ - #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ --#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ - #ifndef CHAR_BIT - #define CHAR_BIT 8 /* Normally in */ - #endif -@@ -242,9 +241,8 @@ again: - } - - scancode = data->body; -- if (data->count == RC6_6A_32_NBITS && -- (scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) { -- /* MCE RC */ -+ if (data->count == RC6_6A_32_NBITS) { -+ /* MCE compatible RC */ - toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0; - scancode &= ~RC6_6A_MCE_TOGGLE_MASK; - } else { diff --git a/packages/linux/patches/3.9.8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch b/packages/linux/patches/3.9.8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch deleted file mode 100644 index 67fc7a0de8..0000000000 --- a/packages/linux/patches/3.9.8/linux-057-add_SMK_Manufacturing_Inc_Infrared_Receiver.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -Naur linux-3.9.4/drivers/media/rc/mceusb.c linux-3.9.4.patch/drivers/media/rc/mceusb.c ---- linux-3.9.4/drivers/media/rc/mceusb.c 2013-05-24 20:45:59.000000000 +0200 -+++ linux-3.9.4.patch/drivers/media/rc/mceusb.c 2013-05-27 12:28:12.811230633 +0200 -@@ -309,6 +309,9 @@ - /* SMK/I-O Data GV-MC7/RCKIT Receiver */ - { USB_DEVICE(VENDOR_SMK, 0x0353), - .driver_info = MCE_GEN2_NO_TX }, -+ /* SMK Manufacturing, Inc. Receiver */ -+ { USB_DEVICE(VENDOR_SMK, 0x0357), -+ .driver_info = MCE_GEN2_NO_TX }, - /* Tatung eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, - /* Shuttle eHome Infrared Transceiver */ diff --git a/packages/linux/patches/3.9.8/linux-058.01-HID-Sony-upstream_patches.patch b/packages/linux/patches/3.9.8/linux-058.01-HID-Sony-upstream_patches.patch deleted file mode 100644 index 60cdb00b31..0000000000 --- a/packages/linux/patches/3.9.8/linux-058.01-HID-Sony-upstream_patches.patch +++ /dev/null @@ -1,860 +0,0 @@ -diff -Naur linux-3.9.8/drivers/hid/hid-core.c linux-3.9.8.patch/drivers/hid/hid-core.c ---- linux-3.9.8/drivers/hid/hid-core.c 2013-06-27 19:41:32.000000000 +0200 -+++ linux-3.9.8.patch/drivers/hid/hid-core.c 2013-06-29 14:25:21.160976576 +0200 -@@ -1697,6 +1697,8 @@ - { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, -diff -Naur linux-3.9.8/drivers/hid/hid-ids.h linux-3.9.8.patch/drivers/hid/hid-ids.h ---- linux-3.9.8/drivers/hid/hid-ids.h 2013-06-27 19:41:32.000000000 +0200 -+++ linux-3.9.8.patch/drivers/hid/hid-ids.h 2013-06-29 14:25:21.161976575 +0200 -@@ -727,6 +727,8 @@ - #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 - #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 - #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f -+#define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 -+#define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 - - #define USB_VENDOR_ID_SOUNDGRAPH 0x15c2 - #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST 0x0034 -diff -Naur linux-3.9.8/drivers/hid/hid-ps3remote.c linux-3.9.8.patch/drivers/hid/hid-ps3remote.c ---- linux-3.9.8/drivers/hid/hid-ps3remote.c 2013-06-27 19:41:32.000000000 +0200 -+++ linux-3.9.8.patch/drivers/hid/hid-ps3remote.c 1970-01-01 01:00:00.000000000 +0100 -@@ -1,204 +0,0 @@ --/* -- * HID driver for Sony PS3 BD Remote Control -- * -- * Copyright (c) 2012 David Dillow -- * Based on a blend of the bluez fakehid user-space code by Marcel Holtmann -- * and other kernel HID drivers. -- */ -- --/* -- * This program is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License as published by the Free -- * Software Foundation; either version 2 of the License, or (at your option) -- * any later version. -- */ -- --/* NOTE: in order for the Sony PS3 BD Remote Control to be found by -- * a Bluetooth host, the key combination Start+Enter has to be kept pressed -- * for about 7 seconds with the Bluetooth Host Controller in discovering mode. -- * -- * There will be no PIN request from the device. -- */ -- --#include --#include --#include -- --#include "hid-ids.h" -- --static __u8 ps3remote_rdesc[] = { -- 0x05, 0x01, /* GUsagePage Generic Desktop */ -- 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ -- 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ -- -- /* Use collection 1 for joypad buttons */ -- 0xA1, 0x02, /* MCollection Logical (interrelated data) */ -- -- /* Ignore the 1st byte, maybe it is used for a controller -- * number but it's not needed for correct operation */ -- 0x75, 0x08, /* GReportSize 0x08 [8] */ -- 0x95, 0x01, /* GReportCount 0x01 [1] */ -- 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ -- -- /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these -- * buttons multiple keypresses are allowed */ -- 0x05, 0x09, /* GUsagePage Button */ -- 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ -- 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ -- 0x14, /* GLogicalMinimum [0] */ -- 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ -- 0x75, 0x01, /* GReportSize 0x01 [1] */ -- 0x95, 0x18, /* GReportCount 0x18 [24] */ -- 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ -- -- 0xC0, /* MEndCollection */ -- -- /* Use collection 2 for remote control buttons */ -- 0xA1, 0x02, /* MCollection Logical (interrelated data) */ -- -- /* 5th byte is used for remote control buttons */ -- 0x05, 0x09, /* GUsagePage Button */ -- 0x18, /* LUsageMinimum [No button pressed] */ -- 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ -- 0x14, /* GLogicalMinimum [0] */ -- 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ -- 0x75, 0x08, /* GReportSize 0x08 [8] */ -- 0x95, 0x01, /* GReportCount 0x01 [1] */ -- 0x80, /* MInput */ -- -- /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at -- * 0xff and 11th is for press indication */ -- 0x75, 0x08, /* GReportSize 0x08 [8] */ -- 0x95, 0x06, /* GReportCount 0x06 [6] */ -- 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ -- -- /* 12th byte is for battery strength */ -- 0x05, 0x06, /* GUsagePage Generic Device Controls */ -- 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ -- 0x14, /* GLogicalMinimum [0] */ -- 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ -- 0x75, 0x08, /* GReportSize 0x08 [8] */ -- 0x95, 0x01, /* GReportCount 0x01 [1] */ -- 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ -- -- 0xC0, /* MEndCollection */ -- -- 0xC0 /* MEndCollection [Game Pad] */ --}; -- --static const unsigned int ps3remote_keymap_joypad_buttons[] = { -- [0x01] = KEY_SELECT, -- [0x02] = BTN_THUMBL, /* L3 */ -- [0x03] = BTN_THUMBR, /* R3 */ -- [0x04] = BTN_START, -- [0x05] = KEY_UP, -- [0x06] = KEY_RIGHT, -- [0x07] = KEY_DOWN, -- [0x08] = KEY_LEFT, -- [0x09] = BTN_TL2, /* L2 */ -- [0x0a] = BTN_TR2, /* R2 */ -- [0x0b] = BTN_TL, /* L1 */ -- [0x0c] = BTN_TR, /* R1 */ -- [0x0d] = KEY_OPTION, /* options/triangle */ -- [0x0e] = KEY_BACK, /* back/circle */ -- [0x0f] = BTN_0, /* cross */ -- [0x10] = KEY_SCREEN, /* view/square */ -- [0x11] = KEY_HOMEPAGE, /* PS button */ -- [0x14] = KEY_ENTER, --}; --static const unsigned int ps3remote_keymap_remote_buttons[] = { -- [0x00] = KEY_1, -- [0x01] = KEY_2, -- [0x02] = KEY_3, -- [0x03] = KEY_4, -- [0x04] = KEY_5, -- [0x05] = KEY_6, -- [0x06] = KEY_7, -- [0x07] = KEY_8, -- [0x08] = KEY_9, -- [0x09] = KEY_0, -- [0x0e] = KEY_ESC, /* return */ -- [0x0f] = KEY_CLEAR, -- [0x16] = KEY_EJECTCD, -- [0x1a] = KEY_MENU, /* top menu */ -- [0x28] = KEY_TIME, -- [0x30] = KEY_PREVIOUS, -- [0x31] = KEY_NEXT, -- [0x32] = KEY_PLAY, -- [0x33] = KEY_REWIND, /* scan back */ -- [0x34] = KEY_FORWARD, /* scan forward */ -- [0x38] = KEY_STOP, -- [0x39] = KEY_PAUSE, -- [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ -- [0x60] = KEY_FRAMEBACK, /* slow/step back */ -- [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ -- [0x63] = KEY_SUBTITLE, -- [0x64] = KEY_AUDIO, -- [0x65] = KEY_ANGLE, -- [0x70] = KEY_INFO, /* display */ -- [0x80] = KEY_BLUE, -- [0x81] = KEY_RED, -- [0x82] = KEY_GREEN, -- [0x83] = KEY_YELLOW, --}; -- --static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, -- unsigned int *rsize) --{ -- *rsize = sizeof(ps3remote_rdesc); -- return ps3remote_rdesc; --} -- --static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, -- struct hid_field *field, struct hid_usage *usage, -- unsigned long **bit, int *max) --{ -- unsigned int key = usage->hid & HID_USAGE; -- -- if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) -- return -1; -- -- switch (usage->collection_index) { -- case 1: -- if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) -- return -1; -- -- key = ps3remote_keymap_joypad_buttons[key]; -- if (!key) -- return -1; -- break; -- case 2: -- if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) -- return -1; -- -- key = ps3remote_keymap_remote_buttons[key]; -- if (!key) -- return -1; -- break; -- default: -- return -1; -- } -- -- hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); -- return 1; --} -- --static const struct hid_device_id ps3remote_devices[] = { -- /* PS3 BD Remote Control */ -- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, -- /* Logitech Harmony Adapter for PS3 */ -- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, -- { } --}; --MODULE_DEVICE_TABLE(hid, ps3remote_devices); -- --static struct hid_driver ps3remote_driver = { -- .name = "ps3_remote", -- .id_table = ps3remote_devices, -- .report_fixup = ps3remote_fixup, -- .input_mapping = ps3remote_mapping, --}; --module_hid_driver(ps3remote_driver); -- --MODULE_LICENSE("GPL"); --MODULE_AUTHOR("David Dillow , Antonio Ospite "); -diff -Naur linux-3.9.8/drivers/hid/hid-sony.c linux-3.9.8.patch/drivers/hid/hid-sony.c ---- linux-3.9.8/drivers/hid/hid-sony.c 2013-06-27 19:41:32.000000000 +0200 -+++ linux-3.9.8.patch/drivers/hid/hid-sony.c 2013-06-29 14:26:02.738933634 +0200 -@@ -1,11 +1,13 @@ - /* -- * HID driver for some sony "special" devices -+ * HID driver for Sony / PS2 / PS3 BD devices. - * - * Copyright (c) 1999 Andreas Gal - * Copyright (c) 2000-2005 Vojtech Pavlik - * Copyright (c) 2005 Michael Haboustak for Concept2, Inc - * Copyright (c) 2008 Jiri Slaby -- * Copyright (c) 2006-2008 Jiri Kosina -+ * Copyright (c) 2012 David Dillow -+ * Copyright (c) 2006-2013 Jiri Kosina -+ * Copyright (c) 2013 Colin Leitner - */ - - /* -@@ -15,17 +17,28 @@ - * any later version. - */ - -+/* NOTE: in order for the Sony PS3 BD Remote Control to be found by -+ * a Bluetooth host, the key combination Start+Enter has to be kept pressed -+ * for about 7 seconds with the Bluetooth Host Controller in discovering mode. -+ * -+ * There will be no PIN request from the device. -+ */ -+ - #include - #include - #include - #include - #include -+#include "usbhid/usbhid.h" -+#include - - #include "hid-ids.h" - - #define VAIO_RDESC_CONSTANT (1 << 0) - #define SIXAXIS_CONTROLLER_USB (1 << 1) - #define SIXAXIS_CONTROLLER_BT (1 << 2) -+#define BUZZ_CONTROLLER (1 << 3) -+#define PS3REMOTE (1 << 4) - - static const u8 sixaxis_rdesc_fixup[] = { - 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, -@@ -55,10 +68,214 @@ - 0xb1, 0x02, 0xc0, 0xc0, - }; - -+static __u8 ps3remote_rdesc[] = { -+ 0x05, 0x01, /* GUsagePage Generic Desktop */ -+ 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ -+ 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ -+ -+ /* Use collection 1 for joypad buttons */ -+ 0xA1, 0x02, /* MCollection Logical (interrelated data) */ -+ -+ /* Ignore the 1st byte, maybe it is used for a controller -+ * number but it's not needed for correct operation */ -+ 0x75, 0x08, /* GReportSize 0x08 [8] */ -+ 0x95, 0x01, /* GReportCount 0x01 [1] */ -+ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ -+ -+ /* Bytes from 2nd to 4th are a bitmap for joypad buttons, for these -+ * buttons multiple keypresses are allowed */ -+ 0x05, 0x09, /* GUsagePage Button */ -+ 0x19, 0x01, /* LUsageMinimum 0x01 [Button 1 (primary/trigger)] */ -+ 0x29, 0x18, /* LUsageMaximum 0x18 [Button 24] */ -+ 0x14, /* GLogicalMinimum [0] */ -+ 0x25, 0x01, /* GLogicalMaximum 0x01 [1] */ -+ 0x75, 0x01, /* GReportSize 0x01 [1] */ -+ 0x95, 0x18, /* GReportCount 0x18 [24] */ -+ 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ -+ -+ 0xC0, /* MEndCollection */ -+ -+ /* Use collection 2 for remote control buttons */ -+ 0xA1, 0x02, /* MCollection Logical (interrelated data) */ -+ -+ /* 5th byte is used for remote control buttons */ -+ 0x05, 0x09, /* GUsagePage Button */ -+ 0x18, /* LUsageMinimum [No button pressed] */ -+ 0x29, 0xFE, /* LUsageMaximum 0xFE [Button 254] */ -+ 0x14, /* GLogicalMinimum [0] */ -+ 0x26, 0xFE, 0x00, /* GLogicalMaximum 0x00FE [254] */ -+ 0x75, 0x08, /* GReportSize 0x08 [8] */ -+ 0x95, 0x01, /* GReportCount 0x01 [1] */ -+ 0x80, /* MInput */ -+ -+ /* Ignore bytes from 6th to 11th, 6th to 10th are always constant at -+ * 0xff and 11th is for press indication */ -+ 0x75, 0x08, /* GReportSize 0x08 [8] */ -+ 0x95, 0x06, /* GReportCount 0x06 [6] */ -+ 0x81, 0x01, /* MInput 0x01 (Const[0] Arr[1] Abs[2]) */ -+ -+ /* 12th byte is for battery strength */ -+ 0x05, 0x06, /* GUsagePage Generic Device Controls */ -+ 0x09, 0x20, /* LUsage 0x20 [Battery Strength] */ -+ 0x14, /* GLogicalMinimum [0] */ -+ 0x25, 0x05, /* GLogicalMaximum 0x05 [5] */ -+ 0x75, 0x08, /* GReportSize 0x08 [8] */ -+ 0x95, 0x01, /* GReportCount 0x01 [1] */ -+ 0x81, 0x02, /* MInput 0x02 (Data[0] Var[1] Abs[2]) */ -+ -+ 0xC0, /* MEndCollection */ -+ -+ 0xC0 /* MEndCollection [Game Pad] */ -+}; -+ -+static const unsigned int ps3remote_keymap_joypad_buttons[] = { -+ [0x01] = KEY_SELECT, -+ [0x02] = BTN_THUMBL, /* L3 */ -+ [0x03] = BTN_THUMBR, /* R3 */ -+ [0x04] = BTN_START, -+ [0x05] = KEY_UP, -+ [0x06] = KEY_RIGHT, -+ [0x07] = KEY_DOWN, -+ [0x08] = KEY_LEFT, -+ [0x09] = BTN_TL2, /* L2 */ -+ [0x0a] = BTN_TR2, /* R2 */ -+ [0x0b] = BTN_TL, /* L1 */ -+ [0x0c] = BTN_TR, /* R1 */ -+ [0x0d] = KEY_OPTION, /* options/triangle */ -+ [0x0e] = KEY_BACK, /* back/circle */ -+ [0x0f] = BTN_0, /* cross */ -+ [0x10] = KEY_SCREEN, /* view/square */ -+ [0x11] = KEY_HOMEPAGE, /* PS button */ -+ [0x14] = KEY_ENTER, -+}; -+static const unsigned int ps3remote_keymap_remote_buttons[] = { -+ [0x00] = KEY_1, -+ [0x01] = KEY_2, -+ [0x02] = KEY_3, -+ [0x03] = KEY_4, -+ [0x04] = KEY_5, -+ [0x05] = KEY_6, -+ [0x06] = KEY_7, -+ [0x07] = KEY_8, -+ [0x08] = KEY_9, -+ [0x09] = KEY_0, -+ [0x0e] = KEY_ESC, /* return */ -+ [0x0f] = KEY_CLEAR, -+ [0x16] = KEY_EJECTCD, -+ [0x1a] = KEY_MENU, /* top menu */ -+ [0x28] = KEY_TIME, -+ [0x30] = KEY_PREVIOUS, -+ [0x31] = KEY_NEXT, -+ [0x32] = KEY_PLAY, -+ [0x33] = KEY_REWIND, /* scan back */ -+ [0x34] = KEY_FORWARD, /* scan forward */ -+ [0x38] = KEY_STOP, -+ [0x39] = KEY_PAUSE, -+ [0x40] = KEY_CONTEXT_MENU, /* pop up/menu */ -+ [0x60] = KEY_FRAMEBACK, /* slow/step back */ -+ [0x61] = KEY_FRAMEFORWARD, /* slow/step forward */ -+ [0x63] = KEY_SUBTITLE, -+ [0x64] = KEY_AUDIO, -+ [0x65] = KEY_ANGLE, -+ [0x70] = KEY_INFO, /* display */ -+ [0x80] = KEY_BLUE, -+ [0x81] = KEY_RED, -+ [0x82] = KEY_GREEN, -+ [0x83] = KEY_YELLOW, -+}; -+ -+static const unsigned int buzz_keymap[] = { -+ /* The controller has 4 remote buzzers, each with one LED and 5 -+ * buttons. -+ * -+ * We use the mapping chosen by the controller, which is: -+ * -+ * Key Offset -+ * ------------------- -+ * Buzz 1 -+ * Blue 5 -+ * Orange 4 -+ * Green 3 -+ * Yellow 2 -+ * -+ * So, for example, the orange button on the third buzzer is mapped to -+ * BTN_TRIGGER_HAPPY14 -+ */ -+ [ 1] = BTN_TRIGGER_HAPPY1, -+ [ 2] = BTN_TRIGGER_HAPPY2, -+ [ 3] = BTN_TRIGGER_HAPPY3, -+ [ 4] = BTN_TRIGGER_HAPPY4, -+ [ 5] = BTN_TRIGGER_HAPPY5, -+ [ 6] = BTN_TRIGGER_HAPPY6, -+ [ 7] = BTN_TRIGGER_HAPPY7, -+ [ 8] = BTN_TRIGGER_HAPPY8, -+ [ 9] = BTN_TRIGGER_HAPPY9, -+ [10] = BTN_TRIGGER_HAPPY10, -+ [11] = BTN_TRIGGER_HAPPY11, -+ [12] = BTN_TRIGGER_HAPPY12, -+ [13] = BTN_TRIGGER_HAPPY13, -+ [14] = BTN_TRIGGER_HAPPY14, -+ [15] = BTN_TRIGGER_HAPPY15, -+ [16] = BTN_TRIGGER_HAPPY16, -+ [17] = BTN_TRIGGER_HAPPY17, -+ [18] = BTN_TRIGGER_HAPPY18, -+ [19] = BTN_TRIGGER_HAPPY19, -+ [20] = BTN_TRIGGER_HAPPY20, -+}; -+ - struct sony_sc { - unsigned long quirks; -+ -+ void *extra; -+}; -+ -+struct buzz_extra { -+ int led_state; -+ struct led_classdev *leds[4]; - }; - -+static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, -+ unsigned int *rsize) -+{ -+ *rsize = sizeof(ps3remote_rdesc); -+ return ps3remote_rdesc; -+} -+ -+static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, -+ struct hid_field *field, struct hid_usage *usage, -+ unsigned long **bit, int *max) -+{ -+ unsigned int key = usage->hid & HID_USAGE; -+ -+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) -+ return -1; -+ -+ switch (usage->collection_index) { -+ case 1: -+ if (key >= ARRAY_SIZE(ps3remote_keymap_joypad_buttons)) -+ return -1; -+ -+ key = ps3remote_keymap_joypad_buttons[key]; -+ if (!key) -+ return -1; -+ break; -+ case 2: -+ if (key >= ARRAY_SIZE(ps3remote_keymap_remote_buttons)) -+ return -1; -+ -+ key = ps3remote_keymap_remote_buttons[key]; -+ if (!key) -+ return -1; -+ break; -+ default: -+ return -1; -+ } -+ -+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); -+ return 1; -+} -+ -+ - /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ - static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) -@@ -95,6 +312,10 @@ - *rsize = sizeof(sixaxis_rdesc_fixup2); - memcpy(rdesc, &sixaxis_rdesc_fixup2, *rsize); - } -+ -+ if (sc->quirks & PS3REMOTE) -+ return ps3remote_fixup(hdev, rdesc, rsize); -+ - return rdesc; - } - -@@ -117,6 +338,41 @@ - return 0; - } - -+static int sony_mapping(struct hid_device *hdev, struct hid_input *hi, -+ struct hid_field *field, struct hid_usage *usage, -+ unsigned long **bit, int *max) -+{ -+ struct sony_sc *sc = hid_get_drvdata(hdev); -+ -+ if (sc->quirks & BUZZ_CONTROLLER) { -+ unsigned int key = usage->hid & HID_USAGE; -+ -+ if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON) -+ return -1; -+ -+ switch (usage->collection_index) { -+ case 1: -+ if (key >= ARRAY_SIZE(buzz_keymap)) -+ return -1; -+ -+ key = buzz_keymap[key]; -+ if (!key) -+ return -1; -+ break; -+ default: -+ return -1; -+ } -+ -+ hid_map_usage_clear(hi, usage, bit, max, EV_KEY, key); -+ return 1; -+ } -+ -+ if (sc->quirks & PS3REMOTE) -+ return ps3remote_mapping(hdev, hi, field, usage, bit, max); -+ -+ return -1; -+} -+ - /* - * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP - * like it should according to usbhid/hid-core.c::usbhid_output_raw_report() -@@ -192,11 +448,181 @@ - return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); - } - -+static void buzz_set_leds(struct hid_device *hdev, int leds) -+{ -+ struct list_head *report_list = -+ &hdev->report_enum[HID_OUTPUT_REPORT].report_list; -+ struct hid_report *report = list_entry(report_list->next, -+ struct hid_report, list); -+ __s32 *value = report->field[0]->value; -+ -+ value[0] = 0x00; -+ value[1] = (leds & 1) ? 0xff : 0x00; -+ value[2] = (leds & 2) ? 0xff : 0x00; -+ value[3] = (leds & 4) ? 0xff : 0x00; -+ value[4] = (leds & 8) ? 0xff : 0x00; -+ value[5] = 0x00; -+ value[6] = 0x00; -+ usbhid_submit_report(hdev, report, USB_DIR_OUT); -+} -+ -+static void buzz_led_set_brightness(struct led_classdev *led, -+ enum led_brightness value) -+{ -+ struct device *dev = led->dev->parent; -+ struct hid_device *hdev = container_of(dev, struct hid_device, dev); -+ struct sony_sc *drv_data; -+ struct buzz_extra *buzz; -+ -+ int n; -+ -+ drv_data = hid_get_drvdata(hdev); -+ if (!drv_data || !drv_data->extra) { -+ hid_err(hdev, "No device data\n"); -+ return; -+ } -+ buzz = drv_data->extra; -+ -+ for (n = 0; n < 4; n++) { -+ if (led == buzz->leds[n]) { -+ int on = !! (buzz->led_state & (1 << n)); -+ if (value == LED_OFF && on) { -+ buzz->led_state &= ~(1 << n); -+ buzz_set_leds(hdev, buzz->led_state); -+ } else if (value != LED_OFF && !on) { -+ buzz->led_state |= (1 << n); -+ buzz_set_leds(hdev, buzz->led_state); -+ } -+ break; -+ } -+ } -+} -+ -+static enum led_brightness buzz_led_get_brightness(struct led_classdev *led) -+{ -+ struct device *dev = led->dev->parent; -+ struct hid_device *hdev = container_of(dev, struct hid_device, dev); -+ struct sony_sc *drv_data; -+ struct buzz_extra *buzz; -+ -+ int n; -+ int on = 0; -+ -+ drv_data = hid_get_drvdata(hdev); -+ if (!drv_data || !drv_data->extra) { -+ hid_err(hdev, "No device data\n"); -+ return LED_OFF; -+ } -+ buzz = drv_data->extra; -+ -+ for (n = 0; n < 4; n++) { -+ if (led == buzz->leds[n]) { -+ on = !! (buzz->led_state & (1 << n)); -+ break; -+ } -+ } -+ -+ return on ? LED_FULL : LED_OFF; -+} -+ -+static int buzz_init(struct hid_device *hdev) -+{ -+ struct sony_sc *drv_data; -+ struct buzz_extra *buzz; -+ int n, ret = 0; -+ struct led_classdev *led; -+ size_t name_sz; -+ char *name; -+ -+ drv_data = hid_get_drvdata(hdev); -+ BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); -+ -+ buzz = kzalloc(sizeof(*buzz), GFP_KERNEL); -+ if (!buzz) { -+ hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); -+ return -ENOMEM; -+ } -+ drv_data->extra = buzz; -+ -+ /* Clear LEDs as we have no way of reading their initial state. This is -+ * only relevant if the driver is loaded after somebody actively set the -+ * LEDs to on */ -+ buzz_set_leds(hdev, 0x00); -+ -+ name_sz = strlen(dev_name(&hdev->dev)) + strlen("::buzz#") + 1; -+ -+ for (n = 0; n < 4; n++) { -+ led = kzalloc(sizeof(struct led_classdev) + name_sz, GFP_KERNEL); -+ if (!led) { -+ hid_err(hdev, "Couldn't allocate memory for LED %d\n", n); -+ goto error_leds; -+ } -+ -+ name = (void *)(&led[1]); -+ snprintf(name, name_sz, "%s::buzz%d", dev_name(&hdev->dev), n + 1); -+ led->name = name; -+ led->brightness = 0; -+ led->max_brightness = 1; -+ led->brightness_get = buzz_led_get_brightness; -+ led->brightness_set = buzz_led_set_brightness; -+ -+ if (led_classdev_register(&hdev->dev, led)) { -+ hid_err(hdev, "Failed to register LED %d\n", n); -+ kfree(led); -+ goto error_leds; -+ } -+ -+ buzz->leds[n] = led; -+ } -+ -+ return ret; -+ -+error_leds: -+ for (n = 0; n < 4; n++) { -+ led = buzz->leds[n]; -+ buzz->leds[n] = NULL; -+ if (!led) -+ continue; -+ led_classdev_unregister(led); -+ kfree(led); -+ } -+ -+ kfree(drv_data->extra); -+ drv_data->extra = NULL; -+ return ret; -+} -+ -+static void buzz_remove(struct hid_device *hdev) -+{ -+ struct sony_sc *drv_data; -+ struct buzz_extra *buzz; -+ struct led_classdev *led; -+ int n; -+ -+ drv_data = hid_get_drvdata(hdev); -+ BUG_ON(!(drv_data->quirks & BUZZ_CONTROLLER)); -+ -+ buzz = drv_data->extra; -+ -+ for (n = 0; n < 4; n++) { -+ led = buzz->leds[n]; -+ buzz->leds[n] = NULL; -+ if (!led) -+ continue; -+ led_classdev_unregister(led); -+ kfree(led); -+ } -+ -+ kfree(drv_data->extra); -+ drv_data->extra = NULL; -+} -+ - static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) - { - int ret; - unsigned long quirks = id->driver_data; - struct sony_sc *sc; -+ unsigned int connect_mask = HID_CONNECT_DEFAULT; - - sc = kzalloc(sizeof(*sc), GFP_KERNEL); - if (sc == NULL) { -@@ -213,8 +639,14 @@ - goto err_free; - } - -- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | -- HID_CONNECT_HIDDEV_FORCE); -+ if (sc->quirks & VAIO_RDESC_CONSTANT) -+ connect_mask |= HID_CONNECT_HIDDEV_FORCE; -+ else if (sc->quirks & SIXAXIS_CONTROLLER_USB) -+ connect_mask |= HID_CONNECT_HIDDEV_FORCE; -+ else if (sc->quirks & SIXAXIS_CONTROLLER_BT) -+ connect_mask |= HID_CONNECT_HIDDEV_FORCE; -+ -+ ret = hid_hw_start(hdev, connect_mask); - if (ret) { - hid_err(hdev, "hw start failed\n"); - goto err_free; -@@ -226,6 +658,8 @@ - } - else if (sc->quirks & SIXAXIS_CONTROLLER_BT) - ret = sixaxis_set_operational_bt(hdev); -+ else if (sc->quirks & BUZZ_CONTROLLER) -+ ret = buzz_init(hdev); - else - ret = 0; - -@@ -242,8 +676,13 @@ - - static void sony_remove(struct hid_device *hdev) - { -+ struct sony_sc *sc = hid_get_drvdata(hdev); -+ -+ if (sc->quirks & BUZZ_CONTROLLER) -+ buzz_remove(hdev); -+ - hid_hw_stop(hdev); -- kfree(hid_get_drvdata(hdev)); -+ kfree(sc); - } - - static const struct hid_device_id sony_devices[] = { -@@ -257,17 +696,30 @@ - .driver_data = VAIO_RDESC_CONSTANT }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE), - .driver_data = VAIO_RDESC_CONSTANT }, -+ /* Wired Buzz Controller. Reported as Sony Hub from its USB ID and as -+ * Logitech joystick from the device descriptor. */ -+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER), -+ .driver_data = BUZZ_CONTROLLER }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER), -+ .driver_data = BUZZ_CONTROLLER }, -+ /* PS3 BD Remote Control */ -+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE), -+ .driver_data = PS3REMOTE }, -+ /* Logitech Harmony Adapter for PS3 */ -+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), -+ .driver_data = PS3REMOTE }, - { } - }; - MODULE_DEVICE_TABLE(hid, sony_devices); - - static struct hid_driver sony_driver = { -- .name = "sony", -- .id_table = sony_devices, -- .probe = sony_probe, -- .remove = sony_remove, -- .report_fixup = sony_report_fixup, -- .raw_event = sony_raw_event -+ .name = "sony", -+ .id_table = sony_devices, -+ .input_mapping = sony_mapping, -+ .probe = sony_probe, -+ .remove = sony_remove, -+ .report_fixup = sony_report_fixup, -+ .raw_event = sony_raw_event - }; - module_hid_driver(sony_driver); - -diff -Naur linux-3.9.8/drivers/hid/Kconfig linux-3.9.8.patch/drivers/hid/Kconfig ---- linux-3.9.8/drivers/hid/Kconfig 2013-06-27 19:41:32.000000000 +0200 -+++ linux-3.9.8.patch/drivers/hid/Kconfig 2013-06-29 14:25:21.173976563 +0200 -@@ -550,15 +550,6 @@ - Support for Primax devices that are not fully compliant with the - HID standard. - --config HID_PS3REMOTE -- tristate "Sony PS3 BD Remote Control" -- depends on BT_HIDP -- ---help--- -- Support for the Sony PS3 Blue-ray Disk Remote Control and Logitech -- Harmony Adapter for PS3, which connect over Bluetooth. -- -- Support for the 6-axis controllers is provided by HID_SONY. -- - config HID_ROCCAT - tristate "Roccat device support" - depends on USB_HID -@@ -583,12 +574,17 @@ - Support for Samsung InfraRed remote control or keyboards. - - config HID_SONY -- tristate "Sony PS3 controller" -+ tristate "Sony PS2/3 accessories" - depends on USB_HID -+ depends on NEW_LEDS -+ depends on LEDS_CLASS - ---help--- -- Support for Sony PS3 6-axis controllers. -- -- Support for the Sony PS3 BD Remote is provided by HID_PS3REMOTE. -+ Support for -+ -+ * Sony PS3 6-axis controllers -+ * Buzz controllers -+ * Sony PS3 Blue-ray Disk Remote Control (Bluetooth) -+ * Logitech Harmony adapter for Sony Playstation 3 (Bluetooth) - - config HID_SPEEDLINK - tristate "Speedlink VAD Cezanne mouse support" -diff -Naur linux-3.9.8/drivers/hid/Makefile linux-3.9.8.patch/drivers/hid/Makefile ---- linux-3.9.8/drivers/hid/Makefile 2013-06-27 19:41:32.000000000 +0200 -+++ linux-3.9.8.patch/drivers/hid/Makefile 2013-06-29 14:25:21.174976562 +0200 -@@ -91,7 +91,6 @@ - endif - - obj-$(CONFIG_HID_PRIMAX) += hid-primax.o --obj-$(CONFIG_HID_PS3REMOTE) += hid-ps3remote.o - obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ - hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ - hid-roccat-koneplus.o hid-roccat-kovaplus.o hid-roccat-lua.o \ diff --git a/packages/linux/patches/3.9.8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch b/packages/linux/patches/3.9.8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch deleted file mode 100644 index abdc74f673..0000000000 --- a/packages/linux/patches/3.9.8/linux-058.05-hid_sony-add_autorepeat_for_PS3_remotes.patch +++ /dev/null @@ -1,61 +0,0 @@ -Betreff: [RFC] hid/sony: add autorepeat for PS3 remotes -Von: David Dillow -Datum: 28.06.2013 04:28 -An: linux-input@vger.kernel.org -Kopie (CC): Stephan Raue - -Some applications using the PS3 remote would like to have autorepeat -from the device. Use the input subsystem's software emulation to provide -this capability, and enable those that don't need it to turn it off. ---- -I'm not sure this is the correct approach, or if it is even appropriate -for a remote to do autorepeat. However, the media/rc subsystem does do -it by default, and it's been requested by users, so there is at least -some demand. - -This compiled against the hid-sony driver with the PS3 remote changes -merged, but I have done no testing of it. If the approach seems -reasonable, I'll try to test it when the MythTV is idle. - - drivers/hid/hid-sony.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) -diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c -index ecbc749..0bbcd07 100644 ---- a/drivers/hid/hid-sony.c -+++ b/drivers/hid/hid-sony.c -@@ -274,6 +274,24 @@ static int ps3remote_mapping(struct hid_device *hdev, struct hid_input *hi, - return 1; - } - -+static int ps3remote_setup_repeat(struct hid_device *hdev) -+{ -+ struct hid_input *hidinput = list_first_entry(&hdev->inputs, -+ struct hid_input, list); -+ struct input_dev *input = hidinput->input; -+ -+ /* -+ * Set up autorepeat defaults per the remote control subsystem; -+ * this must be done after hid_hw_start(), as having these non-zero -+ * at the time of input_register_device() tells the input system that -+ * the hardware does the autorepeat, and the PS3 remote does not. -+ */ -+ set_bit(EV_REP, input->evbit); -+ input->rep[REP_DELAY] = 500; -+ input->rep[REP_PERIOD] = 125; -+ -+ return 0; -+} - - /* Sony Vaio VGX has wrongly mouse pointer declared as constant */ - static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, -@@ -659,6 +677,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) - ret = sixaxis_set_operational_bt(hdev); - else if (sc->quirks & BUZZ_CONTROLLER) - ret = buzz_init(hdev); -+ else if (sc->quirks & PS3REMOTE) -+ ret = ps3remote_setup_repeat(hdev); - else - ret = 0; - - - diff --git a/packages/linux/patches/3.9.8/linux-059-remove_some_xpad_pids-0.2.patch b/packages/linux/patches/3.9.8/linux-059-remove_some_xpad_pids-0.2.patch deleted file mode 100644 index 4a6d1c7a08..0000000000 --- a/packages/linux/patches/3.9.8/linux-059-remove_some_xpad_pids-0.2.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -Naur linux-3.8.4/drivers/input/joystick/xpad.c linux-3.8.4.patch/drivers/input/joystick/xpad.c ---- linux-3.8.4/drivers/input/joystick/xpad.c 2013-03-20 21:11:19.000000000 +0100 -+++ linux-3.8.4.patch/drivers/input/joystick/xpad.c 2013-03-26 20:24:29.273978355 +0100 -@@ -174,7 +174,6 @@ - { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, - { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, - { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, -- { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, - { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } - }; - diff --git a/packages/linux/patches/3.9.8/linux-060-add_AUGUST_DVB-T205.patch b/packages/linux/patches/3.9.8/linux-060-add_AUGUST_DVB-T205.patch deleted file mode 100644 index 814b4a4b25..0000000000 --- a/packages/linux/patches/3.9.8/linux-060-add_AUGUST_DVB-T205.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur linux-3.9.5/drivers/media/usb/dvb-usb-v2/rtl28xxu.c linux-3.9.5.patch/drivers/media/usb/dvb-usb-v2/rtl28xxu.c ---- linux-3.9.5/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2013-06-07 21:54:00.000000000 +0200 -+++ linux-3.9.5.patch/drivers/media/usb/dvb-usb-v2/rtl28xxu.c 2013-06-13 14:48:38.110705193 +0200 -@@ -1372,6 +1372,8 @@ - &rtl2832u_props, "Digivox Micro Hd", NULL) }, - { DVB_USB_DEVICE(USB_VID_COMPRO, 0x0620, - &rtl2832u_props, "Compro VideoMate U620F", NULL) }, -+ { DVB_USB_DEVICE(USB_VID_GTEK, 0xa803, -+ &rtl2832u_props, "Realtek RTL2832U reference design", NULL) }, - { } - }; - MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); diff --git a/packages/linux/patches/3.9.8/linux-203-stb0899_enable_low_symbol_rate.patch b/packages/linux/patches/3.9.8/linux-203-stb0899_enable_low_symbol_rate.patch deleted file mode 100644 index f302b6ce1b..0000000000 --- a/packages/linux/patches/3.9.8/linux-203-stb0899_enable_low_symbol_rate.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c ---- linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-16 10:25:43.479645317 +0100 -@@ -1581,7 +1581,7 @@ - .frequency_max = 2150000, - .frequency_stepsize = 0, - .frequency_tolerance = 0, -- .symbol_rate_min = 5000000, -+ .symbol_rate_min = 1000000, - .symbol_rate_max = 45000000, - - .caps = FE_CAN_INVERSION_AUTO | diff --git a/packages/linux/patches/3.9.8/linux-210-dvbsky.patch b/packages/linux/patches/3.9.8/linux-210-dvbsky.patch deleted file mode 100644 index e084c8cc65..0000000000 --- a/packages/linux/patches/3.9.8/linux-210-dvbsky.patch +++ /dev/null @@ -1,6161 +0,0 @@ -diff -urN a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig ---- a/drivers/media/dvb-frontends/Kconfig 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/dvb-frontends/Kconfig 2013-05-03 17:03:57.000000000 +0800 -@@ -200,6 +200,20 @@ - help - A DVB-S/S2 tuner module. Say Y when you want to support this frontend. - -+config DVB_M88DS3103 -+ tristate "Montage M88DS3103 based" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ A DVB-S/S2 tuner module. Say Y when you want to support this frontend. -+ -+config DVB_M88DC2800 -+ tristate "Montage M88DC2800 based" -+ depends on DVB_CORE && I2C -+ default m if !MEDIA_SUBDRV_AUTOSELECT -+ help -+ A DVB-C tuner module. Say Y when you want to support this frontend. -+ - config DVB_SI21XX - tristate "Silicon Labs SI21XX based" - depends on DVB_CORE && I2C -diff -urN a/drivers/media/dvb-frontends/m88dc2800.c b/drivers/media/dvb-frontends/m88dc2800.c ---- a/drivers/media/dvb-frontends/m88dc2800.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/media/dvb-frontends/m88dc2800.c 2013-01-26 16:03:21.000000000 +0800 -@@ -0,0 +1,2124 @@ -+/* -+ M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage -+ -+ Copyright (C) 2012 Max nibble -+ Copyright (C) 2011 Montage Technology / www.montage-tech.com -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "dvb_frontend.h" -+#include "m88dc2800.h" -+ -+struct m88dc2800_state { -+ struct i2c_adapter *i2c; -+ const struct m88dc2800_config *config; -+ struct dvb_frontend frontend; -+ u32 freq; -+ u32 ber; -+ u32 sym; -+ u16 qam; -+ u8 inverted; -+ u32 xtal; -+ /* tuner state */ -+ u8 tuner_init_OK; /* Tuner initialize status */ -+ u8 tuner_dev_addr; /* Tuner device address */ -+ u32 tuner_freq; /* RF frequency to be set, unit: KHz */ -+ u16 tuner_qam; /* Reserved */ -+ u16 tuner_mode; -+ u8 tuner_bandwidth; /* Bandwidth of the channel, unit: MHz, 6/7/8 */ -+ u8 tuner_loopthrough; /* Tuner loop through switch, 0/1 */ -+ u32 tuner_crystal; /* Tuner crystal frequency, unit: KHz */ -+ u32 tuner_dac; /* Tuner DAC frequency, unit: KHz */ -+ u16 tuner_mtt; /* Tuner chip version, D1: 0x0d, E0: 0x0e, E1: 0x8e */ -+ u16 tuner_custom_cfg; -+ u32 tuner_version; /* Tuner driver version number */ -+ u32 tuner_time; -+}; -+ -+static int debug; -+module_param(debug, int, 0644); -+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); -+ -+#define dprintk(args...) \ -+ do { \ -+ if (debug) \ -+ printk(KERN_INFO "m88dc2800: " args); \ -+ } while (0) -+ -+ -+static int m88dc2800_i2c_write(struct m88dc2800_state *state, u8 addr, -+ u8 * p_data, u8 len) -+{ -+ struct i2c_msg msg = { .flags = 0 }; -+ -+ msg.addr = addr; -+ msg.buf = p_data; -+ msg.len = len; -+ -+ return i2c_transfer(state->i2c, &msg, 1); -+} -+ -+static int m88dc2800_i2c_read(struct m88dc2800_state *state, u8 addr, -+ u8 * p_data, u8 len) -+{ -+ struct i2c_msg msg = { .flags = I2C_M_RD }; -+ -+ msg.addr = addr; -+ msg.buf = p_data; -+ msg.len = len; -+ -+ return i2c_transfer(state->i2c, &msg, 1); -+} -+ -+/*demod register operations.*/ -+static int WriteReg(struct m88dc2800_state *state, u8 reg, u8 data) -+{ -+ u8 buf[] = { reg, data }; -+ u8 addr = state->config->demod_address; -+ int err; -+ -+ dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); -+ -+ err = m88dc2800_i2c_write(state, addr, buf, 2); -+ -+ if (err != 1) { -+ printk(KERN_ERR -+ "%s: writereg error(err == %i, reg == 0x%02x," -+ " value == 0x%02x)\n", __func__, err, reg, data); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static int ReadReg(struct m88dc2800_state *state, u8 reg) -+{ -+ int ret; -+ u8 b0[] = { reg }; -+ u8 b1[] = { 0 }; -+ u8 addr = state->config->demod_address; -+ -+ ret = m88dc2800_i2c_write(state, addr, b0, 1); -+ -+ if (ret != 1) { -+ printk(KERN_ERR "%s: reg=0x%x (error=%d)\n", -+ __func__, reg, ret); -+ return -EIO; -+ } -+ -+ ret = m88dc2800_i2c_read(state, addr, b1, 1); -+ -+ dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]); -+ return b1[0]; -+} -+ -+static int _mt_fe_tn_set_reg(struct m88dc2800_state *state, u8 reg, -+ u8 data) -+{ -+ int ret; -+ u8 buf[2]; -+ u8 addr = state->tuner_dev_addr; -+ -+ buf[1] = ReadReg(state, 0x86); -+ buf[1] |= 0x80; -+ ret = WriteReg(state, 0x86, buf[1]); -+ -+ buf[0] = reg; -+ buf[1] = data; -+ -+ ret = m88dc2800_i2c_write(state, addr, buf, 2); -+ if (ret != 1) -+ return -EIO; -+ return 0; -+} -+ -+static int _mt_fe_tn_get_reg(struct m88dc2800_state *state, u8 reg, -+ u8 * p_data) -+{ -+ int ret; -+ u8 buf[2]; -+ u8 addr = state->tuner_dev_addr; -+ -+ buf[1] = ReadReg(state, 0x86); -+ buf[1] |= 0x80; -+ ret = WriteReg(state, 0x86, buf[1]); -+ -+ buf[0] = reg; -+ ret = m88dc2800_i2c_write(state, addr, buf, 1); -+ -+ msleep(1); -+ -+ buf[1] = ReadReg(state, 0x86); -+ buf[1] |= 0x80; -+ ret = WriteReg(state, 0x86, buf[1]); -+ -+ return m88dc2800_i2c_read(state, addr, p_data, 1); -+} -+ -+/* Tuner operation functions.*/ -+static int _mt_fe_tn_set_RF_front_tc2800(struct m88dc2800_state *state) -+{ -+ u32 freq_KHz = state->tuner_freq; -+ u8 a, b, c; -+ if (state->tuner_mtt == 0xD1) { /* D1 */ -+ if (freq_KHz <= 123000) { -+ if (freq_KHz <= 56000) { -+ a = 0x00; b = 0x00; c = 0x00; -+ } else if (freq_KHz <= 64000) { -+ a = 0x10; b = 0x01; c = 0x08; -+ } else if (freq_KHz <= 72000) { -+ a = 0x20; b = 0x02; c = 0x10; -+ } else if (freq_KHz <= 80000) { -+ a = 0x30; b = 0x03; c = 0x18; -+ } else if (freq_KHz <= 88000) { -+ a = 0x40; b = 0x04; c = 0x20; -+ } else if (freq_KHz <= 96000) { -+ a = 0x50; b = 0x05; c = 0x28; -+ } else if (freq_KHz <= 104000) { -+ a = 0x60; b = 0x06; c = 0x30; -+ } else { -+ a = 0x70; b = 0x07; c = 0x38; -+ } -+ _mt_fe_tn_set_reg(state, 0x58, 0x9b); -+ _mt_fe_tn_set_reg(state, 0x59, a); -+ _mt_fe_tn_set_reg(state, 0x5d, b); -+ _mt_fe_tn_set_reg(state, 0x5e, c); -+ _mt_fe_tn_set_reg(state, 0x5a, 0x75); -+ _mt_fe_tn_set_reg(state, 0x73, 0x0c); -+ } else { /* if (freq_KHz > 112000) */ -+ _mt_fe_tn_set_reg(state, 0x58, 0x7b); -+ if (freq_KHz <= 304000) { -+ if (freq_KHz <= 136000) { -+ _mt_fe_tn_set_reg(state, 0x5e, 0x40); -+ } else if (freq_KHz <= 160000) { -+ _mt_fe_tn_set_reg(state, 0x5e, 0x48); -+ } else if (freq_KHz <= 184000) { -+ _mt_fe_tn_set_reg(state, 0x5e, 0x50); -+ } else if (freq_KHz <= 208000) { -+ _mt_fe_tn_set_reg(state, 0x5e, 0x58); -+ } else if (freq_KHz <= 232000) { -+ _mt_fe_tn_set_reg(state, 0x5e, 0x60); -+ } else if (freq_KHz <= 256000) { -+ _mt_fe_tn_set_reg(state, 0x5e, 0x68); -+ } else if (freq_KHz <= 280000) { -+ _mt_fe_tn_set_reg(state, 0x5e, 0x70); -+ } else { /* if (freq_KHz <= 304000) */ -+ _mt_fe_tn_set_reg(state, 0x5e, 0x78); -+ } -+ if (freq_KHz <= 171000) { -+ _mt_fe_tn_set_reg(state, 0x73, 0x08); -+ } else if (freq_KHz <= 211000) { -+ _mt_fe_tn_set_reg(state, 0x73, 0x0a); -+ } else { -+ _mt_fe_tn_set_reg(state, 0x73, 0x0e); -+ } -+ } else { /* if (freq_KHz > 304000) */ -+ _mt_fe_tn_set_reg(state, 0x5e, 0x88); -+ if (freq_KHz <= 400000) { -+ _mt_fe_tn_set_reg(state, 0x73, 0x0c); -+ } else if (freq_KHz <= 450000) { -+ _mt_fe_tn_set_reg(state, 0x73, 0x09); -+ } else if (freq_KHz <= 550000) { -+ _mt_fe_tn_set_reg(state, 0x73, 0x0e); -+ } else if (freq_KHz <= 650000) { -+ _mt_fe_tn_set_reg(state, 0x73, 0x0d); -+ } else { /*if (freq_KHz > 650000) */ -+ _mt_fe_tn_set_reg(state, 0x73, 0x0e); -+ } -+ } -+ } -+ if (freq_KHz > 800000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x24); -+ else if (freq_KHz > 700000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x34); -+ else if (freq_KHz > 500000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x44); -+ else if (freq_KHz > 300000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x43); -+ else if (freq_KHz > 220000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x54); -+ else if (freq_KHz > 110000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x14); -+ else -+ _mt_fe_tn_set_reg(state, 0x87, 0x54); -+ if (freq_KHz > 600000) -+ _mt_fe_tn_set_reg(state, 0x6a, 0x53); -+ else if (freq_KHz > 500000) -+ _mt_fe_tn_set_reg(state, 0x6a, 0x57); -+ else -+ _mt_fe_tn_set_reg(state, 0x6a, 0x59); -+ if (freq_KHz < 200000) { -+ _mt_fe_tn_set_reg(state, 0x20, 0x5d); -+ } else if (freq_KHz < 500000) { -+ _mt_fe_tn_set_reg(state, 0x20, 0x7d); -+ } else { -+ _mt_fe_tn_set_reg(state, 0x20, 0xfd); -+ } /* end of 0xD1 */ -+ } else if (state->tuner_mtt == 0xE1) { /* E1 */ -+ if (freq_KHz <= 112000) { /* 123MHz */ -+ if (freq_KHz <= 56000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x01); -+ } else if (freq_KHz <= 64000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x09); -+ } else if (freq_KHz <= 72000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x11); -+ } else if (freq_KHz <= 80000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x19); -+ } else if (freq_KHz <= 88000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x21); -+ } else if (freq_KHz <= 96000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x29); -+ } else if (freq_KHz <= 104000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x31); -+ } else { /* if (freq_KHz <= 112000) */ -+ _mt_fe_tn_set_reg(state, 0x5c, 0x39); -+ } -+ _mt_fe_tn_set_reg(state, 0x5b, 0x30); -+ } else { /* if (freq_KHz > 112000) */ -+ if (freq_KHz <= 304000) { -+ if (freq_KHz <= 136000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x41); -+ } else if (freq_KHz <= 160000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x49); -+ } else if (freq_KHz <= 184000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x51); -+ } else if (freq_KHz <= 208000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x59); -+ } else if (freq_KHz <= 232000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x61); -+ } else if (freq_KHz <= 256000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x69); -+ } else if (freq_KHz <= 280000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x71); -+ } else { /* if (freq_KHz <= 304000) */ -+ _mt_fe_tn_set_reg(state, 0x5c, 0x79); -+ } -+ if (freq_KHz <= 150000) { -+ _mt_fe_tn_set_reg(state, 0x5b, 0x28); -+ } else if (freq_KHz <= 256000) { -+ _mt_fe_tn_set_reg(state, 0x5b, 0x29); -+ } else { -+ _mt_fe_tn_set_reg(state, 0x5b, 0x2a); -+ } -+ } else { /* if (freq_KHz > 304000) */ -+ if (freq_KHz <= 400000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x89); -+ } else if (freq_KHz <= 450000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x91); -+ } else if (freq_KHz <= 650000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0x98); -+ } else if (freq_KHz <= 850000) { -+ _mt_fe_tn_set_reg(state, 0x5c, 0xa0); -+ } else { -+ _mt_fe_tn_set_reg(state, 0x5c, 0xa8); -+ } -+ _mt_fe_tn_set_reg(state, 0x5b, 0x08); -+ } -+ } -+ } /* end of 0xE1 */ -+ return 0; -+} -+ -+static int _mt_fe_tn_cali_PLL_tc2800(struct m88dc2800_state *state, -+ u32 freq_KHz, -+ u32 cali_freq_thres_div2, -+ u32 cali_freq_thres_div3r, -+ u32 cali_freq_thres_div3) -+{ -+ s32 N, F, MUL; -+ u8 buf, tmp, tmp2; -+ s32 M; -+ const s32 crystal_KHz = state->tuner_crystal; -+ if (state->tuner_mtt == 0xD1) { -+ M = state->tuner_crystal / 4000; -+ if (freq_KHz > cali_freq_thres_div2) { -+ MUL = 4; -+ tmp = 2; -+ } else if (freq_KHz > 300000) { -+ MUL = 8; -+ tmp = 3; -+ } else if (freq_KHz > (cali_freq_thres_div2 / 2)) { -+ MUL = 8; -+ tmp = 4; -+ } else if (freq_KHz > (cali_freq_thres_div2 / 4)) { -+ MUL = 16; -+ tmp = 5; -+ } else if (freq_KHz > (cali_freq_thres_div2 / 8)) { -+ MUL = 32; -+ tmp = 6; -+ } else if (freq_KHz > (cali_freq_thres_div2 / 16)) { -+ MUL = 64; -+ tmp = 7; -+ } else { /* invalid */ -+ MUL = 0; -+ tmp = 0; -+ return 1; -+ } -+ } else if (state->tuner_mtt == 0xE1) { -+ M = state->tuner_crystal / 1000; -+ _mt_fe_tn_set_reg(state, 0x30, 0xff); -+ _mt_fe_tn_set_reg(state, 0x32, 0xe0); -+ _mt_fe_tn_set_reg(state, 0x33, 0x86); -+ _mt_fe_tn_set_reg(state, 0x37, 0x70); -+ _mt_fe_tn_set_reg(state, 0x38, 0x20); -+ _mt_fe_tn_set_reg(state, 0x39, 0x18); -+ _mt_fe_tn_set_reg(state, 0x89, 0x83); -+ if (freq_KHz > cali_freq_thres_div2) { -+ M = M / 4; -+ MUL = 4; -+ tmp = 2; -+ tmp2 = M + 16; /* 48 */ -+ } else if (freq_KHz > cali_freq_thres_div3r) { -+ M = M / 3; -+ MUL = 6; -+ tmp = 2; -+ tmp2 = M + 32; /* 32 */ -+ } else if (freq_KHz > cali_freq_thres_div3) { -+ M = M / 3; -+ MUL = 6; -+ tmp = 2; -+ tmp2 = M; /* 16 */ -+ } else if (freq_KHz > 304000) { -+ M = M / 4; -+ MUL = 8; -+ tmp = 3; -+ tmp2 = M + 16; /* 48 */ -+ } else if (freq_KHz > (cali_freq_thres_div2 / 2)) { -+ M = M / 4; -+ MUL = 8; -+ tmp = 4; -+ tmp2 = M + 16; /* 48 */ -+ } else if (freq_KHz > (cali_freq_thres_div3r / 2)) { -+ M = M / 3; -+ MUL = 12; -+ tmp = 4; -+ tmp2 = M + 32; /* 32 */ -+ } else if (freq_KHz > (cali_freq_thres_div3 / 2)) { -+ M = M / 3; -+ MUL = 12; -+ tmp = 4; -+ tmp2 = M; /* 16 */ -+ } else if (freq_KHz > (cali_freq_thres_div2 / 4)) { -+ M = M / 4; -+ MUL = 16; -+ tmp = 5; -+ tmp2 = M + 16; /* 48 */ -+ } else if (freq_KHz > (cali_freq_thres_div3r / 4)) { -+ M = M / 3; -+ MUL = 24; -+ tmp = 5; -+ tmp2 = M + 32; /* 32 */ -+ } else if (freq_KHz > (cali_freq_thres_div3 / 4)) { -+ M = M / 3; -+ MUL = 24; -+ tmp = 5; -+ tmp2 = M; /* 16 */ -+ } else if (freq_KHz > (cali_freq_thres_div2 / 8)) { -+ M = M / 4; -+ MUL = 32; -+ tmp = 6; -+ tmp2 = M + 16; /* 48 */ -+ } else if (freq_KHz > (cali_freq_thres_div3r / 8)) { -+ M = M / 3; -+ MUL = 48; -+ tmp = 6; -+ tmp2 = M + 32; /* 32 */ -+ } else if (freq_KHz > (cali_freq_thres_div3 / 8)) { -+ M = M / 3; -+ MUL = 48; -+ tmp = 6; -+ tmp2 = M; /* 16 */ -+ } else if (freq_KHz > (cali_freq_thres_div2 / 16)) { -+ M = M / 4; -+ MUL = 64; -+ tmp = 7; -+ tmp2 = M + 16; /* 48 */ -+ } else if (freq_KHz > (cali_freq_thres_div3r / 16)) { -+ M = M / 3; -+ MUL = 96; -+ tmp = 7; -+ tmp2 = M + 32; /* 32 */ -+ } else if (freq_KHz > (cali_freq_thres_div3 / 16)) { -+ M = M / 3; -+ MUL = 96; -+ tmp = 7; -+ tmp2 = M; /* 16 */ -+ } else { /* invalid */ -+ M = M / 4; -+ MUL = 0; -+ tmp = 0; -+ tmp2 = 48; -+ return 1; -+ } -+ if (freq_KHz == 291000) { -+ M = state->tuner_crystal / 1000 / 3; -+ MUL = 12; -+ tmp = 4; -+ tmp2 = M + 32; /* 32 */ -+ } -+ /* -+ if (freq_KHz == 578000) { -+ M = state->tuner_crystal / 1000 / 4; -+ MUL = 4; -+ tmp = 2; -+ tmp2 = M + 16; // 48 -+ } -+ */ -+ if (freq_KHz == 690000) { -+ M = state->tuner_crystal / 1000 / 3; -+ MUL = 4; -+ tmp = 2; -+ tmp2 = M + 16; /* 48 */ -+ } -+ _mt_fe_tn_get_reg(state, 0x33, &buf); -+ buf &= 0xc0; -+ buf += tmp2; -+ _mt_fe_tn_set_reg(state, 0x33, buf); -+ } else { -+ return 1; -+ } -+ _mt_fe_tn_get_reg(state, 0x39, &buf); -+ buf &= 0xf8; -+ buf += tmp; -+ _mt_fe_tn_set_reg(state, 0x39, buf); -+ N = (freq_KHz * MUL * M / crystal_KHz) / 2 * 2 - 256; -+ buf = (N >> 8) & 0xcf; -+ if (state->tuner_mtt == 0xE1) { -+ buf |= 0x30; -+ } -+ _mt_fe_tn_set_reg(state, 0x34, buf); -+ buf = N & 0xff; -+ _mt_fe_tn_set_reg(state, 0x35, buf); -+ F = ((freq_KHz * MUL * M / (crystal_KHz / 1000) / 2) - -+ (freq_KHz * MUL * M / crystal_KHz / 2 * 1000)) * 64 / 1000; -+ buf = F & 0xff; -+ _mt_fe_tn_set_reg(state, 0x36, buf); -+ if (F == 0) { -+ if (state->tuner_mtt == 0xD1) { -+ _mt_fe_tn_set_reg(state, 0x3d, 0xca); -+ } else if (state->tuner_mtt == 0xE1) { -+ _mt_fe_tn_set_reg(state, 0x3d, 0xfe); -+ } else { -+ return 1; -+ } -+ _mt_fe_tn_set_reg(state, 0x3e, 0x9c); -+ _mt_fe_tn_set_reg(state, 0x3f, 0x34); -+ } -+ if (F > 0) { -+ if (state->tuner_mtt == 0xD1) { -+ if ((F == 32) || (F == 16) || (F == 48)) { -+ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); -+ _mt_fe_tn_set_reg(state, 0x3d, 0x4a); -+ _mt_fe_tn_set_reg(state, 0x3f, 0x36); -+ } else { -+ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); -+ _mt_fe_tn_set_reg(state, 0x3d, 0x4a); -+ _mt_fe_tn_set_reg(state, 0x3f, 0x36); -+ } -+ } else if (state->tuner_mtt == 0xE1) { -+ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); -+ _mt_fe_tn_set_reg(state, 0x3d, 0x7e); -+ _mt_fe_tn_set_reg(state, 0x3f, 0x36); -+ _mt_fe_tn_set_reg(state, 0x89, 0x84); -+ _mt_fe_tn_get_reg(state, 0x39, &buf); -+ buf = buf & 0x1f; -+ _mt_fe_tn_set_reg(state, 0x39, buf); -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = buf | 0x02; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ } else { -+ return 1; -+ } -+ } -+ _mt_fe_tn_set_reg(state, 0x41, 0x00); -+ if (state->tuner_mtt == 0xD1) { -+ msleep(5); -+ } else if (state->tuner_mtt == 0xE1) { -+ msleep(2); -+ } else { -+ return 1; -+ } -+ _mt_fe_tn_set_reg(state, 0x41, 0x02); -+ _mt_fe_tn_set_reg(state, 0x30, 0x7f); -+ _mt_fe_tn_set_reg(state, 0x30, 0xff); -+ _mt_fe_tn_set_reg(state, 0x31, 0x80); -+ _mt_fe_tn_set_reg(state, 0x31, 0x00); -+ -+ return 0; -+} -+ -+static int _mt_fe_tn_set_PLL_freq_tc2800(struct m88dc2800_state *state) -+{ -+ u8 buf, buf1; -+ u32 freq_thres_div2_KHz, freq_thres_div3r_KHz, -+ freq_thres_div3_KHz; -+ const u32 freq_KHz = state->tuner_freq; -+ if (state->tuner_mtt == 0xD1) { -+ _mt_fe_tn_set_reg(state, 0x32, 0xe1); -+ _mt_fe_tn_set_reg(state, 0x33, 0xa6); -+ _mt_fe_tn_set_reg(state, 0x37, 0x7f); -+ _mt_fe_tn_set_reg(state, 0x38, 0x20); -+ _mt_fe_tn_set_reg(state, 0x39, 0x18); -+ _mt_fe_tn_set_reg(state, 0x40, 0x40); -+ freq_thres_div2_KHz = 520000; -+ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, -+ freq_thres_div2_KHz, 0, 0); -+ msleep(5); -+ _mt_fe_tn_get_reg(state, 0x3a, &buf); -+ buf1 = buf; -+ buf = buf & 0x03; -+ buf1 = buf1 & 0x01; -+ if ((buf1 == 0) || (buf == 3)) { -+ freq_thres_div2_KHz = 420000; -+ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, -+ freq_thres_div2_KHz, 0, -+ 0); -+ msleep(5); -+ _mt_fe_tn_get_reg(state, 0x3a, &buf); -+ buf = buf & 0x07; -+ if (buf == 5) { -+ freq_thres_div2_KHz = 520000; -+ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, -+ freq_thres_div2_KHz, -+ 0, 0); -+ msleep(5); -+ } -+ } -+ _mt_fe_tn_get_reg(state, 0x38, &buf); -+ _mt_fe_tn_set_reg(state, 0x38, buf); -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = buf | 0x10; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ _mt_fe_tn_set_reg(state, 0x30, 0x7f); -+ _mt_fe_tn_set_reg(state, 0x30, 0xff); -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = buf & 0xdf; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ _mt_fe_tn_set_reg(state, 0x40, 0x0); -+ _mt_fe_tn_set_reg(state, 0x30, 0x7f); -+ _mt_fe_tn_set_reg(state, 0x30, 0xff); -+ _mt_fe_tn_set_reg(state, 0x31, 0x80); -+ _mt_fe_tn_set_reg(state, 0x31, 0x00); -+ msleep(5); -+ _mt_fe_tn_get_reg(state, 0x39, &buf); -+ buf = buf >> 5; -+ if (buf < 5) { -+ _mt_fe_tn_get_reg(state, 0x39, &buf); -+ buf = buf | 0xa0; -+ buf = buf & 0xbf; -+ _mt_fe_tn_set_reg(state, 0x39, buf); -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = buf | 0x02; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ } -+ _mt_fe_tn_get_reg(state, 0x37, &buf); -+ if (buf > 0x70) { -+ buf = 0x7f; -+ _mt_fe_tn_set_reg(state, 0x40, 0x40); -+ } -+ _mt_fe_tn_set_reg(state, 0x37, buf); -+ _mt_fe_tn_get_reg(state, 0x38, &buf); -+ if (buf < 0x0f) { -+ buf = (buf & 0x0f) << 2; -+ buf = buf + 0x0f; -+ _mt_fe_tn_set_reg(state, 0x37, buf); -+ } else if (buf < 0x1f) { -+ buf = buf + 0x0f; -+ _mt_fe_tn_set_reg(state, 0x37, buf); -+ } -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = (buf | 0x20) & 0xef; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ _mt_fe_tn_set_reg(state, 0x41, 0x00); -+ msleep(5); -+ _mt_fe_tn_set_reg(state, 0x41, 0x02); -+ } else if (state->tuner_mtt == 0xE1) { -+ freq_thres_div2_KHz = 580000; -+ freq_thres_div3r_KHz = 500000; -+ freq_thres_div3_KHz = 440000; -+ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, -+ freq_thres_div2_KHz, -+ freq_thres_div3r_KHz, -+ freq_thres_div3_KHz); -+ msleep(3); -+ _mt_fe_tn_get_reg(state, 0x38, &buf); -+ _mt_fe_tn_set_reg(state, 0x38, buf); -+ _mt_fe_tn_set_reg(state, 0x30, 0x7f); -+ _mt_fe_tn_set_reg(state, 0x30, 0xff); -+ _mt_fe_tn_set_reg(state, 0x31, 0x80); -+ _mt_fe_tn_set_reg(state, 0x31, 0x00); -+ msleep(3); -+ _mt_fe_tn_get_reg(state, 0x38, &buf); -+ _mt_fe_tn_set_reg(state, 0x38, buf); -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = buf | 0x10; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ _mt_fe_tn_set_reg(state, 0x30, 0x7f); -+ _mt_fe_tn_set_reg(state, 0x30, 0xff); -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = buf & 0xdf; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ _mt_fe_tn_set_reg(state, 0x31, 0x80); -+ _mt_fe_tn_set_reg(state, 0x31, 0x00); -+ msleep(3); -+ _mt_fe_tn_get_reg(state, 0x37, &buf); -+ _mt_fe_tn_set_reg(state, 0x37, buf); -+ /* -+ if ((freq_KHz == 802000) || (freq_KHz == 826000)) { -+ _mt_fe_tn_set_reg(state, 0x37, 0x5e); -+ } -+ */ -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = (buf & 0xef) | 0x30; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ _mt_fe_tn_set_reg(state, 0x41, 0x00); -+ msleep(2); -+ _mt_fe_tn_set_reg(state, 0x41, 0x02); -+ } else { -+ return 1; -+ } -+ return 0; -+} -+ -+static int _mt_fe_tn_set_BB_tc2800(struct m88dc2800_state *state) -+{ -+ return 0; -+} -+ -+ static int _mt_fe_tn_set_appendix_tc2800(struct m88dc2800_state *state) -+ -+{ -+ u8 buf; -+ const u32 freq_KHz = state->tuner_freq; -+ if (state->tuner_mtt == 0xD1) { -+ if ((freq_KHz == 123000) || (freq_KHz == 147000) || -+ (freq_KHz == 171000) || (freq_KHz == 195000)) { -+ _mt_fe_tn_set_reg(state, 0x20, 0x1b); -+ } -+ if ((freq_KHz == 371000) || (freq_KHz == 419000) || -+ (freq_KHz == 610000) || (freq_KHz == 730000) || -+ (freq_KHz == 754000) || (freq_KHz == 826000)) { -+ _mt_fe_tn_get_reg(state, 0x0d, &buf); -+ _mt_fe_tn_set_reg(state, 0x0d, (u8) (buf + 1)); -+ } -+ if ((freq_KHz == 522000) || (freq_KHz == 578000) || -+ (freq_KHz == 634000) || (freq_KHz == 690000) || -+ (freq_KHz == 834000)) { -+ _mt_fe_tn_get_reg(state, 0x0d, &buf); -+ _mt_fe_tn_set_reg(state, 0x0d, (u8) (buf - 1)); -+ } -+ } else if (state->tuner_mtt == 0xE1) { -+ _mt_fe_tn_set_reg(state, 0x20, 0xfc); -+ if (freq_KHz == 123000 || freq_KHz == 147000 || -+ freq_KHz == 171000 || freq_KHz == 195000 || -+ freq_KHz == 219000 || freq_KHz == 267000 || -+ freq_KHz == 291000 || freq_KHz == 339000 || -+ freq_KHz == 387000 || freq_KHz == 435000 || -+ freq_KHz == 482000 || freq_KHz == 530000 || -+ freq_KHz == 722000 || -+ (state->tuner_custom_cfg == 1 && freq_KHz == 315000)) { -+ _mt_fe_tn_set_reg(state, 0x20, 0x5c); -+ } -+ } -+ return 0; -+} -+ -+ static int _mt_fe_tn_set_DAC_tc2800(struct m88dc2800_state *state) -+{ -+ u8 buf, tempnumber; -+ s32 N; -+ s32 f1f2number, f1, f2, delta1, Totalnum1; -+ s32 cntT, cntin, NCOI, z0, z1, z2, tmp; -+ u32 fc, fadc, fsd, f2d; -+ u32 FreqTrue108_Hz; -+ s32 M = state->tuner_crystal / 4000; -+ /* const u8 bandwidth = state->tuner_bandwidth; */ -+ const u16 DAC_fre = 108; -+ const u32 crystal_KHz = state->tuner_crystal; -+ const u32 DACFreq_KHz = state->tuner_dac; -+ const u32 freq_KHz = state->tuner_freq; -+ -+ if (state->tuner_mtt == 0xE1) { -+ _mt_fe_tn_get_reg(state, 0x33, &buf); -+ M = buf & 0x0f; -+ if (M == 0) -+ M = 6; -+ } -+ _mt_fe_tn_get_reg(state, 0x34, &buf); -+ N = buf & 0x07; -+ _mt_fe_tn_get_reg(state, 0x35, &buf); -+ N = (N << 8) + buf; -+ buf = ((N + 256) * crystal_KHz / M / DAC_fre + 500) / 1000; -+ if (state->tuner_mtt == 0xE1) { -+ _mt_fe_tn_set_appendix_tc2800(state); -+ if (freq_KHz == 187000 || freq_KHz == 195000 || -+ freq_KHz == 131000 || freq_KHz == 211000 || -+ freq_KHz == 219000 || freq_KHz == 227000 || -+ freq_KHz == 267000 || freq_KHz == 299000 || -+ freq_KHz == 347000 || freq_KHz == 363000 || -+ freq_KHz == 395000 || freq_KHz == 403000 || -+ freq_KHz == 435000 || freq_KHz == 482000 || -+ freq_KHz == 474000 || freq_KHz == 490000 || -+ freq_KHz == 610000 || freq_KHz == 642000 || -+ freq_KHz == 666000 || freq_KHz == 722000 || -+ freq_KHz == 754000 || -+ ((freq_KHz == 379000 || freq_KHz == 467000 || -+ freq_KHz == 762000) && state->tuner_custom_cfg != 1)) { -+ buf = buf + 1; -+ } -+ if (freq_KHz == 123000 || freq_KHz == 139000 || -+ freq_KHz == 147000 || freq_KHz == 171000 || -+ freq_KHz == 179000 || freq_KHz == 203000 || -+ freq_KHz == 235000 || freq_KHz == 251000 || -+ freq_KHz == 259000 || freq_KHz == 283000 || -+ freq_KHz == 331000 || freq_KHz == 363000 || -+ freq_KHz == 371000 || freq_KHz == 387000 || -+ freq_KHz == 411000 || freq_KHz == 427000 || -+ freq_KHz == 443000 || freq_KHz == 451000 || -+ freq_KHz == 459000 || freq_KHz == 506000 || -+ freq_KHz == 514000 || freq_KHz == 538000 || -+ freq_KHz == 546000 || freq_KHz == 554000 || -+ freq_KHz == 562000 || freq_KHz == 570000 || -+ freq_KHz == 578000 || freq_KHz == 602000 || -+ freq_KHz == 626000 || freq_KHz == 658000 || -+ freq_KHz == 690000 || freq_KHz == 714000 || -+ freq_KHz == 746000 || freq_KHz == 522000 || -+ freq_KHz == 826000 || freq_KHz == 155000 || -+ freq_KHz == 530000 || -+ ((freq_KHz == 275000 || freq_KHz == 355000) && -+ state->tuner_custom_cfg != 1) || -+ ((freq_KHz == 467000 || freq_KHz == 762000 || -+ freq_KHz == 778000 || freq_KHz == 818000) && -+ state->tuner_custom_cfg == 1)) { -+ buf = buf - 1; -+ } -+ } -+ _mt_fe_tn_set_reg(state, 0x0e, buf); -+ _mt_fe_tn_set_reg(state, 0x0d, buf); -+ f1f2number = -+ (((DACFreq_KHz * M * buf) / crystal_KHz) << 16) / (N + 256) + -+ (((DACFreq_KHz * M * buf) % crystal_KHz) << 16) / ((N + 256) * -+ crystal_KHz); -+ _mt_fe_tn_set_reg(state, 0xf1, (f1f2number & 0xff00) >> 8); -+ _mt_fe_tn_set_reg(state, 0xf2, f1f2number & 0x00ff); -+ FreqTrue108_Hz = -+ (N + 256) * crystal_KHz / (M * buf) * 1000 + -+ (((N + 256) * crystal_KHz) % (M * buf)) * 1000 / (M * buf); -+ f1 = 4096; -+ fc = FreqTrue108_Hz; -+ fadc = fc / 4; -+ fsd = 27000000; -+ f2d = state->tuner_bandwidth * 1000 / 2 - 150; -+ f2 = (fsd / 250) * f2d / ((fc + 500) / 1000); -+ delta1 = ((f1 - f2) << 15) / f2; -+ Totalnum1 = ((f1 - f2) << 15) - delta1 * f2; -+ cntT = f2; -+ cntin = Totalnum1; -+ NCOI = delta1; -+ z0 = cntin; -+ z1 = cntT; -+ z2 = NCOI; -+ tempnumber = (z0 & 0xff00) >> 8; -+ _mt_fe_tn_set_reg(state, 0xc9, (u8) (tempnumber & 0x0f)); -+ tempnumber = (z0 & 0xff); -+ _mt_fe_tn_set_reg(state, 0xca, tempnumber); -+ tempnumber = (z1 & 0xff00) >> 8; -+ _mt_fe_tn_set_reg(state, 0xcb, tempnumber); -+ tempnumber = (z1 & 0xff); -+ _mt_fe_tn_set_reg(state, 0xcc, tempnumber); -+ tempnumber = (z2 & 0xff00) >> 8; -+ _mt_fe_tn_set_reg(state, 0xcd, tempnumber); -+ tempnumber = (z2 & 0xff); -+ _mt_fe_tn_set_reg(state, 0xce, tempnumber); -+ tmp = f1; -+ f1 = f2; -+ f2 = tmp / 2; -+ delta1 = ((f1 - f2) << 15) / f2; -+ Totalnum1 = ((f1 - f2) << 15) - delta1 * f2; -+ NCOI = (f1 << 15) / f2 - (1 << 15); -+ cntT = f2; -+ cntin = Totalnum1; -+ z0 = cntin; -+ z1 = cntT; -+ z2 = NCOI; -+ tempnumber = (z0 & 0xff00) >> 8; -+ _mt_fe_tn_set_reg(state, 0xd9, (u8) (tempnumber & 0x0f)); -+ tempnumber = (z0 & 0xff); -+ _mt_fe_tn_set_reg(state, 0xda, tempnumber); -+ tempnumber = (z1 & 0xff00) >> 8; -+ _mt_fe_tn_set_reg(state, 0xdb, tempnumber); -+ tempnumber = (z1 & 0xff); -+ _mt_fe_tn_set_reg(state, 0xdc, tempnumber); -+ tempnumber = (z2 & 0xff00) >> 8; -+ _mt_fe_tn_set_reg(state, 0xdd, tempnumber); -+ tempnumber = (z2 & 0xff); -+ _mt_fe_tn_set_reg(state, 0xde, tempnumber); -+ -+ return 0; -+} -+ -+static int _mt_fe_tn_preset_tc2800(struct m88dc2800_state *state) -+{ -+ if (state->tuner_mtt == 0xD1) { -+ _mt_fe_tn_set_reg(state, 0x19, 0x4a); -+ _mt_fe_tn_set_reg(state, 0x1b, 0x4b); -+ _mt_fe_tn_set_reg(state, 0x04, 0x04); -+ _mt_fe_tn_set_reg(state, 0x17, 0x0d); -+ _mt_fe_tn_set_reg(state, 0x62, 0x6c); -+ _mt_fe_tn_set_reg(state, 0x63, 0xf4); -+ _mt_fe_tn_set_reg(state, 0x1f, 0x0e); -+ _mt_fe_tn_set_reg(state, 0x6b, 0xf4); -+ _mt_fe_tn_set_reg(state, 0x14, 0x01); -+ _mt_fe_tn_set_reg(state, 0x5a, 0x75); -+ _mt_fe_tn_set_reg(state, 0x66, 0x74); -+ _mt_fe_tn_set_reg(state, 0x72, 0xe0); -+ _mt_fe_tn_set_reg(state, 0x70, 0x07); -+ _mt_fe_tn_set_reg(state, 0x15, 0x7b); -+ _mt_fe_tn_set_reg(state, 0x55, 0x71); -+ _mt_fe_tn_set_reg(state, 0x75, 0x55); -+ _mt_fe_tn_set_reg(state, 0x76, 0xac); -+ _mt_fe_tn_set_reg(state, 0x77, 0x6c); -+ _mt_fe_tn_set_reg(state, 0x78, 0x8b); -+ _mt_fe_tn_set_reg(state, 0x79, 0x42); -+ _mt_fe_tn_set_reg(state, 0x7a, 0xd2); -+ _mt_fe_tn_set_reg(state, 0x81, 0x01); -+ _mt_fe_tn_set_reg(state, 0x82, 0x00); -+ _mt_fe_tn_set_reg(state, 0x82, 0x02); -+ _mt_fe_tn_set_reg(state, 0x82, 0x04); -+ _mt_fe_tn_set_reg(state, 0x82, 0x06); -+ _mt_fe_tn_set_reg(state, 0x82, 0x08); -+ _mt_fe_tn_set_reg(state, 0x82, 0x09); -+ _mt_fe_tn_set_reg(state, 0x82, 0x29); -+ _mt_fe_tn_set_reg(state, 0x82, 0x49); -+ _mt_fe_tn_set_reg(state, 0x82, 0x58); -+ _mt_fe_tn_set_reg(state, 0x82, 0x59); -+ _mt_fe_tn_set_reg(state, 0x82, 0x98); -+ _mt_fe_tn_set_reg(state, 0x82, 0x99); -+ _mt_fe_tn_set_reg(state, 0x10, 0x05); -+ _mt_fe_tn_set_reg(state, 0x10, 0x0d); -+ _mt_fe_tn_set_reg(state, 0x11, 0x95); -+ _mt_fe_tn_set_reg(state, 0x11, 0x9d); -+ if (state->tuner_loopthrough != 0) { -+ _mt_fe_tn_set_reg(state, 0x67, 0x25); -+ } else { -+ _mt_fe_tn_set_reg(state, 0x67, 0x05); -+ } -+ } else if (state->tuner_mtt == 0xE1) { -+ _mt_fe_tn_set_reg(state, 0x1b, 0x47); -+ if (state->tuner_mode == 0) { /* DVB-C */ -+ _mt_fe_tn_set_reg(state, 0x66, 0x74); -+ _mt_fe_tn_set_reg(state, 0x62, 0x2c); -+ _mt_fe_tn_set_reg(state, 0x63, 0x54); -+ _mt_fe_tn_set_reg(state, 0x68, 0x0b); -+ _mt_fe_tn_set_reg(state, 0x14, 0x00); -+ } else { /* CTTB */ -+ _mt_fe_tn_set_reg(state, 0x66, 0x74); -+ _mt_fe_tn_set_reg(state, 0x62, 0x0c); -+ _mt_fe_tn_set_reg(state, 0x63, 0x54); -+ _mt_fe_tn_set_reg(state, 0x68, 0x0b); -+ _mt_fe_tn_set_reg(state, 0x14, 0x05); -+ } -+ _mt_fe_tn_set_reg(state, 0x6f, 0x00); -+ _mt_fe_tn_set_reg(state, 0x84, 0x04); -+ _mt_fe_tn_set_reg(state, 0x5e, 0xbe); -+ _mt_fe_tn_set_reg(state, 0x87, 0x07); -+ _mt_fe_tn_set_reg(state, 0x8a, 0x1f); -+ _mt_fe_tn_set_reg(state, 0x8b, 0x1f); -+ _mt_fe_tn_set_reg(state, 0x88, 0x30); -+ _mt_fe_tn_set_reg(state, 0x58, 0x34); -+ _mt_fe_tn_set_reg(state, 0x61, 0x8c); -+ _mt_fe_tn_set_reg(state, 0x6a, 0x42); -+ } -+ return 0; -+} -+ -+static int mt_fe_tn_wakeup_tc2800(struct m88dc2800_state *state) -+{ -+ _mt_fe_tn_set_reg(state, 0x16, 0xb1); -+ _mt_fe_tn_set_reg(state, 0x09, 0x7d); -+ return 0; -+} -+ -+ static int mt_fe_tn_sleep_tc2800(struct m88dc2800_state *state) -+{ -+ _mt_fe_tn_set_reg(state, 0x16, 0xb0); -+ _mt_fe_tn_set_reg(state, 0x09, 0x6d); -+ return 0; -+} -+ -+ static int mt_fe_tn_init_tc2800(struct m88dc2800_state *state) -+{ -+ if (state->tuner_init_OK != 1) { -+ state->tuner_dev_addr = 0x61; /* TUNER_I2C_ADDR_TC2800 */ -+ state->tuner_freq = 650000; -+ state->tuner_qam = 0; -+ state->tuner_mode = 0; // 0: DVB-C, 1: CTTB -+ state->tuner_bandwidth = 8; -+ state->tuner_loopthrough = 0; -+ state->tuner_crystal = 24000; -+ state->tuner_dac = 7200; -+ state->tuner_mtt = 0x00; -+ state->tuner_custom_cfg = 0; -+ state->tuner_version = 30022; /* Driver version number */ -+ state->tuner_time = 12092611; -+ state->tuner_init_OK = 1; -+ } -+ _mt_fe_tn_set_reg(state, 0x2b, 0x46); -+ _mt_fe_tn_set_reg(state, 0x2c, 0x75); -+ if (state->tuner_mtt == 0x00) { -+ u8 tmp = 0; -+ _mt_fe_tn_get_reg(state, 0x01, &tmp); -+ printk(KERN_INFO "m88dc2800: tuner id = 0x%02x ", tmp); -+ switch (tmp) { -+ case 0x0d: -+ state->tuner_mtt = 0xD1; -+ break; -+ case 0x8e: -+ default: -+ state->tuner_mtt = 0xE1; -+ break; -+ } -+ } -+ return 0; -+} -+ -+ static int mt_fe_tn_set_freq_tc2800(struct m88dc2800_state *state, -+ u32 freq_KHz) -+{ -+ u8 buf; -+ u8 buf1; -+ -+ mt_fe_tn_init_tc2800(state); -+ state->tuner_freq = freq_KHz; -+ _mt_fe_tn_set_reg(state, 0x21, freq_KHz > 500000 ? 0xb9 : 0x99); -+ mt_fe_tn_wakeup_tc2800(state); -+ _mt_fe_tn_set_reg(state, 0x05, 0x7f); -+ _mt_fe_tn_set_reg(state, 0x06, 0xf8); -+ _mt_fe_tn_set_RF_front_tc2800(state); -+ _mt_fe_tn_set_PLL_freq_tc2800(state); -+ _mt_fe_tn_set_DAC_tc2800(state); -+ _mt_fe_tn_set_BB_tc2800(state); -+ _mt_fe_tn_preset_tc2800(state); -+ _mt_fe_tn_set_reg(state, 0x05, 0x00); -+ _mt_fe_tn_set_reg(state, 0x06, 0x00); -+ if (state->tuner_mtt == 0xD1) { -+ _mt_fe_tn_set_reg(state, 0x00, 0x01); -+ _mt_fe_tn_set_reg(state, 0x00, 0x00); -+ msleep(5); -+ _mt_fe_tn_set_reg(state, 0x41, 0x00); -+ msleep(5); -+ _mt_fe_tn_set_reg(state, 0x41, 0x02); -+ -+ _mt_fe_tn_get_reg(state, 0x69, &buf1); -+ buf1 = buf1 & 0x0f; -+ _mt_fe_tn_get_reg(state, 0x61, &buf); -+ buf = buf & 0x0f; -+ if (buf == 0x0c) -+ _mt_fe_tn_set_reg(state, 0x6a, 0x59); -+ if (buf1 > 0x02) { -+ if (freq_KHz > 600000) -+ _mt_fe_tn_set_reg(state, 0x66, 0x44); -+ else if (freq_KHz > 500000) -+ _mt_fe_tn_set_reg(state, 0x66, 0x64); -+ else -+ _mt_fe_tn_set_reg(state, 0x66, 0x74); -+ } -+ if (buf1 < 0x03) { -+ if (freq_KHz > 800000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x64); -+ else if (freq_KHz > 600000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x54); -+ else if (freq_KHz > 500000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x54); -+ else if (freq_KHz > 300000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x43); -+ else if (freq_KHz > 220000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x54); -+ else if (freq_KHz > 110000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x14); -+ else -+ _mt_fe_tn_set_reg(state, 0x87, 0x54); -+ msleep(5); -+ } else if (buf < 0x0c) { -+ if (freq_KHz > 800000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x14); -+ else if (freq_KHz > 600000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x14); -+ else if (freq_KHz > 500000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x34); -+ else if (freq_KHz > 300000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x43); -+ else if (freq_KHz > 220000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x54); -+ else if (freq_KHz > 110000) -+ _mt_fe_tn_set_reg(state, 0x87, 0x14); -+ else -+ _mt_fe_tn_set_reg(state, 0x87, 0x54); -+ msleep(5); -+ } -+ } else if ((state->tuner_mtt == 0xE1)) { -+ _mt_fe_tn_set_reg(state, 0x00, 0x01); -+ _mt_fe_tn_set_reg(state, 0x00, 0x00); -+ msleep(20); -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = (buf & 0xef) | 0x28; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ msleep(50); -+ _mt_fe_tn_get_reg(state, 0x38, &buf); -+ _mt_fe_tn_set_reg(state, 0x38, buf); -+ _mt_fe_tn_get_reg(state, 0x32, &buf); -+ buf = (buf & 0xf7) | 0x10; -+ _mt_fe_tn_set_reg(state, 0x32, buf); -+ msleep(10); -+ _mt_fe_tn_get_reg(state, 0x69, &buf); -+ buf = buf & 0x03; -+ _mt_fe_tn_set_reg(state, 0x2a, buf); -+ if (buf > 0) { -+ msleep(20); -+ _mt_fe_tn_get_reg(state, 0x84, &buf); -+ buf = buf & 0x1f; -+ _mt_fe_tn_set_reg(state, 0x68, 0x0a); -+ _mt_fe_tn_get_reg(state, 0x88, &buf1); -+ buf1 = buf1 & 0x1f; -+ if (buf <= buf1) -+ _mt_fe_tn_set_reg(state, 0x66, 0x44); -+ else -+ _mt_fe_tn_set_reg(state, 0x66, 0x74); -+ } else { -+ if (freq_KHz <= 600000) -+ _mt_fe_tn_set_reg(state, 0x68, 0x0c); -+ else -+ _mt_fe_tn_set_reg(state, 0x68, 0x0e); -+ _mt_fe_tn_set_reg(state, 0x30, 0xfb); -+ _mt_fe_tn_set_reg(state, 0x30, 0xff); -+ _mt_fe_tn_set_reg(state, 0x31, 0x04); -+ _mt_fe_tn_set_reg(state, 0x31, 0x00); -+ } -+ if (state->tuner_loopthrough != 0) { -+ _mt_fe_tn_get_reg(state, 0x28, &buf); -+ if (buf == 0) { -+ _mt_fe_tn_set_reg(state, 0x28, 0xff); -+ _mt_fe_tn_get_reg(state, 0x61, &buf); -+ buf = buf & 0x0f; -+ if (buf > 9) -+ _mt_fe_tn_set_reg(state, 0x67, 0x74); -+ else if (buf > 6) -+ _mt_fe_tn_set_reg(state, 0x67, 0x64); -+ else if (buf > 3) -+ _mt_fe_tn_set_reg(state, 0x67, 0x54); -+ else -+ _mt_fe_tn_set_reg(state, 0x67, 0x44); -+ } -+ } else { -+ _mt_fe_tn_set_reg(state, 0x67, 0x34); -+ } -+ } else { -+ return 1; -+ } -+ return 0; -+} -+ -+ -+/* -+static int mt_fe_tn_set_BB_filter_band_tc2800(struct m88dc2800_state *state, -+ u8 bandwidth) -+{ -+ u8 buf, tmp; -+ -+ _mt_fe_tn_get_reg(state, 0x53, &tmp); -+ -+ if (bandwidth == 6) -+ buf = 0x01 << 1; -+ else if (bandwidth == 7) -+ buf = 0x02 << 1; -+ else if (bandwidth == 8) -+ buf = 0x04 << 1; -+ else -+ buf = 0x04 << 1; -+ -+ tmp &= 0xf1; -+ tmp |= buf; -+ _mt_fe_tn_set_reg(state, 0x53, tmp); -+ state->tuner_bandwidth = bandwidth; -+ return 0; -+} -+*/ -+ -+static s32 mt_fe_tn_get_signal_strength_tc2800(struct m88dc2800_state -+ *state) -+{ -+ s32 level = -107; -+ s32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; -+ s32 val1, val2, val; -+ s32 result2, result3, result4, result5, result6; -+ s32 append; -+ u8 tmp; -+ s32 freq_KHz = (s32) state->tuner_freq; -+ if (state->tuner_mtt == 0xD1) { -+ _mt_fe_tn_get_reg(state, 0x61, &tmp); -+ tmp1 = tmp & 0x0f; -+ _mt_fe_tn_get_reg(state, 0x69, &tmp); -+ tmp2 = tmp & 0x0f; -+ _mt_fe_tn_get_reg(state, 0x73, &tmp); -+ tmp3 = tmp & 0x07; -+ _mt_fe_tn_get_reg(state, 0x7c, &tmp); -+ tmp4 = (tmp >> 4) & 0x0f; -+ _mt_fe_tn_get_reg(state, 0x7b, &tmp); -+ tmp5 = tmp & 0x0f; -+ _mt_fe_tn_get_reg(state, 0x7f, &tmp); -+ tmp6 = (tmp >> 5) & 0x01; -+ if (tmp1 > 6) { -+ val1 = 0; -+ if (freq_KHz <= 200000) { -+ val2 = (tmp1 - 6) * 267; -+ } else if (freq_KHz <= 600000) { -+ val2 = (tmp1 - 6) * 280; -+ } else { -+ val2 = (tmp1 - 6) * 290; -+ } -+ val = val1 + val2; -+ } else { -+ if (tmp1 == 0) { -+ val1 = -550; -+ } else { -+ val1 = 0; -+ } -+ if ((tmp1 < 4) && (freq_KHz >= 506000)) { -+ val1 = -850; -+ } -+ val2 = 0; -+ val = val1 + val2; -+ } -+ if (freq_KHz <= 95000) { -+ result2 = tmp2 * 289; -+ } else if (freq_KHz <= 155000) { -+ result2 = tmp2 * 278; -+ } else if (freq_KHz <= 245000) { -+ result2 = tmp2 * 267; -+ } else if (freq_KHz <= 305000) { -+ result2 = tmp2 * 256; -+ } else if (freq_KHz <= 335000) { -+ result2 = tmp2 * 244; -+ } else if (freq_KHz <= 425000) { -+ result2 = tmp2 * 233; -+ } else if (freq_KHz <= 575000) { -+ result2 = tmp2 * 222; -+ } else if (freq_KHz <= 665000) { -+ result2 = tmp2 * 211; -+ } else { -+ result2 = tmp2 * 200; -+ } -+ result3 = (6 - tmp3) * 100; -+ result4 = 300 * tmp4; -+ result5 = 50 * tmp5; -+ result6 = 300 * tmp6; -+ if (freq_KHz < 105000) { -+ append = -450; -+ } else if (freq_KHz <= 227000) { -+ append = -4 * (freq_KHz / 1000 - 100) + 150; -+ } else if (freq_KHz <= 305000) { -+ append = -4 * (freq_KHz / 1000 - 100); -+ } else if (freq_KHz <= 419000) { -+ append = 500 - 40 * (freq_KHz / 1000 - 300) / 17 + 130; -+ } else if (freq_KHz <= 640000) { -+ append = 500 - 40 * (freq_KHz / 1000 - 300) / 17; -+ } else { -+ append = -500; -+ } -+ level = append - (val + result2 + result3 + result4 + -+ result5 + result6); -+ level /= 100; -+ } else if (state->tuner_mtt == 0xE1) { -+ _mt_fe_tn_get_reg(state, 0x61, &tmp); -+ tmp1 = tmp & 0x0f; -+ _mt_fe_tn_get_reg(state, 0x84, &tmp); -+ tmp2 = tmp & 0x1f; -+ _mt_fe_tn_get_reg(state, 0x69, &tmp); -+ tmp3 = tmp & 0x03; -+ _mt_fe_tn_get_reg(state, 0x73, &tmp); -+ tmp4 = tmp & 0x0f; -+ _mt_fe_tn_get_reg(state, 0x7c, &tmp); -+ tmp5 = (tmp >> 4) & 0x0f; -+ _mt_fe_tn_get_reg(state, 0x7b, &tmp); -+ tmp6 = tmp & 0x0f; -+ if (freq_KHz < 151000) { -+ result2 = (1150 - freq_KHz / 100) * 163 / 33 + 4230; -+ result3 = (1150 - freq_KHz / 100) * 115 / 33 + 1850; -+ result4 = -3676 * (freq_KHz / 1000) / 100 + 6115; -+ } else if (freq_KHz < 257000) { -+ result2 = (1540 - freq_KHz / 100) * 11 / 4 + 3870; -+ result3 = (1540 - freq_KHz / 100) * 205 / 96 + 2100; -+ result4 = -21 * freq_KHz / 1000 + 5084; -+ } else if (freq_KHz < 305000) { -+ result2 = (2620 - freq_KHz / 100) * 5 / 3 + 2770; -+ result3 = (2620 - freq_KHz / 100) * 10 / 7 + 1700; -+ result4 = 650; -+ } else if (freq_KHz < 449000) { -+ result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270; -+ result3 = (3100 - freq_KHz / 100) * 5 / 3 + 10000; -+ result4 = 134 * freq_KHz / 10000 + 11875; -+ } else { -+ result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270; -+ result3 = 8400; -+ result4 = 5300; -+ } -+ if (tmp1 > 6) { -+ val1 = result2; -+ val2 = 2900; -+ val = 500; -+ } else if (tmp1 > 0) { -+ val1 = result3; -+ val2 = 2700; -+ val = 500; -+ } else { -+ val1 = result4; -+ val2 = 2700; -+ val = 400; -+ } -+ level = val1 - (val2 * tmp1 + 500 * tmp2 + 3000 * tmp3 - -+ 500 * tmp4 + 3000 * tmp5 + val * tmp6) - 1000; -+ level /= 1000; -+ } -+ return level; -+} -+ -+ -+/* m88dc2800 operation functions */ -+u8 M88DC2000GetLock(struct m88dc2800_state * state) -+{ -+ u8 u8ret = 0; -+ if (ReadReg(state, 0x80) < 0x06) { -+ if ((ReadReg(state, 0xdf) & 0x80) == 0x80 -+ &&(ReadReg(state, 0x91) & 0x23) == 0x03 -+ &&(ReadReg(state, 0x43) & 0x08) == 0x08) -+ u8ret = 1; -+ else -+ u8ret = 0; -+ } else { -+ if ((ReadReg(state, 0x85) & 0x08) == 0x08) -+ u8ret = 1; -+ else -+ u8ret = 0; -+ } -+ dprintk("%s, lock=%d\n", __func__, u8ret); -+ return u8ret; -+} -+ -+static int M88DC2000SetTsType(struct m88dc2800_state *state, u8 type) -+{ -+ u8 regC2H; -+ -+ if (type == 3) { -+ WriteReg(state, 0x84, 0x6A); -+ WriteReg(state, 0xC0, 0x43); -+ WriteReg(state, 0xE2, 0x06); -+ regC2H = ReadReg(state, 0xC2); -+ regC2H &= 0xC0; -+ regC2H |= 0x1B; -+ WriteReg(state, 0xC2, regC2H); -+ WriteReg(state, 0xC1, 0x60); /* common interface */ -+ } else if (type == 1) { -+ WriteReg(state, 0x84, 0x6A); -+ WriteReg(state, 0xC0, 0x47); /* serial format */ -+ WriteReg(state, 0xE2, 0x02); -+ regC2H = ReadReg(state, 0xC2); -+ regC2H &= 0xC7; -+ WriteReg(state, 0xC2, regC2H); -+ WriteReg(state, 0xC1, 0x00); -+ } else { -+ WriteReg(state, 0x84, 0x6C); -+ WriteReg(state, 0xC0, 0x43); /* parallel format */ -+ WriteReg(state, 0xE2, 0x06); -+ regC2H = ReadReg(state, 0xC2); -+ regC2H &= 0xC7; -+ WriteReg(state, 0xC2, regC2H); -+ WriteReg(state, 0xC1, 0x00); -+ } -+ return 0; -+} -+ -+static int M88DC2000RegInitial_TC2800(struct m88dc2800_state *state) -+{ -+ u8 RegE3H, RegE4H; -+ -+ WriteReg(state, 0x00, 0x48); -+ WriteReg(state, 0x01, 0x09); -+ WriteReg(state, 0xFB, 0x0A); -+ WriteReg(state, 0xFC, 0x0B); -+ WriteReg(state, 0x02, 0x0B); -+ WriteReg(state, 0x03, 0x18); -+ WriteReg(state, 0x05, 0x0D); -+ WriteReg(state, 0x36, 0x80); -+ WriteReg(state, 0x43, 0x40); -+ WriteReg(state, 0x55, 0x7A); -+ WriteReg(state, 0x56, 0xD9); -+ WriteReg(state, 0x57, 0xDF); -+ WriteReg(state, 0x58, 0x39); -+ WriteReg(state, 0x5A, 0x00); -+ WriteReg(state, 0x5C, 0x71); -+ WriteReg(state, 0x5D, 0x23); -+ WriteReg(state, 0x86, 0x40); -+ WriteReg(state, 0xF9, 0x08); -+ WriteReg(state, 0x61, 0x40); -+ WriteReg(state, 0x62, 0x0A); -+ WriteReg(state, 0x90, 0x06); -+ WriteReg(state, 0xDE, 0x00); -+ WriteReg(state, 0xA0, 0x03); -+ WriteReg(state, 0xDF, 0x81); -+ WriteReg(state, 0xFA, 0x40); -+ WriteReg(state, 0x37, 0x10); -+ WriteReg(state, 0xF0, 0x40); -+ WriteReg(state, 0xF2, 0x9C); -+ WriteReg(state, 0xF3, 0x40); -+ RegE3H = ReadReg(state, 0xE3); -+ RegE4H = ReadReg(state, 0xE4); -+ if (((RegE3H & 0xC0) == 0x00) && ((RegE4H & 0xC0) == 0x00)) { -+ WriteReg(state, 0x30, 0xFF); -+ WriteReg(state, 0x31, 0x00); -+ WriteReg(state, 0x32, 0x00); -+ WriteReg(state, 0x33, 0x00); -+ WriteReg(state, 0x35, 0x32); -+ WriteReg(state, 0x40, 0x00); -+ WriteReg(state, 0x41, 0x10); -+ WriteReg(state, 0xF1, 0x02); -+ WriteReg(state, 0xF4, 0x04); -+ WriteReg(state, 0xF5, 0x00); -+ WriteReg(state, 0x42, 0x14); -+ WriteReg(state, 0xE1, 0x25); -+ } else if (((RegE3H & 0xC0) == 0x80) && ((RegE4H & 0xC0) == 0x40)) { -+ WriteReg(state, 0x30, 0xFF); -+ WriteReg(state, 0x31, 0x00); -+ WriteReg(state, 0x32, 0x00); -+ WriteReg(state, 0x33, 0x00); -+ WriteReg(state, 0x35, 0x32); -+ WriteReg(state, 0x39, 0x00); -+ WriteReg(state, 0x3A, 0x00); -+ WriteReg(state, 0x40, 0x00); -+ WriteReg(state, 0x41, 0x10); -+ WriteReg(state, 0xF1, 0x00); -+ WriteReg(state, 0xF4, 0x00); -+ WriteReg(state, 0xF5, 0x40); -+ WriteReg(state, 0x42, 0x14); -+ WriteReg(state, 0xE1, 0x25); -+ } else if ((RegE3H == 0x80 || RegE3H == 0x81) -+ && (RegE4H == 0x80 || RegE4H == 0x81)) { -+ WriteReg(state, 0x30, 0xFF); -+ WriteReg(state, 0x31, 0x00); -+ WriteReg(state, 0x32, 0x00); -+ WriteReg(state, 0x33, 0x00); -+ WriteReg(state, 0x35, 0x32); -+ WriteReg(state, 0x39, 0x00); -+ WriteReg(state, 0x3A, 0x00); -+ WriteReg(state, 0xF1, 0x00); -+ WriteReg(state, 0xF4, 0x00); -+ WriteReg(state, 0xF5, 0x40); -+ WriteReg(state, 0x42, 0x24); -+ WriteReg(state, 0xE1, 0x25); -+ WriteReg(state, 0x92, 0x7F); -+ WriteReg(state, 0x93, 0x91); -+ WriteReg(state, 0x95, 0x00); -+ WriteReg(state, 0x2B, 0x33); -+ WriteReg(state, 0x2A, 0x2A); -+ WriteReg(state, 0x2E, 0x80); -+ WriteReg(state, 0x25, 0x25); -+ WriteReg(state, 0x2D, 0xFF); -+ WriteReg(state, 0x26, 0xFF); -+ WriteReg(state, 0x27, 0x00); -+ WriteReg(state, 0x24, 0x25); -+ WriteReg(state, 0xA4, 0xFF); -+ WriteReg(state, 0xA3, 0x0D); -+ } else { -+ WriteReg(state, 0x30, 0xFF); -+ WriteReg(state, 0x31, 0x00); -+ WriteReg(state, 0x32, 0x00); -+ WriteReg(state, 0x33, 0x00); -+ WriteReg(state, 0x35, 0x32); -+ WriteReg(state, 0x39, 0x00); -+ WriteReg(state, 0x3A, 0x00); -+ WriteReg(state, 0xF1, 0x00); -+ WriteReg(state, 0xF4, 0x00); -+ WriteReg(state, 0xF5, 0x40); -+ WriteReg(state, 0x42, 0x24); -+ WriteReg(state, 0xE1, 0x27); -+ WriteReg(state, 0x92, 0x7F); -+ WriteReg(state, 0x93, 0x91); -+ WriteReg(state, 0x95, 0x00); -+ WriteReg(state, 0x2B, 0x33); -+ WriteReg(state, 0x2A, 0x2A); -+ WriteReg(state, 0x2E, 0x80); -+ WriteReg(state, 0x25, 0x25); -+ WriteReg(state, 0x2D, 0xFF); -+ WriteReg(state, 0x26, 0xFF); -+ WriteReg(state, 0x27, 0x00); -+ WriteReg(state, 0x24, 0x25); -+ WriteReg(state, 0xA4, 0xFF); -+ WriteReg(state, 0xA3, 0x10); -+ } -+ WriteReg(state, 0xF6, 0x4E); -+ WriteReg(state, 0xF7, 0x20); -+ WriteReg(state, 0x89, 0x02); -+ WriteReg(state, 0x14, 0x08); -+ WriteReg(state, 0x6F, 0x0D); -+ WriteReg(state, 0x10, 0xFF); -+ WriteReg(state, 0x11, 0x00); -+ WriteReg(state, 0x12, 0x30); -+ WriteReg(state, 0x13, 0x23); -+ WriteReg(state, 0x60, 0x00); -+ WriteReg(state, 0x69, 0x00); -+ WriteReg(state, 0x6A, 0x03); -+ WriteReg(state, 0xE0, 0x75); -+ WriteReg(state, 0x8D, 0x29); -+ WriteReg(state, 0x4E, 0xD8); -+ WriteReg(state, 0x88, 0x80); -+ WriteReg(state, 0x52, 0x79); -+ WriteReg(state, 0x53, 0x03); -+ WriteReg(state, 0x59, 0x30); -+ WriteReg(state, 0x5E, 0x02); -+ WriteReg(state, 0x5F, 0x0F); -+ WriteReg(state, 0x71, 0x03); -+ WriteReg(state, 0x72, 0x12); -+ WriteReg(state, 0x73, 0x12); -+ -+ return 0; -+} -+ -+static int M88DC2000AutoTSClock_P(struct m88dc2800_state *state, u32 sym, -+ u16 qam) -+{ -+ u32 dataRate; -+ u8 clk_div, value; -+ printk(KERN_INFO -+ "m88dc2800: M88DC2000AutoTSClock_P, symrate=%d qam=%d\n", -+ sym, qam); -+ switch (qam) { -+ case 16: -+ dataRate = 4; -+ break; -+ case 32: -+ dataRate = 5; -+ break; -+ case 128: -+ dataRate = 7; -+ break; -+ case 256: -+ dataRate = 8; -+ break; -+ case 64: -+ default: -+ dataRate = 6; -+ break; -+ } -+ dataRate *= sym * 105; -+ dataRate /= 800; -+ if (dataRate <= 4115) -+ clk_div = 0x05; -+ else if (dataRate <= 4800) -+ clk_div = 0x04; -+ else if (dataRate <= 5760) -+ clk_div = 0x03; -+ else if (dataRate <= 7200) -+ clk_div = 0x02; -+ else if (dataRate <= 9600) -+ clk_div = 0x01; -+ else -+ clk_div = 0x00; -+ value = ReadReg(state, 0xC2); -+ value &= 0xc0; -+ value |= clk_div; -+ WriteReg(state, 0xC2, value); -+ return 0; -+} -+ -+static int M88DC2000AutoTSClock_C(struct m88dc2800_state *state, u32 sym, -+ u16 qam) -+{ -+ u32 dataRate; -+ u8 clk_div, value; -+ printk(KERN_INFO -+ "m88dc2800: M88DC2000AutoTSClock_C, symrate=%d qam=%d\n", -+ sym, qam); -+ switch (qam) { -+ case 16: -+ dataRate = 4; -+ break; -+ case 32: -+ dataRate = 5; -+ break; -+ case 128: -+ dataRate = 7; -+ break; -+ case 256: -+ dataRate = 8; -+ break; -+ case 64: -+ default: -+ dataRate = 6; -+ break; -+ } -+ dataRate *= sym * 105; -+ dataRate /= 800; -+ if (dataRate <= 4115) -+ clk_div = 0x3F; -+ else if (dataRate <= 4800) -+ clk_div = 0x36; -+ else if (dataRate <= 5760) -+ clk_div = 0x2D; -+ else if (dataRate <= 7200) -+ clk_div = 0x24; -+ else if (dataRate <= 9600) -+ clk_div = 0x1B; -+ else -+ clk_div = 0x12; -+ value = ReadReg(state, 0xC2); -+ value &= 0xc0; -+ value |= clk_div; -+ WriteReg(state, 0xC2, value); -+ return 0; -+} -+ -+static int M88DC2000SetTxMode(struct m88dc2800_state *state, u8 inverted, -+ u8 j83) -+{ -+ u8 value = 0; -+ if (inverted) -+ value |= 0x08; /* spectrum inverted */ -+ if (j83) -+ value |= 0x01; /* J83C */ -+ WriteReg(state, 0x83, value); -+ return 0; -+} -+ -+static int M88DC2000SoftReset(struct m88dc2800_state *state) -+{ -+ WriteReg(state, 0x80, 0x01); -+ WriteReg(state, 0x82, 0x00); -+ msleep(1); -+ WriteReg(state, 0x80, 0x00); -+ return 0; -+} -+ -+static int M88DC2000SetSym(struct m88dc2800_state *state, u32 sym, u32 xtal) -+{ -+ u8 value; -+ u8 reg6FH, reg12H; -+ u64 fValue; -+ u32 dwValue; -+ -+ printk(KERN_INFO "%s, sym=%d, xtal=%d\n", __func__, sym, xtal); -+ fValue = 4294967296 * (sym + 10); -+ do_div(fValue, xtal); -+ -+ /* fValue = 4294967296 * (sym + 10) / xtal; */ -+ dwValue = (u32) fValue; -+ printk(KERN_INFO "%s, fvalue1=%x\n", __func__, dwValue); -+ WriteReg(state, 0x58, (u8) ((dwValue >> 24) & 0xff)); -+ WriteReg(state, 0x57, (u8) ((dwValue >> 16) & 0xff)); -+ WriteReg(state, 0x56, (u8) ((dwValue >> 8) & 0xff)); -+ WriteReg(state, 0x55, (u8) ((dwValue >> 0) & 0xff)); -+ -+ /* fValue = 2048 * xtal / sym; */ -+ fValue = 2048 * xtal; -+ do_div(fValue, sym); -+ dwValue = (u32) fValue; -+ printk(KERN_INFO "%s, fvalue2=%x\n", __func__, dwValue); -+ WriteReg(state, 0x5D, (u8) ((dwValue >> 8) & 0xff)); -+ WriteReg(state, 0x5C, (u8) ((dwValue >> 0) & 0xff)); -+ value = ReadReg(state, 0x5A); -+ if (((dwValue >> 16) & 0x0001) == 0) -+ value &= 0x7F; -+ else -+ value |= 0x80; -+ WriteReg(state, 0x5A, value); -+ value = ReadReg(state, 0x89); -+ if (sym <= 1800) -+ value |= 0x01; -+ else -+ value &= 0xFE; -+ WriteReg(state, 0x89, value); -+ if (sym >= 6700) { -+ reg6FH = 0x0D; -+ reg12H = 0x30; -+ } else if (sym >= 4000) { -+ fValue = 22 * 4096 / sym; -+ reg6FH = (u8) fValue; -+ reg12H = 0x30; -+ } else if (sym >= 2000) { -+ fValue = 14 * 4096 / sym; -+ reg6FH = (u8) fValue; -+ reg12H = 0x20; -+ } else { -+ fValue = 7 * 4096 / sym; -+ reg6FH = (u8) fValue; -+ reg12H = 0x10; -+ } -+ WriteReg(state, 0x6F, reg6FH); -+ WriteReg(state, 0x12, reg12H); -+ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) -+ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { -+ if (sym < 3000) { -+ WriteReg(state, 0x6C, 0x16); -+ WriteReg(state, 0x6D, 0x10); -+ WriteReg(state, 0x6E, 0x18); -+ } else { -+ WriteReg(state, 0x6C, 0x14); -+ WriteReg(state, 0x6D, 0x0E); -+ WriteReg(state, 0x6E, 0x36); -+ } -+ } else { -+ WriteReg(state, 0x6C, 0x16); -+ WriteReg(state, 0x6D, 0x10); -+ WriteReg(state, 0x6E, 0x18); -+ } -+ return 0; -+} -+ -+static int M88DC2000SetQAM(struct m88dc2800_state *state, u16 qam) -+{ -+ u8 reg00H, reg4AH, regC2H, reg44H, reg4CH, reg4DH, reg74H, value; -+ u8 reg8BH, reg8EH; -+ printk(KERN_INFO "%s, qam=%d\n", __func__, qam); -+ regC2H = ReadReg(state, 0xC2); -+ regC2H &= 0xF8; -+ switch (qam) { -+ case 16: /* 16 QAM */ -+ reg00H = 0x08; -+ reg4AH = 0x0F; -+ regC2H |= 0x02; -+ reg44H = 0xAA; -+ reg4CH = 0x0C; -+ reg4DH = 0xF7; -+ reg74H = 0x0E; -+ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) -+ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { -+ reg8BH = 0x5A; -+ reg8EH = 0xBD; -+ } else { -+ reg8BH = 0x5B; -+ reg8EH = 0x9D; -+ } -+ WriteReg(state, 0x6E, 0x18); -+ break; -+ case 32: /* 32 QAM */ -+ reg00H = 0x18; -+ reg4AH = 0xFB; -+ regC2H |= 0x02; -+ reg44H = 0xAA; -+ reg4CH = 0x0C; -+ reg4DH = 0xF7; -+ reg74H = 0x0E; -+ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) -+ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { -+ reg8BH = 0x5A; -+ reg8EH = 0xBD; -+ } else { -+ reg8BH = 0x5B; -+ reg8EH = 0x9D; -+ } -+ WriteReg(state, 0x6E, 0x18); -+ break; -+ case 64: /* 64 QAM */ -+ reg00H = 0x48; -+ reg4AH = 0xCD; -+ regC2H |= 0x02; -+ reg44H = 0xAA; -+ reg4CH = 0x0C; -+ reg4DH = 0xF7; -+ reg74H = 0x0E; -+ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) -+ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { -+ reg8BH = 0x5A; -+ reg8EH = 0xBD; -+ } else { -+ reg8BH = 0x5B; -+ reg8EH = 0x9D; -+ } -+ break; -+ case 128: /* 128 QAM */ -+ reg00H = 0x28; -+ reg4AH = 0xFF; -+ regC2H |= 0x02; -+ reg44H = 0xA9; -+ reg4CH = 0x08; -+ reg4DH = 0xF5; -+ reg74H = 0x0E; -+ reg8BH = 0x5B; -+ reg8EH = 0x9D; -+ break; -+ case 256: /* 256 QAM */ -+ reg00H = 0x38; -+ reg4AH = 0xCD; -+ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) -+ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { -+ regC2H |= 0x02; -+ } else { -+ regC2H |= 0x01; -+ } -+ reg44H = 0xA9; -+ reg4CH = 0x08; -+ reg4DH = 0xF5; -+ reg74H = 0x0E; -+ reg8BH = 0x5B; -+ reg8EH = 0x9D; -+ break; -+ default: /* 64 QAM */ -+ reg00H = 0x48; -+ reg4AH = 0xCD; -+ regC2H |= 0x02; -+ reg44H = 0xAA; -+ reg4CH = 0x0C; -+ reg4DH = 0xF7; -+ reg74H = 0x0E; -+ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) -+ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { -+ reg8BH = 0x5A; -+ reg8EH = 0xBD; -+ } else { -+ reg8BH = 0x5B; -+ reg8EH = 0x9D; -+ } -+ break; -+ } -+ WriteReg(state, 0x00, reg00H); -+ value = ReadReg(state, 0x88); -+ value |= 0x08; -+ WriteReg(state, 0x88, value); -+ WriteReg(state, 0x4B, 0xFF); -+ WriteReg(state, 0x4A, reg4AH); -+ value &= 0xF7; -+ WriteReg(state, 0x88, value); -+ WriteReg(state, 0xC2, regC2H); -+ WriteReg(state, 0x44, reg44H); -+ WriteReg(state, 0x4C, reg4CH); -+ WriteReg(state, 0x4D, reg4DH); -+ WriteReg(state, 0x74, reg74H); -+ WriteReg(state, 0x8B, reg8BH); -+ WriteReg(state, 0x8E, reg8EH); -+ return 0; -+} -+ -+static int M88DC2000WriteTuner_TC2800(struct m88dc2800_state *state, -+ u32 freq_KHz) -+{ -+ printk(KERN_INFO "%s, freq=%d KHz\n", __func__, freq_KHz); -+ return mt_fe_tn_set_freq_tc2800(state, freq_KHz); -+} -+ -+static int m88dc2800_init(struct dvb_frontend *fe) -+{ -+ dprintk("%s()\n", __func__); -+ return 0; -+} -+ -+static int m88dc2800_set_parameters(struct dvb_frontend *fe) -+{ -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ u8 is_annex_c, is_update; -+ u16 temp_qam; -+ s32 waiting_time; -+ struct m88dc2800_state *state = fe->demodulator_priv; -+ -+ is_annex_c = c->delivery_system == SYS_DVBC_ANNEX_C ? 1 : 0; -+ -+ switch (c->modulation) { -+ case QAM_16: -+ temp_qam = 16; -+ break; -+ case QAM_32: -+ temp_qam = 32; -+ break; -+ case QAM_128: -+ temp_qam = 128; -+ break; -+ case QAM_256: -+ temp_qam = 256; -+ break; -+ default: /* QAM_64 */ -+ temp_qam = 64; -+ break; -+ } -+ -+ state->inverted = c->inversion == INVERSION_ON ? 1 : 0; -+ -+ printk(KERN_INFO -+ "m88dc2800: state, freq=%d qam=%d sym=%d inverted=%d xtal=%d\n", -+ state->freq, state->qam, state->sym, state->inverted, -+ state->xtal); -+ printk(KERN_INFO -+ "m88dc2800: set frequency to %d qam=%d symrate=%d annex-c=%d\n", -+ c->frequency, temp_qam, c->symbol_rate, is_annex_c); -+ -+ is_update = 0; -+ WriteReg(state, 0x80, 0x01); -+ if (c->frequency != state->freq) { -+ M88DC2000WriteTuner_TC2800(state, c->frequency / 1000); -+ state->freq = c->frequency; -+ } -+ if (c->symbol_rate != state->sym) { -+ M88DC2000SetSym(state, c->symbol_rate / 1000, state->xtal); -+ state->sym = c->symbol_rate; -+ is_update = 1; -+ } -+ if (temp_qam != state->qam) { -+ M88DC2000SetQAM(state, temp_qam); -+ state->qam = temp_qam; -+ is_update = 1; -+ } -+ -+ if (is_update != 0) { -+ if (state->config->ts_mode == 3) -+ M88DC2000AutoTSClock_C(state, state->sym / 1000, -+ temp_qam); -+ else -+ M88DC2000AutoTSClock_P(state, state->sym / 1000, -+ temp_qam); -+ } -+ -+ M88DC2000SetTxMode(state, state->inverted, is_annex_c); -+ M88DC2000SoftReset(state); -+ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) -+ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) -+ waiting_time = 800; -+ else -+ waiting_time = 500; -+ while (waiting_time > 0) { -+ msleep(50); -+ waiting_time -= 50; -+ if (M88DC2000GetLock(state)) -+ return 0; -+ } -+ -+ state->inverted = (state->inverted != 0) ? 0 : 1; -+ M88DC2000SetTxMode(state, state->inverted, is_annex_c); -+ M88DC2000SoftReset(state); -+ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) && -+ ((ReadReg(state, 0xE4) & 0x80) == 0x80)) -+ waiting_time = 800; -+ else -+ waiting_time = 500; -+ while (waiting_time > 0) { -+ msleep(50); -+ waiting_time -= 50; -+ if (M88DC2000GetLock(state)) -+ return 0; -+ } -+ return 0; -+} -+ -+static int m88dc2800_read_status(struct dvb_frontend *fe, -+ fe_status_t * status) -+{ -+ struct m88dc2800_state *state = fe->demodulator_priv; -+ *status = 0; -+ -+ if (M88DC2000GetLock(state)) { -+ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER -+ |FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK; -+ } -+ return 0; -+} -+ -+static int m88dc2800_read_ber(struct dvb_frontend *fe, u32 * ber) -+{ -+ struct m88dc2800_state *state = fe->demodulator_priv; -+ u16 tmp; -+ -+ if (M88DC2000GetLock(state) == 0) { -+ state->ber = 0; -+ } else if ((ReadReg(state, 0xA0) & 0x80) != 0x80) { -+ tmp = ReadReg(state, 0xA2) << 8; -+ tmp += ReadReg(state, 0xA1); -+ state->ber = tmp; -+ WriteReg(state, 0xA0, 0x05); -+ WriteReg(state, 0xA0, 0x85); -+ } -+ *ber = state->ber; -+ return 0; -+} -+ -+static int m88dc2800_read_signal_strength(struct dvb_frontend *fe, -+ u16 * strength) -+{ -+ struct m88dc2800_state *state = fe->demodulator_priv; -+ s16 tuner_strength; -+ -+ tuner_strength = mt_fe_tn_get_signal_strength_tc2800(state); -+ *strength = tuner_strength < -107 ? 0 : tuner_strength + 107; -+ -+ return 0; -+} -+ -+static int m88dc2800_read_snr(struct dvb_frontend *fe, u16 * snr) -+{ -+ static const u32 mes_log[] = { -+ 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000, -+ 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788, -+ 13010, 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472, -+ 14624, 14771, 14914, 15052, 15185, 15315, 15441, 15563, 15682, -+ 15798, 15911, 16021, 16128, 16232, 16335, 16435, 16532, 16628, -+ 16721, 16812, 16902, 16990, 17076, 17160, 17243, 17324, 17404, -+ 17482, 17559, 17634, 17709, 17782, 17853, 17924, 17993, 18062, -+ 18129, 18195, 18261, 18325, 18388, 18451, 18513, 18573, 18633, -+ 18692, 18751, 18808, 18865, 18921, 18976, 19031 -+ }; -+ struct m88dc2800_state *state = fe->demodulator_priv; -+ u8 i; -+ u32 _snr, mse; -+ -+ if ((ReadReg(state, 0x91) & 0x23) != 0x03) { -+ *snr = 0; -+ return 0; -+ } -+ mse = 0; -+ for (i = 0; i < 30; i++) { -+ mse += (ReadReg(state, 0x08) << 8) + ReadReg(state, 0x07); -+ } -+ mse /= 30; -+ if (mse > 80) -+ mse = 80; -+ switch (state->qam) { -+ case 16: -+ _snr = 34080; -+ break; /* 16QAM */ -+ case 32: -+ _snr = 37600; -+ break; /* 32QAM */ -+ case 64: -+ _snr = 40310; -+ break; /* 64QAM */ -+ case 128: -+ _snr = 43720; -+ break; /* 128QAM */ -+ case 256: -+ _snr = 46390; -+ break; /* 256QAM */ -+ default: -+ _snr = 40310; -+ break; -+ } -+ _snr -= mes_log[mse - 1]; /* C - 10*log10(MSE) */ -+ _snr /= 1000; -+ if (_snr > 0xff) -+ _snr = 0xff; -+ *snr = _snr; -+ return 0; -+} -+ -+static int m88dc2800_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) -+{ -+ struct m88dc2800_state *state = fe->demodulator_priv; -+ u8 u8Value; -+ -+ u8Value = ReadReg(state, 0xdf); -+ u8Value |= 0x02; /* Hold */ -+ WriteReg(state, 0xdf, u8Value); -+ -+ *ucblocks = ReadReg(state, 0xd5); -+ *ucblocks = (*ucblocks << 8) | ReadReg(state, 0xd4); -+ -+ u8Value &= 0xfe; /* Clear */ -+ WriteReg(state, 0xdf, u8Value); -+ u8Value &= 0xfc; /* Update */ -+ u8Value |= 0x01; -+ WriteReg(state, 0xdf, u8Value); -+ -+ return 0; -+} -+ -+static int m88dc2800_sleep(struct dvb_frontend *fe) -+{ -+ struct m88dc2800_state *state = fe->demodulator_priv; -+ -+ mt_fe_tn_sleep_tc2800(state); -+ state->freq = 0; -+ -+ return 0; -+} -+ -+static void m88dc2800_release(struct dvb_frontend *fe) -+{ -+ struct m88dc2800_state *state = fe->demodulator_priv; -+ kfree(state); -+} -+ -+static struct dvb_frontend_ops m88dc2800_ops; -+ -+struct dvb_frontend *m88dc2800_attach(const struct m88dc2800_config -+ *config, struct i2c_adapter *i2c) -+{ -+ struct m88dc2800_state *state = NULL; -+ -+ /* allocate memory for the internal state */ -+ state = kzalloc(sizeof(struct m88dc2800_state), GFP_KERNEL); -+ if (state == NULL) -+ goto error; -+ -+ /* setup the state */ -+ state->config = config; -+ state->i2c = i2c; -+ state->xtal = 28800; -+ -+ WriteReg(state, 0x80, 0x01); -+ M88DC2000RegInitial_TC2800(state); -+ M88DC2000SetTsType(state, state->config->ts_mode); -+ mt_fe_tn_init_tc2800(state); -+ -+ /* create dvb_frontend */ -+ memcpy(&state->frontend.ops, &m88dc2800_ops, -+ sizeof(struct dvb_frontend_ops)); -+ state->frontend.demodulator_priv = state; -+ return &state->frontend; -+ -+ error: -+ kfree(state); -+ return NULL; -+} -+ -+EXPORT_SYMBOL(m88dc2800_attach); -+ -+static struct dvb_frontend_ops m88dc2800_ops = { -+ .delsys = {SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C}, -+ .info = { -+ .name = "Montage M88DC2800 DVB-C", -+ .frequency_stepsize = 62500, -+ .frequency_min = 48000000, -+ .frequency_max = 870000000, -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 9000000, -+ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO -+ }, -+ .release = m88dc2800_release, -+ .init = m88dc2800_init, -+ .sleep = m88dc2800_sleep, -+ .set_frontend = m88dc2800_set_parameters, -+ .read_status = m88dc2800_read_status, -+ .read_ber = m88dc2800_read_ber, -+ .read_signal_strength = m88dc2800_read_signal_strength, -+ .read_snr = m88dc2800_read_snr, -+ .read_ucblocks = m88dc2800_read_ucblocks, -+}; -+ -+MODULE_DESCRIPTION("Montage DVB-C demodulator driver"); -+MODULE_AUTHOR("Max Nibble "); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION("1.00"); -diff -urN a/drivers/media/dvb-frontends/m88dc2800.h b/drivers/media/dvb-frontends/m88dc2800.h ---- a/drivers/media/dvb-frontends/m88dc2800.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/media/dvb-frontends/m88dc2800.h 2013-01-26 14:57:32.000000000 +0800 -@@ -0,0 +1,43 @@ -+/* -+ M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage -+ -+ Copyright (C) 2012 Max Nibble -+ Copyright (C) 2011 Montage Technology - www.montage-tech.com -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#ifndef M88DC2800_H -+#define M88DC2800_H -+ -+#include -+ -+struct m88dc2800_config { -+ u8 demod_address; -+ u8 ts_mode; -+}; -+ -+#if defined(CONFIG_DVB_M88DC2800) || (defined(CONFIG_DVB_M88DC2800_MODULE) && defined(MODULE)) -+extern struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config, -+ struct i2c_adapter* i2c); -+#else -+static inline struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config, -+ struct i2c_adapter* i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_M88DC2800 */ -+#endif /* M88DC2800_H */ -diff -urN a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c ---- a/drivers/media/dvb-frontends/m88ds3103.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/media/dvb-frontends/m88ds3103.c 2013-01-30 12:33:47.000000000 +0800 -@@ -0,0 +1,1710 @@ -+/* -+ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver -+ -+ Copyright (C) 2011 Max nibble -+ Copyright (C) 2010 Montage Technology -+ Copyright (C) 2009 Konstantin Dimitrov. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "m88ds3103.h" -+#include "m88ds3103_priv.h" -+ -+static int debug; -+module_param(debug, int, 0644); -+MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); -+ -+#define dprintk(args...) \ -+ do { \ -+ if (debug) \ -+ printk(KERN_INFO "m88ds3103: " args); \ -+ } while (0) -+ -+/*demod register operations.*/ -+static int m88ds3103_writereg(struct m88ds3103_state *state, int reg, int data) -+{ -+ u8 buf[] = { reg, data }; -+ struct i2c_msg msg = { .addr = state->config->demod_address, -+ .flags = 0, .buf = buf, .len = 2 }; -+ int err; -+ -+ if (debug > 1) -+ printk("m88ds3103: %s: write reg 0x%02x, value 0x%02x\n", -+ __func__, reg, data); -+ -+ err = i2c_transfer(state->i2c, &msg, 1); -+ if (err != 1) { -+ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x," -+ " value == 0x%02x)\n", __func__, err, reg, data); -+ return -EREMOTEIO; -+ } -+ return 0; -+} -+ -+static int m88ds3103_readreg(struct m88ds3103_state *state, u8 reg) -+{ -+ int ret; -+ u8 b0[] = { reg }; -+ u8 b1[] = { 0 }; -+ struct i2c_msg msg[] = { -+ { .addr = state->config->demod_address, .flags = 0, -+ .buf = b0, .len = 1 }, -+ { .addr = state->config->demod_address, .flags = I2C_M_RD, -+ .buf = b1, .len = 1 } -+ }; -+ ret = i2c_transfer(state->i2c, msg, 2); -+ -+ if (ret != 2) { -+ printk(KERN_ERR "%s: reg=0x%x (error=%d)\n", -+ __func__, reg, ret); -+ return ret; -+ } -+ -+ if (debug > 1) -+ printk(KERN_INFO "m88ds3103: read reg 0x%02x, value 0x%02x\n", -+ reg, b1[0]); -+ -+ return b1[0]; -+} -+ -+/*tuner register operations.*/ -+static int m88ds3103_tuner_writereg(struct m88ds3103_state *state, int reg, int data) -+{ -+ u8 buf[] = { reg, data }; -+ struct i2c_msg msg = { .addr = 0x60, -+ .flags = 0, .buf = buf, .len = 2 }; -+ int err; -+ -+ m88ds3103_writereg(state, 0x03, 0x11); -+ err = i2c_transfer(state->i2c, &msg, 1); -+ -+ if (err != 1) { -+ printk("%s: writereg error(err == %i, reg == 0x%02x," -+ " value == 0x%02x)\n", __func__, err, reg, data); -+ return -EREMOTEIO; -+ } -+ -+ return 0; -+} -+ -+static int m88ds3103_tuner_readreg(struct m88ds3103_state *state, u8 reg) -+{ -+ int ret; -+ u8 b0[] = { reg }; -+ u8 b1[] = { 0 }; -+ struct i2c_msg msg[] = { -+ { .addr = 0x60, .flags = 0, -+ .buf = b0, .len = 1 }, -+ { .addr = 0x60, .flags = I2C_M_RD, -+ .buf = b1, .len = 1 } -+ }; -+ -+ m88ds3103_writereg(state, 0x03, 0x11); -+ ret = i2c_transfer(state->i2c, msg, 2); -+ -+ if (ret != 2) { -+ printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret); -+ return ret; -+ } -+ -+ return b1[0]; -+} -+ -+/* Bulk demod I2C write, for firmware download. */ -+static int m88ds3103_writeregN(struct m88ds3103_state *state, int reg, -+ const u8 *data, u16 len) -+{ -+ int ret = -EREMOTEIO; -+ struct i2c_msg msg; -+ u8 *buf; -+ -+ buf = kmalloc(len + 1, GFP_KERNEL); -+ if (buf == NULL) { -+ printk("Unable to kmalloc\n"); -+ ret = -ENOMEM; -+ goto error; -+ } -+ -+ *(buf) = reg; -+ memcpy(buf + 1, data, len); -+ -+ msg.addr = state->config->demod_address; -+ msg.flags = 0; -+ msg.buf = buf; -+ msg.len = len + 1; -+ -+ if (debug > 1) -+ printk(KERN_INFO "m88ds3103: %s: write regN 0x%02x, len = %d\n", -+ __func__, reg, len); -+ -+ ret = i2c_transfer(state->i2c, &msg, 1); -+ if (ret != 1) { -+ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n", -+ __func__, ret, reg); -+ ret = -EREMOTEIO; -+ } -+ -+error: -+ kfree(buf); -+ -+ return ret; -+} -+ -+static int m88ds3103_load_firmware(struct dvb_frontend *fe) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ const struct firmware *fw; -+ int i, ret = 0; -+ -+ dprintk("%s()\n", __func__); -+ -+ if (state->skip_fw_load) -+ return 0; -+ /* Load firmware */ -+ /* request the firmware, this will block until someone uploads it */ -+ if(state->demod_id == DS3000_ID){ -+ printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, -+ DS3000_DEFAULT_FIRMWARE); -+ ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE, -+ state->i2c->dev.parent); -+ }else if(state->demod_id == DS3103_ID){ -+ printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, -+ DS3103_DEFAULT_FIRMWARE); -+ ret = request_firmware(&fw, DS3103_DEFAULT_FIRMWARE, -+ state->i2c->dev.parent); -+ } -+ -+ printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); -+ if (ret) { -+ printk(KERN_ERR "%s: No firmware uploaded (timeout or file not " -+ "found?)\n", __func__); -+ return ret; -+ } -+ -+ /* Make sure we don't recurse back through here during loading */ -+ state->skip_fw_load = 1; -+ -+ dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n", -+ fw->size, -+ fw->data[0], -+ fw->data[1], -+ fw->data[fw->size - 2], -+ fw->data[fw->size - 1]); -+ -+ /* stop internal mcu. */ -+ m88ds3103_writereg(state, 0xb2, 0x01); -+ /* split firmware to download.*/ -+ for(i = 0; i < FW_DOWN_LOOP; i++){ -+ ret = m88ds3103_writeregN(state, 0xb0, &(fw->data[FW_DOWN_SIZE*i]), FW_DOWN_SIZE); -+ if(ret != 1) break; -+ } -+ /* start internal mcu. */ -+ if(ret == 1) -+ m88ds3103_writereg(state, 0xb2, 0x00); -+ -+ release_firmware(fw); -+ -+ dprintk("%s: Firmware upload %s\n", __func__, -+ ret == 1 ? "complete" : "failed"); -+ -+ if(ret == 1) ret = 0; -+ -+ /* Ensure firmware is always loaded if required */ -+ state->skip_fw_load = 0; -+ -+ return ret; -+} -+ -+ -+static int m88ds3103_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u8 data; -+ -+ dprintk("%s(%d)\n", __func__, voltage); -+ -+ dprintk("m88ds3103:pin_ctrl = (%02x)\n", state->config->pin_ctrl); -+ -+ if(state->config->set_voltage) -+ state->config->set_voltage(fe, voltage); -+ -+ data = m88ds3103_readreg(state, 0xa2); -+ -+ if(state->config->pin_ctrl & 0x80){ /*If control pin is assigned.*/ -+ data &= ~0x03; /* bit0 V/H, bit1 off/on */ -+ if(state->config->pin_ctrl & 0x02) -+ data |= 0x02; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_18: -+ if((state->config->pin_ctrl & 0x01) == 0) -+ data |= 0x01; -+ break; -+ case SEC_VOLTAGE_13: -+ if(state->config->pin_ctrl & 0x01) -+ data |= 0x01; -+ break; -+ case SEC_VOLTAGE_OFF: -+ if(state->config->pin_ctrl & 0x02) -+ data &= ~0x02; -+ else -+ data |= 0x02; -+ break; -+ } -+ } -+ -+ m88ds3103_writereg(state, 0xa2, data); -+ -+ return 0; -+} -+ -+static int m88ds3103_read_status(struct dvb_frontend *fe, fe_status_t* status) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ int lock = 0; -+ -+ *status = 0; -+ -+ switch (state->delivery_system){ -+ case SYS_DVBS: -+ lock = m88ds3103_readreg(state, 0xd1); -+ dprintk("%s: SYS_DVBS status=%x.\n", __func__, lock); -+ -+ if ((lock & 0x07) == 0x07){ -+ /*if((m88ds3103_readreg(state, 0x0d) & 0x07) == 0x07)*/ -+ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER -+ | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; -+ -+ } -+ break; -+ case SYS_DVBS2: -+ lock = m88ds3103_readreg(state, 0x0d); -+ dprintk("%s: SYS_DVBS2 status=%x.\n", __func__, lock); -+ -+ if ((lock & 0x8f) == 0x8f) -+ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER -+ | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; -+ -+ break; -+ default: -+ break; -+ } -+ -+ return 0; -+} -+ -+static int m88ds3103_read_ber(struct dvb_frontend *fe, u32* ber) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u8 tmp1, tmp2, tmp3; -+ u32 ldpc_frame_cnt, pre_err_packags, code_rate_fac = 0; -+ -+ dprintk("%s()\n", __func__); -+ -+ switch (state->delivery_system) { -+ case SYS_DVBS: -+ m88ds3103_writereg(state, 0xf9, 0x04); -+ tmp3 = m88ds3103_readreg(state, 0xf8); -+ if ((tmp3&0x10) == 0){ -+ tmp1 = m88ds3103_readreg(state, 0xf7); -+ tmp2 = m88ds3103_readreg(state, 0xf6); -+ tmp3 |= 0x10; -+ m88ds3103_writereg(state, 0xf8, tmp3); -+ state->preBer = (tmp1<<8) | tmp2; -+ } -+ break; -+ case SYS_DVBS2: -+ tmp1 = m88ds3103_readreg(state, 0x7e) & 0x0f; -+ switch(tmp1){ -+ case 0: code_rate_fac = 16008 - 80; break; -+ case 1: code_rate_fac = 21408 - 80; break; -+ case 2: code_rate_fac = 25728 - 80; break; -+ case 3: code_rate_fac = 32208 - 80; break; -+ case 4: code_rate_fac = 38688 - 80; break; -+ case 5: code_rate_fac = 43040 - 80; break; -+ case 6: code_rate_fac = 48408 - 80; break; -+ case 7: code_rate_fac = 51648 - 80; break; -+ case 8: code_rate_fac = 53840 - 80; break; -+ case 9: code_rate_fac = 57472 - 80; break; -+ case 10: code_rate_fac = 58192 - 80; break; -+ } -+ -+ tmp1 = m88ds3103_readreg(state, 0xd7) & 0xff; -+ tmp2 = m88ds3103_readreg(state, 0xd6) & 0xff; -+ tmp3 = m88ds3103_readreg(state, 0xd5) & 0xff; -+ ldpc_frame_cnt = (tmp1 << 16) | (tmp2 << 8) | tmp3; -+ -+ tmp1 = m88ds3103_readreg(state, 0xf8) & 0xff; -+ tmp2 = m88ds3103_readreg(state, 0xf7) & 0xff; -+ pre_err_packags = tmp1<<8 | tmp2; -+ -+ if (ldpc_frame_cnt > 1000){ -+ m88ds3103_writereg(state, 0xd1, 0x01); -+ m88ds3103_writereg(state, 0xf9, 0x01); -+ m88ds3103_writereg(state, 0xf9, 0x00); -+ m88ds3103_writereg(state, 0xd1, 0x00); -+ state->preBer = pre_err_packags; -+ } -+ break; -+ default: -+ break; -+ } -+ *ber = state->preBer; -+ -+ return 0; -+} -+ -+static int m88ds3103_read_signal_strength(struct dvb_frontend *fe, -+ u16 *signal_strength) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u16 gain; -+ u8 gain1, gain2, gain3 = 0; -+ -+ dprintk("%s()\n", __func__); -+ -+ gain1 = m88ds3103_tuner_readreg(state, 0x3d) & 0x1f; -+ dprintk("%s: gain1 = 0x%02x \n", __func__, gain1); -+ -+ if (gain1 > 15) gain1 = 15; -+ gain2 = m88ds3103_tuner_readreg(state, 0x21) & 0x1f; -+ dprintk("%s: gain2 = 0x%02x \n", __func__, gain2); -+ -+ if(state->tuner_id == TS2022_ID){ -+ gain3 = (m88ds3103_tuner_readreg(state, 0x66)>>3) & 0x07; -+ dprintk("%s: gain3 = 0x%02x \n", __func__, gain3); -+ -+ if (gain2 > 16) gain2 = 16; -+ if (gain2 < 2) gain2 = 2; -+ if (gain3 > 6) gain3 = 6; -+ }else{ -+ if (gain2 > 13) gain2 = 13; -+ gain3 = 0; -+ } -+ -+ gain = gain1*23 + gain2*35 + gain3*29; -+ *signal_strength = 60000 - gain*55; -+ -+ return 0; -+} -+ -+ -+static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *p_snr) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u8 val, npow1, npow2, spow1, cnt; -+ u16 tmp, snr; -+ u32 npow, spow, snr_total; -+ static const u16 mes_log10[] ={ -+ 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000, -+ 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788, 13010, -+ 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472, 14624, 14771, -+ 14914, 15052, 15185, 15315, 15441, 15563, 15682, 15798, 15911, 16021, -+ 16128, 16232, 16335, 16435, 16532, 16628, 16721, 16812, 16902, 16990, -+ 17076, 17160, 17243, 17324, 17404, 17482, 17559, 17634, 17709, 17782, -+ 17853, 17924, 17993, 18062, 18129, 18195, 18261, 18325, 18388, 18451, -+ 18513, 18573, 18633, 18692, 18751, 18808, 18865, 18921, 18976, 19031 -+ }; -+ static const u16 mes_loge[] ={ -+ 0, 6931, 10986, 13863, 16094, 17918, 19459, 20794, 21972, 23026, -+ 23979, 24849, 25649, 26391, 27081, 27726, 28332, 28904, 29444, 29957, -+ 30445, 30910, 31355, 31781, 32189, 32581, 32958, 33322, 33673, 34012, -+ 34340, 34657, -+ }; -+ -+ dprintk("%s()\n", __func__); -+ -+ snr = 0; -+ -+ switch (state->delivery_system){ -+ case SYS_DVBS: -+ cnt = 10; snr_total = 0; -+ while(cnt > 0){ -+ val = m88ds3103_readreg(state, 0xff); -+ snr_total += val; -+ cnt--; -+ } -+ tmp = (u16)(snr_total/80); -+ if(tmp > 0){ -+ if (tmp > 32) tmp = 32; -+ snr = (mes_loge[tmp - 1] * 100) / 45; -+ }else{ -+ snr = 0; -+ } -+ break; -+ case SYS_DVBS2: -+ cnt = 10; npow = 0; spow = 0; -+ while(cnt >0){ -+ npow1 = m88ds3103_readreg(state, 0x8c) & 0xff; -+ npow2 = m88ds3103_readreg(state, 0x8d) & 0xff; -+ npow += (((npow1 & 0x3f) + (u16)(npow2 << 6)) >> 2); -+ -+ spow1 = m88ds3103_readreg(state, 0x8e) & 0xff; -+ spow += ((spow1 * spow1) >> 1); -+ cnt--; -+ } -+ npow /= 10; spow /= 10; -+ if(spow == 0){ -+ snr = 0; -+ }else if(npow == 0){ -+ snr = 19; -+ }else{ -+ if(spow > npow){ -+ tmp = (u16)(spow / npow); -+ if (tmp > 80) tmp = 80; -+ snr = mes_log10[tmp - 1]*3; -+ }else{ -+ tmp = (u16)(npow / spow); -+ if (tmp > 80) tmp = 80; -+ snr = -(mes_log10[tmp - 1] / 1000); -+ } -+ } -+ break; -+ default: -+ break; -+ } -+ *p_snr = snr; -+ -+ return 0; -+} -+ -+ -+static int m88ds3103_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u8 tmp1, tmp2, tmp3, data; -+ -+ dprintk("%s()\n", __func__); -+ -+ switch (state->delivery_system) { -+ case SYS_DVBS: -+ data = m88ds3103_readreg(state, 0xf8); -+ data |= 0x40; -+ m88ds3103_writereg(state, 0xf8, data); -+ tmp1 = m88ds3103_readreg(state, 0xf5); -+ tmp2 = m88ds3103_readreg(state, 0xf4); -+ *ucblocks = (tmp1 <<8) | tmp2; -+ data &= ~0x20; -+ m88ds3103_writereg(state, 0xf8, data); -+ data |= 0x20; -+ m88ds3103_writereg(state, 0xf8, data); -+ data &= ~0x40; -+ m88ds3103_writereg(state, 0xf8, data); -+ break; -+ case SYS_DVBS2: -+ tmp1 = m88ds3103_readreg(state, 0xda); -+ tmp2 = m88ds3103_readreg(state, 0xd9); -+ tmp3 = m88ds3103_readreg(state, 0xd8); -+ *ucblocks = (tmp1 <<16)|(tmp2 <<8)|tmp3; -+ data = m88ds3103_readreg(state, 0xd1); -+ data |= 0x01; -+ m88ds3103_writereg(state, 0xd1, data); -+ data &= ~0x01; -+ m88ds3103_writereg(state, 0xd1, data); -+ break; -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static int m88ds3103_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u8 data_a1, data_a2; -+ -+ dprintk("%s(%d)\n", __func__, tone); -+ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { -+ printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone); -+ return -EINVAL; -+ } -+ -+ data_a1 = m88ds3103_readreg(state, 0xa1); -+ data_a2 = m88ds3103_readreg(state, 0xa2); -+ if(state->demod_id == DS3103_ID) -+ data_a2 &= 0xdf; /* Normal mode */ -+ switch (tone) { -+ case SEC_TONE_ON: -+ dprintk("%s: SEC_TONE_ON\n", __func__); -+ data_a1 |= 0x04; -+ data_a1 &= ~0x03; -+ data_a1 &= ~0x40; -+ data_a2 &= ~0xc0; -+ break; -+ case SEC_TONE_OFF: -+ dprintk("%s: SEC_TONE_OFF\n", __func__); -+ data_a2 &= ~0xc0; -+ data_a2 |= 0x80; -+ break; -+ } -+ m88ds3103_writereg(state, 0xa2, data_a2); -+ m88ds3103_writereg(state, 0xa1, data_a1); -+ return 0; -+} -+ -+static int m88ds3103_send_diseqc_msg(struct dvb_frontend *fe, -+ struct dvb_diseqc_master_cmd *d) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ int i, ret = 0; -+ u8 tmp, time_out; -+ -+ /* Dump DiSEqC message */ -+ if (debug) { -+ printk(KERN_INFO "m88ds3103: %s(", __func__); -+ for (i = 0 ; i < d->msg_len ;) { -+ printk(KERN_INFO "0x%02x", d->msg[i]); -+ if (++i < d->msg_len) -+ printk(KERN_INFO ", "); -+ } -+ } -+ -+ tmp = m88ds3103_readreg(state, 0xa2); -+ tmp &= ~0xc0; -+ if(state->demod_id == DS3103_ID) -+ tmp &= ~0x20; -+ m88ds3103_writereg(state, 0xa2, tmp); -+ -+ for (i = 0; i < d->msg_len; i ++) -+ m88ds3103_writereg(state, (0xa3+i), d->msg[i]); -+ -+ tmp = m88ds3103_readreg(state, 0xa1); -+ tmp &= ~0x38; -+ tmp &= ~0x40; -+ tmp |= ((d->msg_len-1) << 3) | 0x07; -+ tmp &= ~0x80; -+ m88ds3103_writereg(state, 0xa1, tmp); -+ /* 1.5 * 9 * 8 = 108ms */ -+ time_out = 150; -+ while (time_out > 0){ -+ msleep(10); -+ time_out -= 10; -+ tmp = m88ds3103_readreg(state, 0xa1); -+ if ((tmp & 0x40) == 0) -+ break; -+ } -+ if (time_out == 0){ -+ tmp = m88ds3103_readreg(state, 0xa1); -+ tmp &= ~0x80; -+ tmp |= 0x40; -+ m88ds3103_writereg(state, 0xa1, tmp); -+ ret = 1; -+ } -+ tmp = m88ds3103_readreg(state, 0xa2); -+ tmp &= ~0xc0; -+ tmp |= 0x80; -+ m88ds3103_writereg(state, 0xa2, tmp); -+ return ret; -+} -+ -+ -+static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, -+ fe_sec_mini_cmd_t burst) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u8 val, time_out; -+ -+ dprintk("%s()\n", __func__); -+ -+ val = m88ds3103_readreg(state, 0xa2); -+ val &= ~0xc0; -+ if(state->demod_id == DS3103_ID) -+ val &= 0xdf; /* Normal mode */ -+ m88ds3103_writereg(state, 0xa2, val); -+ /* DiSEqC burst */ -+ if (burst == SEC_MINI_B) -+ m88ds3103_writereg(state, 0xa1, 0x01); -+ else -+ m88ds3103_writereg(state, 0xa1, 0x02); -+ -+ msleep(13); -+ -+ time_out = 5; -+ do{ -+ val = m88ds3103_readreg(state, 0xa1); -+ if ((val & 0x40) == 0) -+ break; -+ msleep(1); -+ time_out --; -+ } while (time_out > 0); -+ -+ val = m88ds3103_readreg(state, 0xa2); -+ val &= ~0xc0; -+ val |= 0x80; -+ m88ds3103_writereg(state, 0xa2, val); -+ -+ return 0; -+} -+ -+static void m88ds3103_release(struct dvb_frontend *fe) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ -+ dprintk("%s\n", __func__); -+ kfree(state); -+} -+ -+static int m88ds3103_check_id(struct m88ds3103_state *state) -+{ -+ int val_00, val_01; -+ -+ /*check demod id*/ -+ val_01 = m88ds3103_readreg(state, 0x01); -+ printk(KERN_INFO "DS3000 chip version: %x attached.\n", val_01); -+ -+ if(val_01 == 0xD0) -+ state->demod_id = DS3103_ID; -+ else if(val_01 == 0xC0) -+ state->demod_id = DS3000_ID; -+ else -+ state->demod_id = UNKNOW_ID; -+ -+ /*check tuner id*/ -+ val_00 = m88ds3103_tuner_readreg(state, 0x00); -+ printk(KERN_INFO "TS202x chip version[1]: %x attached.\n", val_00); -+ val_00 &= 0x03; -+ if(val_00 == 0) -+ { -+ m88ds3103_tuner_writereg(state, 0x00, 0x01); -+ msleep(3); -+ } -+ m88ds3103_tuner_writereg(state, 0x00, 0x03); -+ msleep(5); -+ -+ val_00 = m88ds3103_tuner_readreg(state, 0x00); -+ printk(KERN_INFO "TS202x chip version[2]: %x attached.\n", val_00); -+ val_00 &= 0xff; -+ if((val_00 == 0x01) || (val_00 == 0x41) || (val_00 == 0x81)) -+ state->tuner_id = TS2020_ID; -+ else if(((val_00 & 0xc0)== 0xc0) || (val_00 == 0x83)) -+ state->tuner_id = TS2022_ID; -+ else -+ state->tuner_id = UNKNOW_ID; -+ -+ return state->demod_id; -+} -+ -+static struct dvb_frontend_ops m88ds3103_ops; -+static int m88ds3103_initilaze(struct dvb_frontend *fe); -+ -+struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *config, -+ struct i2c_adapter *i2c) -+{ -+ struct m88ds3103_state *state = NULL; -+ -+ dprintk("%s\n", __func__); -+ -+ /* allocate memory for the internal state */ -+ state = kzalloc(sizeof(struct m88ds3103_state), GFP_KERNEL); -+ if (state == NULL) { -+ printk(KERN_ERR "Unable to kmalloc\n"); -+ goto error2; -+ } -+ -+ state->config = config; -+ state->i2c = i2c; -+ state->preBer = 0xffff; -+ state->delivery_system = SYS_DVBS; /*Default to DVB-S.*/ -+ -+ /* check demod id */ -+ if(m88ds3103_check_id(state) == UNKNOW_ID){ -+ printk(KERN_ERR "Unable to find Montage chip\n"); -+ goto error3; -+ } -+ -+ memcpy(&state->frontend.ops, &m88ds3103_ops, -+ sizeof(struct dvb_frontend_ops)); -+ state->frontend.demodulator_priv = state; -+ -+ m88ds3103_initilaze(&state->frontend); -+ -+ return &state->frontend; -+ -+error3: -+ kfree(state); -+error2: -+ return NULL; -+} -+EXPORT_SYMBOL(m88ds3103_attach); -+ -+static int m88ds3103_set_carrier_offset(struct dvb_frontend *fe, -+ s32 carrier_offset_khz) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ s32 tmp; -+ -+ tmp = carrier_offset_khz; -+ tmp *= 65536; -+ -+ tmp = (2*tmp + MT_FE_MCLK_KHZ) / (2*MT_FE_MCLK_KHZ); -+ -+ if (tmp < 0) -+ tmp += 65536; -+ -+ m88ds3103_writereg(state, 0x5f, tmp >> 8); -+ m88ds3103_writereg(state, 0x5e, tmp & 0xff); -+ -+ return 0; -+} -+ -+static int m88ds3103_set_symrate(struct dvb_frontend *fe) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ u16 value; -+ -+ value = (((c->symbol_rate / 1000) << 15) + (MT_FE_MCLK_KHZ / 4)) / (MT_FE_MCLK_KHZ / 2); -+ m88ds3103_writereg(state, 0x61, value & 0x00ff); -+ m88ds3103_writereg(state, 0x62, (value & 0xff00) >> 8); -+ -+ return 0; -+} -+ -+static int m88ds3103_set_CCI(struct dvb_frontend *fe) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u8 tmp; -+ -+ tmp = m88ds3103_readreg(state, 0x56); -+ tmp &= ~0x01; -+ m88ds3103_writereg(state, 0x56, tmp); -+ -+ tmp = m88ds3103_readreg(state, 0x76); -+ tmp &= ~0x80; -+ m88ds3103_writereg(state, 0x76, tmp); -+ -+ return 0; -+} -+ -+static int m88ds3103_init_reg(struct m88ds3103_state *state, const u8 *p_reg_tab, u32 size) -+{ -+ u32 i; -+ -+ for(i = 0; i < size; i+=2) -+ m88ds3103_writereg(state, p_reg_tab[i], p_reg_tab[i+1]); -+ -+ return 0; -+} -+ -+static int m88ds3103_get_locked_sym_rate(struct m88ds3103_state *state, u32 *sym_rate_KSs) -+{ -+ u16 tmp; -+ u32 sym_rate_tmp; -+ u8 val_0x6d, val_0x6e; -+ -+ val_0x6d = m88ds3103_readreg(state, 0x6d); -+ val_0x6e = m88ds3103_readreg(state, 0x6e); -+ -+ tmp = (u16)((val_0x6e<<8) | val_0x6d); -+ -+ sym_rate_tmp = (u32)(tmp * MT_FE_MCLK_KHZ); -+ sym_rate_tmp = (u32)(sym_rate_tmp / (1<<16)); -+ *sym_rate_KSs = sym_rate_tmp; -+ -+ return 0; -+} -+ -+static int m88ds3103_get_channel_info(struct m88ds3103_state *state, u8 *p_mode, u8 *p_coderate) -+{ -+ u8 tmp, val_0x7E; -+ -+ if(state->delivery_system == SYS_DVBS2){ -+ val_0x7E = m88ds3103_readreg(state, 0x7e); -+ tmp = (u8)((val_0x7E&0xC0) >> 6); -+ *p_mode = tmp; -+ tmp = (u8)(val_0x7E & 0x0f); -+ *p_coderate = tmp; -+ } else { -+ *p_mode = 0; -+ tmp = m88ds3103_readreg(state, 0xe6); -+ tmp = (u8)(tmp >> 5); -+ *p_coderate = tmp; -+ } -+ -+ return 0; -+} -+ -+static int m88ds3103_set_clock_ratio(struct m88ds3103_state *state) -+{ -+ u8 val, mod_fac, tmp1, tmp2; -+ u32 input_datarate, locked_sym_rate_KSs; -+ u32 MClk_KHz = 96000; -+ u8 mod_mode, code_rate, divid_ratio = 0; -+ -+ locked_sym_rate_KSs = 0; -+ m88ds3103_get_locked_sym_rate(state, &locked_sym_rate_KSs); -+ if(locked_sym_rate_KSs == 0) -+ return 0; -+ -+ m88ds3103_get_channel_info(state, &mod_mode, &code_rate); -+ -+ if (state->delivery_system == SYS_DVBS2) -+ { -+ switch(mod_mode) { -+ case 1: mod_fac = 3; break; -+ case 2: mod_fac = 4; break; -+ case 3: mod_fac = 5; break; -+ default: mod_fac = 2; break; -+ } -+ -+ switch(code_rate) { -+ case 0: input_datarate = locked_sym_rate_KSs*mod_fac/8/4; break; -+ case 1: input_datarate = locked_sym_rate_KSs*mod_fac/8/3; break; -+ case 2: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/5; break; -+ case 3: input_datarate = locked_sym_rate_KSs*mod_fac/8/2; break; -+ case 4: input_datarate = locked_sym_rate_KSs*mod_fac*3/8/5; break; -+ case 5: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/3; break; -+ case 6: input_datarate = locked_sym_rate_KSs*mod_fac*3/8/4; break; -+ case 7: input_datarate = locked_sym_rate_KSs*mod_fac*4/8/5; break; -+ case 8: input_datarate = locked_sym_rate_KSs*mod_fac*5/8/6; break; -+ case 9: input_datarate = locked_sym_rate_KSs*mod_fac*8/8/9; break; -+ case 10: input_datarate = locked_sym_rate_KSs*mod_fac*9/8/10; break; -+ default: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/3; break; -+ } -+ -+ if(state->demod_id == DS3000_ID) -+ input_datarate = input_datarate * 115 / 100; -+ -+ if(input_datarate < 4800) {tmp1 = 15;tmp2 = 15;} //4.8MHz TS clock -+ else if(input_datarate < 4966) {tmp1 = 14;tmp2 = 15;} //4.966MHz TS clock -+ else if(input_datarate < 5143) {tmp1 = 14;tmp2 = 14;} //5.143MHz TS clock -+ else if(input_datarate < 5333) {tmp1 = 13;tmp2 = 14;} //5.333MHz TS clock -+ else if(input_datarate < 5538) {tmp1 = 13;tmp2 = 13;} //5.538MHz TS clock -+ else if(input_datarate < 5760) {tmp1 = 12;tmp2 = 13;} //5.76MHz TS clock allan 0809 -+ else if(input_datarate < 6000) {tmp1 = 12;tmp2 = 12;} //6MHz TS clock -+ else if(input_datarate < 6260) {tmp1 = 11;tmp2 = 12;} //6.26MHz TS clock -+ else if(input_datarate < 6545) {tmp1 = 11;tmp2 = 11;} //6.545MHz TS clock -+ else if(input_datarate < 6857) {tmp1 = 10;tmp2 = 11;} //6.857MHz TS clock -+ else if(input_datarate < 7200) {tmp1 = 10;tmp2 = 10;} //7.2MHz TS clock -+ else if(input_datarate < 7578) {tmp1 = 9;tmp2 = 10;} //7.578MHz TS clock -+ else if(input_datarate < 8000) {tmp1 = 9;tmp2 = 9;} //8MHz TS clock -+ else if(input_datarate < 8470) {tmp1 = 8;tmp2 = 9;} //8.47MHz TS clock -+ else if(input_datarate < 9000) {tmp1 = 8;tmp2 = 8;} //9MHz TS clock -+ else if(input_datarate < 9600) {tmp1 = 7;tmp2 = 8;} //9.6MHz TS clock -+ else if(input_datarate < 10285) {tmp1 = 7;tmp2 = 7;} //10.285MHz TS clock -+ else if(input_datarate < 12000) {tmp1 = 6;tmp2 = 6;} //12MHz TS clock -+ else if(input_datarate < 14400) {tmp1 = 5;tmp2 = 5;} //14.4MHz TS clock -+ else if(input_datarate < 18000) {tmp1 = 4;tmp2 = 4;} //18MHz TS clock -+ else {tmp1 = 3;tmp2 = 3;} //24MHz TS clock -+ -+ if(state->demod_id == DS3000_ID) { -+ val = (u8)((tmp1<<4) + tmp2); -+ m88ds3103_writereg(state, 0xfe, val); -+ } else { -+ tmp1 = m88ds3103_readreg(state, 0x22); -+ tmp2 = m88ds3103_readreg(state, 0x24); -+ -+ tmp1 >>= 6; -+ tmp1 &= 0x03; -+ tmp2 >>= 6; -+ tmp2 &= 0x03; -+ -+ if((tmp1 == 0x00) && (tmp2 == 0x01)) -+ MClk_KHz = 144000; -+ else if((tmp1 == 0x00) && (tmp2 == 0x03)) -+ MClk_KHz = 72000; -+ else if((tmp1 == 0x01) && (tmp2 == 0x01)) -+ MClk_KHz = 115200; -+ else if((tmp1 == 0x02) && (tmp2 == 0x01)) -+ MClk_KHz = 96000; -+ else if((tmp1 == 0x03) && (tmp2 == 0x00)) -+ MClk_KHz = 192000; -+ else -+ return 0; -+ -+ if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/ -+ input_datarate = 5200; -+ -+ if(input_datarate != 0) -+ divid_ratio = (u8)(MClk_KHz / input_datarate); -+ else -+ divid_ratio = 0xFF; -+ -+ if(divid_ratio > 128) -+ divid_ratio = 128; -+ -+ if(divid_ratio < 2) -+ divid_ratio = 2; -+ -+ tmp1 = (u8)(divid_ratio / 2); -+ tmp2 = (u8)(divid_ratio / 2); -+ -+ if((divid_ratio % 2) != 0) -+ tmp2 += 1; -+ -+ tmp1 -= 1; -+ tmp2 -= 1; -+ -+ tmp1 &= 0x3f; -+ tmp2 &= 0x3f; -+ -+ val = m88ds3103_readreg(state, 0xfe); -+ val &= 0xF0; -+ val |= (tmp2 >> 2) & 0x0f; -+ m88ds3103_writereg(state, 0xfe, val); -+ -+ val = (u8)((tmp2 & 0x03) << 6); -+ val |= tmp1; -+ m88ds3103_writereg(state, 0xea, val); -+ } -+ } else { -+ mod_fac = 2; -+ -+ switch(code_rate) { -+ case 4: input_datarate = locked_sym_rate_KSs*mod_fac/2/8; break; -+ case 3: input_datarate = locked_sym_rate_KSs*mod_fac*2/3/8; break; -+ case 2: input_datarate = locked_sym_rate_KSs*mod_fac*3/4/8; break; -+ case 1: input_datarate = locked_sym_rate_KSs*mod_fac*5/6/8; break; -+ case 0: input_datarate = locked_sym_rate_KSs*mod_fac*7/8/8; break; -+ default: input_datarate = locked_sym_rate_KSs*mod_fac*3/4/8; break; -+ } -+ -+ if(state->demod_id == DS3000_ID) -+ input_datarate = input_datarate * 115 / 100; -+ -+ if(input_datarate < 6857) {tmp1 = 7;tmp2 = 7;} //6.857MHz TS clock -+ else if(input_datarate < 7384) {tmp1 = 6;tmp2 = 7;} //7.384MHz TS clock -+ else if(input_datarate < 8000) {tmp1 = 6;tmp2 = 6;} //8MHz TS clock -+ else if(input_datarate < 8727) {tmp1 = 5;tmp2 = 6;} //8.727MHz TS clock -+ else if(input_datarate < 9600) {tmp1 = 5;tmp2 = 5;} //9.6MHz TS clock -+ else if(input_datarate < 10666) {tmp1 = 4;tmp2 = 5;} //10.666MHz TS clock -+ else if(input_datarate < 12000) {tmp1 = 4;tmp2 = 4;} //12MHz TS clock -+ else if(input_datarate < 13714) {tmp1 = 3;tmp2 = 4;} //13.714MHz TS clock -+ else if(input_datarate < 16000) {tmp1 = 3;tmp2 = 3;} //16MHz TS clock -+ else if(input_datarate < 19200) {tmp1 = 2;tmp2 = 3;} //19.2MHz TS clock -+ else {tmp1 = 2;tmp2 = 2;} //24MHz TS clock -+ -+ if(state->demod_id == DS3000_ID) { -+ val = m88ds3103_readreg(state, 0xfe); -+ val &= 0xc0; -+ val |= ((u8)((tmp1<<3) + tmp2)); -+ m88ds3103_writereg(state, 0xfe, val); -+ } else { -+ if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/ -+ input_datarate = 5200; -+ -+ if(input_datarate != 0) -+ divid_ratio = (u8)(MClk_KHz / input_datarate); -+ else -+ divid_ratio = 0xFF; -+ -+ if(divid_ratio > 128) -+ divid_ratio = 128; -+ -+ if(divid_ratio < 2) -+ divid_ratio = 2; -+ -+ tmp1 = (u8)(divid_ratio / 2); -+ tmp2 = (u8)(divid_ratio / 2); -+ -+ if((divid_ratio % 2) != 0) -+ tmp2 += 1; -+ -+ tmp1 -= 1; -+ tmp2 -= 1; -+ -+ tmp1 &= 0x3f; -+ tmp2 &= 0x3f; -+ -+ val = m88ds3103_readreg(state, 0xfe); -+ val &= 0xF0; -+ val |= (tmp2 >> 2) & 0x0f; -+ m88ds3103_writereg(state, 0xfe, val); -+ -+ val = (u8)((tmp2 & 0x03) << 6); -+ val |= tmp1; -+ m88ds3103_writereg(state, 0xea, val); -+ } -+ } -+ return 0; -+} -+ -+static int m88ds3103_demod_connect(struct dvb_frontend *fe, s32 carrier_offset_khz) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ u16 value; -+ u8 val1,val2,data; -+ -+ dprintk("connect delivery system = %d\n", state->delivery_system); -+ -+ /* ds3000 global reset */ -+ m88ds3103_writereg(state, 0x07, 0x80); -+ m88ds3103_writereg(state, 0x07, 0x00); -+ /* ds3000 build-in uC reset */ -+ m88ds3103_writereg(state, 0xb2, 0x01); -+ /* ds3000 software reset */ -+ m88ds3103_writereg(state, 0x00, 0x01); -+ -+ switch (state->delivery_system) { -+ case SYS_DVBS: -+ /* initialise the demod in DVB-S mode */ -+ if(state->demod_id == DS3000_ID){ -+ m88ds3103_init_reg(state, ds3000_dvbs_init_tab, sizeof(ds3000_dvbs_init_tab)); -+ -+ value = m88ds3103_readreg(state, 0xfe); -+ value &= 0xc0; -+ value |= 0x1b; -+ m88ds3103_writereg(state, 0xfe, value); -+ -+ if(state->config->ci_mode) -+ val1 = 0x80; -+ else if(state->config->ts_mode) -+ val1 = 0x60; -+ else -+ val1 = 0x20; -+ m88ds3103_writereg(state, 0xfd, val1); -+ -+ }else if(state->demod_id == DS3103_ID){ -+ m88ds3103_init_reg(state, ds3103_dvbs_init_tab, sizeof(ds3103_dvbs_init_tab)); -+ -+ /* set ts clock */ -+ if(state->config->ci_mode == 2){ -+ val1 = 6; val2 = 6; -+ }else if(state->config->ts_mode == 0) { -+ val1 = 3; val2 = 3; -+ }else{ -+ val1 = 0; val2 = 0; -+ } -+ val1 -= 1; val2 -= 1; -+ val1 &= 0x3f; val2 &= 0x3f; -+ data = m88ds3103_readreg(state, 0xfe); -+ data &= 0xf0; -+ data |= (val2 >> 2) & 0x0f; -+ m88ds3103_writereg(state, 0xfe, data); -+ data = (val2 & 0x03) << 6; -+ data |= val1; -+ m88ds3103_writereg(state, 0xea, data); -+ -+ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); -+ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); -+ -+ /* set master clock */ -+ val1 = m88ds3103_readreg(state, 0x22); -+ val2 = m88ds3103_readreg(state, 0x24); -+ -+ val1 &= 0x3f; -+ val2 &= 0x3f; -+ val1 |= 0x80; -+ val2 |= 0x40; -+ -+ m88ds3103_writereg(state, 0x22, val1); -+ m88ds3103_writereg(state, 0x24, val2); -+ -+ if(state->config->ci_mode) -+ val1 = 0x03; -+ else if(state->config->ts_mode) -+ val1 = 0x06; -+ else -+ val1 = 0x42; -+ m88ds3103_writereg(state, 0xfd, val1); -+ } -+ break; -+ case SYS_DVBS2: -+ /* initialise the demod in DVB-S2 mode */ -+ if(state->demod_id == DS3000_ID){ -+ m88ds3103_init_reg(state, ds3000_dvbs2_init_tab, sizeof(ds3000_dvbs2_init_tab)); -+ -+ if (c->symbol_rate >= 30000000) -+ m88ds3103_writereg(state, 0xfe, 0x54); -+ else -+ m88ds3103_writereg(state, 0xfe, 0x98); -+ -+ }else if(state->demod_id == DS3103_ID){ -+ m88ds3103_init_reg(state, ds3103_dvbs2_init_tab, sizeof(ds3103_dvbs2_init_tab)); -+ -+ /* set ts clock */ -+ if(state->config->ci_mode == 2){ -+ val1 = 6; val2 = 6; -+ }else if(state->config->ts_mode == 0){ -+ val1 = 5; val2 = 4; -+ }else{ -+ val1 = 0; val2 = 0; -+ } -+ val1 -= 1; val2 -= 1; -+ val1 &= 0x3f; val2 &= 0x3f; -+ data = m88ds3103_readreg(state, 0xfe); -+ data &= 0xf0; -+ data |= (val2 >> 2) & 0x0f; -+ m88ds3103_writereg(state, 0xfe, data); -+ data = (val2 & 0x03) << 6; -+ data |= val1; -+ m88ds3103_writereg(state, 0xea, data); -+ -+ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); -+ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); -+ -+ /* set master clock */ -+ val1 = m88ds3103_readreg(state, 0x22); -+ val2 = m88ds3103_readreg(state, 0x24); -+ -+ val1 &= 0x3f; -+ val2 &= 0x3f; -+ if((state->config->ci_mode == 2) || (state->config->ts_mode == 1)){ -+ val1 |= 0x80; -+ val2 |= 0x40; -+ }else{ -+ if (c->symbol_rate >= 28000000){ -+ val1 |= 0xc0; -+ }else if (c->symbol_rate >= 18000000){ -+ val2 |= 0x40; -+ }else{ -+ val1 |= 0x80; -+ val2 |= 0x40; -+ } -+ } -+ m88ds3103_writereg(state, 0x22, val1); -+ m88ds3103_writereg(state, 0x24, val2); -+ } -+ -+ if(state->config->ci_mode) -+ val1 = 0x03; -+ else if(state->config->ts_mode) -+ val1 = 0x06; -+ else -+ val1 = 0x42; -+ m88ds3103_writereg(state, 0xfd, val1); -+ -+ break; -+ default: -+ return 1; -+ } -+ /* disable 27MHz clock output */ -+ m88ds3103_writereg(state, 0x29, 0x80); -+ /* enable ac coupling */ -+ m88ds3103_writereg(state, 0x25, 0x8a); -+ -+ if ((c->symbol_rate / 1000) <= 3000){ -+ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 32 * 100 / 64 = 400*/ -+ m88ds3103_writereg(state, 0xc8, 0x20); -+ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ -+ m88ds3103_writereg(state, 0xc7, 0x00); -+ }else if((c->symbol_rate / 1000) <= 10000){ -+ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 16 * 100 / 64 = 200*/ -+ m88ds3103_writereg(state, 0xc8, 0x10); -+ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ -+ m88ds3103_writereg(state, 0xc7, 0x00); -+ }else{ -+ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 6 * 100 / 64 = 75*/ -+ m88ds3103_writereg(state, 0xc8, 0x06); -+ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ -+ m88ds3103_writereg(state, 0xc7, 0x00); -+ } -+ -+ m88ds3103_set_symrate(fe); -+ -+ m88ds3103_set_CCI(fe); -+ -+ m88ds3103_set_carrier_offset(fe, carrier_offset_khz); -+ -+ /* ds3000 out of software reset */ -+ m88ds3103_writereg(state, 0x00, 0x00); -+ /* start ds3000 build-in uC */ -+ m88ds3103_writereg(state, 0xb2, 0x00); -+ -+ return 0; -+} -+ -+static int m88ds3103_set_frontend(struct dvb_frontend *fe) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ struct dtv_frontend_properties *c = &fe->dtv_property_cache; -+ -+ int i; -+ fe_status_t status; -+ u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf, div4, capCode, changePLL; -+ s32 offset_khz, lpf_offset_KHz; -+ u16 value, ndiv, lpf_coeff; -+ u32 f3db, gdiv28, realFreq; -+ u8 RFgain; -+ -+ dprintk("%s() ", __func__); -+ dprintk("c frequency = %d\n", c->frequency); -+ dprintk("symbol rate = %d\n", c->symbol_rate); -+ dprintk("delivery system = %d\n", c->delivery_system); -+ -+ realFreq = c->frequency; -+ lpf_offset_KHz = 0; -+ if(c->symbol_rate < 5000000){ -+ lpf_offset_KHz = FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz; -+ realFreq += FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz; -+ } -+ -+ if (state->config->set_ts_params) -+ state->config->set_ts_params(fe, 0); -+ -+ div4 = 0; -+ RFgain = 0; -+ if(state->tuner_id == TS2022_ID){ -+ m88ds3103_tuner_writereg(state, 0x10, 0x0a); -+ m88ds3103_tuner_writereg(state, 0x11, 0x40); -+ if (realFreq < 1103000) { -+ m88ds3103_tuner_writereg(state, 0x10, 0x1b); -+ div4 = 1; -+ ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ; -+ }else { -+ ndiv = (realFreq * (6 + 8) * 2)/MT_FE_CRYSTAL_KHZ; -+ } -+ ndiv = ndiv + ndiv%2; -+ if(ndiv < 4095) -+ ndiv = ndiv - 1024; -+ else if (ndiv < 6143) -+ ndiv = ndiv + 1024; -+ else -+ ndiv = ndiv + 3072; -+ -+ m88ds3103_tuner_writereg(state, 0x01, (ndiv & 0x3f00) >> 8); -+ }else{ -+ m88ds3103_tuner_writereg(state, 0x10, 0x00); -+ if (realFreq < 1146000){ -+ m88ds3103_tuner_writereg(state, 0x10, 0x11); -+ div4 = 1; -+ ndiv = (realFreq * (6 + 8) * 4) / MT_FE_CRYSTAL_KHZ; -+ }else{ -+ m88ds3103_tuner_writereg(state, 0x10, 0x01); -+ ndiv = (realFreq * (6 + 8) * 2) / MT_FE_CRYSTAL_KHZ; -+ } -+ ndiv = ndiv + ndiv%2; -+ ndiv = ndiv - 1024; -+ m88ds3103_tuner_writereg(state, 0x01, (ndiv>>8)&0x0f); -+ } -+ /* set pll */ -+ m88ds3103_tuner_writereg(state, 0x02, ndiv & 0x00ff); -+ m88ds3103_tuner_writereg(state, 0x03, 0x06); -+ m88ds3103_tuner_writereg(state, 0x51, 0x0f); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x10); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ -+ if(state->tuner_id == TS2022_ID){ -+ if(( realFreq >= 1650000 ) && (realFreq <= 1850000)){ -+ msleep(5); -+ value = m88ds3103_tuner_readreg(state, 0x14); -+ value &= 0x7f; -+ if(value < 64){ -+ m88ds3103_tuner_writereg(state, 0x10, 0x82); -+ m88ds3103_tuner_writereg(state, 0x11, 0x6f); -+ -+ m88ds3103_tuner_writereg(state, 0x51, 0x0f); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x10); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ } -+ } -+ msleep(5); -+ value = m88ds3103_tuner_readreg(state, 0x14); -+ value &= 0x1f; -+ -+ if(value > 19){ -+ value = m88ds3103_tuner_readreg(state, 0x10); -+ value &= 0x1d; -+ m88ds3103_tuner_writereg(state, 0x10, value); -+ } -+ }else{ -+ msleep(5); -+ value = m88ds3103_tuner_readreg(state, 0x66); -+ changePLL = (((value & 0x80) >> 7) != div4); -+ -+ if(changePLL){ -+ m88ds3103_tuner_writereg(state, 0x10, 0x11); -+ div4 = 1; -+ ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ; -+ ndiv = ndiv + ndiv%2; -+ ndiv = ndiv - 1024; -+ -+ m88ds3103_tuner_writereg(state, 0x01, (ndiv>>8) & 0x0f); -+ m88ds3103_tuner_writereg(state, 0x02, ndiv & 0xff); -+ -+ m88ds3103_tuner_writereg(state, 0x51, 0x0f); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x10); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ } -+ } -+ /*set the RF gain*/ -+ if(state->tuner_id == TS2020_ID) -+ m88ds3103_tuner_writereg(state, 0x60, 0x79); -+ -+ m88ds3103_tuner_writereg(state, 0x51, 0x17); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x08); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ msleep(5); -+ -+ if(state->tuner_id == TS2020_ID){ -+ RFgain = m88ds3103_tuner_readreg(state, 0x3d); -+ RFgain &= 0x0f; -+ if(RFgain < 15){ -+ if(RFgain < 4) -+ RFgain = 0; -+ else -+ RFgain = RFgain -3; -+ value = ((RFgain << 3) | 0x01) & 0x79; -+ m88ds3103_tuner_writereg(state, 0x60, value); -+ m88ds3103_tuner_writereg(state, 0x51, 0x17); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x08); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ } -+ } -+ -+ /* set the LPF */ -+ if(state->tuner_id == TS2022_ID){ -+ m88ds3103_tuner_writereg(state, 0x25, 0x00); -+ m88ds3103_tuner_writereg(state, 0x27, 0x70); -+ m88ds3103_tuner_writereg(state, 0x41, 0x09); -+ m88ds3103_tuner_writereg(state, 0x08, 0x0b); -+ } -+ -+ f3db = ((c->symbol_rate / 1000) *135) / 200 + 2000; -+ f3db += lpf_offset_KHz; -+ if (f3db < 7000) -+ f3db = 7000; -+ if (f3db > 40000) -+ f3db = 40000; -+ -+ gdiv28 = (MT_FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000; -+ m88ds3103_tuner_writereg(state, 0x04, gdiv28 & 0xff); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1b); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x04); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ msleep(5); -+ -+ value = m88ds3103_tuner_readreg(state, 0x26); -+ capCode = value & 0x3f; -+ if(state->tuner_id == TS2022_ID){ -+ m88ds3103_tuner_writereg(state, 0x41, 0x0d); -+ -+ m88ds3103_tuner_writereg(state, 0x51, 0x1b); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x04); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ -+ msleep(2); -+ -+ value = m88ds3103_tuner_readreg(state, 0x26); -+ value &= 0x3f; -+ value = (capCode + value) / 2; -+ } -+ else -+ value = capCode; -+ -+ gdiv28 = gdiv28 * 207 / (value * 2 + 151); -+ mlpf_max = gdiv28 * 135 / 100; -+ mlpf_min = gdiv28 * 78 / 100; -+ if (mlpf_max > 63) -+ mlpf_max = 63; -+ -+ if(state->tuner_id == TS2022_ID) -+ lpf_coeff = 3200; -+ else -+ lpf_coeff = 2766; -+ -+ nlpf = (f3db * gdiv28 * 2 / lpf_coeff / (MT_FE_CRYSTAL_KHZ / 1000) + 1) / 2 ; -+ if (nlpf > 23) nlpf = 23; -+ if (nlpf < 1) nlpf = 1; -+ -+ lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2; -+ -+ if (lpf_mxdiv < mlpf_min){ -+ nlpf++; -+ lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2; -+ } -+ -+ if (lpf_mxdiv > mlpf_max) -+ lpf_mxdiv = mlpf_max; -+ -+ m88ds3103_tuner_writereg(state, 0x04, lpf_mxdiv); -+ m88ds3103_tuner_writereg(state, 0x06, nlpf); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1b); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x04); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ msleep(5); -+ -+ if(state->tuner_id == TS2022_ID){ -+ msleep(2); -+ value = m88ds3103_tuner_readreg(state, 0x26); -+ capCode = value & 0x3f; -+ -+ m88ds3103_tuner_writereg(state, 0x41, 0x09); -+ -+ m88ds3103_tuner_writereg(state, 0x51, 0x1b); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x04); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ -+ msleep(2); -+ value = m88ds3103_tuner_readreg(state, 0x26); -+ value &= 0x3f; -+ value = (capCode + value) / 2; -+ -+ value = value | 0x80; -+ m88ds3103_tuner_writereg(state, 0x25, value); -+ m88ds3103_tuner_writereg(state, 0x27, 0x30); -+ -+ m88ds3103_tuner_writereg(state, 0x08, 0x09); -+ } -+ -+ /* Set the BB gain */ -+ m88ds3103_tuner_writereg(state, 0x51, 0x1e); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x01); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ if(state->tuner_id == TS2020_ID){ -+ if(RFgain == 15){ -+ msleep(40); -+ value = m88ds3103_tuner_readreg(state, 0x21); -+ value &= 0x0f; -+ if(value < 3){ -+ m88ds3103_tuner_writereg(state, 0x60, 0x61); -+ m88ds3103_tuner_writereg(state, 0x51, 0x17); -+ m88ds3103_tuner_writereg(state, 0x51, 0x1f); -+ m88ds3103_tuner_writereg(state, 0x50, 0x08); -+ m88ds3103_tuner_writereg(state, 0x50, 0x00); -+ } -+ } -+ } -+ msleep(60); -+ -+ offset_khz = (ndiv - ndiv % 2 + 1024) * MT_FE_CRYSTAL_KHZ -+ / (6 + 8) / (div4 + 1) / 2 - realFreq; -+ -+ m88ds3103_demod_connect(fe, offset_khz+lpf_offset_KHz); -+ -+ for (i = 0; i < 30 ; i++) { -+ m88ds3103_read_status(fe, &status); -+ if (status & FE_HAS_LOCK){ -+ break; -+ } -+ msleep(20); -+ } -+ -+ if((status & FE_HAS_LOCK) == 0){ -+ state->delivery_system = (state->delivery_system == SYS_DVBS) ? SYS_DVBS2 : SYS_DVBS; -+ m88ds3103_demod_connect(fe, offset_khz); -+ -+ for (i = 0; i < 30 ; i++) { -+ m88ds3103_read_status(fe, &status); -+ if (status & FE_HAS_LOCK){ -+ break; -+ } -+ msleep(20); -+ } -+ } -+ -+ if (status & FE_HAS_LOCK){ -+ if(state->config->ci_mode == 2) -+ m88ds3103_set_clock_ratio(state); -+ if(state->config->start_ctrl){ -+ if(state->first_lock == 0){ -+ state->config->start_ctrl(fe); -+ state->first_lock = 1; -+ } -+ } -+ } -+ -+ return 0; -+} -+ -+static int m88ds3103_tune(struct dvb_frontend *fe, -+ bool re_tune, -+ unsigned int mode_flags, -+ unsigned int *delay, -+ fe_status_t *status) -+{ -+ *delay = HZ / 5; -+ -+ dprintk("%s() ", __func__); -+ dprintk("re_tune = %d\n", re_tune); -+ -+ if (re_tune) { -+ int ret = m88ds3103_set_frontend(fe); -+ if (ret) -+ return ret; -+ } -+ -+ return m88ds3103_read_status(fe, status); -+} -+ -+static enum dvbfe_algo m88ds3103_get_algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_HW; -+} -+ -+ /* -+ * Power config will reset and load initial firmware if required -+ */ -+static int m88ds3103_initilaze(struct dvb_frontend *fe) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ int ret; -+ -+ dprintk("%s()\n", __func__); -+ /* hard reset */ -+ m88ds3103_writereg(state, 0x07, 0x80); -+ m88ds3103_writereg(state, 0x07, 0x00); -+ msleep(1); -+ -+ m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08)); -+ msleep(1); -+ -+ if(state->tuner_id == TS2020_ID){ -+ /* TS2020 init */ -+ m88ds3103_tuner_writereg(state, 0x42, 0x73); -+ msleep(2); -+ m88ds3103_tuner_writereg(state, 0x05, 0x01); -+ m88ds3103_tuner_writereg(state, 0x62, 0xb5); -+ m88ds3103_tuner_writereg(state, 0x07, 0x02); -+ m88ds3103_tuner_writereg(state, 0x08, 0x01); -+ } -+ else if(state->tuner_id == TS2022_ID){ -+ /* TS2022 init */ -+ m88ds3103_tuner_writereg(state, 0x62, 0x6c); -+ msleep(2); -+ m88ds3103_tuner_writereg(state, 0x42, 0x6c); -+ msleep(2); -+ m88ds3103_tuner_writereg(state, 0x7d, 0x9d); -+ m88ds3103_tuner_writereg(state, 0x7c, 0x9a); -+ m88ds3103_tuner_writereg(state, 0x7a, 0x76); -+ -+ m88ds3103_tuner_writereg(state, 0x3b, 0x01); -+ m88ds3103_tuner_writereg(state, 0x63, 0x88); -+ -+ m88ds3103_tuner_writereg(state, 0x61, 0x85); -+ m88ds3103_tuner_writereg(state, 0x22, 0x30); -+ m88ds3103_tuner_writereg(state, 0x30, 0x40); -+ m88ds3103_tuner_writereg(state, 0x20, 0x23); -+ m88ds3103_tuner_writereg(state, 0x24, 0x02); -+ m88ds3103_tuner_writereg(state, 0x12, 0xa0); -+ } -+ -+ if(state->demod_id == DS3103_ID){ -+ m88ds3103_writereg(state, 0x07, 0xe0); -+ m88ds3103_writereg(state, 0x07, 0x00); -+ msleep(1); -+ } -+ m88ds3103_writereg(state, 0xb2, 0x01); -+ -+ /* Load the firmware if required */ -+ ret = m88ds3103_load_firmware(fe); -+ if (ret != 0){ -+ printk(KERN_ERR "%s: Unable initialize firmware\n", __func__); -+ return ret; -+ } -+ if(state->demod_id == DS3103_ID){ -+ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); -+ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); -+ } -+ -+ return 0; -+} -+ -+/* -+ * Initialise or wake up device -+ */ -+static int m88ds3103_initfe(struct dvb_frontend *fe) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ u8 val; -+ -+ dprintk("%s()\n", __func__); -+ -+ /* 1st step to wake up demod */ -+ m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08)); -+ m88ds3103_writereg(state, 0x04, 0xfe & m88ds3103_readreg(state, 0x04)); -+ m88ds3103_writereg(state, 0x23, 0xef & m88ds3103_readreg(state, 0x23)); -+ -+ /* 2nd step to wake up tuner */ -+ val = m88ds3103_tuner_readreg(state, 0x00) & 0xff; -+ if((val & 0x01) == 0){ -+ m88ds3103_tuner_writereg(state, 0x00, 0x01); -+ msleep(50); -+ } -+ m88ds3103_tuner_writereg(state, 0x00, 0x03); -+ msleep(50); -+ -+ return 0; -+} -+ -+/* Put device to sleep */ -+static int m88ds3103_sleep(struct dvb_frontend *fe) -+{ -+ struct m88ds3103_state *state = fe->demodulator_priv; -+ -+ dprintk("%s()\n", __func__); -+ -+ /* 1st step to sleep tuner */ -+ m88ds3103_tuner_writereg(state, 0x00, 0x00); -+ -+ /* 2nd step to sleep demod */ -+ m88ds3103_writereg(state, 0x08, 0xfe & m88ds3103_readreg(state, 0x08)); -+ m88ds3103_writereg(state, 0x04, 0x01 | m88ds3103_readreg(state, 0x04)); -+ m88ds3103_writereg(state, 0x23, 0x10 | m88ds3103_readreg(state, 0x23)); -+ -+ -+ return 0; -+} -+ -+static struct dvb_frontend_ops m88ds3103_ops = { -+ .delsys = { SYS_DVBS, SYS_DVBS2}, -+ .info = { -+ .name = "Montage DS3103/TS2022", -+ .type = FE_QPSK, -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ -+ .frequency_tolerance = 5000, -+ .symbol_rate_min = 1000000, -+ .symbol_rate_max = 45000000, -+ .caps = FE_CAN_INVERSION_AUTO | -+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | -+ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_2G_MODULATION | -+ FE_CAN_QPSK | FE_CAN_RECOVER -+ }, -+ -+ .release = m88ds3103_release, -+ -+ .init = m88ds3103_initfe, -+ .sleep = m88ds3103_sleep, -+ .read_status = m88ds3103_read_status, -+ .read_ber = m88ds3103_read_ber, -+ .read_signal_strength = m88ds3103_read_signal_strength, -+ .read_snr = m88ds3103_read_snr, -+ .read_ucblocks = m88ds3103_read_ucblocks, -+ .set_tone = m88ds3103_set_tone, -+ .set_voltage = m88ds3103_set_voltage, -+ .diseqc_send_master_cmd = m88ds3103_send_diseqc_msg, -+ .diseqc_send_burst = m88ds3103_diseqc_send_burst, -+ .get_frontend_algo = m88ds3103_get_algo, -+ .tune = m88ds3103_tune, -+ .set_frontend = m88ds3103_set_frontend, -+}; -+ -+MODULE_DESCRIPTION("DVB Frontend module for Montage DS3103/TS2022 hardware"); -+MODULE_AUTHOR("Max nibble"); -+MODULE_LICENSE("GPL"); -diff -urN a/drivers/media/dvb-frontends/m88ds3103.h b/drivers/media/dvb-frontends/m88ds3103.h ---- a/drivers/media/dvb-frontends/m88ds3103.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/media/dvb-frontends/m88ds3103.h 2013-01-30 12:33:51.000000000 +0800 -@@ -0,0 +1,53 @@ -+/* -+ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef M88DS3103_H -+#define M88DS3103_H -+ -+#include -+ -+struct m88ds3103_config { -+ /* the demodulator's i2c address */ -+ u8 demod_address; -+ u8 ci_mode; -+ u8 pin_ctrl; -+ u8 ts_mode; /* 0: Parallel, 1: Serial */ -+ -+ /* Set device param to start dma */ -+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); -+ /* Start to transfer data */ -+ int (*start_ctrl)(struct dvb_frontend *fe); -+ /* Set LNB voltage */ -+ int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); -+}; -+ -+#if defined(CONFIG_DVB_M88DS3103) || \ -+ (defined(CONFIG_DVB_M88DS3103_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *m88ds3103_attach( -+ const struct m88ds3103_config *config, -+ struct i2c_adapter *i2c); -+#else -+static inline struct dvb_frontend *m88ds3103_attach( -+ const struct m88ds3103_config *config, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_M88DS3103 */ -+#endif /* M88DS3103_H */ -diff -urN a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h ---- a/drivers/media/dvb-frontends/m88ds3103_priv.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h 2013-01-30 12:33:56.000000000 +0800 -@@ -0,0 +1,403 @@ -+/* -+ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef M88DS3103_PRIV_H -+#define M88DS3103_PRIV_H -+ -+#define FW_DOWN_SIZE 32 -+#define FW_DOWN_LOOP (8192/FW_DOWN_SIZE) -+#define DS3103_DEFAULT_FIRMWARE "dvb-fe-ds3103.fw" -+#define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds300x.fw" -+#define MT_FE_MCLK_KHZ 96000 /* in kHz */ -+#define MT_FE_CRYSTAL_KHZ 27000 /* in kHz */ -+#define FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz 3000 -+#define DS3000_ID 0x3000 -+#define DS3103_ID 0x3103 -+#define TS2020_ID 0x2020 -+#define TS2022_ID 0x2022 -+#define UNKNOW_ID 0x0000 -+ -+struct m88ds3103_state { -+ struct i2c_adapter *i2c; -+ const struct m88ds3103_config *config; -+ -+ struct dvb_frontend frontend; -+ -+ u32 preBer; -+ u8 skip_fw_load; -+ u8 first_lock; /* The first time of signal lock */ -+ u16 demod_id; /* demod chip type */ -+ u16 tuner_id; /* tuner chip type */ -+ fe_delivery_system_t delivery_system; -+}; -+ -+/* For M88DS3103 demod dvbs mode.*/ -+static u8 ds3103_dvbs_init_tab[] = { -+ 0x23, 0x07, -+ 0x08, 0x03, -+ 0x0c, 0x02, -+ 0x21, 0x54, -+ 0x25, 0x82, -+ 0x27, 0x31, -+ 0x30, 0x08, -+ 0x31, 0x40, -+ 0x32, 0x32, -+ 0x33, 0x35, -+ 0x35, 0xff, -+ 0x3a, 0x00, -+ 0x37, 0x10, -+ 0x38, 0x10, -+ 0x39, 0x02, -+ 0x42, 0x60, -+ 0x4a, 0x80, -+ 0x4b, 0x04, -+ 0x4d, 0x91, -+ 0x5d, 0xc8, -+ 0x50, 0x36, -+ 0x51, 0x36, -+ 0x52, 0x36, -+ 0x53, 0x36, -+ 0x63, 0x0f, -+ 0x64, 0x30, -+ 0x65, 0x40, -+ 0x68, 0x26, -+ 0x69, 0x4c, -+ 0x70, 0x20, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x40, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x60, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x80, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0xa0, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x1f, -+ 0x76, 0x38, -+ 0x77, 0xa6, -+ 0x78, 0x0c, -+ 0x79, 0x80, -+ 0x7f, 0x14, -+ 0x7c, 0x00, -+ 0xae, 0x82, -+ 0x80, 0x64, -+ 0x81, 0x66, -+ 0x82, 0x44, -+ 0x85, 0x04, -+ 0xcd, 0xf4, -+ 0x90, 0x33, -+ 0xa0, 0x44, -+ 0xc0, 0x08, -+ 0xc3, 0x10, -+ 0xc4, 0x08, -+ 0xc5, 0xf0, -+ 0xc6, 0xff, -+ 0xc7, 0x00, -+ 0xc8, 0x1a, -+ 0xc9, 0x80, -+ 0xe0, 0xf8, -+ 0xe6, 0x8b, -+ 0xd0, 0x40, -+ 0xf8, 0x20, -+ 0xfa, 0x0f, -+ 0x00, 0x00, -+ 0xbd, 0x01, -+ 0xb8, 0x00, -+}; -+/* For M88DS3103 demod dvbs2 mode.*/ -+static u8 ds3103_dvbs2_init_tab[] = { -+ 0x23, 0x07, -+ 0x08, 0x07, -+ 0x0c, 0x02, -+ 0x21, 0x54, -+ 0x25, 0x82, -+ 0x27, 0x31, -+ 0x30, 0x08, -+ 0x32, 0x32, -+ 0x33, 0x35, -+ 0x35, 0xff, -+ 0x3a, 0x00, -+ 0x37, 0x10, -+ 0x38, 0x10, -+ 0x39, 0x02, -+ 0x42, 0x60, -+ 0x4a, 0x80, -+ 0x4b, 0x04, -+ 0x4d, 0x91, -+ 0x5d, 0xc8, -+ 0x50, 0x36, -+ 0x51, 0x36, -+ 0x52, 0x36, -+ 0x53, 0x36, -+ 0x63, 0x0f, -+ 0x64, 0x10, -+ 0x65, 0x20, -+ 0x68, 0x46, -+ 0x69, 0xcd, -+ 0x70, 0x20, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x40, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x60, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x80, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0xa0, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x1f, -+ 0x76, 0x38, -+ 0x77, 0xa6, -+ 0x78, 0x0c, -+ 0x79, 0x80, -+ 0x7f, 0x14, -+ 0x85, 0x08, -+ 0xcd, 0xf4, -+ 0x90, 0x33, -+ 0x86, 0x00, -+ 0x87, 0x0f, -+ 0x89, 0x00, -+ 0x8b, 0x44, -+ 0x8c, 0x66, -+ 0x9d, 0xc1, -+ 0x8a, 0x10, -+ 0xad, 0x40, -+ 0xa0, 0x44, -+ 0xc0, 0x08, -+ 0xc1, 0x10, -+ 0xc2, 0x08, -+ 0xc3, 0x10, -+ 0xc4, 0x08, -+ 0xc5, 0xf0, -+ 0xc6, 0xff, -+ 0xc7, 0x00, -+ 0xc8, 0x1a, -+ 0xc9, 0x80, -+ 0xca, 0x23, -+ 0xcb, 0x24, -+ 0xcc, 0xf4, -+ 0xce, 0x74, -+ 0x00, 0x00, -+ 0xbd, 0x01, -+ 0xb8, 0x00, -+}; -+ -+/* For M88DS3000 demod dvbs mode.*/ -+static u8 ds3000_dvbs_init_tab[] = { -+ 0x23, 0x05, -+ 0x08, 0x03, -+ 0x0c, 0x02, -+ 0x21, 0x54, -+ 0x25, 0x82, -+ 0x27, 0x31, -+ 0x30, 0x08, -+ 0x31, 0x40, -+ 0x32, 0x32, -+ 0x33, 0x35, -+ 0x35, 0xff, -+ 0x3a, 0x00, -+ 0x37, 0x10, -+ 0x38, 0x10, -+ 0x39, 0x02, -+ 0x42, 0x60, -+ 0x4a, 0x40, -+ 0x4b, 0x04, -+ 0x4d, 0x91, -+ 0x5d, 0xc8, -+ 0x50, 0x77, -+ 0x51, 0x77, -+ 0x52, 0x36, -+ 0x53, 0x36, -+ 0x56, 0x01, -+ 0x63, 0x47, -+ 0x64, 0x30, -+ 0x65, 0x40, -+ 0x68, 0x26, -+ 0x69, 0x4c, -+ 0x70, 0x20, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x40, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x60, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x80, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0xa0, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x1f, -+ 0x76, 0x00, -+ 0x77, 0xd1, -+ 0x78, 0x0c, -+ 0x79, 0x80, -+ 0x7f, 0x04, -+ 0x7c, 0x00, -+ 0x80, 0x86, -+ 0x81, 0xa6, -+ 0x85, 0x04, -+ 0xcd, 0xf4, -+ 0x90, 0x33, -+ 0xa0, 0x44, -+ 0xc0, 0x18, -+ 0xc3, 0x10, -+ 0xc4, 0x08, -+ 0xc5, 0x80, -+ 0xc6, 0x80, -+ 0xc7, 0x0a, -+ 0xc8, 0x1a, -+ 0xc9, 0x80, -+ 0xfe, 0xb6, -+ 0xe0, 0xf8, -+ 0xe6, 0x8b, -+ 0xd0, 0x40, -+ 0xf8, 0x20, -+ 0xfa, 0x0f, -+ 0xad, 0x20, -+ 0xae, 0x07, -+ 0xb8, 0x00, -+}; -+ -+/* For M88DS3000 demod dvbs2 mode.*/ -+static u8 ds3000_dvbs2_init_tab[] = { -+ 0x23, 0x0f, -+ 0x08, 0x07, -+ 0x0c, 0x02, -+ 0x21, 0x54, -+ 0x25, 0x82, -+ 0x27, 0x31, -+ 0x30, 0x08, -+ 0x31, 0x32, -+ 0x32, 0x32, -+ 0x33, 0x35, -+ 0x35, 0xff, -+ 0x3a, 0x00, -+ 0x37, 0x10, -+ 0x38, 0x10, -+ 0x39, 0x02, -+ 0x42, 0x60, -+ 0x4a, 0x80, -+ 0x4b, 0x04, -+ 0x4d, 0x91, -+ 0x5d, 0x88, -+ 0x50, 0x36, -+ 0x51, 0x36, -+ 0x52, 0x36, -+ 0x53, 0x36, -+ 0x63, 0x60, -+ 0x64, 0x10, -+ 0x65, 0x10, -+ 0x68, 0x04, -+ 0x69, 0x29, -+ 0x70, 0x20, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x40, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x60, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x80, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0xa0, -+ 0x71, 0x70, -+ 0x72, 0x04, -+ 0x73, 0x00, -+ 0x70, 0x1f, -+ 0xa0, 0x44, -+ 0xc0, 0x08, -+ 0xc1, 0x10, -+ 0xc2, 0x08, -+ 0xc3, 0x10, -+ 0xc4, 0x08, -+ 0xc5, 0xf0, -+ 0xc6, 0xf0, -+ 0xc7, 0x0a, -+ 0xc8, 0x1a, -+ 0xc9, 0x80, -+ 0xca, 0x23, -+ 0xcb, 0x24, -+ 0xce, 0x74, -+ 0x56, 0x01, -+ 0x90, 0x03, -+ 0x76, 0x80, -+ 0x77, 0x42, -+ 0x78, 0x0a, -+ 0x79, 0x80, -+ 0xad, 0x40, -+ 0xae, 0x07, -+ 0x7f, 0xd4, -+ 0x7c, 0x00, -+ 0x80, 0xa8, -+ 0x81, 0xda, -+ 0x7c, 0x01, -+ 0x80, 0xda, -+ 0x81, 0xec, -+ 0x7c, 0x02, -+ 0x80, 0xca, -+ 0x81, 0xeb, -+ 0x7c, 0x03, -+ 0x80, 0xba, -+ 0x81, 0xdb, -+ 0x85, 0x08, -+ 0x86, 0x00, -+ 0x87, 0x02, -+ 0x89, 0x80, -+ 0x8b, 0x44, -+ 0x8c, 0xaa, -+ 0x8a, 0x10, -+ 0xba, 0x00, -+ 0xf5, 0x04, -+ 0xd2, 0x32, -+ 0xb8, 0x00, -+}; -+ -+#endif /* M88DS3103_PRIV_H */ -diff -urN a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile ---- a/drivers/media/dvb-frontends/Makefile 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/dvb-frontends/Makefile 2013-05-03 17:04:31.000000000 +0800 -@@ -103,4 +103,5 @@ - obj-$(CONFIG_DVB_RTL2832) += rtl2832.o - obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o - obj-$(CONFIG_DVB_AF9033) += af9033.o -- -+obj-$(CONFIG_DVB_M88DS3103) += m88ds3103.o -+obj-$(CONFIG_DVB_M88DC2800) += m88dc2800.o -diff -urN a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c ---- a/drivers/media/pci/cx23885/cimax2.c 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx23885/cimax2.c 2013-03-31 22:03:29.000000000 +0800 -@@ -415,7 +415,7 @@ - return state->status; - } - --int netup_ci_init(struct cx23885_tsport *port) -+int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky) - { - struct netup_ci_state *state; - u8 cimax_init[34] = { -@@ -464,6 +464,11 @@ - goto err; - } - -+ if(isDVBSky) { -+ cimax_init[32] = 0x22; -+ cimax_init[33] = 0x00; -+ } -+ - port->port_priv = state; - - switch (port->nr) { -@@ -537,3 +542,19 @@ - dvb_ca_en50221_release(&state->ca); - kfree(state); - } -+ -+/* CI irq handler for DVBSky board*/ -+int dvbsky_ci_slot_status(struct cx23885_dev *dev) -+{ -+ struct cx23885_tsport *port = NULL; -+ struct netup_ci_state *state = NULL; -+ -+ ci_dbg_print("%s:\n", __func__); -+ -+ port = &dev->ts1; -+ state = port->port_priv; -+ schedule_work(&state->work); -+ ci_dbg_print("%s: Wakeup CI0\n", __func__); -+ -+ return 1; -+} -diff -urN a/drivers/media/pci/cx23885/cimax2.h b/drivers/media/pci/cx23885/cimax2.h ---- a/drivers/media/pci/cx23885/cimax2.h 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx23885/cimax2.h 2013-01-30 12:34:37.000000000 +0800 -@@ -41,7 +41,9 @@ - extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status); - extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, - int slot, int open); --extern int netup_ci_init(struct cx23885_tsport *port); -+extern int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky); - extern void netup_ci_exit(struct cx23885_tsport *port); - -+extern int dvbsky_ci_slot_status(struct cx23885_dev *dev); -+ - #endif -diff -urN a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c ---- a/drivers/media/pci/cx23885/cx23885-cards.c 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx23885/cx23885-cards.c 2013-05-03 17:34:46.000000000 +0800 -@@ -569,6 +569,34 @@ - .name = "TeVii S471", - .portb = CX23885_MPEG_DVB, - }, -+ [CX23885_BOARD_BST_PS8512] = { -+ .name = "Bestunar PS8512", -+ .portb = CX23885_MPEG_DVB, -+ }, -+ [CX23885_BOARD_DVBSKY_S950] = { -+ .name = "DVBSKY S950", -+ .portb = CX23885_MPEG_DVB, -+ }, -+ [CX23885_BOARD_DVBSKY_S952] = { -+ .name = "DVBSKY S952", -+ .portb = CX23885_MPEG_DVB, -+ .portc = CX23885_MPEG_DVB, -+ }, -+ [CX23885_BOARD_DVBSKY_S950_CI] = { -+ .ci_type = 3, -+ .name = "DVBSKY S950CI DVB-S2 CI", -+ .portb = CX23885_MPEG_DVB, -+ }, -+ [CX23885_BOARD_DVBSKY_C2800E_CI] = { -+ .ci_type = 3, -+ .name = "DVBSKY C2800E DVB-C CI", -+ .portb = CX23885_MPEG_DVB, -+ }, -+ [CX23885_BOARD_DVBSKY_T9580] = { -+ .name = "DVBSKY T9580", -+ .portb = CX23885_MPEG_DVB, -+ .portc = CX23885_MPEG_DVB, -+ }, - [CX23885_BOARD_PROF_8000] = { - .name = "Prof Revolution DVB-S2 8000", - .portb = CX23885_MPEG_DVB, -@@ -605,7 +633,7 @@ - CX25840_NONE1_CH3, - .amux = CX25840_AUDIO6, - } }, -- } -+ } - }; - const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); - -@@ -818,6 +846,30 @@ - .subdevice = 0x9022, - .card = CX23885_BOARD_TEVII_S471, - }, { -+ .subvendor = 0x14f1, -+ .subdevice = 0x8512, -+ .card = CX23885_BOARD_BST_PS8512, -+ }, { -+ .subvendor = 0x4254, -+ .subdevice = 0x0950, -+ .card = CX23885_BOARD_DVBSKY_S950, -+ }, { -+ .subvendor = 0x4254, -+ .subdevice = 0x0952, -+ .card = CX23885_BOARD_DVBSKY_S952, -+ }, { -+ .subvendor = 0x4254, -+ .subdevice = 0x950C, -+ .card = CX23885_BOARD_DVBSKY_S950_CI, -+ }, { -+ .subvendor = 0x4254, -+ .subdevice = 0x2800, -+ .card = CX23885_BOARD_DVBSKY_C2800E_CI, -+ }, { -+ .subvendor = 0x4254, -+ .subdevice = 0x9580, -+ .card = CX23885_BOARD_DVBSKY_T9580, -+ }, { - .subvendor = 0x8000, - .subdevice = 0x3034, - .card = CX23885_BOARD_PROF_8000, -@@ -1224,7 +1276,7 @@ - cx_set(GP0_IO, 0x00040004); - break; - case CX23885_BOARD_TBS_6920: -- case CX23885_BOARD_PROF_8000: -+ case CX23885_BOARD_PROF_8000: - cx_write(MC417_CTL, 0x00000036); - cx_write(MC417_OEN, 0x00001000); - cx_set(MC417_RWD, 0x00000002); -@@ -1394,9 +1446,84 @@ - cx_set(GP0_IO, 0x00040004); - mdelay(60); - break; -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_BST_PS8512: -+ cx23885_gpio_enable(dev, GPIO_2, 1); -+ cx23885_gpio_clear(dev, GPIO_2); -+ msleep(100); -+ cx23885_gpio_set(dev, GPIO_2); -+ break; -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_T9580: -+ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ -+ -+ cx23885_gpio_enable(dev, GPIO_2, 1); -+ cx23885_gpio_enable(dev, GPIO_11, 1); -+ -+ cx23885_gpio_clear(dev, GPIO_2); -+ cx23885_gpio_clear(dev, GPIO_11); -+ msleep(100); -+ cx23885_gpio_set(dev, GPIO_2); -+ cx23885_gpio_set(dev, GPIO_11); -+ break; -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ /* GPIO-0 INTA from CiMax, input -+ GPIO-1 reset CiMax, output, high active -+ GPIO-2 reset demod, output, low active -+ GPIO-3 to GPIO-10 data/addr for CAM -+ GPIO-11 ~CS0 to CiMax1 -+ GPIO-12 ~CS1 to CiMax2 -+ GPIO-13 ADL0 load LSB addr -+ GPIO-14 ADL1 load MSB addr -+ GPIO-15 ~RDY from CiMax -+ GPIO-17 ~RD to CiMax -+ GPIO-18 ~WR to CiMax -+ */ -+ cx_set(GP0_IO, 0x00060002); /* GPIO 1/2 as output */ -+ cx_clear(GP0_IO, 0x00010004); /*GPIO 0 as input*/ -+ mdelay(100);/* reset delay */ -+ cx_set(GP0_IO, 0x00060004); /* GPIO as out, reset high */ -+ cx_clear(GP0_IO, 0x00010002); -+ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ -+ /* GPIO-15 IN as ~ACK, rest as OUT */ -+ cx_write(MC417_OEN, 0x00001000); -+ /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */ -+ cx_write(MC417_RWD, 0x0000c300); -+ /* enable irq */ -+ cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ -+ break; - } - } - -+static int cx23885_ir_patch(struct i2c_adapter *i2c, u8 reg, u8 mask) -+{ -+ struct i2c_msg msgs[2]; -+ u8 tx_buf[2], rx_buf[1]; -+ /* Write register address */ -+ tx_buf[0] = reg; -+ msgs[0].addr = 0x4c; -+ msgs[0].flags = 0; -+ msgs[0].len = 1; -+ msgs[0].buf = (char *) tx_buf; -+ /* Read data from register */ -+ msgs[1].addr = 0x4c; -+ msgs[1].flags = I2C_M_RD; -+ msgs[1].len = 1; -+ msgs[1].buf = (char *) rx_buf; -+ -+ i2c_transfer(i2c, msgs, 2); -+ -+ tx_buf[0] = reg; -+ tx_buf[1] = rx_buf[0] | mask; -+ msgs[0].addr = 0x4c; -+ msgs[0].flags = 0; -+ msgs[0].len = 2; -+ msgs[0].buf = (char *) tx_buf; -+ -+ return i2c_transfer(i2c, msgs, 1); -+} -+ - int cx23885_ir_init(struct cx23885_dev *dev) - { - static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = { -@@ -1482,6 +1609,23 @@ - v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, - ir_rx_pin_cfg_count, ir_rx_pin_cfg); - break; -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ case CX23885_BOARD_DVBSKY_T9580: -+ dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE); -+ if (dev->sd_ir == NULL) { -+ ret = -ENODEV; -+ break; -+ } -+ v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, -+ ir_rx_pin_cfg_count, ir_rx_pin_cfg); -+ -+ cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x1f,0x80); -+ cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x23,0x80); -+ break; - case CX23885_BOARD_HAUPPAUGE_HVR1250: - if (!enable_885_ir) - break; -@@ -1511,9 +1655,15 @@ - cx23888_ir_remove(dev); - dev->sd_ir = NULL; - break; -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ case CX23885_BOARD_DVBSKY_T9580: - case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: - case CX23885_BOARD_TEVII_S470: -- case CX23885_BOARD_HAUPPAUGE_HVR1250: -+ case CX23885_BOARD_HAUPPAUGE_HVR1250: - case CX23885_BOARD_MYGICA_X8507: - cx23885_irq_remove(dev, PCI_MSK_AV_CORE); - /* sd_ir is a duplicate pointer to the AV Core, just clear it */ -@@ -1556,6 +1706,12 @@ - if (dev->sd_ir) - cx23885_irq_add_enable(dev, PCI_MSK_IR); - break; -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ case CX23885_BOARD_DVBSKY_T9580: - case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: - case CX23885_BOARD_TEVII_S470: - case CX23885_BOARD_HAUPPAUGE_HVR1250: -@@ -1657,6 +1813,10 @@ - ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ - ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; - break; -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: - case CX23885_BOARD_TEVII_S470: - case CX23885_BOARD_TEVII_S471: - case CX23885_BOARD_DVBWORLD_2005: -@@ -1694,6 +1854,22 @@ - ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ - ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; - break; -+ case CX23885_BOARD_DVBSKY_S952: -+ ts1->gen_ctrl_val = 0x5; /* Parallel */ -+ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ -+ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; -+ ts2->gen_ctrl_val = 0xe; /* Serial bus + punctured clock */ -+ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ -+ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; -+ break; -+ case CX23885_BOARD_DVBSKY_T9580: -+ ts1->gen_ctrl_val = 0x5; /* Parallel */ -+ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ -+ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; -+ ts2->gen_ctrl_val = 0x8; /* Serial bus */ -+ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ -+ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; -+ break; - case CX23885_BOARD_HAUPPAUGE_HVR1250: - case CX23885_BOARD_HAUPPAUGE_HVR1500: - case CX23885_BOARD_HAUPPAUGE_HVR1500Q: -@@ -1749,6 +1925,12 @@ - case CX23885_BOARD_MPX885: - case CX23885_BOARD_MYGICA_X8507: - case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ case CX23885_BOARD_DVBSKY_T9580: - case CX23885_BOARD_AVERMEDIA_HC81R: - dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_bus[2].i2c_adap, -diff -urN a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c ---- a/drivers/media/pci/cx23885/cx23885-core.c 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx23885/cx23885-core.c 2013-05-03 17:36:31.000000000 +0800 -@@ -1909,6 +1909,10 @@ - (pci_status & PCI_MSK_GPIO0)) - handled += altera_ci_irq(dev); - -+ if (cx23885_boards[dev->board].ci_type == 3 && -+ (pci_status & PCI_MSK_GPIO0)) -+ handled += dvbsky_ci_slot_status(dev); -+ - if (ts1_status) { - if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) - handled += cx23885_irq_ts(ts1, ts1_status); -@@ -2144,6 +2148,8 @@ - cx23885_irq_add_enable(dev, PCI_MSK_GPIO1 | PCI_MSK_GPIO0); - break; - case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: - cx23885_irq_add_enable(dev, PCI_MSK_GPIO0); - break; - } -diff -urN a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c ---- a/drivers/media/pci/cx23885/cx23885-dvb.c 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx23885/cx23885-dvb.c 2013-05-03 17:38:34.000000000 +0800 -@@ -51,6 +51,8 @@ - #include "stv6110.h" - #include "lnbh24.h" - #include "cx24116.h" -+#include "m88ds3103.h" -+#include "m88dc2800.h" - #include "cimax2.h" - #include "lgs8gxx.h" - #include "netup-eeprom.h" -@@ -64,8 +66,8 @@ - #include "stv0367.h" - #include "drxk.h" - #include "mt2063.h" --#include "stv090x.h" --#include "stb6100.h" -+#include "stv090x.h" -+#include "stb6100.h" - #include "stb6100_cfg.h" - #include "tda10071.h" - #include "a8293.h" -@@ -500,42 +502,130 @@ - .if_khz = 5380, - }; - --static struct stv090x_config prof_8000_stv090x_config = { -- .device = STV0903, -- .demod_mode = STV090x_SINGLE, -- .clk_mode = STV090x_CLK_EXT, -- .xtal = 27000000, -- .address = 0x6A, -- .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, -- .repeater_level = STV090x_RPTLEVEL_64, -- .adc1_range = STV090x_ADC_2Vpp, -- .diseqc_envelope_mode = false, -- -- .tuner_get_frequency = stb6100_get_frequency, -- .tuner_set_frequency = stb6100_set_frequency, -- .tuner_set_bandwidth = stb6100_set_bandwidth, -- .tuner_get_bandwidth = stb6100_get_bandwidth, --}; - --static struct stb6100_config prof_8000_stb6100_config = { -- .tuner_address = 0x60, -- .refclock = 27000000, --}; -- --static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+/* bst control */ -+int bst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) - { - struct cx23885_tsport *port = fe->dvb->priv; - struct cx23885_dev *dev = port->dev; -+ -+ cx23885_gpio_enable(dev, GPIO_1, 1); -+ cx23885_gpio_enable(dev, GPIO_0, 1); -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ cx23885_gpio_set(dev, GPIO_1); -+ cx23885_gpio_clear(dev, GPIO_0); -+ break; -+ case SEC_VOLTAGE_18: -+ cx23885_gpio_set(dev, GPIO_1); -+ cx23885_gpio_set(dev, GPIO_0); -+ break; -+ case SEC_VOLTAGE_OFF: -+ cx23885_gpio_clear(dev, GPIO_1); -+ cx23885_gpio_clear(dev, GPIO_0); -+ break; -+ } -+ return 0; -+} - -- if (voltage == SEC_VOLTAGE_18) -- cx_write(MC417_RWD, 0x00001e00); -- else if (voltage == SEC_VOLTAGE_13) -- cx_write(MC417_RWD, 0x00001a00); -- else -- cx_write(MC417_RWD, 0x00001800); -+int dvbsky_set_voltage_sec(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct cx23885_tsport *port = fe->dvb->priv; -+ struct cx23885_dev *dev = port->dev; -+ -+ cx23885_gpio_enable(dev, GPIO_12, 1); -+ cx23885_gpio_enable(dev, GPIO_13, 1); -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ cx23885_gpio_set(dev, GPIO_13); -+ cx23885_gpio_clear(dev, GPIO_12); -+ break; -+ case SEC_VOLTAGE_18: -+ cx23885_gpio_set(dev, GPIO_13); -+ cx23885_gpio_set(dev, GPIO_12); -+ break; -+ case SEC_VOLTAGE_OFF: -+ cx23885_gpio_clear(dev, GPIO_13); -+ cx23885_gpio_clear(dev, GPIO_12); -+ break; -+ } - return 0; - } - -+/* bestunar single dvb-s2 */ -+static struct m88ds3103_config bst_ds3103_config = { -+ .demod_address = 0x68, -+ .ci_mode = 0, -+ .pin_ctrl = 0x82, -+ .ts_mode = 0, -+ .set_voltage = bst_set_voltage, -+}; -+/* DVBSKY dual dvb-s2 */ -+static struct m88ds3103_config dvbsky_ds3103_config_pri = { -+ .demod_address = 0x68, -+ .ci_mode = 0, -+ .pin_ctrl = 0x82, -+ .ts_mode = 0, -+ .set_voltage = bst_set_voltage, -+}; -+static struct m88ds3103_config dvbsky_ds3103_config_sec = { -+ .demod_address = 0x68, -+ .ci_mode = 0, -+ .pin_ctrl = 0x82, -+ .ts_mode = 1, -+ .set_voltage = dvbsky_set_voltage_sec, -+}; -+ -+static struct m88ds3103_config dvbsky_ds3103_ci_config = { -+ .demod_address = 0x68, -+ .ci_mode = 2, -+ .pin_ctrl = 0x82, -+ .ts_mode = 0, -+}; -+ -+static struct m88dc2800_config dvbsky_dc2800_config = { -+ .demod_address = 0x1c, -+ .ts_mode = 3, -+}; -+ -+static struct stv090x_config prof_8000_stv090x_config = { -+ .device = STV0903, -+ .demod_mode = STV090x_SINGLE, -+ .clk_mode = STV090x_CLK_EXT, -+ .xtal = 27000000, -+ .address = 0x6A, -+ .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, -+ .repeater_level = STV090x_RPTLEVEL_64, -+ .adc1_range = STV090x_ADC_2Vpp, -+ .diseqc_envelope_mode = false, -+ -+ .tuner_get_frequency = stb6100_get_frequency, -+ .tuner_set_frequency = stb6100_set_frequency, -+ .tuner_set_bandwidth = stb6100_set_bandwidth, -+ .tuner_get_bandwidth = stb6100_get_bandwidth, -+}; -+ -+static struct stb6100_config prof_8000_stb6100_config = { -+ .tuner_address = 0x60, -+ .refclock = 27000000, -+}; -+ -+static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct cx23885_tsport *port = fe->dvb->priv; -+ struct cx23885_dev *dev = port->dev; -+ -+ if (voltage == SEC_VOLTAGE_18) -+ cx_write(MC417_RWD, 0x00001e00); -+ else if (voltage == SEC_VOLTAGE_13) -+ cx_write(MC417_RWD, 0x00001a00); -+ else -+ cx_write(MC417_RWD, 0x00001800); -+ return 0; -+} -+ - static int cx23885_dvb_set_frontend(struct dvb_frontend *fe) - { - struct dtv_frontend_properties *p = &fe->dtv_property_cache; -@@ -1250,23 +1340,79 @@ - &tevii_ds3000_config, - &i2c_bus->i2c_adap); - break; -- case CX23885_BOARD_PROF_8000: -- i2c_bus = &dev->i2c_bus[0]; -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ i2c_bus = &dev->i2c_bus[1]; -+ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, -+ &bst_ds3103_config, -+ &i2c_bus->i2c_adap); -+ break; -+ -+ case CX23885_BOARD_DVBSKY_S952: -+ switch (port->nr) { -+ /* port B */ -+ case 1: -+ i2c_bus = &dev->i2c_bus[1]; -+ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, -+ &dvbsky_ds3103_config_pri, -+ &i2c_bus->i2c_adap); -+ break; -+ /* port C */ -+ case 2: -+ i2c_bus = &dev->i2c_bus[0]; -+ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, -+ &dvbsky_ds3103_config_sec, -+ &i2c_bus->i2c_adap); -+ break; -+ } -+ break; - -- fe0->dvb.frontend = dvb_attach(stv090x_attach, -- &prof_8000_stv090x_config, -- &i2c_bus->i2c_adap, -- STV090x_DEMODULATOR_0); -- if (fe0->dvb.frontend != NULL) { -- if (!dvb_attach(stb6100_attach, -- fe0->dvb.frontend, -- &prof_8000_stb6100_config, -- &i2c_bus->i2c_adap)) -- goto frontend_detach; -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ i2c_bus = &dev->i2c_bus[1]; -+ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, -+ &dvbsky_ds3103_ci_config, -+ &i2c_bus->i2c_adap); -+ break; -+ -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ i2c_bus = &dev->i2c_bus[1]; -+ fe0->dvb.frontend = dvb_attach(m88dc2800_attach, -+ &dvbsky_dc2800_config, -+ &i2c_bus->i2c_adap); -+ break; - -- fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; -+ case CX23885_BOARD_DVBSKY_T9580: -+ switch (port->nr) { -+ /* port B */ -+ case 1: -+ i2c_bus = &dev->i2c_bus[1]; -+ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, -+ &dvbsky_ds3103_config_pri, -+ &i2c_bus->i2c_adap); -+ break; -+ /* port C */ -+ case 2: -+ break; - } - break; -+ -+ case CX23885_BOARD_PROF_8000: -+ i2c_bus = &dev->i2c_bus[0]; -+ -+ fe0->dvb.frontend = dvb_attach(stv090x_attach, -+ &prof_8000_stv090x_config, -+ &i2c_bus->i2c_adap, -+ STV090x_DEMODULATOR_0); -+ if (fe0->dvb.frontend != NULL) { -+ if (!dvb_attach(stb6100_attach, -+ fe0->dvb.frontend, -+ &prof_8000_stb6100_config, -+ &i2c_bus->i2c_adap)) -+ goto frontend_detach; -+ -+ fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; -+ } -+ break; - case CX23885_BOARD_HAUPPAUGE_HVR4400: - i2c_bus = &dev->i2c_bus[0]; - fe0->dvb.frontend = dvb_attach(tda10071_attach, -@@ -1325,7 +1471,7 @@ - printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n", - port->nr, port->frontends.adapter.proposed_mac); - -- netup_ci_init(port); -+ netup_ci_init(port, false); - break; - } - case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: { -@@ -1352,6 +1498,41 @@ - memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); - break; - } -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_T9580:{ -+ u8 eeprom[256]; /* 24C02 i2c eeprom */ -+ -+ if(port->nr > 2) -+ break; -+ -+ dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; -+ tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); -+ printk(KERN_INFO "DVBSKY PCIe MAC= %pM\n", eeprom + 0xc0+(port->nr-1)*8); -+ memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 + -+ (port->nr-1)*8, 6); -+ break; -+ } -+ case CX23885_BOARD_DVBSKY_S950_CI: { -+ u8 eeprom[256]; /* 24C02 i2c eeprom */ -+ -+ if(port->nr > 2) -+ break; -+ -+ dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; -+ tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); -+ printk(KERN_INFO "DVBSKY PCIe MAC= %pM\n", eeprom + 0xc0+(port->nr-1)*8); -+ memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 + -+ (port->nr-1)*8, 6); -+ -+ netup_ci_init(port, true); -+ break; -+ } -+ case CX23885_BOARD_DVBSKY_C2800E_CI: { -+ netup_ci_init(port, true); -+ break; -+ } - } - - return ret; -@@ -1434,6 +1615,8 @@ - - switch (port->dev->board) { - case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: - netup_ci_exit(port); - break; - case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: -diff -urN a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h ---- a/drivers/media/pci/cx23885/cx23885.h 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx23885/cx23885.h 2013-05-03 17:14:20.000000000 +0800 -@@ -94,6 +94,14 @@ - #define CX23885_BOARD_HAUPPAUGE_HVR4400 38 - #define CX23885_BOARD_AVERMEDIA_HC81R 39 - -+#define CX23885_BOARD_BASE_INDEX 40 -+#define CX23885_BOARD_BST_PS8512 (CX23885_BOARD_BASE_INDEX) -+#define CX23885_BOARD_DVBSKY_S952 (CX23885_BOARD_BASE_INDEX+1) -+#define CX23885_BOARD_DVBSKY_S950 (CX23885_BOARD_BASE_INDEX+2) -+#define CX23885_BOARD_DVBSKY_S950_CI (CX23885_BOARD_BASE_INDEX+3) -+#define CX23885_BOARD_DVBSKY_C2800E_CI (CX23885_BOARD_BASE_INDEX+4) -+#define CX23885_BOARD_DVBSKY_T9580 (CX23885_BOARD_BASE_INDEX+5) -+ - #define GPIO_0 0x00000001 - #define GPIO_1 0x00000002 - #define GPIO_2 0x00000004 -@@ -231,7 +239,7 @@ - */ - u32 clk_freq; - struct cx23885_input input[MAX_CX23885_INPUT]; -- int ci_type; /* for NetUP */ -+ int ci_type; /* 1 and 2 for NetUP, 3 for DVBSky. */ - /* Force bottom field first during DMA (888 workaround) */ - u32 force_bff; - }; -diff -urN a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c ---- a/drivers/media/pci/cx23885/cx23885-input.c 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx23885/cx23885-input.c 2013-05-03 17:42:09.000000000 +0800 -@@ -89,6 +89,12 @@ - case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: - case CX23885_BOARD_TEVII_S470: - case CX23885_BOARD_HAUPPAUGE_HVR1250: -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ case CX23885_BOARD_DVBSKY_T9580: - case CX23885_BOARD_MYGICA_X8507: - /* - * The only boards we handle right now. However other boards -@@ -141,6 +147,12 @@ - case CX23885_BOARD_HAUPPAUGE_HVR1850: - case CX23885_BOARD_HAUPPAUGE_HVR1290: - case CX23885_BOARD_HAUPPAUGE_HVR1250: -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ case CX23885_BOARD_DVBSKY_T9580: - case CX23885_BOARD_MYGICA_X8507: - /* - * The IR controller on this board only returns pulse widths. -@@ -291,6 +303,18 @@ - /* A guess at the remote */ - rc_map = RC_MAP_TEVII_NEC; - break; -+ case CX23885_BOARD_BST_PS8512: -+ case CX23885_BOARD_DVBSKY_S950: -+ case CX23885_BOARD_DVBSKY_S952: -+ case CX23885_BOARD_DVBSKY_S950_CI: -+ case CX23885_BOARD_DVBSKY_C2800E_CI: -+ case CX23885_BOARD_DVBSKY_T9580: -+ /* Integrated CX2388[58] IR controller */ -+ driver_type = RC_DRIVER_IR_RAW; -+ allowed_protos = RC_BIT_ALL; -+ /* A guess at the remote */ -+ rc_map = RC_MAP_DVBSKY; -+ break; - case CX23885_BOARD_MYGICA_X8507: - /* Integrated CX23885 IR controller */ - driver_type = RC_DRIVER_IR_RAW; -diff -urN a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig ---- a/drivers/media/pci/cx23885/Kconfig 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx23885/Kconfig 2013-05-03 17:43:05.000000000 +0800 -@@ -23,6 +23,8 @@ - select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT - select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_M88DC2800 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT - select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT - select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT -diff -urN a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c ---- a/drivers/media/pci/cx88/cx88-cards.c 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx88/cx88-cards.c 2013-05-03 17:06:55.000000000 +0800 -@@ -2309,6 +2309,18 @@ - } }, - .mpeg = CX88_MPEG_DVB, - }, -+ [CX88_BOARD_BST_PS8312] = { -+ .name = "Bestunar PS8312 DVB-S/S2", -+ .tuner_type = UNSET, -+ .radio_type = UNSET, -+ .tuner_addr = ADDR_UNSET, -+ .radio_addr = ADDR_UNSET, -+ .input = { { -+ .type = CX88_VMUX_DVB, -+ .vmux = 0, -+ } }, -+ .mpeg = CX88_MPEG_DVB, -+ }, - }; - - /* ------------------------------------------------------------------ */ -@@ -2813,6 +2825,10 @@ - .subvendor = 0x1822, - .subdevice = 0x0023, - .card = CX88_BOARD_TWINHAN_VP1027_DVBS, -+ }, { -+ .subvendor = 0x14f1, -+ .subdevice = 0x8312, -+ .card = CX88_BOARD_BST_PS8312, - }, - }; - -@@ -3547,6 +3563,12 @@ - cx_write(MO_SRST_IO, 1); - msleep(100); - break; -+ case CX88_BOARD_BST_PS8312: -+ cx_write(MO_GP1_IO, 0x808000); -+ msleep(100); -+ cx_write(MO_GP1_IO, 0x808080); -+ msleep(100); -+ break; - } /*end switch() */ - - -diff -urN a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c ---- a/drivers/media/pci/cx88/cx88-dvb.c 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx88/cx88-dvb.c 2013-05-03 17:09:09.000000000 +0800 -@@ -54,6 +54,7 @@ - #include "stv0288.h" - #include "stb6000.h" - #include "cx24116.h" -+#include "m88ds3103.h" - #include "stv0900.h" - #include "stb6100.h" - #include "stb6100_proc.h" -@@ -459,6 +460,56 @@ - return core->prev_set_voltage(fe, voltage); - return 0; - } -+/*CX88_BOARD_BST_PS8312*/ -+static int bst_dvbs_set_voltage(struct dvb_frontend *fe, -+ fe_sec_voltage_t voltage) -+{ -+ struct cx8802_dev *dev= fe->dvb->priv; -+ struct cx88_core *core = dev->core; -+ -+ cx_write(MO_GP1_IO, 0x111111); -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ cx_write(MO_GP1_IO, 0x020200); -+ break; -+ case SEC_VOLTAGE_18: -+ cx_write(MO_GP1_IO, 0x020202); -+ break; -+ case SEC_VOLTAGE_OFF: -+ cx_write(MO_GP1_IO, 0x111100); -+ break; -+ } -+ -+ if (core->prev_set_voltage) -+ return core->prev_set_voltage(fe, voltage); -+ return 0; -+} -+ -+static int bst_dvbs_set_voltage_v2(struct dvb_frontend *fe, -+ fe_sec_voltage_t voltage) -+{ -+ struct cx8802_dev *dev= fe->dvb->priv; -+ struct cx88_core *core = dev->core; -+ -+ cx_write(MO_GP1_IO, 0x111101); -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ cx_write(MO_GP1_IO, 0x020200); -+ break; -+ case SEC_VOLTAGE_18: -+ -+ cx_write(MO_GP1_IO, 0x020202); -+ break; -+ case SEC_VOLTAGE_OFF: -+ -+ cx_write(MO_GP1_IO, 0x111110); -+ break; -+ } -+ -+ if (core->prev_set_voltage) -+ return core->prev_set_voltage(fe, voltage); -+ return 0; -+} - - static int vp1027_set_voltage(struct dvb_frontend *fe, - fe_sec_voltage_t voltage) -@@ -706,6 +757,11 @@ - .clk_out_div = 1, - }; - -+static struct m88ds3103_config dvbsky_ds3103_config = { -+ .demod_address = 0x68, -+ .set_ts_params = ds3000_set_ts_param, -+}; -+ - static const struct stv0900_config prof_7301_stv0900_config = { - .demod_address = 0x6a, - /* demod_mode = 0,*/ -@@ -1477,6 +1533,35 @@ - &tevii_ts2020_config, &core->i2c_adap); - fe0->dvb.frontend->ops.set_voltage = - tevii_dvbs_set_voltage; -+ } -+ break; -+ case CX88_BOARD_BST_PS8312: -+ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, -+ &dvbsky_ds3103_config, -+ &core->i2c_adap); -+ if (fe0->dvb.frontend != NULL){ -+ int ret; -+ u8 b0[] = { 0x60 }; -+ u8 b1[2] = { 0 }; -+ struct i2c_msg msg[] = { -+ { -+ .addr = 0x50, -+ .flags = 0, -+ .buf = b0, -+ .len = 1 -+ }, { -+ .addr = 0x50, -+ .flags = I2C_M_RD, -+ .buf = b1, -+ .len = 2 -+ } -+ }; -+ ret = i2c_transfer(&core->i2c_adap, msg, 2); -+ printk("PS8312: config = %02x, %02x", b1[0],b1[1]); -+ if(b1[0] == 0xaa) -+ fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage_v2; -+ else -+ fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage; - } - break; - case CX88_BOARD_OMICOM_SS4_PCI: -diff -urN a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h ---- a/drivers/media/pci/cx88/cx88.h 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx88/cx88.h 2013-05-03 17:05:57.000000000 +0800 -@@ -238,6 +238,7 @@ - #define CX88_BOARD_WINFAST_DTV1800H_XC4000 88 - #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89 - #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90 -+#define CX88_BOARD_BST_PS8312 91 - - enum cx88_itype { - CX88_VMUX_COMPOSITE1 = 1, -diff -urN a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c ---- a/drivers/media/pci/cx88/cx88-input.c 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx88/cx88-input.c 2013-01-26 14:52:03.000000000 +0800 -@@ -419,6 +419,10 @@ - rc_type = RC_BIT_NEC; - ir->sampling = 0xff00; /* address */ - break; -+ case CX88_BOARD_BST_PS8312: -+ ir_codes = RC_MAP_DVBSKY; -+ ir->sampling = 0xff00; /* address */ -+ break; - } - - if (!ir_codes) { -diff -urN a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig ---- a/drivers/media/pci/cx88/Kconfig 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/pci/cx88/Kconfig 2013-05-03 17:10:41.000000000 +0800 -@@ -57,6 +57,7 @@ - select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT - select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT - select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT - select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT -diff -urN a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile ---- a/drivers/media/rc/keymaps/Makefile 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/rc/keymaps/Makefile 2013-05-03 17:43:41.000000000 +0800 -@@ -27,6 +27,7 @@ - rc-dm1105-nec.o \ - rc-dntv-live-dvb-t.o \ - rc-dntv-live-dvbt-pro.o \ -+ rc-dvbsky.o \ - rc-em-terratec.o \ - rc-encore-enltv2.o \ - rc-encore-enltv.o \ -diff -urN a/drivers/media/rc/keymaps/rc-dvbsky.c b/drivers/media/rc/keymaps/rc-dvbsky.c ---- a/drivers/media/rc/keymaps/rc-dvbsky.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/media/rc/keymaps/rc-dvbsky.c 2013-01-26 14:52:49.000000000 +0800 -@@ -0,0 +1,78 @@ -+/* rc-dvbsky.c - Keytable for Dvbsky Remote Controllers -+ * -+ * keymap imported from ir-keymaps.c -+ * -+ * -+ * Copyright (c) 2010-2012 by Nibble Max -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#include -+#include -+/* -+ * This table contains the complete RC5 code, instead of just the data part -+ */ -+ -+static struct rc_map_table rc5_dvbsky[] = { -+ { 0x0000, KEY_0 }, -+ { 0x0001, KEY_1 }, -+ { 0x0002, KEY_2 }, -+ { 0x0003, KEY_3 }, -+ { 0x0004, KEY_4 }, -+ { 0x0005, KEY_5 }, -+ { 0x0006, KEY_6 }, -+ { 0x0007, KEY_7 }, -+ { 0x0008, KEY_8 }, -+ { 0x0009, KEY_9 }, -+ { 0x000a, KEY_MUTE }, -+ { 0x000d, KEY_OK }, -+ { 0x000b, KEY_STOP }, -+ { 0x000c, KEY_EXIT }, -+ { 0x000e, KEY_CAMERA }, /*Snap shot*/ -+ { 0x000f, KEY_SUBTITLE }, /*PIP*/ -+ { 0x0010, KEY_VOLUMEUP }, -+ { 0x0011, KEY_VOLUMEDOWN }, -+ { 0x0012, KEY_FAVORITES }, -+ { 0x0013, KEY_LIST }, /*Info*/ -+ { 0x0016, KEY_PAUSE }, -+ { 0x0017, KEY_PLAY }, -+ { 0x001f, KEY_RECORD }, -+ { 0x0020, KEY_CHANNELDOWN }, -+ { 0x0021, KEY_CHANNELUP }, -+ { 0x0025, KEY_POWER2 }, -+ { 0x0026, KEY_REWIND }, -+ { 0x0027, KEY_FASTFORWARD }, -+ { 0x0029, KEY_LAST }, -+ { 0x002b, KEY_MENU }, -+ { 0x002c, KEY_EPG }, -+ { 0x002d, KEY_ZOOM }, -+}; -+ -+static struct rc_map_list rc5_dvbsky_map = { -+ .map = { -+ .scan = rc5_dvbsky, -+ .size = ARRAY_SIZE(rc5_dvbsky), -+ .rc_type = RC_TYPE_RC5, -+ .name = RC_MAP_DVBSKY, -+ } -+}; -+ -+static int __init init_rc_map_rc5_dvbsky(void) -+{ -+ return rc_map_register(&rc5_dvbsky_map); -+} -+ -+static void __exit exit_rc_map_rc5_dvbsky(void) -+{ -+ rc_map_unregister(&rc5_dvbsky_map); -+} -+ -+module_init(init_rc_map_rc5_dvbsky) -+module_exit(exit_rc_map_rc5_dvbsky) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Nibble Max "); -diff -urN a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c ---- a/drivers/media/usb/dvb-usb-v2/dvbsky.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c 2013-05-03 17:47:38.000000000 +0800 -@@ -0,0 +1,665 @@ -+/* -+ * Driver for DVBSky USB2.0 receiver -+ * -+ * Copyright (C) 2013 Max nibble -+ * -+ * CIMax code is copied and modified from: -+ * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card -+ * Copyright (C) 2009 NetUP Inc. -+ * Copyright (C) 2009 Igor M. Liplianin -+ * Copyright (C) 2009 Abylay Ospan -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#include "dvb_ca_en50221.h" -+#include "dvb_usb.h" -+#include "m88ds3103.h" -+ -+static int dvbsky_debug; -+module_param(dvbsky_debug, int, 0644); -+MODULE_PARM_DESC(dvbsky_debug, "Activates dvbsky usb debugging (default:0)"); -+ -+#define DVBSKY_CI_CTL 0x04 -+#define DVBSKY_CI_RD 1 -+ -+#define dprintk(args...) \ -+ do { \ -+ if (dvbsky_debug) \ -+ printk(KERN_INFO "dvbsky_usb: " args); \ -+ } while (0) -+ -+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -+ -+struct dvbsky_state { -+ struct mutex stream_mutex; -+ u8 has_ci; -+ u8 ci_attached; -+ struct dvb_ca_en50221 ci; -+ unsigned long next_status_checked_time; -+ u8 ci_i2c_addr; -+ u8 current_ci_flag; -+ int ci_status; -+}; -+ -+static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) -+{ -+ struct dvbsky_state *state = d_to_priv(d); -+ int ret; -+ u8 obuf_pre[3] = { 0x37, 0, 0 }; -+ u8 obuf_post[3] = { 0x36, 3, 0 }; -+ dprintk("%s() -off \n", __func__); -+ mutex_lock(&state->stream_mutex); -+ ret = dvb_usbv2_generic_write(d, obuf_pre, 3); -+ if (!ret && onoff) { -+ msleep(10); -+ ret = dvb_usbv2_generic_write(d, obuf_post, 3); -+ dprintk("%s() -on \n", __func__); -+ } -+ mutex_unlock(&state->stream_mutex); -+ return ret; -+} -+ -+/* CI opertaions */ -+static int dvbsky_ci_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, -+ u8 *buf, int len) -+{ -+ int ret; -+ struct i2c_msg msg[] = { -+ { -+ .addr = addr, -+ .flags = 0, -+ .buf = ®, -+ .len = 1 -+ }, { -+ .addr = addr, -+ .flags = I2C_M_RD, -+ .buf = buf, -+ .len = len -+ } -+ }; -+ -+ ret = i2c_transfer(i2c_adap, msg, 2); -+ -+ if (ret != 2) { -+ dprintk("%s: error, Reg = 0x%02x, Status = %d\n", __func__, reg, ret); -+ return -1; -+ } -+ return 0; -+} -+ -+static int dvbsky_ci_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, -+ u8 *buf, int len) -+{ -+ int ret; -+ u8 buffer[len + 1]; -+ -+ struct i2c_msg msg = { -+ .addr = addr, -+ .flags = 0, -+ .buf = &buffer[0], -+ .len = len + 1 -+ }; -+ -+ buffer[0] = reg; -+ memcpy(&buffer[1], buf, len); -+ -+ ret = i2c_transfer(i2c_adap, &msg, 1); -+ -+ if (ret != 1) { -+ dprintk("%s: error, Reg=[0x%02x], Status=%d\n", __func__, reg, ret); -+ return -1; -+ } -+ return 0; -+} -+ -+static int dvbsky_ci_op_cam(struct dvb_ca_en50221 *ci, int slot, -+ u8 flag, u8 read, int addr, u8 data) -+{ -+ struct dvb_usb_device *d = ci->data; -+ struct dvbsky_state *state = d_to_priv(d); -+ u8 store; -+ int ret; -+ u8 command[4], respond[2], command_size, respond_size; -+ -+ /*dprintk("%s()\n", __func__);*/ -+ if (0 != slot) -+ return -EINVAL; -+ -+ if (state->current_ci_flag != flag) { -+ ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0, &store, 1); -+ if (ret != 0) -+ return ret; -+ -+ store &= ~0x0c; -+ store |= flag; -+ -+ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0, &store, 1); -+ if (ret != 0) -+ return ret; -+ } -+ state->current_ci_flag = flag; -+ -+ command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/ -+ command[2] = (u8)(addr & 0xff); /*low part of address*/ -+ if (read) { -+ command[0] = 0x71; -+ command_size = 3; -+ respond_size = 2; -+ } else { -+ command[0] = 0x70; -+ command[3] = data; -+ command_size = 4; -+ respond_size = 1; -+ } -+ ret = dvb_usbv2_generic_rw(d, command, command_size, respond, respond_size); -+ -+ return (read) ? respond[1] : 0; -+} -+ -+static int dvbsky_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, -+ int slot, int addr) -+{ -+ return dvbsky_ci_op_cam(ci, slot, 0, DVBSKY_CI_RD, addr, 0); -+} -+ -+static int dvbsky_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, -+ int slot, int addr, u8 data) -+{ -+ return dvbsky_ci_op_cam(ci, slot, 0, 0, addr, data); -+} -+ -+static int dvbsky_ci_read_cam_ctl(struct dvb_ca_en50221 *ci, int slot, u8 addr) -+{ -+ return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, DVBSKY_CI_RD, addr, 0); -+} -+ -+static int dvbsky_ci_write_cam_ctl(struct dvb_ca_en50221 *ci, int slot, -+ u8 addr, u8 data) -+{ -+ return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, 0, addr, data); -+} -+ -+static int dvbsky_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot) -+{ -+ struct dvb_usb_device *d = ci->data; -+ struct dvbsky_state *state = d_to_priv(d); -+ u8 buf = 0x80; -+ int ret; -+ dprintk("%s() slot=%d\n", __func__, slot); -+ -+ if (0 != slot) -+ return -EINVAL; -+ -+ udelay(500); -+ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0, &buf, 1); -+ -+ if (ret != 0) -+ return ret; -+ -+ udelay(500); -+ -+ buf = 0x00; -+ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0, &buf, 1); -+ msleep(1000); -+ dprintk("%s() slot=%d complete\n", __func__, slot); -+ return 0; -+ -+} -+ -+static int dvbsky_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot) -+{ -+ /* not implemented */ -+ dprintk("%s()\n", __func__); -+ return 0; -+} -+ -+static int dvbsky_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot) -+{ -+ struct dvb_usb_device *d = ci->data; -+ struct dvbsky_state *state = d_to_priv(d); -+ u8 buf; -+ int ret; -+ -+ dprintk("%s()\n", __func__); -+ if (0 != slot) -+ return -EINVAL; -+ -+ dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0, &buf, 1); -+ buf |= 0x60; -+ -+ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0, &buf, 1); -+ return ret; -+} -+ -+static int dvbsky_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, -+ int open) -+{ -+ struct dvb_usb_device *d = ci->data; -+ struct dvbsky_state *state = d_to_priv(d); -+ int ret = 0; -+ u8 buf = 0; -+ /*dprintk("%s()\n", __func__);*/ -+ -+ /* CAM module INSERT/REMOVE processing. slow operation because of i2c -+ * transfers */ -+ if (time_after(jiffies, state->next_status_checked_time)) { -+ ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0, &buf, 1); -+ -+ /*dprintk("%s() status=%x\n", __func__, buf);*/ -+ -+ state->next_status_checked_time = jiffies -+ + msecs_to_jiffies(1000); -+ -+ if (ret != 0) -+ return 0; -+ -+ if (buf & 1) { -+ state->ci_status = DVB_CA_EN50221_POLL_CAM_PRESENT | -+ DVB_CA_EN50221_POLL_CAM_READY; -+ } -+ else -+ state->ci_status = 0; -+ } -+ /*dprintk("%s() ret=%x\n", __func__, state->ci_status);*/ -+ return state->ci_status; -+} -+ -+static int dvbsky_ci_init(struct dvb_usb_device *d) -+{ -+ struct dvbsky_state *state = d_to_priv(d); -+ int ret; -+ u8 cimax_init[34] = { -+ 0x00, /* module A control*/ -+ 0x00, /* auto select mask high A */ -+ 0x00, /* auto select mask low A */ -+ 0x00, /* auto select pattern high A */ -+ 0x00, /* auto select pattern low A */ -+ 0x44, /* memory access time A */ -+ 0x00, /* invert input A */ -+ 0x00, /* RFU */ -+ 0x00, /* RFU */ -+ 0x00, /* module B control*/ -+ 0x00, /* auto select mask high B */ -+ 0x00, /* auto select mask low B */ -+ 0x00, /* auto select pattern high B */ -+ 0x00, /* auto select pattern low B */ -+ 0x44, /* memory access time B */ -+ 0x00, /* invert input B */ -+ 0x00, /* RFU */ -+ 0x00, /* RFU */ -+ 0x00, /* auto select mask high Ext */ -+ 0x00, /* auto select mask low Ext */ -+ 0x00, /* auto select pattern high Ext */ -+ 0x00, /* auto select pattern low Ext */ -+ 0x00, /* RFU */ -+ 0x02, /* destination - module A */ -+ 0x01, /* power on (use it like store place) */ -+ 0x00, /* RFU */ -+ 0x00, /* int status read only */ -+ 0x00, /* Max: Disable the interrupt in USB solution.*/ -+ 0x05, /* EXTINT=active-high, INT=push-pull */ -+ 0x00, /* USCG1 */ -+ 0x04, /* ack active low */ -+ 0x00, /* LOCK = 0 */ -+ 0x22, /* serial mode, rising in, rising out, MSB first*/ -+ 0x00 /* synchronization */ -+ }; -+ dprintk("%s()\n", __func__); -+ state->current_ci_flag = 0xff; -+ state->ci_status = 0; -+ state->next_status_checked_time = jiffies + msecs_to_jiffies(1000); -+ state->ci_i2c_addr = 0x40; -+ -+ state->ci.owner = THIS_MODULE; -+ state->ci.read_attribute_mem = dvbsky_ci_read_attribute_mem; -+ state->ci.write_attribute_mem = dvbsky_ci_write_attribute_mem; -+ state->ci.read_cam_control = dvbsky_ci_read_cam_ctl; -+ state->ci.write_cam_control = dvbsky_ci_write_cam_ctl; -+ state->ci.slot_reset = dvbsky_ci_slot_reset; -+ state->ci.slot_shutdown = dvbsky_ci_slot_shutdown; -+ state->ci.slot_ts_enable = dvbsky_ci_slot_ts_enable; -+ state->ci.poll_slot_status = dvbsky_ci_poll_slot_status; -+ state->ci.data = d; -+ -+ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0, &cimax_init[0], 34); -+ /* lock registers */ -+ ret |= dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0x1f, &cimax_init[0x18], 1); -+ /* power on slots */ -+ ret |= dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, -+ 0x18, &cimax_init[0x18], 1); -+ if (0 != ret) -+ return ret; -+ -+ ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1); -+ if (ret) -+ return ret; -+ state->ci_attached = 1; -+ dprintk("%s() complete.\n", __func__); -+ return 0; -+} -+ -+static void dvbsky_ci_release(struct dvb_usb_device *d) -+{ -+ struct dvbsky_state *state = d_to_priv(d); -+ -+ /* detach CI */ -+ if (state->ci_attached) -+ dvb_ca_en50221_release(&state->ci); -+ -+ return; -+} -+ -+static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff) -+{ -+ struct dvb_usb_device *d = fe_to_d(fe); -+ /*dprintk("%s() %d\n", __func__, onoff);*/ -+ return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1); -+} -+ -+/* GPIO */ -+static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value) -+{ -+ u8 obuf[64], ibuf[64]; -+ obuf[0] = 0x0e; -+ obuf[1] = gport; -+ obuf[2] = value; -+ return dvb_usbv2_generic_rw(d, obuf, 3, ibuf, 1); -+} -+ -+/* I2C */ -+static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], -+ int num) -+{ -+ struct dvb_usb_device *d = i2c_get_adapdata(adap); -+ int ret = 0; -+ u8 ibuf[64], obuf[64]; -+ -+ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) -+ return -EAGAIN; -+ -+ if (num > 2) { -+ printk(KERN_ERR "dvbsky_usb: too many i2c messages[%d] than 2.", num); -+ ret = -EOPNOTSUPP; -+ goto i2c_error; -+ } -+ -+ if(num == 1) { -+ if (msg[0].len > 60) { -+ printk(KERN_ERR "dvbsky_usb: too many i2c bytes[%d] than 60.", msg[0].len); -+ ret = -EOPNOTSUPP; -+ goto i2c_error; -+ } -+ if (msg[0].flags & I2C_M_RD) { -+ /* single read */ -+ obuf[0] = 0x09; -+ obuf[1] = 0; -+ obuf[2] = msg[0].len; -+ obuf[3] = msg[0].addr; -+ ret = dvb_usbv2_generic_rw(d, obuf, 4, ibuf, msg[0].len + 1); -+ /*dprintk("%s(): read status = %d\n", __func__, ibuf[0]);*/ -+ if (!ret) -+ memcpy(msg[0].buf, &ibuf[1], msg[0].len); -+ } else { -+ /* write */ -+ obuf[0] = 0x08; -+ obuf[1] = msg[0].addr; -+ obuf[2] = msg[0].len; -+ memcpy(&obuf[3], msg[0].buf, msg[0].len); -+ ret = dvb_usbv2_generic_rw(d, obuf, msg[0].len + 3, ibuf, 1); -+ /*dprintk("%s(): write status = %d\n", __func__, ibuf[0]);*/ -+ } -+ } else { -+ if ((msg[0].len > 60) || (msg[1].len > 60)) { -+ printk(KERN_ERR "dvbsky_usb: too many i2c bytes[w-%d][r-%d] than 60.", msg[0].len, msg[1].len); -+ ret = -EOPNOTSUPP; -+ goto i2c_error; -+ } -+ /* write then read */ -+ obuf[0] = 0x09; -+ obuf[1] = msg[0].len; -+ obuf[2] = msg[1].len; -+ obuf[3] = msg[0].addr; -+ memcpy(&obuf[4], msg[0].buf, msg[0].len); -+ ret = dvb_usbv2_generic_rw(d, obuf, msg[0].len + 4, ibuf, msg[1].len + 1); -+ /*dprintk("%s(): write then read status = %d\n", __func__, ibuf[0]);*/ -+ if (!ret) -+ memcpy(msg[1].buf, &ibuf[1], msg[1].len); -+ } -+i2c_error: -+ mutex_unlock(&d->i2c_mutex); -+ return (ret) ? ret : num; -+} -+ -+static u32 dvbsky_i2c_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_I2C; -+} -+ -+static struct i2c_algorithm dvbsky_i2c_algo = { -+ .master_xfer = dvbsky_i2c_xfer, -+ .functionality = dvbsky_i2c_func, -+}; -+ -+#if IS_ENABLED(CONFIG_RC_CORE) -+static int dvbsky_rc_query(struct dvb_usb_device *d) -+{ -+ u32 code = 0xffff; -+ u8 obuf[2], ibuf[2], toggle; -+ int ret; -+ obuf[0] = 0x10; -+ ret = dvb_usbv2_generic_rw(d, obuf, 1, ibuf, 2); -+ if(ret == 0) -+ code = (ibuf[0] << 8) | ibuf[1]; -+ -+ if (code != 0xffff) { -+ dprintk("rc code: %x", code); -+ toggle = (code & 0x800) ? 1 : 0; -+ code &= 0x3f; -+ rc_keydown(d->rc_dev, code, toggle); -+ } -+ return 0; -+} -+ -+static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) -+{ -+ rc->allowed_protos = RC_BIT_RC5; -+ rc->query = dvbsky_rc_query; -+ rc->interval = 300; -+ return 0; -+} -+#else -+ #define dvbsky_get_rc_config NULL -+#endif -+ -+static int dvbsky_sync_ctrl(struct dvb_frontend *fe) -+{ -+ struct dvb_usb_device *d = fe_to_d(fe); -+ return dvbsky_stream_ctrl(d, 1); -+} -+ -+static int dvbsky_usb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct dvb_usb_device *d = fe_to_d(fe); -+ u8 value; -+ -+ if (voltage == SEC_VOLTAGE_OFF) -+ value = 0; -+ else -+ value = 1; -+ return dvbsky_gpio_ctrl(d, 0x80, value); -+} -+ -+static int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6]) -+{ -+ struct dvb_usb_device *d = adap_to_d(adap); -+ u8 obuf[] = { 0x1e, 0x00 }; -+ u8 ibuf[6] = { 0 }; -+ struct i2c_msg msg[] = { -+ { -+ .addr = 0x51, -+ .flags = 0, -+ .buf = obuf, -+ .len = 2, -+ }, { -+ .addr = 0x51, -+ .flags = I2C_M_RD, -+ .buf = ibuf, -+ .len = 6, -+ -+ } -+ }; -+ -+ if (i2c_transfer(&d->i2c_adap, msg, 2) == 2) -+ memcpy(mac, ibuf, 6); -+ -+ printk(KERN_INFO "dvbsky_usb MAC address=%pM\n", mac); -+ -+ return 0; -+} -+ -+static struct m88ds3103_config dvbsky_usb_ds3103_config = { -+ .demod_address = 0x68, -+ .ci_mode = 1, -+ .pin_ctrl = 0x83, -+ .ts_mode = 0, -+ .start_ctrl = dvbsky_sync_ctrl, -+ .set_voltage = dvbsky_usb_set_voltage, -+}; -+ -+static int dvbsky_s960_attach(struct dvb_usb_adapter *adap) -+{ -+ struct dvbsky_state *state = adap_to_priv(adap); -+ struct dvb_usb_device *d = adap_to_d(adap); -+ int ret = 0; -+ -+ dprintk("%s()\n", __func__); -+ -+ dvbsky_gpio_ctrl(d, 0x04, 1); -+ -+ dvbsky_gpio_ctrl(d, 0x83, 0); -+ msleep(50); -+ dvbsky_gpio_ctrl(d, 0x83, 1); -+ msleep(20); -+ -+ adap->fe[0] = dvb_attach(m88ds3103_attach, -+ &dvbsky_usb_ds3103_config, -+ &d->i2c_adap); -+ if (!adap->fe[0]) { -+ printk(KERN_ERR "dvbsky_s960_attach fail."); -+ ret = -ENODEV; -+ } -+ -+ state->has_ci = 0; -+ -+ return ret; -+} -+ -+static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name) -+{ -+ return WARM; -+} -+ -+static int dvbsky_init(struct dvb_usb_device *d) -+{ -+ struct dvbsky_state *state = d_to_priv(d); -+ int ret; -+ -+ /* use default interface */ -+ ret = usb_set_interface(d->udev, 0, 0); -+ if (ret) -+ return ret; -+ -+ mutex_init(&state->stream_mutex); -+ -+ /* attach CI */ -+ if (state->has_ci) { -+ dvbsky_gpio_ctrl(d, 0xc0, 1); -+ msleep(100); -+ dvbsky_gpio_ctrl(d, 0xc0, 0); -+ msleep(50); -+ state->ci_attached = 0; -+ ret = dvbsky_ci_init(d); -+ if (ret) -+ return ret; -+ } -+ return 0; -+} -+ -+static void dvbsky_exit(struct dvb_usb_device *d) -+{ -+ return dvbsky_ci_release(d); -+} -+ -+/* DVB USB Driver stuff */ -+static struct dvb_usb_device_properties dvbsky_s960_props = { -+ .driver_name = KBUILD_MODNAME, -+ .owner = THIS_MODULE, -+ .adapter_nr = adapter_nr, -+ .size_of_priv = sizeof(struct dvbsky_state), -+ -+ .generic_bulk_ctrl_endpoint = 0x01, -+ .generic_bulk_ctrl_endpoint_response = 0x81, -+ -+ .i2c_algo = &dvbsky_i2c_algo, -+ .frontend_attach = dvbsky_s960_attach, -+ .init = dvbsky_init, -+ .get_rc_config = dvbsky_get_rc_config, -+ .streaming_ctrl = dvbsky_streaming_ctrl, -+ .identify_state = dvbsky_identify_state, -+ .exit = dvbsky_exit, -+ .read_mac_address = dvbsky_read_mac_addr, -+ -+ .num_adapters = 1, -+ .adapter = { -+ { -+ .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), -+ } -+ } -+}; -+ -+static const struct usb_device_id dvbsky_id_table[] = { -+ { DVB_USB_DEVICE(0x0572, 0x6831, -+ &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) }, -+ { } -+}; -+MODULE_DEVICE_TABLE(usb, dvbsky_id_table); -+ -+static struct usb_driver dvbsky_usb_driver = { -+ .name = KBUILD_MODNAME, -+ .id_table = dvbsky_id_table, -+ .probe = dvb_usbv2_probe, -+ .disconnect = dvb_usbv2_disconnect, -+ .suspend = dvb_usbv2_suspend, -+ .resume = dvb_usbv2_resume, -+ .reset_resume = dvb_usbv2_reset_resume, -+ .no_dynamic_id = 1, -+ .soft_unbind = 1, -+}; -+ -+module_usb_driver(dvbsky_usb_driver); -+ -+MODULE_AUTHOR("Max nibble "); -+MODULE_DESCRIPTION("Driver for DVBSky USB2.0"); -+MODULE_LICENSE("GPL"); -diff -urN a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig ---- a/drivers/media/usb/dvb-usb-v2/Kconfig 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/usb/dvb-usb-v2/Kconfig 2013-05-03 17:45:35.000000000 +0800 -@@ -149,3 +149,10 @@ - help - Say Y here to support the Realtek RTL28xxU DVB USB receiver. - -+config DVB_USB_DVBSKY -+ tristate "DVBSky USB2.0 support" -+ depends on DVB_USB_V2 -+ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT -+ help -+ Say Y here to support the USB receivers from DVBSky. -+ -diff -urN a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile ---- a/drivers/media/usb/dvb-usb-v2/Makefile 2013-04-29 08:36:01.000000000 +0800 -+++ b/drivers/media/usb/dvb-usb-v2/Makefile 2013-02-17 12:03:00.000000000 +0800 -@@ -43,6 +43,9 @@ - dvb-usb-rtl28xxu-objs := rtl28xxu.o - obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o - -+dvb-usb-dvbsky-objs := dvbsky.o -+obj-$(CONFIG_DVB_USB_DVBSKY) += dvb-usb-dvbsky.o -+ - ccflags-y += -I$(srctree)/drivers/media/dvb-core - ccflags-y += -I$(srctree)/drivers/media/dvb-frontends - ccflags-y += -I$(srctree)/drivers/media/tuners -diff -urN a/include/media/rc-map.h b/include/media/rc-map.h ---- a/include/media/rc-map.h 2013-04-29 08:36:01.000000000 +0800 -+++ b/include/media/rc-map.h 2013-05-03 17:02:46.000000000 +0800 -@@ -118,6 +118,7 @@ - #define RC_MAP_DM1105_NEC "rc-dm1105-nec" - #define RC_MAP_DNTV_LIVE_DVBT_PRO "rc-dntv-live-dvbt-pro" - #define RC_MAP_DNTV_LIVE_DVB_T "rc-dntv-live-dvb-t" -+#define RC_MAP_DVBSKY "rc-dvbsky" - #define RC_MAP_EMPTY "rc-empty" - #define RC_MAP_EM_TERRATEC "rc-em-terratec" - #define RC_MAP_ENCORE_ENLTV2 "rc-encore-enltv2" diff --git a/packages/linux/patches/3.9.8/linux-212-mantis_stb0899_faster_lock.patch b/packages/linux/patches/3.9.8/linux-212-mantis_stb0899_faster_lock.patch deleted file mode 100644 index eef4e1effc..0000000000 --- a/packages/linux/patches/3.9.8/linux-212-mantis_stb0899_faster_lock.patch +++ /dev/null @@ -1,138 +0,0 @@ -diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_algo.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_algo.c ---- linux-3.7.2/drivers/media/dvb-frontends/stb0899_algo.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_algo.c 2013-01-16 10:28:33.633409961 +0100 -@@ -206,7 +206,6 @@ - static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) - { - struct stb0899_internal *internal = &state->internal; -- struct stb0899_params *params = &state->params; - - short int derot_step, derot_freq = 0, derot_limit, next_loop = 3; - int index = 0; -@@ -216,10 +215,9 @@ - - /* timing loop computation & symbol rate optimisation */ - derot_limit = (internal->sub_range / 2L) / internal->mclk; -- derot_step = (params->srate / 2L) / internal->mclk; -+ derot_step = internal->derot_step * 4; /* dertot_step = decreasing delta */ - - while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) { -- index++; - derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ - - if (abs(derot_freq) > derot_limit) -@@ -230,6 +228,7 @@ - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); - stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ - } -+ index++; - internal->direction = -internal->direction; /* Change zigzag direction */ - } - -@@ -278,14 +277,18 @@ - { - struct stb0899_internal *internal = &state->internal; - -- short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3; -+ short int derot_freq = 0, last_derot_freq = 0, derot_limit, derot_step, next_loop = 3; - int index = 0; -+ int base_freq; - u8 cfr[2]; - u8 reg; - - internal->status = NOCARRIER; - derot_limit = (internal->sub_range / 2L) / internal->mclk; - derot_freq = internal->derot_freq; -+ derot_step = internal->derot_step * 2; -+ last_derot_freq = internal->derot_freq; -+ base_freq = internal->derot_freq; - - reg = stb0899_read_reg(state, STB0899_CFD); - STB0899_SETFIELD_VAL(CFD_ON, reg, 1); -@@ -294,11 +297,10 @@ - do { - dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk); - if (stb0899_check_carrier(state) == NOCARRIER) { -- index++; - last_derot_freq = derot_freq; -- derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ -+ derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - -- if(abs(derot_freq) > derot_limit) -+ if (derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) - next_loop--; - - if (next_loop) { -@@ -310,9 +312,10 @@ - STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq)); - stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ - } -+ index++; -+ internal->direction = -internal->direction; /* Change zigzag direction */ - } - -- internal->direction = -internal->direction; /* Change zigzag direction */ - } while ((internal->status != CARRIEROK) && next_loop); - - if (internal->status == CARRIEROK) { -@@ -338,6 +341,7 @@ - int lock = 0, index = 0, dataTime = 500, loop; - u8 reg; - -+ msleep(1); - internal->status = NODATA; - - /* RESET FEC */ -@@ -348,6 +352,7 @@ - reg = stb0899_read_reg(state, STB0899_TSTRES); - STB0899_SETFIELD_VAL(FRESACS, reg, 0); - stb0899_write_reg(state, STB0899_TSTRES, reg); -+ msleep(1); - - if (params->srate <= 2000000) - dataTime = 2000; -@@ -363,6 +368,7 @@ - - stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop */ - while (1) { -+ msleep(1); // Alex: added 1 mSec - /* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP */ - reg = stb0899_read_reg(state, STB0899_VSTATUS); - lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg); -@@ -390,20 +396,21 @@ - short int derot_freq, derot_step, derot_limit, next_loop = 3; - u8 cfr[2]; - u8 reg; -- int index = 1; -+ int index = 0; -+ int base_freq; - - struct stb0899_internal *internal = &state->internal; -- struct stb0899_params *params = &state->params; - -- derot_step = (params->srate / 4L) / internal->mclk; -+ derot_step = internal->derot_step; - derot_limit = (internal->sub_range / 2L) / internal->mclk; - derot_freq = internal->derot_freq; -+ base_freq = internal->derot_freq; - - do { - if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { - - derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ -- if (abs(derot_freq) > derot_limit) -+ if (derot_freq > base_freq + derot_limit || derot_freq < base_freq - derot_limit) - next_loop--; - - if (next_loop) { -@@ -417,9 +424,9 @@ - stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency */ - - stb0899_check_carrier(state); -- index++; - } - } -+ index++; - internal->direction = -internal->direction; /* change zig zag direction */ - } while ((internal->status != DATAOK) && next_loop); - diff --git a/packages/linux/patches/3.9.8/linux-213-cinergy_s2_usb_r2.patch b/packages/linux/patches/3.9.8/linux-213-cinergy_s2_usb_r2.patch deleted file mode 100644 index f781c625ee..0000000000 --- a/packages/linux/patches/3.9.8/linux-213-cinergy_s2_usb_r2.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff -Naur linux-3.7.2/drivers/media/usb/dvb-usb/dw2102.c linux-3.7.2.patch/drivers/media/usb/dvb-usb/dw2102.c ---- linux-3.7.2/drivers/media/usb/dvb-usb/dw2102.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/usb/dvb-usb/dw2102.c 2013-01-16 10:35:01.131342123 +0100 -@@ -1179,6 +1179,13 @@ - u8 ibuf[] = { 0 }; - - if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) -+ err("command 0x0e transfer failed."); -+ -+ obuf[0] = 0xe; -+ obuf[1] = 0x02; -+ obuf[2] = 1; -+ -+ if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0) - err("command 0x0e transfer failed."); - - obuf[0] = 0xe; -@@ -1444,6 +1451,7 @@ - PROF_7500, - GENIATECH_SU3000, - TERRATEC_CINERGY_S2, -+ TERRATEC_CINERGY_S2_R2, - TEVII_S480_1, - TEVII_S480_2, - X3M_SPC1400HD, -@@ -1462,6 +1470,7 @@ - [PROF_7500] = {USB_DEVICE(0x3034, 0x7500)}, - [GENIATECH_SU3000] = {USB_DEVICE(0x1f4d, 0x3000)}, - [TERRATEC_CINERGY_S2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00a8)}, -+ [TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)}, - [TEVII_S480_1] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)}, - [TEVII_S480_2] = {USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)}, - [X3M_SPC1400HD] = {USB_DEVICE(0x1f4d, 0x3100)}, -@@ -1853,7 +1862,7 @@ - }}, - } - }, -- .num_device_descs = 3, -+ .num_device_descs = 4, - .devices = { - { "SU3000HD DVB-S USB2.0", - { &dw2102_table[GENIATECH_SU3000], NULL }, -@@ -1867,6 +1876,10 @@ - { &dw2102_table[X3M_SPC1400HD], NULL }, - { NULL }, - }, -+ { "Terratec Cinergy S2 USB HD Rev.2", -+ { &dw2102_table[TERRATEC_CINERGY_S2_R2], NULL }, -+ { NULL }, -+ }, - } - }; - diff --git a/packages/linux/patches/3.9.8/linux-221-ngene-octopus.patch b/packages/linux/patches/3.9.8/linux-221-ngene-octopus.patch deleted file mode 100644 index ea092a58f9..0000000000 --- a/packages/linux/patches/3.9.8/linux-221-ngene-octopus.patch +++ /dev/null @@ -1,12735 +0,0 @@ -From c5891c83d5777a2e691c2a452a7f57a6b6a13344 Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Sun, 12 May 2013 23:47:07 +0300 -Subject: [PATCH] dvb: ngene/octopus - ---- - drivers/media/dvb-frontends/Kconfig | 26 + - drivers/media/dvb-frontends/Makefile | 2 + - drivers/media/dvb-frontends/stv0367dd.c | 2269 +++++++++++++++++ - drivers/media/dvb-frontends/stv0367dd.h | 17 + - drivers/media/dvb-frontends/stv0367dd_regs.h | 3431 ++++++++++++++++++++++++++ - drivers/media/dvb-frontends/tda18212dd.c | 906 +++++++ - drivers/media/dvb-frontends/tda18212dd.h | 5 + - drivers/media/pci/ddbridge/Kconfig | 14 +- - drivers/media/pci/ddbridge/ddbridge-core.c | 1947 ++++++++++++---- - drivers/media/pci/ddbridge/ddbridge-regs.h | 56 +- - drivers/media/pci/ddbridge/ddbridge.h | 97 +- - drivers/media/pci/ngene/Kconfig | 17 +- - drivers/media/pci/ngene/Makefile | 3 +- - drivers/media/pci/ngene/ngene-av.c | 348 +++ - drivers/media/pci/ngene/ngene-cards.c | 778 +++++-- - drivers/media/pci/ngene/ngene-core.c | 378 +++- - drivers/media/pci/ngene/ngene-dvb.c | 372 +++ - drivers/media/pci/ngene/ngene-eeprom.c | 284 +++ - drivers/media/pci/ngene/ngene-i2c.c | 113 + - drivers/media/pci/ngene/ngene.h | 40 + - drivers/staging/media/cxd2099/TODO | 12 - - drivers/staging/media/cxd2099/cxd2099.c | 47 +- - drivers/staging/media/cxd2099/cxd2099.h | 2 +- - 23 files changed, 10416 insertions(+), 748 deletions(-) - create mode 100644 drivers/media/dvb-frontends/stv0367dd.c - create mode 100644 drivers/media/dvb-frontends/stv0367dd.h - create mode 100644 drivers/media/dvb-frontends/stv0367dd_regs.h - create mode 100644 drivers/media/dvb-frontends/tda18212dd.c - create mode 100644 drivers/media/dvb-frontends/tda18212dd.h - create mode 100644 drivers/media/pci/ngene/ngene-av.c - create mode 100644 drivers/media/pci/ngene/ngene-eeprom.c - delete mode 100644 drivers/staging/media/cxd2099/TODO - -diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig -index 05cf66f..1e0275f 100644 ---- a/drivers/media/dvb-frontends/Kconfig -+++ b/drivers/media/dvb-frontends/Kconfig -@@ -19,6 +19,14 @@ config DVB_STB0899 - A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want - to support this demodulator based frontends - -+config DVB_CXD2099 -+ tristate "CXD2099AR Common Interface driver" -+ depends on DVB_CORE && PCI && I2C -+ ---help--- -+ Support for the CI module found on cards based on -+ - Micronas ngene PCIe bridge: cineS2 etc. -+ - Digital Devices PCIe bridge: Octopus series -+ - config DVB_STB6100 - tristate "STB6100 based tuners" - depends on DVB_CORE && I2C -@@ -63,6 +71,24 @@ config DVB_TDA18271C2DD - - Say Y when you want to support this tuner. - -+config DVB_STV0367DD -+ tristate "STV 0367 (DD)" -+ depends on DVB_CORE && I2C -+ default m if DVB_FE_CUSTOMISE -+ help -+ STV 0367 DVB-C/T demodulator (Digital Devices driver). -+ -+ Say Y when you want to support this frontend. -+ -+config DVB_TDA18212DD -+ tristate "NXP TDA18212 silicon tuner (DD)" -+ depends on DVB_CORE && I2C -+ default m if DVB_FE_CUSTOMISE -+ help -+ NXP TDA18212 silicon tuner (Digital Devices driver). -+ -+ Say Y when you want to support this tuner. -+ - comment "DVB-S (satellite) frontends" - depends on DVB_CORE - -diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile -index 75440de..25ab5f8 100644 ---- a/drivers/media/dvb-frontends/Makefile -+++ b/drivers/media/dvb-frontends/Makefile -@@ -100,6 +100,8 @@ obj-$(CONFIG_DVB_STV0367) += stv0367.o - obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o - obj-$(CONFIG_DVB_DRXK) += drxk.o - obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o -+obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o -+obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o - obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o - obj-$(CONFIG_DVB_A8293) += a8293.o - obj-$(CONFIG_DVB_TDA10071) += tda10071.o -diff --git a/drivers/media/dvb-frontends/stv0367dd.c b/drivers/media/dvb-frontends/stv0367dd.c -new file mode 100644 -index 0000000..34a38cf ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd.c -@@ -0,0 +1,2269 @@ -+/* -+ * stv0367dd: STV0367 DVB-C/T demodulator driver -+ * -+ * Copyright (C) 2011 Digital Devices GmbH -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+#include "stv0367dd.h" -+#include "stv0367dd_regs.h" -+ -+enum omode { OM_NONE, OM_DVBT, OM_DVBC, OM_QAM_ITU_C }; -+enum { QAM_MOD_QAM4 = 0, -+ QAM_MOD_QAM16, -+ QAM_MOD_QAM32, -+ QAM_MOD_QAM64, -+ QAM_MOD_QAM128, -+ QAM_MOD_QAM256, -+ QAM_MOD_QAM512, -+ QAM_MOD_QAM1024 -+}; -+ -+enum {QAM_SPECT_NORMAL, QAM_SPECT_INVERTED }; -+ -+enum { -+ QAM_FEC_A = 1, /* J83 Annex A */ -+ QAM_FEC_B = (1<<1), /* J83 Annex B */ -+ QAM_FEC_C = (1<<2) /* J83 Annex C */ -+}; -+ -+enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted }; -+ -+struct stv_state { -+#ifdef USE_API3 -+ struct dvb_frontend c_frontend; -+ struct dvb_frontend t_frontend; -+#else -+ struct dvb_frontend frontend; -+#endif -+ fe_modulation_t modulation; -+ u32 symbol_rate; -+ u32 bandwidth; -+ struct device *dev; -+ -+ struct i2c_adapter *i2c; -+ u8 adr; -+ void *priv; -+ -+ struct mutex mutex; -+ struct mutex ctlock; -+ -+ u32 master_clock; -+ u32 adc_clock; -+ u8 ID; -+ u8 I2CRPT; -+ u32 omode; -+ u8 qam_inversion; -+ -+ s32 IF; -+ -+ s32 m_FECTimeOut; -+ s32 m_DemodTimeOut; -+ s32 m_SignalTimeOut; -+ s32 m_DemodLockTime; -+ s32 m_FFTTimeOut; -+ s32 m_TSTimeOut; -+ -+ bool m_bFirstTimeLock; -+ -+ u8 m_Save_QAM_AGC_CTL; -+ -+ enum EDemodState demod_state; -+ -+ u8 m_OFDM_FFTMode; // 0 = 2k, 1 = 8k, 2 = 4k -+ u8 m_OFDM_Modulation; // -+ u8 m_OFDM_FEC; // -+ u8 m_OFDM_Guard; -+ -+ u32 ucblocks; -+}; -+ -+struct init_table { -+ u16 adr; -+ u8 data; -+}; -+ -+struct init_table base_init[] = { -+ { R367_IOCFG0, 0x80 }, -+ { R367_DAC0R, 0x00 }, -+ { R367_IOCFG1, 0x00 }, -+ { R367_DAC1R, 0x00 }, -+ { R367_IOCFG2, 0x00 }, -+ { R367_SDFR, 0x00 }, -+ { R367_AUX_CLK, 0x00 }, -+ { R367_FREESYS1, 0x00 }, -+ { R367_FREESYS2, 0x00 }, -+ { R367_FREESYS3, 0x00 }, -+ { R367_GPIO_CFG, 0x55 }, -+ { R367_GPIO_CMD, 0x01 }, -+ { R367_TSTRES, 0x00 }, -+ { R367_ANACTRL, 0x00 }, -+ { R367_TSTBUS, 0x00 }, -+ { R367_RF_AGC2, 0x20 }, -+ { R367_ANADIGCTRL, 0x0b }, -+ { R367_PLLMDIV, 0x01 }, -+ { R367_PLLNDIV, 0x08 }, -+ { R367_PLLSETUP, 0x18 }, -+ { R367_DUAL_AD12, 0x04 }, -+ { R367_TSTBIST, 0x00 }, -+ { 0x0000, 0x00 } -+}; -+ -+struct init_table qam_init[] = { -+ { R367_QAM_CTRL_1, 0x06 },// Orginal 0x04 -+ { R367_QAM_CTRL_2, 0x03 }, -+ { R367_QAM_IT_STATUS1, 0x2b }, -+ { R367_QAM_IT_STATUS2, 0x08 }, -+ { R367_QAM_IT_EN1, 0x00 }, -+ { R367_QAM_IT_EN2, 0x00 }, -+ { R367_QAM_CTRL_STATUS, 0x04 }, -+ { R367_QAM_TEST_CTL, 0x00 }, -+ { R367_QAM_AGC_CTL, 0x73 }, -+ { R367_QAM_AGC_IF_CFG, 0x50 }, -+ { R367_QAM_AGC_RF_CFG, 0x02 },// RF Freeze -+ { R367_QAM_AGC_PWM_CFG, 0x03 }, -+ { R367_QAM_AGC_PWR_REF_L, 0x5a }, -+ { R367_QAM_AGC_PWR_REF_H, 0x00 }, -+ { R367_QAM_AGC_RF_TH_L, 0xff }, -+ { R367_QAM_AGC_RF_TH_H, 0x07 }, -+ { R367_QAM_AGC_IF_LTH_L, 0x00 }, -+ { R367_QAM_AGC_IF_LTH_H, 0x08 }, -+ { R367_QAM_AGC_IF_HTH_L, 0xff }, -+ { R367_QAM_AGC_IF_HTH_H, 0x07 }, -+ { R367_QAM_AGC_PWR_RD_L, 0xa0 }, -+ { R367_QAM_AGC_PWR_RD_M, 0xe9 }, -+ { R367_QAM_AGC_PWR_RD_H, 0x03 }, -+ { R367_QAM_AGC_PWM_IFCMD_L, 0xe4 }, -+ { R367_QAM_AGC_PWM_IFCMD_H, 0x00 }, -+ { R367_QAM_AGC_PWM_RFCMD_L, 0xff }, -+ { R367_QAM_AGC_PWM_RFCMD_H, 0x07 }, -+ { R367_QAM_IQDEM_CFG, 0x01 }, -+ { R367_QAM_MIX_NCO_LL, 0x22 }, -+ { R367_QAM_MIX_NCO_HL, 0x96 }, -+ { R367_QAM_MIX_NCO_HH, 0x55 }, -+ { R367_QAM_SRC_NCO_LL, 0xff }, -+ { R367_QAM_SRC_NCO_LH, 0x0c }, -+ { R367_QAM_SRC_NCO_HL, 0xf5 }, -+ { R367_QAM_SRC_NCO_HH, 0x20 }, -+ { R367_QAM_IQDEM_GAIN_SRC_L, 0x06 }, -+ { R367_QAM_IQDEM_GAIN_SRC_H, 0x01 }, -+ { R367_QAM_IQDEM_DCRM_CFG_LL, 0xfe }, -+ { R367_QAM_IQDEM_DCRM_CFG_LH, 0xff }, -+ { R367_QAM_IQDEM_DCRM_CFG_HL, 0x0f }, -+ { R367_QAM_IQDEM_DCRM_CFG_HH, 0x00 }, -+ { R367_QAM_IQDEM_ADJ_COEFF0, 0x34 }, -+ { R367_QAM_IQDEM_ADJ_COEFF1, 0xae }, -+ { R367_QAM_IQDEM_ADJ_COEFF2, 0x46 }, -+ { R367_QAM_IQDEM_ADJ_COEFF3, 0x77 }, -+ { R367_QAM_IQDEM_ADJ_COEFF4, 0x96 }, -+ { R367_QAM_IQDEM_ADJ_COEFF5, 0x69 }, -+ { R367_QAM_IQDEM_ADJ_COEFF6, 0xc7 }, -+ { R367_QAM_IQDEM_ADJ_COEFF7, 0x01 }, -+ { R367_QAM_IQDEM_ADJ_EN, 0x04 }, -+ { R367_QAM_IQDEM_ADJ_AGC_REF, 0x94 }, -+ { R367_QAM_ALLPASSFILT1, 0xc9 }, -+ { R367_QAM_ALLPASSFILT2, 0x2d }, -+ { R367_QAM_ALLPASSFILT3, 0xa3 }, -+ { R367_QAM_ALLPASSFILT4, 0xfb }, -+ { R367_QAM_ALLPASSFILT5, 0xf6 }, -+ { R367_QAM_ALLPASSFILT6, 0x45 }, -+ { R367_QAM_ALLPASSFILT7, 0x6f }, -+ { R367_QAM_ALLPASSFILT8, 0x7e }, -+ { R367_QAM_ALLPASSFILT9, 0x05 }, -+ { R367_QAM_ALLPASSFILT10, 0x0a }, -+ { R367_QAM_ALLPASSFILT11, 0x51 }, -+ { R367_QAM_TRL_AGC_CFG, 0x20 }, -+ { R367_QAM_TRL_LPF_CFG, 0x28 }, -+ { R367_QAM_TRL_LPF_ACQ_GAIN, 0x44 }, -+ { R367_QAM_TRL_LPF_TRK_GAIN, 0x22 }, -+ { R367_QAM_TRL_LPF_OUT_GAIN, 0x03 }, -+ { R367_QAM_TRL_LOCKDET_LTH, 0x04 }, -+ { R367_QAM_TRL_LOCKDET_HTH, 0x11 }, -+ { R367_QAM_TRL_LOCKDET_TRGVAL, 0x20 }, -+ { R367_QAM_IQ_QAM, 0x01 }, -+ { R367_QAM_FSM_STATE, 0xa0 }, -+ { R367_QAM_FSM_CTL, 0x08 }, -+ { R367_QAM_FSM_STS, 0x0c }, -+ { R367_QAM_FSM_SNR0_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR1_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR2_HTH, 0x00 }, -+ { R367_QAM_FSM_SNR0_LTH, 0x00 }, -+ { R367_QAM_FSM_SNR1_LTH, 0x00 }, -+ { R367_QAM_FSM_EQA1_HTH, 0x00 }, -+ { R367_QAM_FSM_TEMPO, 0x32 }, -+ { R367_QAM_FSM_CONFIG, 0x03 }, -+ { R367_QAM_EQU_I_TESTTAP_L, 0x11 }, -+ { R367_QAM_EQU_I_TESTTAP_M, 0x00 }, -+ { R367_QAM_EQU_I_TESTTAP_H, 0x00 }, -+ { R367_QAM_EQU_TESTAP_CFG, 0x00 }, -+ { R367_QAM_EQU_Q_TESTTAP_L, 0xff }, -+ { R367_QAM_EQU_Q_TESTTAP_M, 0x00 }, -+ { R367_QAM_EQU_Q_TESTTAP_H, 0x00 }, -+ { R367_QAM_EQU_TAP_CTRL, 0x00 }, -+ { R367_QAM_EQU_CTR_CRL_CONTROL_L, 0x11 }, -+ { R367_QAM_EQU_CTR_CRL_CONTROL_H, 0x05 }, -+ { R367_QAM_EQU_CTR_HIPOW_L, 0x00 }, -+ { R367_QAM_EQU_CTR_HIPOW_H, 0x00 }, -+ { R367_QAM_EQU_I_EQU_LO, 0xef }, -+ { R367_QAM_EQU_I_EQU_HI, 0x00 }, -+ { R367_QAM_EQU_Q_EQU_LO, 0xee }, -+ { R367_QAM_EQU_Q_EQU_HI, 0x00 }, -+ { R367_QAM_EQU_MAPPER, 0xc5 }, -+ { R367_QAM_EQU_SWEEP_RATE, 0x80 }, -+ { R367_QAM_EQU_SNR_LO, 0x64 }, -+ { R367_QAM_EQU_SNR_HI, 0x03 }, -+ { R367_QAM_EQU_GAMMA_LO, 0x00 }, -+ { R367_QAM_EQU_GAMMA_HI, 0x00 }, -+ { R367_QAM_EQU_ERR_GAIN, 0x36 }, -+ { R367_QAM_EQU_RADIUS, 0xaa }, -+ { R367_QAM_EQU_FFE_MAINTAP, 0x00 }, -+ { R367_QAM_EQU_FFE_LEAKAGE, 0x63 }, -+ { R367_QAM_EQU_FFE_MAINTAP_POS, 0xdf }, -+ { R367_QAM_EQU_GAIN_WIDE, 0x88 }, -+ { R367_QAM_EQU_GAIN_NARROW, 0x41 }, -+ { R367_QAM_EQU_CTR_LPF_GAIN, 0xd1 }, -+ { R367_QAM_EQU_CRL_LPF_GAIN, 0xa7 }, -+ { R367_QAM_EQU_GLOBAL_GAIN, 0x06 }, -+ { R367_QAM_EQU_CRL_LD_SEN, 0x85 }, -+ { R367_QAM_EQU_CRL_LD_VAL, 0xe2 }, -+ { R367_QAM_EQU_CRL_TFR, 0x20 }, -+ { R367_QAM_EQU_CRL_BISTH_LO, 0x00 }, -+ { R367_QAM_EQU_CRL_BISTH_HI, 0x00 }, -+ { R367_QAM_EQU_SWEEP_RANGE_LO, 0x00 }, -+ { R367_QAM_EQU_SWEEP_RANGE_HI, 0x00 }, -+ { R367_QAM_EQU_CRL_LIMITER, 0x40 }, -+ { R367_QAM_EQU_MODULUS_MAP, 0x90 }, -+ { R367_QAM_EQU_PNT_GAIN, 0xa7 }, -+ { R367_QAM_FEC_AC_CTR_0, 0x16 }, -+ { R367_QAM_FEC_AC_CTR_1, 0x0b }, -+ { R367_QAM_FEC_AC_CTR_2, 0x88 }, -+ { R367_QAM_FEC_AC_CTR_3, 0x02 }, -+ { R367_QAM_FEC_STATUS, 0x12 }, -+ { R367_QAM_RS_COUNTER_0, 0x7d }, -+ { R367_QAM_RS_COUNTER_1, 0xd0 }, -+ { R367_QAM_RS_COUNTER_2, 0x19 }, -+ { R367_QAM_RS_COUNTER_3, 0x0b }, -+ { R367_QAM_RS_COUNTER_4, 0xa3 }, -+ { R367_QAM_RS_COUNTER_5, 0x00 }, -+ { R367_QAM_BERT_0, 0x01 }, -+ { R367_QAM_BERT_1, 0x25 }, -+ { R367_QAM_BERT_2, 0x41 }, -+ { R367_QAM_BERT_3, 0x39 }, -+ { R367_QAM_OUTFORMAT_0, 0xc2 }, -+ { R367_QAM_OUTFORMAT_1, 0x22 }, -+ { R367_QAM_SMOOTHER_2, 0x28 }, -+ { R367_QAM_TSMF_CTRL_0, 0x01 }, -+ { R367_QAM_TSMF_CTRL_1, 0xc6 }, -+ { R367_QAM_TSMF_CTRL_3, 0x43 }, -+ { R367_QAM_TS_ON_ID_0, 0x00 }, -+ { R367_QAM_TS_ON_ID_1, 0x00 }, -+ { R367_QAM_TS_ON_ID_2, 0x00 }, -+ { R367_QAM_TS_ON_ID_3, 0x00 }, -+ { R367_QAM_RE_STATUS_0, 0x00 }, -+ { R367_QAM_RE_STATUS_1, 0x00 }, -+ { R367_QAM_RE_STATUS_2, 0x00 }, -+ { R367_QAM_RE_STATUS_3, 0x00 }, -+ { R367_QAM_TS_STATUS_0, 0x00 }, -+ { R367_QAM_TS_STATUS_1, 0x00 }, -+ { R367_QAM_TS_STATUS_2, 0xa0 }, -+ { R367_QAM_TS_STATUS_3, 0x00 }, -+ { R367_QAM_T_O_ID_0, 0x00 }, -+ { R367_QAM_T_O_ID_1, 0x00 }, -+ { R367_QAM_T_O_ID_2, 0x00 }, -+ { R367_QAM_T_O_ID_3, 0x00 }, -+ { 0x0000, 0x00 } // EOT -+}; -+ -+struct init_table ofdm_init[] = { -+ //{R367_OFDM_ID ,0x60}, -+ //{R367_OFDM_I2CRPT ,0x22}, -+ //{R367_OFDM_TOPCTRL ,0x02}, -+ //{R367_OFDM_IOCFG0 ,0x40}, -+ //{R367_OFDM_DAC0R ,0x00}, -+ //{R367_OFDM_IOCFG1 ,0x00}, -+ //{R367_OFDM_DAC1R ,0x00}, -+ //{R367_OFDM_IOCFG2 ,0x62}, -+ //{R367_OFDM_SDFR ,0x00}, -+ //{R367_OFDM_STATUS ,0xf8}, -+ //{R367_OFDM_AUX_CLK ,0x0a}, -+ //{R367_OFDM_FREESYS1 ,0x00}, -+ //{R367_OFDM_FREESYS2 ,0x00}, -+ //{R367_OFDM_FREESYS3 ,0x00}, -+ //{R367_OFDM_GPIO_CFG ,0x55}, -+ //{R367_OFDM_GPIO_CMD ,0x00}, -+ {R367_OFDM_AGC2MAX ,0xff}, -+ {R367_OFDM_AGC2MIN ,0x00}, -+ {R367_OFDM_AGC1MAX ,0xff}, -+ {R367_OFDM_AGC1MIN ,0x00}, -+ {R367_OFDM_AGCR ,0xbc}, -+ {R367_OFDM_AGC2TH ,0x00}, -+ //{R367_OFDM_AGC12C ,0x01}, //Note: This defines AGC pins, also needed for QAM -+ {R367_OFDM_AGCCTRL1 ,0x85}, -+ {R367_OFDM_AGCCTRL2 ,0x1f}, -+ {R367_OFDM_AGC1VAL1 ,0x00}, -+ {R367_OFDM_AGC1VAL2 ,0x00}, -+ {R367_OFDM_AGC2VAL1 ,0x6f}, -+ {R367_OFDM_AGC2VAL2 ,0x05}, -+ {R367_OFDM_AGC2PGA ,0x00}, -+ {R367_OFDM_OVF_RATE1 ,0x00}, -+ {R367_OFDM_OVF_RATE2 ,0x00}, -+ {R367_OFDM_GAIN_SRC1 ,0x2b}, -+ {R367_OFDM_GAIN_SRC2 ,0x04}, -+ {R367_OFDM_INC_DEROT1 ,0x55}, -+ {R367_OFDM_INC_DEROT2 ,0x55}, -+ {R367_OFDM_PPM_CPAMP_DIR ,0x2c}, -+ {R367_OFDM_PPM_CPAMP_INV ,0x00}, -+ {R367_OFDM_FREESTFE_1 ,0x00}, -+ {R367_OFDM_FREESTFE_2 ,0x1c}, -+ {R367_OFDM_DCOFFSET ,0x00}, -+ {R367_OFDM_EN_PROCESS ,0x05}, -+ {R367_OFDM_SDI_SMOOTHER ,0x80}, -+ {R367_OFDM_FE_LOOP_OPEN ,0x1c}, -+ {R367_OFDM_FREQOFF1 ,0x00}, -+ {R367_OFDM_FREQOFF2 ,0x00}, -+ {R367_OFDM_FREQOFF3 ,0x00}, -+ {R367_OFDM_TIMOFF1 ,0x00}, -+ {R367_OFDM_TIMOFF2 ,0x00}, -+ {R367_OFDM_EPQ ,0x02}, -+ {R367_OFDM_EPQAUTO ,0x01}, -+ {R367_OFDM_SYR_UPDATE ,0xf5}, -+ {R367_OFDM_CHPFREE ,0x00}, -+ {R367_OFDM_PPM_STATE_MAC ,0x23}, -+ {R367_OFDM_INR_THRESHOLD ,0xff}, -+ {R367_OFDM_EPQ_TPS_ID_CELL ,0xf9}, -+ {R367_OFDM_EPQ_CFG ,0x00}, -+ {R367_OFDM_EPQ_STATUS ,0x01}, -+ {R367_OFDM_AUTORELOCK ,0x81}, -+ {R367_OFDM_BER_THR_VMSB ,0x00}, -+ {R367_OFDM_BER_THR_MSB ,0x00}, -+ {R367_OFDM_BER_THR_LSB ,0x00}, -+ {R367_OFDM_CCD ,0x83}, -+ {R367_OFDM_SPECTR_CFG ,0x00}, -+ {R367_OFDM_CHC_DUMMY ,0x18}, -+ {R367_OFDM_INC_CTL ,0x88}, -+ {R367_OFDM_INCTHRES_COR1 ,0xb4}, -+ {R367_OFDM_INCTHRES_COR2 ,0x96}, -+ {R367_OFDM_INCTHRES_DET1 ,0x0e}, -+ {R367_OFDM_INCTHRES_DET2 ,0x11}, -+ {R367_OFDM_IIR_CELLNB ,0x8d}, -+ {R367_OFDM_IIRCX_COEFF1_MSB ,0x00}, -+ {R367_OFDM_IIRCX_COEFF1_LSB ,0x00}, -+ {R367_OFDM_IIRCX_COEFF2_MSB ,0x09}, -+ {R367_OFDM_IIRCX_COEFF2_LSB ,0x18}, -+ {R367_OFDM_IIRCX_COEFF3_MSB ,0x14}, -+ {R367_OFDM_IIRCX_COEFF3_LSB ,0x9c}, -+ {R367_OFDM_IIRCX_COEFF4_MSB ,0x00}, -+ {R367_OFDM_IIRCX_COEFF4_LSB ,0x00}, -+ {R367_OFDM_IIRCX_COEFF5_MSB ,0x36}, -+ {R367_OFDM_IIRCX_COEFF5_LSB ,0x42}, -+ {R367_OFDM_FEPATH_CFG ,0x00}, -+ {R367_OFDM_PMC1_FUNC ,0x65}, -+ {R367_OFDM_PMC1_FOR ,0x00}, -+ {R367_OFDM_PMC2_FUNC ,0x00}, -+ {R367_OFDM_STATUS_ERR_DA ,0xe0}, -+ {R367_OFDM_DIG_AGC_R ,0xfe}, -+ {R367_OFDM_COMAGC_TARMSB ,0x0b}, -+ {R367_OFDM_COM_AGC_TAR_ENMODE ,0x41}, -+ {R367_OFDM_COM_AGC_CFG ,0x3e}, -+ {R367_OFDM_COM_AGC_GAIN1 ,0x39}, -+ {R367_OFDM_AUT_AGC_TARGETMSB ,0x0b}, -+ {R367_OFDM_LOCK_DET_MSB ,0x01}, -+ {R367_OFDM_AGCTAR_LOCK_LSBS ,0x40}, -+ {R367_OFDM_AUT_GAIN_EN ,0xf4}, -+ {R367_OFDM_AUT_CFG ,0xf0}, -+ {R367_OFDM_LOCKN ,0x23}, -+ {R367_OFDM_INT_X_3 ,0x00}, -+ {R367_OFDM_INT_X_2 ,0x03}, -+ {R367_OFDM_INT_X_1 ,0x8d}, -+ {R367_OFDM_INT_X_0 ,0xa0}, -+ {R367_OFDM_MIN_ERRX_MSB ,0x00}, -+ {R367_OFDM_COR_CTL ,0x00}, -+ {R367_OFDM_COR_STAT ,0xf6}, -+ {R367_OFDM_COR_INTEN ,0x00}, -+ {R367_OFDM_COR_INTSTAT ,0x3f}, -+ {R367_OFDM_COR_MODEGUARD ,0x03}, -+ {R367_OFDM_AGC_CTL ,0x08}, -+ {R367_OFDM_AGC_MANUAL1 ,0x00}, -+ {R367_OFDM_AGC_MANUAL2 ,0x00}, -+ {R367_OFDM_AGC_TARG ,0x16}, -+ {R367_OFDM_AGC_GAIN1 ,0x53}, -+ {R367_OFDM_AGC_GAIN2 ,0x1d}, -+ {R367_OFDM_RESERVED_1 ,0x00}, -+ {R367_OFDM_RESERVED_2 ,0x00}, -+ {R367_OFDM_RESERVED_3 ,0x00}, -+ {R367_OFDM_CAS_CTL ,0x44}, -+ {R367_OFDM_CAS_FREQ ,0xb3}, -+ {R367_OFDM_CAS_DAGCGAIN ,0x12}, -+ {R367_OFDM_SYR_CTL ,0x04}, -+ {R367_OFDM_SYR_STAT ,0x10}, -+ {R367_OFDM_SYR_NCO1 ,0x00}, -+ {R367_OFDM_SYR_NCO2 ,0x00}, -+ {R367_OFDM_SYR_OFFSET1 ,0x00}, -+ {R367_OFDM_SYR_OFFSET2 ,0x00}, -+ {R367_OFDM_FFT_CTL ,0x00}, -+ {R367_OFDM_SCR_CTL ,0x70}, -+ {R367_OFDM_PPM_CTL1 ,0xf8}, -+ {R367_OFDM_TRL_CTL ,0xac}, -+ {R367_OFDM_TRL_NOMRATE1 ,0x1e}, -+ {R367_OFDM_TRL_NOMRATE2 ,0x58}, -+ {R367_OFDM_TRL_TIME1 ,0x1d}, -+ {R367_OFDM_TRL_TIME2 ,0xfc}, -+ {R367_OFDM_CRL_CTL ,0x24}, -+ {R367_OFDM_CRL_FREQ1 ,0xad}, -+ {R367_OFDM_CRL_FREQ2 ,0x9d}, -+ {R367_OFDM_CRL_FREQ3 ,0xff}, -+ {R367_OFDM_CHC_CTL ,0x01}, -+ {R367_OFDM_CHC_SNR ,0xf0}, -+ {R367_OFDM_BDI_CTL ,0x00}, -+ {R367_OFDM_DMP_CTL ,0x00}, -+ {R367_OFDM_TPS_RCVD1 ,0x30}, -+ {R367_OFDM_TPS_RCVD2 ,0x02}, -+ {R367_OFDM_TPS_RCVD3 ,0x01}, -+ {R367_OFDM_TPS_RCVD4 ,0x00}, -+ {R367_OFDM_TPS_ID_CELL1 ,0x00}, -+ {R367_OFDM_TPS_ID_CELL2 ,0x00}, -+ {R367_OFDM_TPS_RCVD5_SET1 ,0x02}, -+ {R367_OFDM_TPS_SET2 ,0x02}, -+ {R367_OFDM_TPS_SET3 ,0x01}, -+ {R367_OFDM_TPS_CTL ,0x00}, -+ {R367_OFDM_CTL_FFTOSNUM ,0x34}, -+ {R367_OFDM_TESTSELECT ,0x09}, -+ {R367_OFDM_MSC_REV ,0x0a}, -+ {R367_OFDM_PIR_CTL ,0x00}, -+ {R367_OFDM_SNR_CARRIER1 ,0xa1}, -+ {R367_OFDM_SNR_CARRIER2 ,0x9a}, -+ {R367_OFDM_PPM_CPAMP ,0x2c}, -+ {R367_OFDM_TSM_AP0 ,0x00}, -+ {R367_OFDM_TSM_AP1 ,0x00}, -+ {R367_OFDM_TSM_AP2 ,0x00}, -+ {R367_OFDM_TSM_AP3 ,0x00}, -+ {R367_OFDM_TSM_AP4 ,0x00}, -+ {R367_OFDM_TSM_AP5 ,0x00}, -+ {R367_OFDM_TSM_AP6 ,0x00}, -+ {R367_OFDM_TSM_AP7 ,0x00}, -+ //{R367_OFDM_TSTRES ,0x00}, -+ //{R367_OFDM_ANACTRL ,0x0D},/*caution PLL stopped, to be restarted at init!!!*/ -+ //{R367_OFDM_TSTBUS ,0x00}, -+ //{R367_OFDM_TSTRATE ,0x00}, -+ {R367_OFDM_CONSTMODE ,0x01}, -+ {R367_OFDM_CONSTCARR1 ,0x00}, -+ {R367_OFDM_CONSTCARR2 ,0x00}, -+ {R367_OFDM_ICONSTEL ,0x0a}, -+ {R367_OFDM_QCONSTEL ,0x15}, -+ {R367_OFDM_TSTBISTRES0 ,0x00}, -+ {R367_OFDM_TSTBISTRES1 ,0x00}, -+ {R367_OFDM_TSTBISTRES2 ,0x28}, -+ {R367_OFDM_TSTBISTRES3 ,0x00}, -+ //{R367_OFDM_RF_AGC1 ,0xff}, -+ //{R367_OFDM_RF_AGC2 ,0x83}, -+ //{R367_OFDM_ANADIGCTRL ,0x19}, -+ //{R367_OFDM_PLLMDIV ,0x0c}, -+ //{R367_OFDM_PLLNDIV ,0x55}, -+ //{R367_OFDM_PLLSETUP ,0x18}, -+ //{R367_OFDM_DUAL_AD12 ,0x00}, -+ //{R367_OFDM_TSTBIST ,0x00}, -+ //{R367_OFDM_PAD_COMP_CTRL ,0x00}, -+ //{R367_OFDM_PAD_COMP_WR ,0x00}, -+ //{R367_OFDM_PAD_COMP_RD ,0xe0}, -+ {R367_OFDM_SYR_TARGET_FFTADJT_MSB ,0x00}, -+ {R367_OFDM_SYR_TARGET_FFTADJT_LSB ,0x00}, -+ {R367_OFDM_SYR_TARGET_CHCADJT_MSB ,0x00}, -+ {R367_OFDM_SYR_TARGET_CHCADJT_LSB ,0x00}, -+ {R367_OFDM_SYR_FLAG ,0x00}, -+ {R367_OFDM_CRL_TARGET1 ,0x00}, -+ {R367_OFDM_CRL_TARGET2 ,0x00}, -+ {R367_OFDM_CRL_TARGET3 ,0x00}, -+ {R367_OFDM_CRL_TARGET4 ,0x00}, -+ {R367_OFDM_CRL_FLAG ,0x00}, -+ {R367_OFDM_TRL_TARGET1 ,0x00}, -+ {R367_OFDM_TRL_TARGET2 ,0x00}, -+ {R367_OFDM_TRL_CHC ,0x00}, -+ {R367_OFDM_CHC_SNR_TARG ,0x00}, -+ {R367_OFDM_TOP_TRACK ,0x00}, -+ {R367_OFDM_TRACKER_FREE1 ,0x00}, -+ {R367_OFDM_ERROR_CRL1 ,0x00}, -+ {R367_OFDM_ERROR_CRL2 ,0x00}, -+ {R367_OFDM_ERROR_CRL3 ,0x00}, -+ {R367_OFDM_ERROR_CRL4 ,0x00}, -+ {R367_OFDM_DEC_NCO1 ,0x2c}, -+ {R367_OFDM_DEC_NCO2 ,0x0f}, -+ {R367_OFDM_DEC_NCO3 ,0x20}, -+ {R367_OFDM_SNR ,0xf1}, -+ {R367_OFDM_SYR_FFTADJ1 ,0x00}, -+ {R367_OFDM_SYR_FFTADJ2 ,0x00}, -+ {R367_OFDM_SYR_CHCADJ1 ,0x00}, -+ {R367_OFDM_SYR_CHCADJ2 ,0x00}, -+ {R367_OFDM_SYR_OFF ,0x00}, -+ {R367_OFDM_PPM_OFFSET1 ,0x00}, -+ {R367_OFDM_PPM_OFFSET2 ,0x03}, -+ {R367_OFDM_TRACKER_FREE2 ,0x00}, -+ {R367_OFDM_DEBG_LT10 ,0x00}, -+ {R367_OFDM_DEBG_LT11 ,0x00}, -+ {R367_OFDM_DEBG_LT12 ,0x00}, -+ {R367_OFDM_DEBG_LT13 ,0x00}, -+ {R367_OFDM_DEBG_LT14 ,0x00}, -+ {R367_OFDM_DEBG_LT15 ,0x00}, -+ {R367_OFDM_DEBG_LT16 ,0x00}, -+ {R367_OFDM_DEBG_LT17 ,0x00}, -+ {R367_OFDM_DEBG_LT18 ,0x00}, -+ {R367_OFDM_DEBG_LT19 ,0x00}, -+ {R367_OFDM_DEBG_LT1A ,0x00}, -+ {R367_OFDM_DEBG_LT1B ,0x00}, -+ {R367_OFDM_DEBG_LT1C ,0x00}, -+ {R367_OFDM_DEBG_LT1D ,0x00}, -+ {R367_OFDM_DEBG_LT1E ,0x00}, -+ {R367_OFDM_DEBG_LT1F ,0x00}, -+ {R367_OFDM_RCCFGH ,0x00}, -+ {R367_OFDM_RCCFGM ,0x00}, -+ {R367_OFDM_RCCFGL ,0x00}, -+ {R367_OFDM_RCINSDELH ,0x00}, -+ {R367_OFDM_RCINSDELM ,0x00}, -+ {R367_OFDM_RCINSDELL ,0x00}, -+ {R367_OFDM_RCSTATUS ,0x00}, -+ {R367_OFDM_RCSPEED ,0x6f}, -+ {R367_OFDM_RCDEBUGM ,0xe7}, -+ {R367_OFDM_RCDEBUGL ,0x9b}, -+ {R367_OFDM_RCOBSCFG ,0x00}, -+ {R367_OFDM_RCOBSM ,0x00}, -+ {R367_OFDM_RCOBSL ,0x00}, -+ {R367_OFDM_RCFECSPY ,0x00}, -+ {R367_OFDM_RCFSPYCFG ,0x00}, -+ {R367_OFDM_RCFSPYDATA ,0x00}, -+ {R367_OFDM_RCFSPYOUT ,0x00}, -+ {R367_OFDM_RCFSTATUS ,0x00}, -+ {R367_OFDM_RCFGOODPACK ,0x00}, -+ {R367_OFDM_RCFPACKCNT ,0x00}, -+ {R367_OFDM_RCFSPYMISC ,0x00}, -+ {R367_OFDM_RCFBERCPT4 ,0x00}, -+ {R367_OFDM_RCFBERCPT3 ,0x00}, -+ {R367_OFDM_RCFBERCPT2 ,0x00}, -+ {R367_OFDM_RCFBERCPT1 ,0x00}, -+ {R367_OFDM_RCFBERCPT0 ,0x00}, -+ {R367_OFDM_RCFBERERR2 ,0x00}, -+ {R367_OFDM_RCFBERERR1 ,0x00}, -+ {R367_OFDM_RCFBERERR0 ,0x00}, -+ {R367_OFDM_RCFSTATESM ,0x00}, -+ {R367_OFDM_RCFSTATESL ,0x00}, -+ {R367_OFDM_RCFSPYBER ,0x00}, -+ {R367_OFDM_RCFSPYDISTM ,0x00}, -+ {R367_OFDM_RCFSPYDISTL ,0x00}, -+ {R367_OFDM_RCFSPYOBS7 ,0x00}, -+ {R367_OFDM_RCFSPYOBS6 ,0x00}, -+ {R367_OFDM_RCFSPYOBS5 ,0x00}, -+ {R367_OFDM_RCFSPYOBS4 ,0x00}, -+ {R367_OFDM_RCFSPYOBS3 ,0x00}, -+ {R367_OFDM_RCFSPYOBS2 ,0x00}, -+ {R367_OFDM_RCFSPYOBS1 ,0x00}, -+ {R367_OFDM_RCFSPYOBS0 ,0x00}, -+ //{R367_OFDM_TSGENERAL ,0x00}, -+ //{R367_OFDM_RC1SPEED ,0x6f}, -+ //{R367_OFDM_TSGSTATUS ,0x18}, -+ {R367_OFDM_FECM ,0x01}, -+ {R367_OFDM_VTH12 ,0xff}, -+ {R367_OFDM_VTH23 ,0xa1}, -+ {R367_OFDM_VTH34 ,0x64}, -+ {R367_OFDM_VTH56 ,0x40}, -+ {R367_OFDM_VTH67 ,0x00}, -+ {R367_OFDM_VTH78 ,0x2c}, -+ {R367_OFDM_VITCURPUN ,0x12}, -+ {R367_OFDM_VERROR ,0x01}, -+ {R367_OFDM_PRVIT ,0x3f}, -+ {R367_OFDM_VAVSRVIT ,0x00}, -+ {R367_OFDM_VSTATUSVIT ,0xbd}, -+ {R367_OFDM_VTHINUSE ,0xa1}, -+ {R367_OFDM_KDIV12 ,0x20}, -+ {R367_OFDM_KDIV23 ,0x40}, -+ {R367_OFDM_KDIV34 ,0x20}, -+ {R367_OFDM_KDIV56 ,0x30}, -+ {R367_OFDM_KDIV67 ,0x00}, -+ {R367_OFDM_KDIV78 ,0x30}, -+ {R367_OFDM_SIGPOWER ,0x54}, -+ {R367_OFDM_DEMAPVIT ,0x40}, -+ {R367_OFDM_VITSCALE ,0x00}, -+ {R367_OFDM_FFEC1PRG ,0x00}, -+ {R367_OFDM_FVITCURPUN ,0x12}, -+ {R367_OFDM_FVERROR ,0x01}, -+ {R367_OFDM_FVSTATUSVIT ,0xbd}, -+ {R367_OFDM_DEBUG_LT1 ,0x00}, -+ {R367_OFDM_DEBUG_LT2 ,0x00}, -+ {R367_OFDM_DEBUG_LT3 ,0x00}, -+ {R367_OFDM_TSTSFMET ,0x00}, -+ {R367_OFDM_SELOUT ,0x00}, -+ {R367_OFDM_TSYNC ,0x00}, -+ {R367_OFDM_TSTERR ,0x00}, -+ {R367_OFDM_TSFSYNC ,0x00}, -+ {R367_OFDM_TSTSFERR ,0x00}, -+ {R367_OFDM_TSTTSSF1 ,0x01}, -+ {R367_OFDM_TSTTSSF2 ,0x1f}, -+ {R367_OFDM_TSTTSSF3 ,0x00}, -+ {R367_OFDM_TSTTS1 ,0x00}, -+ {R367_OFDM_TSTTS2 ,0x1f}, -+ {R367_OFDM_TSTTS3 ,0x01}, -+ {R367_OFDM_TSTTS4 ,0x00}, -+ {R367_OFDM_TSTTSRC ,0x00}, -+ {R367_OFDM_TSTTSRS ,0x00}, -+ {R367_OFDM_TSSTATEM ,0xb0}, -+ {R367_OFDM_TSSTATEL ,0x40}, -+ {R367_OFDM_TSCFGH ,0x80}, -+ {R367_OFDM_TSCFGM ,0x00}, -+ {R367_OFDM_TSCFGL ,0x20}, -+ {R367_OFDM_TSSYNC ,0x00}, -+ {R367_OFDM_TSINSDELH ,0x00}, -+ {R367_OFDM_TSINSDELM ,0x00}, -+ {R367_OFDM_TSINSDELL ,0x00}, -+ {R367_OFDM_TSDIVN ,0x03}, -+ {R367_OFDM_TSDIVPM ,0x00}, -+ {R367_OFDM_TSDIVPL ,0x00}, -+ {R367_OFDM_TSDIVQM ,0x00}, -+ {R367_OFDM_TSDIVQL ,0x00}, -+ {R367_OFDM_TSDILSTKM ,0x00}, -+ {R367_OFDM_TSDILSTKL ,0x00}, -+ {R367_OFDM_TSSPEED ,0x6f}, -+ {R367_OFDM_TSSTATUS ,0x81}, -+ {R367_OFDM_TSSTATUS2 ,0x6a}, -+ {R367_OFDM_TSBITRATEM ,0x0f}, -+ {R367_OFDM_TSBITRATEL ,0xc6}, -+ {R367_OFDM_TSPACKLENM ,0x00}, -+ {R367_OFDM_TSPACKLENL ,0xfc}, -+ {R367_OFDM_TSBLOCLENM ,0x0a}, -+ {R367_OFDM_TSBLOCLENL ,0x80}, -+ {R367_OFDM_TSDLYH ,0x90}, -+ {R367_OFDM_TSDLYM ,0x68}, -+ {R367_OFDM_TSDLYL ,0x01}, -+ {R367_OFDM_TSNPDAV ,0x00}, -+ {R367_OFDM_TSBUFSTATH ,0x00}, -+ {R367_OFDM_TSBUFSTATM ,0x00}, -+ {R367_OFDM_TSBUFSTATL ,0x00}, -+ {R367_OFDM_TSDEBUGM ,0xcf}, -+ {R367_OFDM_TSDEBUGL ,0x1e}, -+ {R367_OFDM_TSDLYSETH ,0x00}, -+ {R367_OFDM_TSDLYSETM ,0x68}, -+ {R367_OFDM_TSDLYSETL ,0x00}, -+ {R367_OFDM_TSOBSCFG ,0x00}, -+ {R367_OFDM_TSOBSM ,0x47}, -+ {R367_OFDM_TSOBSL ,0x1f}, -+ {R367_OFDM_ERRCTRL1 ,0x95}, -+ {R367_OFDM_ERRCNT1H ,0x80}, -+ {R367_OFDM_ERRCNT1M ,0x00}, -+ {R367_OFDM_ERRCNT1L ,0x00}, -+ {R367_OFDM_ERRCTRL2 ,0x95}, -+ {R367_OFDM_ERRCNT2H ,0x00}, -+ {R367_OFDM_ERRCNT2M ,0x00}, -+ {R367_OFDM_ERRCNT2L ,0x00}, -+ {R367_OFDM_FECSPY ,0x88}, -+ {R367_OFDM_FSPYCFG ,0x2c}, -+ {R367_OFDM_FSPYDATA ,0x3a}, -+ {R367_OFDM_FSPYOUT ,0x06}, -+ {R367_OFDM_FSTATUS ,0x61}, -+ {R367_OFDM_FGOODPACK ,0xff}, -+ {R367_OFDM_FPACKCNT ,0xff}, -+ {R367_OFDM_FSPYMISC ,0x66}, -+ {R367_OFDM_FBERCPT4 ,0x00}, -+ {R367_OFDM_FBERCPT3 ,0x00}, -+ {R367_OFDM_FBERCPT2 ,0x36}, -+ {R367_OFDM_FBERCPT1 ,0x36}, -+ {R367_OFDM_FBERCPT0 ,0x14}, -+ {R367_OFDM_FBERERR2 ,0x00}, -+ {R367_OFDM_FBERERR1 ,0x03}, -+ {R367_OFDM_FBERERR0 ,0x28}, -+ {R367_OFDM_FSTATESM ,0x00}, -+ {R367_OFDM_FSTATESL ,0x02}, -+ {R367_OFDM_FSPYBER ,0x00}, -+ {R367_OFDM_FSPYDISTM ,0x01}, -+ {R367_OFDM_FSPYDISTL ,0x9f}, -+ {R367_OFDM_FSPYOBS7 ,0xc9}, -+ {R367_OFDM_FSPYOBS6 ,0x99}, -+ {R367_OFDM_FSPYOBS5 ,0x08}, -+ {R367_OFDM_FSPYOBS4 ,0xec}, -+ {R367_OFDM_FSPYOBS3 ,0x01}, -+ {R367_OFDM_FSPYOBS2 ,0x0f}, -+ {R367_OFDM_FSPYOBS1 ,0xf5}, -+ {R367_OFDM_FSPYOBS0 ,0x08}, -+ {R367_OFDM_SFDEMAP ,0x40}, -+ {R367_OFDM_SFERROR ,0x00}, -+ {R367_OFDM_SFAVSR ,0x30}, -+ {R367_OFDM_SFECSTATUS ,0xcc}, -+ {R367_OFDM_SFKDIV12 ,0x20}, -+ {R367_OFDM_SFKDIV23 ,0x40}, -+ {R367_OFDM_SFKDIV34 ,0x20}, -+ {R367_OFDM_SFKDIV56 ,0x20}, -+ {R367_OFDM_SFKDIV67 ,0x00}, -+ {R367_OFDM_SFKDIV78 ,0x20}, -+ {R367_OFDM_SFDILSTKM ,0x00}, -+ {R367_OFDM_SFDILSTKL ,0x00}, -+ {R367_OFDM_SFSTATUS ,0xb5}, -+ {R367_OFDM_SFDLYH ,0x90}, -+ {R367_OFDM_SFDLYM ,0x60}, -+ {R367_OFDM_SFDLYL ,0x01}, -+ {R367_OFDM_SFDLYSETH ,0xc0}, -+ {R367_OFDM_SFDLYSETM ,0x60}, -+ {R367_OFDM_SFDLYSETL ,0x00}, -+ {R367_OFDM_SFOBSCFG ,0x00}, -+ {R367_OFDM_SFOBSM ,0x47}, -+ {R367_OFDM_SFOBSL ,0x05}, -+ {R367_OFDM_SFECINFO ,0x40}, -+ {R367_OFDM_SFERRCTRL ,0x74}, -+ {R367_OFDM_SFERRCNTH ,0x80}, -+ {R367_OFDM_SFERRCNTM ,0x00}, -+ {R367_OFDM_SFERRCNTL ,0x00}, -+ {R367_OFDM_SYMBRATEM ,0x2f}, -+ {R367_OFDM_SYMBRATEL ,0x50}, -+ {R367_OFDM_SYMBSTATUS ,0x7f}, -+ {R367_OFDM_SYMBCFG ,0x00}, -+ {R367_OFDM_SYMBFIFOM ,0xf4}, -+ {R367_OFDM_SYMBFIFOL ,0x0d}, -+ {R367_OFDM_SYMBOFFSM ,0xf0}, -+ {R367_OFDM_SYMBOFFSL ,0x2d}, -+ //{R367_OFDM_DEBUG_LT4 ,0x00}, -+ //{R367_OFDM_DEBUG_LT5 ,0x00}, -+ //{R367_OFDM_DEBUG_LT6 ,0x00}, -+ //{R367_OFDM_DEBUG_LT7 ,0x00}, -+ //{R367_OFDM_DEBUG_LT8 ,0x00}, -+ //{R367_OFDM_DEBUG_LT9 ,0x00}, -+ { 0x0000, 0x00 } // EOT -+}; -+ -+inline u32 MulDiv32(u32 a, u32 b, u32 c) -+{ -+ u64 tmp64; -+ -+ tmp64 = (u64)a * (u64)b; -+ do_div(tmp64, c); -+ -+ return (u32) tmp64; -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = -+ {.addr = adr, .flags = 0, .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ printk("stv0367: i2c_write error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+#if 0 -+static int i2c_read(struct i2c_adapter *adap, -+ u8 adr, u8 *msg, int len, u8 *answ, int alen) -+{ -+ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, -+ .buf = msg, .len = len}, -+ { .addr = adr, .flags = I2C_M_RD, -+ .buf = answ, .len = alen } }; -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ printk("stv0367: i2c_read error\n"); -+ return -1; -+ } -+ return 0; -+} -+#endif -+ -+static int writereg(struct stv_state *state, u16 reg, u8 dat) -+{ -+ u8 mm[3] = { (reg >> 8), reg & 0xff, dat }; -+ -+ return i2c_write(state->i2c, state->adr, mm, 3); -+} -+ -+static int readreg(struct stv_state *state, u16 reg, u8 *val) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = state->adr, .flags = I2C_M_RD, -+ .buf = val, .len = 1}}; -+ return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int readregs(struct stv_state *state, u16 reg, u8 *val, int count) -+{ -+ u8 msg[2] = {reg >> 8, reg & 0xff}; -+ struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0, -+ .buf = msg, .len = 2}, -+ {.addr = state->adr, .flags = I2C_M_RD, -+ .buf = val, .len = count}}; -+ return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int write_init_table(struct stv_state *state, struct init_table *tab) -+{ -+ while (1) { -+ if (!tab->adr) -+ break; -+ if (writereg(state, tab->adr, tab->data) < 0) -+ return -1; -+ tab++; -+ } -+ return 0; -+} -+ -+static int qam_set_modulation(struct stv_state *state) -+{ -+ int stat = 0; -+ -+ switch(state->modulation) { -+ case QAM_16: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM16 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x64); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ -+ writereg(state, R367_QAM_FSM_STATE,0x90); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0x8a); -+ break; -+ case QAM_32: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM32 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x6e); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ -+ writereg(state, R367_QAM_FSM_STATE,0xb0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xb7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x9d); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); -+ break; -+ case QAM_64: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM64 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x82); /* Set digital AGC reference */ -+ if(state->symbol_rate>4500000) -+ { -+ writereg(state, R367_QAM_FSM_STATE,0xb0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa5); -+ } -+ else if(state->symbol_rate>2500000) // 25000000 -+ { -+ writereg(state, R367_QAM_FSM_STATE,0xa0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6); -+ } -+ else -+ { -+ writereg(state, R367_QAM_FSM_STATE,0xa0); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1); -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0x99); -+ break; -+ case QAM_128: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM128 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x76); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00); /* Set digital AGC reference */ -+ writereg(state, R367_QAM_FSM_STATE,0x90); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xb1); -+ if(state->symbol_rate>4500000) // 45000000 -+ { -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); -+ } -+ else if(state->symbol_rate>2500000) // 25000000 -+ { -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6); -+ } -+ else -+ { -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0x97); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x8e); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); -+ break; -+ case QAM_256: -+ writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM256 ); -+ writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a); /* Set analog AGC reference */ -+ writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x94); /* Set digital AGC reference */ -+ writereg(state, R367_QAM_FSM_STATE,0xa0); -+ if(state->symbol_rate>4500000) // 45000000 -+ { -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ } -+ else if(state->symbol_rate>2500000) // 25000000 -+ { -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1); -+ } -+ else -+ { -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1); -+ } -+ writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7); -+ writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x85); -+ writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7); -+ break; -+ default: -+ stat = -EINVAL; -+ break; -+ } -+ return stat; -+} -+ -+ -+static int QAM_SetSymbolRate(struct stv_state *state) -+{ -+ int status = 0; -+ u32 sr = state->symbol_rate; -+ u32 Corr = 0; -+ u32 Temp, Temp1, AdpClk; -+ -+ switch(state->modulation) { -+ default: -+ case QAM_16: Corr = 1032; break; -+ case QAM_32: Corr = 954; break; -+ case QAM_64: Corr = 983; break; -+ case QAM_128: Corr = 957; break; -+ case QAM_256: Corr = 948; break; -+ } -+ -+ // Transfer ration -+ Temp = (256*sr) / state->adc_clock; -+ writereg(state, R367_QAM_EQU_CRL_TFR,(Temp)); -+ -+ /* Symbol rate and SRC gain calculation */ -+ AdpClk = (state->master_clock)/2000; /* TRL works at half the system clock */ -+ -+ Temp = state->symbol_rate; -+ Temp1 = sr; -+ -+ if(sr < 2097152) /* 2097152 = 2^21 */ -+ { -+ Temp = ((((sr * 2048) / AdpClk) * 16384 ) / 125 ) * 8; -+ Temp1 = (((((sr * 2048) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 10000000; -+ } -+ else if(sr < 4194304) /* 4194304 = 2**22 */ -+ { -+ Temp = ((((sr * 1024) / AdpClk) * 16384 ) / 125 ) * 16; -+ Temp1 = (((((sr * 1024) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 5000000; -+ } -+ else if(sr < 8388608) /* 8388608 = 2**23 */ -+ { -+ Temp = ((((sr * 512) / AdpClk) * 16384 ) / 125 ) * 32; -+ Temp1 = (((((sr * 512) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 2500000; -+ } -+ else -+ { -+ Temp = ((((sr * 256) / AdpClk) * 16384 ) / 125 ) * 64; -+ Temp1 = (((((sr * 256) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 1250000; -+ } -+ -+ ///* Filters' coefficients are calculated and written into registers only if the filters are enabled */ -+ //if (ChipGetField(hChip,F367qam_ADJ_EN)) // Is disabled from init! -+ //{ -+ // FE_367qam_SetIirAdjacentcoefficient(hChip, MasterClk_Hz, SymbolRate); -+ //} -+ ///* AllPass filter is never used on this IC */ -+ //ChipSetField(hChip,F367qam_ALLPASSFILT_EN,0); // should be disabled from init! -+ -+ writereg(state, R367_QAM_SRC_NCO_LL,(Temp)); -+ writereg(state, R367_QAM_SRC_NCO_LH,(Temp>>8)); -+ writereg(state, R367_QAM_SRC_NCO_HL,(Temp>>16)); -+ writereg(state, R367_QAM_SRC_NCO_HH,(Temp>>24)); -+ -+ writereg(state, R367_QAM_IQDEM_GAIN_SRC_L,(Temp1)); -+ writereg(state, R367_QAM_IQDEM_GAIN_SRC_H,(Temp1>>8)); -+ return status; -+} -+ -+ -+static int QAM_SetDerotFrequency(struct stv_state *state, u32 DerotFrequency) -+{ -+ int status = 0; -+ u32 Sampled_IF; -+ -+ do { -+ //if (DerotFrequency < 1000000) -+ // DerotFrequency = state->adc_clock/4; /* ZIF operation */ -+ if (DerotFrequency > state->adc_clock) -+ DerotFrequency = DerotFrequency - state->adc_clock; // User Alias -+ -+ Sampled_IF = ((32768 * (DerotFrequency/1000)) / (state->adc_clock/1000)) * 256; -+ if(Sampled_IF > 8388607) -+ Sampled_IF = 8388607; -+ -+ writereg(state, R367_QAM_MIX_NCO_LL, (Sampled_IF)); -+ writereg(state, R367_QAM_MIX_NCO_HL, (Sampled_IF>>8)); -+ writereg(state, R367_QAM_MIX_NCO_HH, (Sampled_IF>>16)); -+ } while(0); -+ -+ return status; -+} -+ -+ -+ -+static int QAM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency) -+{ -+ int status = 0; -+ u32 AGCTimeOut = 25; -+ u32 TRLTimeOut = 100000000 / state->symbol_rate; -+ u32 CRLSymbols = 0; -+ u32 EQLTimeOut = 100; -+ u32 SearchRange = state->symbol_rate / 25; -+ u32 CRLTimeOut; -+ u8 Temp; -+ -+ if( state->demod_state != QAMSet ) { -+ writereg(state, R367_DEBUG_LT4,0x00); -+ writereg(state, R367_DEBUG_LT5,0x01); -+ writereg(state, R367_DEBUG_LT6,0x06);// R367_QAM_CTRL_1 -+ writereg(state, R367_DEBUG_LT7,0x03);// R367_QAM_CTRL_2 -+ writereg(state, R367_DEBUG_LT8,0x00); -+ writereg(state, R367_DEBUG_LT9,0x00); -+ -+ // Tuner Setup -+ writereg(state, R367_ANADIGCTRL,0x8B); /* Buffer Q disabled, I Enabled, signed ADC */ -+ writereg(state, R367_DUAL_AD12,0x04); /* ADCQ disabled */ -+ -+ // Clock setup -+ writereg(state, R367_ANACTRL,0x0D); /* PLL bypassed and disabled */ -+ writereg(state, R367_TOPCTRL,0x10); // Set QAM -+ -+ writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLNDIV,232); -+ writereg(state, R367_PLLSETUP,0x18); /* ADC clock is equal to system clock */ -+ -+ msleep(50); -+ writereg(state, R367_ANACTRL,0x00); /* PLL enabled and used */ -+ -+ state->master_clock = 58000000; -+ state->adc_clock = 58000000; -+ -+ state->demod_state = QAMSet; -+ } -+ -+ state->m_bFirstTimeLock = true; -+ state->m_DemodLockTime = -1; -+ -+ qam_set_modulation(state); -+ QAM_SetSymbolRate(state); -+ -+ // Will make problems on low symbol rates ( < 2500000 ) -+ -+ switch(state->modulation) { -+ default: -+ case QAM_16: CRLSymbols = 150000; break; -+ case QAM_32: CRLSymbols = 250000; break; -+ case QAM_64: CRLSymbols = 200000; break; -+ case QAM_128: CRLSymbols = 250000; break; -+ case QAM_256: CRLSymbols = 250000; break; -+ } -+ -+ CRLTimeOut = (25 * CRLSymbols * (SearchRange/1000)) / (state->symbol_rate/1000); -+ CRLTimeOut = (1000 * CRLTimeOut) / state->symbol_rate; -+ if( CRLTimeOut < 50 ) CRLTimeOut = 50; -+ -+ state->m_FECTimeOut = 20; -+ state->m_DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut; -+ state->m_SignalTimeOut = AGCTimeOut + TRLTimeOut; -+ -+ // QAM_AGC_ACCUMRSTSEL = 0; -+ readreg(state, R367_QAM_AGC_CTL,&state->m_Save_QAM_AGC_CTL); -+ writereg(state, R367_QAM_AGC_CTL,state->m_Save_QAM_AGC_CTL & ~0x0F); -+ -+ // QAM_MODULUSMAP_EN = 0 -+ readreg(state, R367_QAM_EQU_PNT_GAIN,&Temp); -+ writereg(state, R367_QAM_EQU_PNT_GAIN,Temp & ~0x40); -+ -+ // QAM_SWEEP_EN = 0 -+ readreg(state, R367_QAM_EQU_CTR_LPF_GAIN,&Temp); -+ writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,Temp & ~0x08); -+ -+ QAM_SetDerotFrequency(state, IntermediateFrequency); -+ -+ // Release TRL -+ writereg(state, R367_QAM_CTRL_1,0x00); -+ -+ state->IF = IntermediateFrequency; -+ state->demod_state = QAMStarted; -+ -+ return status; -+} -+ -+static int OFDM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency) -+{ -+ int status = 0; -+ u8 GAIN_SRC1; -+ u32 Derot; -+ u8 SYR_CTL; -+ u8 tmp1; -+ u8 tmp2; -+ -+ if ( state->demod_state != OFDMSet ) { -+ // QAM Disable -+ writereg(state, R367_DEBUG_LT4, 0x00); -+ writereg(state, R367_DEBUG_LT5, 0x00); -+ writereg(state, R367_DEBUG_LT6, 0x00);// R367_QAM_CTRL_1 -+ writereg(state, R367_DEBUG_LT7, 0x00);// R367_QAM_CTRL_2 -+ writereg(state, R367_DEBUG_LT8, 0x00); -+ writereg(state, R367_DEBUG_LT9, 0x00); -+ -+ // Tuner Setup -+ writereg(state, R367_ANADIGCTRL, 0x89); /* Buffer Q disabled, I Enabled, unsigned ADC */ -+ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ -+ -+ // Clock setup -+ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ -+ writereg(state, R367_TOPCTRL, 0x00); // Set OFDM -+ -+ writereg(state, R367_PLLMDIV, 1); /* IC runs at 54 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLNDIV, 8); -+ writereg(state, R367_PLLSETUP, 0x18); /* ADC clock is equal to system clock */ -+ -+ msleep(50); -+ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ -+ -+ state->master_clock = 54000000; -+ state->adc_clock = 54000000; -+ -+ state->demod_state = OFDMSet; -+ } -+ -+ state->m_bFirstTimeLock = true; -+ state->m_DemodLockTime = -1; -+ -+ // Set inversion in GAIN_SRC1 (fixed from init) -+ // is in GAIN_SRC1, see below -+ -+ GAIN_SRC1 = 0xA0; -+ // Bandwidth -+ -+ // Fixed values for 54 MHz -+ switch(state->bandwidth) { -+ case 0: -+ case 8000000: -+ // Normrate = 44384; -+ writereg(state, R367_OFDM_TRL_CTL,0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1,0xB0); -+ writereg(state, R367_OFDM_TRL_NOMRATE2,0x56); -+ // Gain SRC = 2774 -+ writereg(state, R367_OFDM_GAIN_SRC1,0x0A | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2,0xD6); -+ break; -+ case 7000000: -+ // Normrate = 38836; -+ writereg(state, R367_OFDM_TRL_CTL,0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1,0xDA); -+ writereg(state, R367_OFDM_TRL_NOMRATE2,0x4B); -+ // Gain SRC = 2427 -+ writereg(state, R367_OFDM_GAIN_SRC1,0x09 | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2,0x7B); -+ break; -+ case 6000000: -+ // Normrate = 33288; -+ writereg(state, R367_OFDM_TRL_CTL,0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1,0x04); -+ writereg(state, R367_OFDM_TRL_NOMRATE2,0x41); -+ // Gain SRC = 2080 -+ writereg(state, R367_OFDM_GAIN_SRC1,0x08 | GAIN_SRC1); -+ writereg(state, R367_OFDM_GAIN_SRC2,0x20); -+ break; -+ default: -+ return -EINVAL; -+ break; -+ } -+ -+ Derot = ((IntermediateFrequency/1000) * 65536) / (state->master_clock / 1000); -+ -+ writereg(state, R367_OFDM_INC_DEROT1,(Derot>>8)); -+ writereg(state, R367_OFDM_INC_DEROT2,(Derot)); -+ -+ readreg(state, R367_OFDM_SYR_CTL,&SYR_CTL); -+ SYR_CTL &= ~0x78; -+ writereg(state, R367_OFDM_SYR_CTL,SYR_CTL); // EchoPos = 0 -+ -+ -+ writereg(state, R367_OFDM_COR_MODEGUARD,0x03); // Force = 0, Mode = 0, Guard = 3 -+ SYR_CTL &= 0x01; -+ writereg(state, R367_OFDM_SYR_CTL,SYR_CTL); // SYR_TR_DIS = 0 -+ -+ msleep(5); -+ -+ writereg(state, R367_OFDM_COR_CTL,0x20); // Start core -+ -+ // -- Begin M.V. -+ // Reset FEC and Read Solomon -+ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); -+ readreg(state, R367_TSGENERAL,&tmp2); -+ writereg(state, R367_OFDM_SFDLYSETH,tmp1 | 0x08); -+ writereg(state, R367_TSGENERAL,tmp2 | 0x01); -+ // -- End M.V. -+ -+ state->m_SignalTimeOut = 200; -+ state->IF = IntermediateFrequency; -+ state->demod_state = OFDMStarted; -+ state->m_DemodTimeOut = 0; -+ state->m_FECTimeOut = 0; -+ state->m_TSTimeOut = 0; -+ -+ return status; -+} -+ -+#if 0 -+static int Stop(struct stv_state *state) -+{ -+ int status = 0; -+ -+ switch(state->demod_state) -+ { -+ case QAMStarted: -+ status = writereg(state, R367_QAM_CTRL_1,0x06); -+ state->demod_state = QAMSet; -+ break; -+ case OFDMStarted: -+ status = writereg(state, R367_OFDM_COR_CTL,0x00); -+ state->demod_state = OFDMSet; -+ break; -+ default: -+ break; -+ } -+ return status; -+} -+#endif -+ -+static s32 Log10x100(u32 x) -+{ -+ static u32 LookupTable[100] = { -+ 101157945, 103514217, 105925373, 108392691, 110917482, -+ 113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5 -+ 127350308, 130316678, 133352143, 136458314, 139636836, -+ 142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5 -+ 160324539, 164058977, 167880402, 171790839, 175792361, -+ 179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5 -+ 201836636, 206538016, 211348904, 216271852, 221309471, -+ 226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5 -+ 254097271, 260015956, 266072506, 272270131, 278612117, -+ 285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5 -+ 319889511, 327340695, 334965439, 342767787, 350751874, -+ 358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5 -+ 402717034, 412097519, 421696503, 431519077, 441570447, -+ 451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5 -+ 506990708, 518800039, 530884444, 543250331, 555904257, -+ 568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5 -+ 638263486, 653130553, 668343918, 683911647, 699841996, -+ 716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5 -+ 803526122, 822242650, 841395142, 860993752, 881048873, -+ 901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5 -+ }; -+ s32 y; -+ int i; -+ -+ if (x == 0) -+ return 0; -+ y = 800; -+ if (x >= 1000000000) { -+ x /= 10; -+ y += 100; -+ } -+ -+ while (x < 100000000) { -+ x *= 10; -+ y -= 100; -+ } -+ i = 0; -+ while (i < 100 && x > LookupTable[i]) -+ i += 1; -+ y += i; -+ return y; -+} -+ -+static int QAM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise) -+{ -+ u32 RegValAvg = 0; -+ u8 RegVal[2]; -+ int status = 0, i; -+ -+ *pSignalToNoise = 0; -+ for (i = 0; i < 10; i += 1 ) { -+ readregs(state, R367_QAM_EQU_SNR_LO, RegVal, 2); -+ RegValAvg += RegVal[0] + 256 * RegVal[1]; -+ } -+ if (RegValAvg != 0) { -+ s32 Power = 1; -+ switch(state->modulation) { -+ case QAM_16: -+ Power = 20480; -+ break; -+ case QAM_32: -+ Power = 23040; -+ break; -+ case QAM_64: -+ Power = 21504; -+ break; -+ case QAM_128: -+ Power = 23616; break; -+ case QAM_256: -+ Power = 21760; break; -+ default: -+ break; -+ } -+ *pSignalToNoise = Log10x100((Power * 320) / RegValAvg); -+ } else { -+ *pSignalToNoise = 380; -+ } -+ return status; -+} -+ -+static int OFDM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise) -+{ -+ u8 CHC_SNR = 0; -+ -+ int status = readreg(state, R367_OFDM_CHC_SNR, &CHC_SNR); -+ if (status >= 0) { -+ // Note: very unclear documentation on this. -+ // Datasheet states snr = CHC_SNR/4 dB -> way to high values! -+ // Software snr = ( 1000 * CHC_SNR ) / 8 / 32 / 10; -> to low values -+ // Comment in SW states this should be ( 1000 * CHC_SNR ) / 4 / 32 / 10; for the 367 -+ // 361/362 Datasheet: snr = CHC_SNR/8 dB -> this looks best -+ *pSignalToNoise = ( (s32)CHC_SNR * 10) / 8; -+ } -+ //printk("SNR %d\n", *pSignalToNoise); -+ return status; -+} -+ -+#if 0 -+static int DVBC_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) -+{ -+ *pQuality = 100; -+ return 0; -+}; -+ -+static int DVBT_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) -+{ -+ static s32 QE_SN[] = { -+ 51, // QPSK 1/2 -+ 69, // QPSK 2/3 -+ 79, // QPSK 3/4 -+ 89, // QPSK 5/6 -+ 97, // QPSK 7/8 -+ 108, // 16-QAM 1/2 -+ 131, // 16-QAM 2/3 -+ 146, // 16-QAM 3/4 -+ 156, // 16-QAM 5/6 -+ 160, // 16-QAM 7/8 -+ 165, // 64-QAM 1/2 -+ 187, // 64-QAM 2/3 -+ 202, // 64-QAM 3/4 -+ 216, // 64-QAM 5/6 -+ 225, // 64-QAM 7/8 -+ }; -+ u8 TPS_Received[2]; -+ int Constellation; -+ int CodeRate; -+ s32 SignalToNoiseRel, BERQuality; -+ -+ *pQuality = 0; -+ readregs(state, R367_OFDM_TPS_RCVD2, TPS_Received, sizeof(TPS_Received)); -+ Constellation = TPS_Received[0] & 0x03; -+ CodeRate = TPS_Received[1] & 0x07; -+ -+ if( Constellation > 2 || CodeRate > 5 ) -+ return -1; -+ SignalToNoiseRel = SignalToNoise - QE_SN[Constellation * 5 + CodeRate]; -+ BERQuality = 100; -+ -+ if( SignalToNoiseRel < -70 ) -+ *pQuality = 0; -+ else if( SignalToNoiseRel < 30 ) { -+ *pQuality = ((SignalToNoiseRel + 70) * BERQuality)/100; -+ } else -+ *pQuality = BERQuality; -+ return 0; -+}; -+ -+static s32 DVBCQuality(struct stv_state *state, s32 SignalToNoise) -+{ -+ s32 SignalToNoiseRel = 0; -+ s32 Quality = 0; -+ s32 BERQuality = 100; -+ -+ switch(state->modulation) { -+ case QAM_16: SignalToNoiseRel = SignalToNoise - 200 ; break; -+ case QAM_32: SignalToNoiseRel = SignalToNoise - 230 ; break; // Not in NorDig -+ case QAM_64: SignalToNoiseRel = SignalToNoise - 260 ; break; -+ case QAM_128: SignalToNoiseRel = SignalToNoise - 290 ; break; -+ case QAM_256: SignalToNoiseRel = SignalToNoise - 320 ; break; -+ } -+ -+ if( SignalToNoiseRel < -70 ) Quality = 0; -+ else if( SignalToNoiseRel < 30 ) -+ { -+ Quality = ((SignalToNoiseRel + 70) * BERQuality)/100; -+ } -+ else -+ Quality = BERQuality; -+ -+ return Quality; -+} -+ -+static int GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality) -+{ -+ *pQuality = 0; -+ switch(state->demod_state) -+ { -+ case QAMStarted: -+ *pQuality = DVBCQuality(state, SignalToNoise); -+ break; -+ case OFDMStarted: -+ return DVBT_GetQuality(state, SignalToNoise, pQuality); -+ } -+ return 0; -+}; -+#endif -+ -+static int attach_init(struct stv_state *state) -+{ -+ int stat = 0; -+ -+ stat = readreg(state, R367_ID, &state->ID); -+ if ( stat < 0 || state->ID != 0x60 ) -+ return -ENODEV; -+ printk("stv0367 found\n"); -+ -+ writereg(state, R367_TOPCTRL, 0x10); -+ write_init_table(state, base_init); -+ write_init_table(state, qam_init); -+ -+ writereg(state, R367_TOPCTRL, 0x00); -+ write_init_table(state, ofdm_init); -+ -+ writereg(state, R367_OFDM_GAIN_SRC1, 0x2A); -+ writereg(state, R367_OFDM_GAIN_SRC2, 0xD6); -+ writereg(state, R367_OFDM_INC_DEROT1, 0x55); -+ writereg(state, R367_OFDM_INC_DEROT2, 0x55); -+ writereg(state, R367_OFDM_TRL_CTL, 0x14); -+ writereg(state, R367_OFDM_TRL_NOMRATE1, 0xAE); -+ writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56); -+ writereg(state, R367_OFDM_FEPATH_CFG, 0x0); -+ -+ // OFDM TS Setup -+ -+ writereg(state, R367_OFDM_TSCFGH, 0x70); -+ writereg(state, R367_OFDM_TSCFGM, 0xC0); -+ writereg(state, R367_OFDM_TSCFGL, 0x20); -+ writereg(state, R367_OFDM_TSSPEED, 0x40); // Fixed at 54 MHz -+ //writereg(state, R367_TSTBUS, 0x80); // Invert CLK -+ -+ writereg(state, R367_OFDM_TSCFGH, 0x71); -+ writereg(state, R367_OFDM_TSCFGH, 0x70); -+ -+ writereg(state, R367_TOPCTRL, 0x10); -+ -+ // Also needed for QAM -+ writereg(state, R367_OFDM_AGC12C, 0x01); // AGC Pin setup -+ -+ writereg(state, R367_OFDM_AGCCTRL1, 0x8A); // -+ -+ // QAM TS setup, note exact format also depends on descrambler settings -+ writereg(state, R367_QAM_OUTFORMAT_0, 0x85); // Inverted Clock, Swap, serial -+ // writereg(state, R367_QAM_OUTFORMAT_1, 0x00); // -+ -+ // Clock setup -+ writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */ -+ -+ if( state->master_clock == 58000000 ) { -+ writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLNDIV,232); -+ } else { -+ writereg(state, R367_PLLMDIV,1); /* IC runs at 54 MHz with a 27 MHz crystal */ -+ writereg(state, R367_PLLNDIV,8); -+ } -+ writereg(state, R367_PLLSETUP, 0x18); /* ADC clock is equal to system clock */ -+ -+ // Tuner setup -+ writereg(state, R367_ANADIGCTRL, 0x8b); /* Buffer Q disabled, I Enabled, signed ADC */ -+ writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */ -+ -+ writereg(state, R367_QAM_FSM_SNR2_HTH, 0x23); /* Improves the C/N lock limit */ -+ writereg(state, R367_QAM_IQ_QAM, 0x01); /* ZIF/IF Automatic mode */ -+ writereg(state, R367_QAM_EQU_FFE_LEAKAGE, 0x83); /* Improving burst noise performances */ -+ writereg(state, R367_QAM_IQDEM_ADJ_EN, 0x05); /* Improving ACI performances */ -+ -+ writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */ -+ -+ writereg(state, R367_I2CRPT, state->I2CRPT); -+ state->demod_state = QAMSet; -+ return stat; -+} -+ -+#ifdef USE_API3 -+static void c_release(struct dvb_frontend* fe) -+#else -+static void release(struct dvb_frontend* fe) -+#endif -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ printk("%s\n", __FUNCTION__); -+ kfree(state); -+} -+ -+#ifdef USE_API3 -+static int c_init (struct dvb_frontend *fe) -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ -+ if (mutex_trylock(&state->ctlock)==0) -+ return -EBUSY; -+ state->omode = OM_DVBC; -+ return 0; -+} -+ -+static int c_sleep(struct dvb_frontend* fe) -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ -+ mutex_unlock(&state->ctlock); -+ return 0; -+} -+#endif -+ -+static int gate_ctrl(struct dvb_frontend* fe, int enable) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u8 i2crpt = state->I2CRPT & ~0x80; -+ -+ if (enable) -+ i2crpt |= 0x80; -+ if (writereg(state, R367_I2CRPT, i2crpt) < 0) -+ return -1; -+ state->I2CRPT = i2crpt; -+ return 0; -+} -+ -+#if 0 -+static int c_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -+{ -+ return DVBFE_ALGO_SEARCH_AGAIN; -+} -+#endif -+ -+#if 0 -+int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); -+int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); -+#endif -+ -+static int ofdm_lock(struct stv_state *state) -+{ -+ int status = 0; -+ u8 OFDM_Status; -+ s32 DemodTimeOut = 10; -+ s32 FECTimeOut = 0; -+ s32 TSTimeOut = 0; -+ u8 CPAMPMin = 255; -+ u8 CPAMPValue; -+ u8 SYR_STAT; -+ u8 FFTMode; -+ u8 TSStatus; -+ -+ msleep(state->m_SignalTimeOut); -+ readreg(state, R367_OFDM_STATUS,&OFDM_Status); -+ -+ if (!(OFDM_Status & 0x40)) -+ return -1; -+ //printk("lock 1\n"); -+ -+ readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); -+ FFTMode = (SYR_STAT & 0x0C) >> 2; -+ -+ switch(FFTMode) -+ { -+ case 0: // 2K -+ DemodTimeOut = 10; -+ FECTimeOut = 150; -+ TSTimeOut = 125; -+ CPAMPMin = 20; -+ break; -+ case 1: // 8K -+ DemodTimeOut = 55; -+ FECTimeOut = 600; -+ TSTimeOut = 500; -+ CPAMPMin = 80; -+ break; -+ case 2: // 4K -+ DemodTimeOut = 40; -+ FECTimeOut = 300; -+ TSTimeOut = 250; -+ CPAMPMin = 30; -+ break; -+ } -+ state->m_OFDM_FFTMode = FFTMode; -+ readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue); -+ msleep(DemodTimeOut); -+ { -+ // Release FEC and Read Solomon Reset -+ u8 tmp1; -+ u8 tmp2; -+ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); -+ readreg(state, R367_TSGENERAL,&tmp2); -+ writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08); -+ writereg(state, R367_TSGENERAL,tmp2 & ~0x01); -+ } -+ msleep(FECTimeOut); -+ if( (OFDM_Status & 0x98) != 0x98 ) -+ ;//return -1; -+ //printk("lock 2\n"); -+ -+ { -+ u8 Guard = (SYR_STAT & 0x03); -+ if(Guard < 2) -+ { -+ u8 tmp; -+ readreg(state, R367_OFDM_SYR_CTL,&tmp); -+ writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN -+ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); -+ writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER -+ } else { -+ u8 tmp; -+ readreg(state, R367_OFDM_SYR_CTL,&tmp); -+ writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN -+ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); -+ writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER -+ } -+ -+ // apply Sfec workaround if 8K 64QAM CR!=1/2 -+ if( FFTMode == 1) -+ { -+ u8 tmp[2]; -+ readregs(state, R367_OFDM_TPS_RCVD2, tmp, 2); -+ if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) ) -+ { -+ writereg(state, R367_OFDM_SFDLYSETH,0xc0); -+ writereg(state, R367_OFDM_SFDLYSETM,0x60); -+ writereg(state, R367_OFDM_SFDLYSETL,0x00); -+ } -+ else -+ { -+ writereg(state, R367_OFDM_SFDLYSETH,0x00); -+ } -+ } -+ } -+ msleep(TSTimeOut); -+ readreg(state, R367_OFDM_TSSTATUS,&TSStatus); -+ if( (TSStatus & 0x80) != 0x80 ) -+ return -1; -+ //printk("lock 3\n"); -+ return status; -+} -+ -+ -+ -+#ifdef USE_API3 -+static int set_parameters(struct dvb_frontend *fe, -+ struct dvb_frontend_parameters *p) -+{ -+ int stat; -+ struct stv_state *state = fe->demodulator_priv; -+ u32 OF = 0; -+ u32 IF; -+ -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe, p); -+ -+ switch (state->omode) { -+ case OM_DVBC: -+ case OM_QAM_ITU_C: -+ state->modulation = p->u.qam.modulation; -+ state->symbol_rate = p->u.qam.symbol_rate; -+ break; -+ case OM_DVBT: -+ switch (p->u.ofdm.bandwidth) { -+ case BANDWIDTH_AUTO: -+ case BANDWIDTH_8_MHZ: -+ state->bandwidth = 8000000; -+ break; -+ case BANDWIDTH_7_MHZ: -+ state->bandwidth = 7000000; -+ break; -+ case BANDWIDTH_6_MHZ: -+ state->bandwidth = 6000000; -+ break; -+ default: -+ return -EINVAL; -+ } -+ break; -+ default: -+ return -EINVAL; -+ } -+#else -+static int set_parameters(struct dvb_frontend *fe) -+{ -+ int stat; -+ struct stv_state *state = fe->demodulator_priv; -+ u32 OF = 0; -+ u32 IF; -+ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ state->omode = OM_DVBC; -+ /* symbol rate 0 might cause an oops */ -+ if (fe->dtv_property_cache.symbol_rate == 0) { -+ printk(KERN_ERR "stv0367dd: Invalid symbol rate\n"); -+ return -EINVAL; -+ } -+ break; -+ case SYS_DVBT: -+ state->omode = OM_DVBT; -+ break; -+ default: -+ return -EINVAL; -+ } -+ if (fe->ops.tuner_ops.set_params) -+ fe->ops.tuner_ops.set_params(fe); -+ state->modulation = fe->dtv_property_cache.modulation; -+ state->symbol_rate = fe->dtv_property_cache.symbol_rate; -+ state->bandwidth = fe->dtv_property_cache.bandwidth_hz; -+#endif -+ fe->ops.tuner_ops.get_if_frequency(fe, &IF); -+ //fe->ops.tuner_ops.get_frequency(fe, &IF); -+ -+ switch(state->omode) { -+ case OM_DVBT: -+ stat = OFDM_Start(state, OF, IF); -+ ofdm_lock(state); -+ break; -+ case OM_DVBC: -+ case OM_QAM_ITU_C: -+ stat = QAM_Start(state, OF, IF); -+ break; -+ default: -+ stat = -EINVAL; -+ } -+ //printk("%s IF=%d OF=%d done\n", __FUNCTION__, IF, OF); -+ return stat; -+} -+ -+#if 0 -+static int c_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -+{ -+ //struct stv_state *state = fe->demodulator_priv; -+ //printk("%s\n", __FUNCTION__); -+ return 0; -+} -+ -+static int OFDM_GetLockStatus(struct stv_state *state, LOCK_STATUS* pLockStatus, s32 Time) -+{ -+ int status = STATUS_SUCCESS; -+ u8 OFDM_Status; -+ s32 DemodTimeOut = 0; -+ s32 FECTimeOut = 0; -+ s32 TSTimeOut = 0; -+ u8 CPAMPMin = 255; -+ u8 CPAMPValue; -+ bool SYRLock; -+ u8 SYR_STAT; -+ u8 FFTMode; -+ u8 TSStatus; -+ -+ readreg(state, R367_OFDM_STATUS,&OFDM_Status); -+ -+ SYRLock = (OFDM_Status & 0x40) != 0; -+ -+ if( Time > m_SignalTimeOut && !SYRLock ) -+ { -+ *pLockStatus = NEVER_LOCK; -+ break; -+ } -+ -+ if( !SYRLock ) break; -+ -+ *pLockStatus = SIGNAL_PRESENT; -+ -+ // Check Mode -+ -+ readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT); -+ FFTMode = (SYR_STAT & 0x0C) >> 2; -+ -+ switch(FFTMode) -+ { -+ case 0: // 2K -+ DemodTimeOut = 10; -+ FECTimeOut = 150; -+ TSTimeOut = 125; -+ CPAMPMin = 20; -+ break; -+ case 1: // 8K -+ DemodTimeOut = 55; -+ FECTimeOut = 600; -+ TSTimeOut = 500; -+ CPAMPMin = 80; -+ break; -+ case 2: // 4K -+ DemodTimeOut = 40; -+ FECTimeOut = 300; -+ TSTimeOut = 250; -+ CPAMPMin = 30; -+ break; -+ } -+ -+ m_OFDM_FFTMode = FFTMode; -+ -+ if( m_DemodTimeOut == 0 && m_bFirstTimeLock ) -+ { -+ m_DemodTimeOut = Time + DemodTimeOut; -+ //break; -+ } -+ -+ readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue); -+ -+ if( Time <= m_DemodTimeOut && CPAMPValue < CPAMPMin ) -+ { -+ break; -+ } -+ -+ if( CPAMPValue < CPAMPMin && m_bFirstTimeLock ) -+ { -+ // initiate retry -+ *pLockStatus = NEVER_LOCK; -+ break; -+ } -+ -+ if( CPAMPValue < CPAMPMin ) break; -+ -+ *pLockStatus = DEMOD_LOCK; -+ -+ if( m_FECTimeOut == 0 && m_bFirstTimeLock ) -+ { -+ // Release FEC and Read Solomon Reset -+ u8 tmp1; -+ u8 tmp2; -+ readreg(state, R367_OFDM_SFDLYSETH,&tmp1); -+ readreg(state, R367_TSGENERAL,&tmp2); -+ writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08); -+ writereg(state, R367_TSGENERAL,tmp2 & ~0x01); -+ -+ m_FECTimeOut = Time + FECTimeOut; -+ } -+ -+ // Wait for TSP_LOCK, LK, PRF -+ if( (OFDM_Status & 0x98) != 0x98 ) -+ { -+ if( Time > m_FECTimeOut ) *pLockStatus = NEVER_LOCK; -+ break; -+ } -+ -+ if( m_bFirstTimeLock && m_TSTimeOut == 0) -+ { -+ u8 Guard = (SYR_STAT & 0x03); -+ if(Guard < 2) -+ { -+ u8 tmp; -+ readreg(state, R367_OFDM_SYR_CTL,&tmp); -+ writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN -+ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); -+ writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER -+ } else { -+ u8 tmp; -+ readreg(state, R367_OFDM_SYR_CTL,&tmp); -+ writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN -+ readreg(state, R367_OFDM_SYR_UPDATE,&tmp); -+ writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER -+ } -+ -+ // apply Sfec workaround if 8K 64QAM CR!=1/2 -+ if( FFTMode == 1) -+ { -+ u8 tmp[2]; -+ readreg(state, R367_OFDM_TPS_RCVD2,tmp,2); -+ if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) ) -+ { -+ writereg(state, R367_OFDM_SFDLYSETH,0xc0); -+ writereg(state, R367_OFDM_SFDLYSETM,0x60); -+ writereg(state, R367_OFDM_SFDLYSETL,0x00); -+ } -+ else -+ { -+ writereg(state, R367_OFDM_SFDLYSETH,0x00); -+ } -+ } -+ -+ m_TSTimeOut = Time + TSTimeOut; -+ } -+ readreg(state, R367_OFDM_TSSTATUS,&TSStatus); -+ if( (TSStatus & 0x80) != 0x80 ) -+ { -+ if( Time > m_TSTimeOut ) *pLockStatus = NEVER_LOCK; -+ break; -+ } -+ *pLockStatus = MPEG_LOCK; -+ m_bFirstTimeLock = false; -+ return status; -+} -+ -+#endif -+ -+static int read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ *status=0; -+ -+ switch(state->demod_state) { -+ case QAMStarted: -+ { -+ u8 FEC_Lock; -+ u8 QAM_Lock; -+ -+ readreg(state, R367_QAM_FSM_STS, &QAM_Lock); -+ QAM_Lock &= 0x0F; -+ if (QAM_Lock >10) -+ *status|=0x07; -+ readreg(state, R367_QAM_FEC_STATUS,&FEC_Lock); -+ if (FEC_Lock&2) -+ *status|=0x1f; -+ if (state->m_bFirstTimeLock) { -+ state->m_bFirstTimeLock = false; -+ // QAM_AGC_ACCUMRSTSEL to Tracking; -+ writereg(state, R367_QAM_AGC_CTL, state->m_Save_QAM_AGC_CTL); -+ } -+ break; -+ } -+ case OFDMStarted: -+ { -+ u8 OFDM_Status; -+ u8 TSStatus; -+ -+ readreg(state, R367_OFDM_TSSTATUS, &TSStatus); -+ -+ readreg(state, R367_OFDM_STATUS, &OFDM_Status); -+ if (OFDM_Status & 0x40) -+ *status |= FE_HAS_SIGNAL; -+ -+ if ((OFDM_Status & 0x98) == 0x98) -+ *status|=0x0f; -+ -+ if (TSStatus & 0x80) -+ *status |= 0x1f; -+ break; -+ } -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static int read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ //struct stv_state *state = fe->demodulator_priv; -+ *ber=0; -+ return 0; -+} -+ -+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength) -+{ -+ if (fe->ops.tuner_ops.get_rf_strength) -+ fe->ops.tuner_ops.get_rf_strength(fe, strength); -+ else -+ *strength = 0; -+ return 0; -+} -+ -+static int read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ s32 snr2 = 0; -+ -+ switch(state->demod_state) { -+ case QAMStarted: -+ QAM_GetSignalToNoise(state, &snr2); -+ break; -+ case OFDMStarted: -+ OFDM_GetSignalToNoise(state, &snr2); -+ break; -+ default: -+ break; -+ } -+ *snr = snr2&0xffff; -+ return 0; -+} -+ -+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) -+{ -+ struct stv_state *state = fe->demodulator_priv; -+ u8 errl, errm, errh; -+ u8 val; -+ -+ switch(state->demod_state) { -+ case QAMStarted: -+ readreg(state, R367_QAM_RS_COUNTER_4, &errl); -+ readreg(state, R367_QAM_RS_COUNTER_5, &errm); -+ *ucblocks = (errm << 8) | errl; -+ break; -+ case OFDMStarted: -+ readreg(state, R367_OFDM_SFERRCNTH, &val); -+ if ((val & 0x80) == 0) { -+ readreg(state, R367_OFDM_ERRCNT1H, &errh); -+ readreg(state, R367_OFDM_ERRCNT1M, &errl); -+ readreg(state, R367_OFDM_ERRCNT1L, &errm); -+ state->ucblocks = (errh <<16) | (errm << 8) | errl; -+ } -+ *ucblocks = state->ucblocks; -+ break; -+ default: -+ *ucblocks = 0; -+ break; -+ } -+ return 0; -+} -+ -+static int c_get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *sets) -+{ -+ sets->min_delay_ms=3000; -+ sets->max_drift=0; -+ sets->step_size=0; -+ return 0; -+} -+ -+#ifndef USE_API3 -+static int get_tune_settings(struct dvb_frontend *fe, -+ struct dvb_frontend_tune_settings *sets) -+{ -+ switch (fe->dtv_property_cache.delivery_system) { -+ case SYS_DVBC_ANNEX_A: -+ case SYS_DVBC_ANNEX_C: -+ return c_get_tune_settings(fe, sets); -+ default: -+ /* DVB-T: Use info.frequency_stepsize. */ -+ return -EINVAL; -+ } -+} -+#endif -+ -+#ifdef USE_API3 -+static void t_release(struct dvb_frontend* fe) -+{ -+ //struct stv_state *state=fe->demodulator_priv; -+ //printk("%s\n", __FUNCTION__); -+ //kfree(state); -+} -+ -+static int t_init (struct dvb_frontend *fe) -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ if (mutex_trylock(&state->ctlock)==0) -+ return -EBUSY; -+ state->omode = OM_DVBT; -+ return 0; -+} -+ -+static int t_sleep(struct dvb_frontend* fe) -+{ -+ struct stv_state *state=fe->demodulator_priv; -+ mutex_unlock(&state->ctlock); -+ return 0; -+} -+#endif -+ -+#if 0 -+static int t_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -+{ -+ //struct stv_state *state = fe->demodulator_priv; -+ //printk("%s\n", __FUNCTION__); -+ return 0; -+} -+ -+static enum dvbfe_algo algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_CUSTOM; -+} -+#endif -+ -+#ifdef USE_API3 -+static struct dvb_frontend_ops c_ops = { -+ .info = { -+ .name = "STV0367 DVB-C", -+ .type = FE_QAM, -+ .frequency_stepsize = 62500, -+ .frequency_min = 47000000, -+ .frequency_max = 862000000, -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO -+ }, -+ .release = c_release, -+ .init = c_init, -+ .sleep = c_sleep, -+ .i2c_gate_ctrl = gate_ctrl, -+ -+ .get_tune_settings = c_get_tune_settings, -+ -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+ -+#if 1 -+ .set_frontend = set_parameters, -+#else -+ .get_frontend_algo = algo, -+ .search = search, -+#endif -+}; -+ -+static struct dvb_frontend_ops t_ops = { -+ .info = { -+ .name = "STV0367 DVB-T", -+ .type = FE_OFDM, -+ .frequency_min = 47125000, -+ .frequency_max = 865000000, -+ .frequency_stepsize = 166667, -+ .frequency_tolerance = 0, -+ .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | -+ FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | -+ FE_CAN_FEC_AUTO | -+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | -+ FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | -+ FE_CAN_MUTE_TS -+ }, -+ .release = t_release, -+ .init = t_init, -+ .sleep = t_sleep, -+ .i2c_gate_ctrl = gate_ctrl, -+ -+ .set_frontend = set_parameters, -+ -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+}; -+ -+#else -+ -+static struct dvb_frontend_ops common_ops = { -+ .delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT }, -+ .info = { -+ .name = "STV0367 DVB-C DVB-T", -+ .frequency_stepsize = 166667, /* DVB-T only */ -+ .frequency_min = 47000000, /* DVB-T: 47125000 */ -+ .frequency_max = 865000000, /* DVB-C: 862000000 */ -+ .symbol_rate_min = 870000, -+ .symbol_rate_max = 11700000, -+ .caps = /* DVB-C */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | -+ FE_CAN_QAM_128 | FE_CAN_QAM_256 | -+ FE_CAN_FEC_AUTO | -+ /* DVB-T */ -+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | -+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | -+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | -+ FE_CAN_TRANSMISSION_MODE_AUTO | -+ FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO | -+ FE_CAN_RECOVER | FE_CAN_MUTE_TS -+ }, -+ .release = release, -+ .i2c_gate_ctrl = gate_ctrl, -+ -+ .get_tune_settings = get_tune_settings, -+ -+ .set_frontend = set_parameters, -+ -+ .read_status = read_status, -+ .read_ber = read_ber, -+ .read_signal_strength = read_signal_strength, -+ .read_snr = read_snr, -+ .read_ucblocks = read_ucblocks, -+}; -+#endif -+ -+ -+static void init_state(struct stv_state *state, struct stv0367_cfg *cfg) -+{ -+ u32 ulENARPTLEVEL = 5; -+ u32 ulQAMInversion = 2; -+ state->omode = OM_NONE; -+ state->adr = cfg->adr; -+ -+ mutex_init(&state->mutex); -+ mutex_init(&state->ctlock); -+ -+#ifdef USE_API3 -+ memcpy(&state->c_frontend.ops, &c_ops, sizeof(struct dvb_frontend_ops)); -+ memcpy(&state->t_frontend.ops, &t_ops, sizeof(struct dvb_frontend_ops)); -+ state->c_frontend.demodulator_priv = state; -+ state->t_frontend.demodulator_priv = state; -+#else -+ memcpy(&state->frontend.ops, &common_ops, sizeof(struct dvb_frontend_ops)); -+ state->frontend.demodulator_priv = state; -+#endif -+ -+ state->master_clock = 58000000; -+ state->adc_clock = 58000000; -+ state->I2CRPT = 0x08 | ((ulENARPTLEVEL & 0x07) << 4); -+ state->qam_inversion = ((ulQAMInversion & 3) << 6 ); -+ state->demod_state = Off; -+} -+ -+ -+struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, struct stv0367_cfg *cfg, -+ struct dvb_frontend **fe_t) -+{ -+ struct stv_state *state = NULL; -+ -+ state = kzalloc(sizeof(struct stv_state), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ -+ state->i2c = i2c; -+ init_state(state, cfg); -+ -+ if (attach_init(state)<0) -+ goto error; -+#ifdef USE_API3 -+ *fe_t = &state->t_frontend; -+ return &state->c_frontend; -+#else -+ return &state->frontend; -+#endif -+ -+error: -+ printk("stv0367: not found\n"); -+ kfree(state); -+ return NULL; -+} -+ -+ -+MODULE_DESCRIPTION("STV0367DD driver"); -+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel"); -+MODULE_LICENSE("GPL"); -+ -+EXPORT_SYMBOL(stv0367_attach); -+ -+ -+ -diff --git a/drivers/media/dvb-frontends/stv0367dd.h b/drivers/media/dvb-frontends/stv0367dd.h -new file mode 100644 -index 0000000..665d4c8 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd.h -@@ -0,0 +1,17 @@ -+#ifndef _STV0367DD_H_ -+#define _STV0367DD_H_ -+ -+#include -+#include -+ -+struct stv0367_cfg { -+ u8 adr; -+ u32 xtal; -+ u32 ts_mode; -+}; -+ -+ -+extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, -+ struct stv0367_cfg *cfg, -+ struct dvb_frontend **fe_t); -+#endif -diff --git a/drivers/media/dvb-frontends/stv0367dd_regs.h b/drivers/media/dvb-frontends/stv0367dd_regs.h -new file mode 100644 -index 0000000..f33e787 ---- /dev/null -+++ b/drivers/media/dvb-frontends/stv0367dd_regs.h -@@ -0,0 +1,3431 @@ -+// @DVB-C/DVB-T STMicroelectronics STV0367 register defintions -+// Author Manfred Vlkel, Februar 2011 -+// (c) 2010 DigitalDevices GmbH Germany. All rights reserved -+ -+// $Id: DD_STV0367Register.h 357 2011-04-27 02:39:13Z manfred $ -+ -+/* ======================================================================= -+ -- Registers Declaration -+ -- ------------------------- -+ -- Each register (R367_XXXXX) is defined by its address (2 bytes). -+ -- -+ -- Each field (F367_XXXXX)is defined as follow: -+ -- [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte] -+ ======================================================================= */ -+ -+/* ID */ -+#define R367_ID 0xF000 -+#define F367_IDENTIFICATIONREG 0xF00000FF -+ -+/* I2CRPT */ -+#define R367_I2CRPT 0xF001 -+#define F367_I2CT_ON 0xF0010080 -+#define F367_ENARPT_LEVEL 0xF0010070 -+#define F367_SCLT_DELAY 0xF0010008 -+#define F367_SCLT_NOD 0xF0010004 -+#define F367_STOP_ENABLE 0xF0010002 -+#define F367_SDAT_NOD 0xF0010001 -+ -+/* TOPCTRL */ -+#define R367_TOPCTRL 0xF002 -+#define F367_STDBY 0xF0020080 -+#define F367_STDBY_FEC 0xF0020040 -+#define F367_STDBY_CORE 0xF0020020 -+#define F367_QAM_COFDM 0xF0020010 -+#define F367_TS_DIS 0xF0020008 -+#define F367_DIR_CLK_216 0xF0020004 -+#define F367_TUNER_BB 0xF0020002 -+#define F367_DVBT_H 0xF0020001 -+ -+/* IOCFG0 */ -+#define R367_IOCFG0 0xF003 -+#define F367_OP0_SD 0xF0030080 -+#define F367_OP0_VAL 0xF0030040 -+#define F367_OP0_OD 0xF0030020 -+#define F367_OP0_INV 0xF0030010 -+#define F367_OP0_DACVALUE_HI 0xF003000F -+ -+/* DAC0R */ -+#define R367_DAC0R 0xF004 -+#define F367_OP0_DACVALUE_LO 0xF00400FF -+ -+/* IOCFG1 */ -+#define R367_IOCFG1 0xF005 -+#define F367_IP0 0xF0050040 -+#define F367_OP1_OD 0xF0050020 -+#define F367_OP1_INV 0xF0050010 -+#define F367_OP1_DACVALUE_HI 0xF005000F -+ -+/* DAC1R */ -+#define R367_DAC1R 0xF006 -+#define F367_OP1_DACVALUE_LO 0xF00600FF -+ -+/* IOCFG2 */ -+#define R367_IOCFG2 0xF007 -+#define F367_OP2_LOCK_CONF 0xF00700E0 -+#define F367_OP2_OD 0xF0070010 -+#define F367_OP2_VAL 0xF0070008 -+#define F367_OP1_LOCK_CONF 0xF0070007 -+ -+/* SDFR */ -+#define R367_SDFR 0xF008 -+#define F367_OP0_FREQ 0xF00800F0 -+#define F367_OP1_FREQ 0xF008000F -+ -+/* STATUS */ -+#define R367_OFDM_STATUS 0xF009 -+#define F367_TPS_LOCK 0xF0090080 -+#define F367_SYR_LOCK 0xF0090040 -+#define F367_AGC_LOCK 0xF0090020 -+#define F367_PRF 0xF0090010 -+#define F367_LK 0xF0090008 -+#define F367_PR 0xF0090007 -+ -+/* AUX_CLK */ -+#define R367_AUX_CLK 0xF00A -+#define F367_AUXFEC_CTL 0xF00A00C0 -+#define F367_DIS_CKX4 0xF00A0020 -+#define F367_CKSEL 0xF00A0018 -+#define F367_CKDIV_PROG 0xF00A0006 -+#define F367_AUXCLK_ENA 0xF00A0001 -+ -+/* FREESYS1 */ -+#define R367_FREESYS1 0xF00B -+#define F367_FREE_SYS1 0xF00B00FF -+ -+/* FREESYS2 */ -+#define R367_FREESYS2 0xF00C -+#define F367_FREE_SYS2 0xF00C00FF -+ -+/* FREESYS3 */ -+#define R367_FREESYS3 0xF00D -+#define F367_FREE_SYS3 0xF00D00FF -+ -+/* GPIO_CFG */ -+#define R367_GPIO_CFG 0xF00E -+#define F367_GPIO7_NOD 0xF00E0080 -+#define F367_GPIO7_CFG 0xF00E0040 -+#define F367_GPIO6_NOD 0xF00E0020 -+#define F367_GPIO6_CFG 0xF00E0010 -+#define F367_GPIO5_NOD 0xF00E0008 -+#define F367_GPIO5_CFG 0xF00E0004 -+#define F367_GPIO4_NOD 0xF00E0002 -+#define F367_GPIO4_CFG 0xF00E0001 -+ -+/* GPIO_CMD */ -+#define R367_GPIO_CMD 0xF00F -+#define F367_GPIO7_VAL 0xF00F0008 -+#define F367_GPIO6_VAL 0xF00F0004 -+#define F367_GPIO5_VAL 0xF00F0002 -+#define F367_GPIO4_VAL 0xF00F0001 -+ -+/* AGC2MAX */ -+#define R367_OFDM_AGC2MAX 0xF010 -+#define F367_OFDM_AGC2_MAX 0xF01000FF -+ -+/* AGC2MIN */ -+#define R367_OFDM_AGC2MIN 0xF011 -+#define F367_OFDM_AGC2_MIN 0xF01100FF -+ -+/* AGC1MAX */ -+#define R367_OFDM_AGC1MAX 0xF012 -+#define F367_OFDM_AGC1_MAX 0xF01200FF -+ -+/* AGC1MIN */ -+#define R367_OFDM_AGC1MIN 0xF013 -+#define F367_OFDM_AGC1_MIN 0xF01300FF -+ -+/* AGCR */ -+#define R367_OFDM_AGCR 0xF014 -+#define F367_OFDM_RATIO_A 0xF01400E0 -+#define F367_OFDM_RATIO_B 0xF0140018 -+#define F367_OFDM_RATIO_C 0xF0140007 -+ -+/* AGC2TH */ -+#define R367_OFDM_AGC2TH 0xF015 -+#define F367_OFDM_AGC2_THRES 0xF01500FF -+ -+/* AGC12C */ -+#define R367_OFDM_AGC12C 0xF016 -+#define F367_OFDM_AGC1_IV 0xF0160080 -+#define F367_OFDM_AGC1_OD 0xF0160040 -+#define F367_OFDM_AGC1_LOAD 0xF0160020 -+#define F367_OFDM_AGC2_IV 0xF0160010 -+#define F367_OFDM_AGC2_OD 0xF0160008 -+#define F367_OFDM_AGC2_LOAD 0xF0160004 -+#define F367_OFDM_AGC12_MODE 0xF0160003 -+ -+/* AGCCTRL1 */ -+#define R367_OFDM_AGCCTRL1 0xF017 -+#define F367_OFDM_DAGC_ON 0xF0170080 -+#define F367_OFDM_INVERT_AGC12 0xF0170040 -+#define F367_OFDM_AGC1_MODE 0xF0170008 -+#define F367_OFDM_AGC2_MODE 0xF0170007 -+ -+/* AGCCTRL2 */ -+#define R367_OFDM_AGCCTRL2 0xF018 -+#define F367_OFDM_FRZ2_CTRL 0xF0180060 -+#define F367_OFDM_FRZ1_CTRL 0xF0180018 -+#define F367_OFDM_TIME_CST 0xF0180007 -+ -+/* AGC1VAL1 */ -+#define R367_OFDM_AGC1VAL1 0xF019 -+#define F367_OFDM_AGC1_VAL_LO 0xF01900FF -+ -+/* AGC1VAL2 */ -+#define R367_OFDM_AGC1VAL2 0xF01A -+#define F367_OFDM_AGC1_VAL_HI 0xF01A000F -+ -+/* AGC2VAL1 */ -+#define R367_OFDM_AGC2VAL1 0xF01B -+#define F367_OFDM_AGC2_VAL_LO 0xF01B00FF -+ -+/* AGC2VAL2 */ -+#define R367_OFDM_AGC2VAL2 0xF01C -+#define F367_OFDM_AGC2_VAL_HI 0xF01C000F -+ -+/* AGC2PGA */ -+#define R367_OFDM_AGC2PGA 0xF01D -+#define F367_OFDM_AGC2_PGA 0xF01D00FF -+ -+/* OVF_RATE1 */ -+#define R367_OFDM_OVF_RATE1 0xF01E -+#define F367_OFDM_OVF_RATE_HI 0xF01E000F -+ -+/* OVF_RATE2 */ -+#define R367_OFDM_OVF_RATE2 0xF01F -+#define F367_OFDM_OVF_RATE_LO 0xF01F00FF -+ -+/* GAIN_SRC1 */ -+#define R367_OFDM_GAIN_SRC1 0xF020 -+#define F367_OFDM_INV_SPECTR 0xF0200080 -+#define F367_OFDM_IQ_INVERT 0xF0200040 -+#define F367_OFDM_INR_BYPASS 0xF0200020 -+#define F367_OFDM_STATUS_INV_SPECRUM 0xF0200010 -+#define F367_OFDM_GAIN_SRC_HI 0xF020000F -+ -+/* GAIN_SRC2 */ -+#define R367_OFDM_GAIN_SRC2 0xF021 -+#define F367_OFDM_GAIN_SRC_LO 0xF02100FF -+ -+/* INC_DEROT1 */ -+#define R367_OFDM_INC_DEROT1 0xF022 -+#define F367_OFDM_INC_DEROT_HI 0xF02200FF -+ -+/* INC_DEROT2 */ -+#define R367_OFDM_INC_DEROT2 0xF023 -+#define F367_OFDM_INC_DEROT_LO 0xF02300FF -+ -+/* PPM_CPAMP_DIR */ -+#define R367_OFDM_PPM_CPAMP_DIR 0xF024 -+#define F367_OFDM_PPM_CPAMP_DIRECT 0xF02400FF -+ -+/* PPM_CPAMP_INV */ -+#define R367_OFDM_PPM_CPAMP_INV 0xF025 -+#define F367_OFDM_PPM_CPAMP_INVER 0xF02500FF -+ -+/* FREESTFE_1 */ -+#define R367_OFDM_FREESTFE_1 0xF026 -+#define F367_OFDM_SYMBOL_NUMBER_INC 0xF02600C0 -+#define F367_OFDM_SEL_LSB 0xF0260004 -+#define F367_OFDM_AVERAGE_ON 0xF0260002 -+#define F367_OFDM_DC_ADJ 0xF0260001 -+ -+/* FREESTFE_2 */ -+#define R367_OFDM_FREESTFE_2 0xF027 -+#define F367_OFDM_SEL_SRCOUT 0xF02700C0 -+#define F367_OFDM_SEL_SYRTHR 0xF027001F -+ -+/* DCOFFSET */ -+#define R367_OFDM_DCOFFSET 0xF028 -+#define F367_OFDM_SELECT_I_Q 0xF0280080 -+#define F367_OFDM_DC_OFFSET 0xF028007F -+ -+/* EN_PROCESS */ -+#define R367_OFDM_EN_PROCESS 0xF029 -+#define F367_OFDM_FREE 0xF02900F0 -+#define F367_OFDM_ENAB_MANUAL 0xF0290001 -+ -+/* SDI_SMOOTHER */ -+#define R367_OFDM_SDI_SMOOTHER 0xF02A -+#define F367_OFDM_DIS_SMOOTH 0xF02A0080 -+#define F367_OFDM_SDI_INC_SMOOTHER 0xF02A007F -+ -+/* FE_LOOP_OPEN */ -+#define R367_OFDM_FE_LOOP_OPEN 0xF02B -+#define F367_OFDM_TRL_LOOP_OP 0xF02B0002 -+#define F367_OFDM_CRL_LOOP_OP 0xF02B0001 -+ -+/* FREQOFF1 */ -+#define R367_OFDM_FREQOFF1 0xF02C -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_VHI 0xF02C00FF -+ -+/* FREQOFF2 */ -+#define R367_OFDM_FREQOFF2 0xF02D -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_HI 0xF02D00FF -+ -+/* FREQOFF3 */ -+#define R367_OFDM_FREQOFF3 0xF02E -+#define F367_OFDM_FREQ_OFFSET_LOOP_OPEN_LO 0xF02E00FF -+ -+/* TIMOFF1 */ -+#define R367_OFDM_TIMOFF1 0xF02F -+#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_HI 0xF02F00FF -+ -+/* TIMOFF2 */ -+#define R367_OFDM_TIMOFF2 0xF030 -+#define F367_OFDM_TIM_OFFSET_LOOP_OPEN_LO 0xF03000FF -+ -+/* EPQ */ -+#define R367_OFDM_EPQ 0xF031 -+#define F367_OFDM_EPQ1 0xF03100FF -+ -+/* EPQAUTO */ -+#define R367_OFDM_EPQAUTO 0xF032 -+#define F367_OFDM_EPQ2 0xF03200FF -+ -+/* SYR_UPDATE */ -+#define R367_OFDM_SYR_UPDATE 0xF033 -+#define F367_OFDM_SYR_PROTV 0xF0330080 -+#define F367_OFDM_SYR_PROTV_GAIN 0xF0330060 -+#define F367_OFDM_SYR_FILTER 0xF0330010 -+#define F367_OFDM_SYR_TRACK_THRES 0xF033000C -+ -+/* CHPFREE */ -+#define R367_OFDM_CHPFREE 0xF034 -+#define F367_OFDM_CHP_FREE 0xF03400FF -+ -+/* PPM_STATE_MAC */ -+#define R367_OFDM_PPM_STATE_MAC 0xF035 -+#define F367_OFDM_PPM_STATE_MACHINE_DECODER 0xF035003F -+ -+/* INR_THRESHOLD */ -+#define R367_OFDM_INR_THRESHOLD 0xF036 -+#define F367_OFDM_INR_THRESH 0xF03600FF -+ -+/* EPQ_TPS_ID_CELL */ -+#define R367_OFDM_EPQ_TPS_ID_CELL 0xF037 -+#define F367_OFDM_ENABLE_LGTH_TO_CF 0xF0370080 -+#define F367_OFDM_DIS_TPS_RSVD 0xF0370040 -+#define F367_OFDM_DIS_BCH 0xF0370020 -+#define F367_OFDM_DIS_ID_CEL 0xF0370010 -+#define F367_OFDM_TPS_ADJUST_SYM 0xF037000F -+ -+/* EPQ_CFG */ -+#define R367_OFDM_EPQ_CFG 0xF038 -+#define F367_OFDM_EPQ_RANGE 0xF0380002 -+#define F367_OFDM_EPQ_SOFT 0xF0380001 -+ -+/* EPQ_STATUS */ -+#define R367_OFDM_EPQ_STATUS 0xF039 -+#define F367_OFDM_SLOPE_INC 0xF03900FC -+#define F367_OFDM_TPS_FIELD 0xF0390003 -+ -+/* AUTORELOCK */ -+#define R367_OFDM_AUTORELOCK 0xF03A -+#define F367_OFDM_BYPASS_BER_TEMPO 0xF03A0080 -+#define F367_OFDM_BER_TEMPO 0xF03A0070 -+#define F367_OFDM_BYPASS_COFDM_TEMPO 0xF03A0008 -+#define F367_OFDM_COFDM_TEMPO 0xF03A0007 -+ -+/* BER_THR_VMSB */ -+#define R367_OFDM_BER_THR_VMSB 0xF03B -+#define F367_OFDM_BER_THRESHOLD_HI 0xF03B00FF -+ -+/* BER_THR_MSB */ -+#define R367_OFDM_BER_THR_MSB 0xF03C -+#define F367_OFDM_BER_THRESHOLD_MID 0xF03C00FF -+ -+/* BER_THR_LSB */ -+#define R367_OFDM_BER_THR_LSB 0xF03D -+#define F367_OFDM_BER_THRESHOLD_LO 0xF03D00FF -+ -+/* CCD */ -+#define R367_OFDM_CCD 0xF03E -+#define F367_OFDM_CCD_DETECTED 0xF03E0080 -+#define F367_OFDM_CCD_RESET 0xF03E0040 -+#define F367_OFDM_CCD_THRESHOLD 0xF03E000F -+ -+/* SPECTR_CFG */ -+#define R367_OFDM_SPECTR_CFG 0xF03F -+#define F367_OFDM_SPECT_CFG 0xF03F0003 -+ -+/* CONSTMU_MSB */ -+#define R367_OFDM_CONSTMU_MSB 0xF040 -+#define F367_OFDM_CONSTMU_FREEZE 0xF0400080 -+#define F367_OFDM_CONSTNU_FORCE_EN 0xF0400040 -+#define F367_OFDM_CONST_MU_MSB 0xF040003F -+ -+/* CONSTMU_LSB */ -+#define R367_OFDM_CONSTMU_LSB 0xF041 -+#define F367_OFDM_CONST_MU_LSB 0xF04100FF -+ -+/* CONSTMU_MAX_MSB */ -+#define R367_OFDM_CONSTMU_MAX_MSB 0xF042 -+#define F367_OFDM_CONST_MU_MAX_MSB 0xF042003F -+ -+/* CONSTMU_MAX_LSB */ -+#define R367_OFDM_CONSTMU_MAX_LSB 0xF043 -+#define F367_OFDM_CONST_MU_MAX_LSB 0xF04300FF -+ -+/* ALPHANOISE */ -+#define R367_OFDM_ALPHANOISE 0xF044 -+#define F367_OFDM_USE_ALLFILTER 0xF0440080 -+#define F367_OFDM_INTER_ON 0xF0440040 -+#define F367_OFDM_ALPHA_NOISE 0xF044001F -+ -+/* MAXGP_MSB */ -+#define R367_OFDM_MAXGP_MSB 0xF045 -+#define F367_OFDM_MUFILTER_LENGTH 0xF04500F0 -+#define F367_OFDM_MAX_GP_MSB 0xF045000F -+ -+/* MAXGP_LSB */ -+#define R367_OFDM_MAXGP_LSB 0xF046 -+#define F367_OFDM_MAX_GP_LSB 0xF04600FF -+ -+/* ALPHAMSB */ -+#define R367_OFDM_ALPHAMSB 0xF047 -+#define F367_OFDM_CHC_DATARATE 0xF04700C0 -+#define F367_OFDM_ALPHA_MSB 0xF047003F -+ -+/* ALPHALSB */ -+#define R367_OFDM_ALPHALSB 0xF048 -+#define F367_OFDM_ALPHA_LSB 0xF04800FF -+ -+/* PILOT_ACCU */ -+#define R367_OFDM_PILOT_ACCU 0xF049 -+#define F367_OFDM_USE_SCAT4ADDAPT 0xF0490080 -+#define F367_OFDM_PILOT_ACC 0xF049001F -+ -+/* PILOTMU_ACCU */ -+#define R367_OFDM_PILOTMU_ACCU 0xF04A -+#define F367_OFDM_DISCARD_BAD_SP 0xF04A0080 -+#define F367_OFDM_DISCARD_BAD_CP 0xF04A0040 -+#define F367_OFDM_PILOT_MU_ACCU 0xF04A001F -+ -+/* FILT_CHANNEL_EST */ -+#define R367_OFDM_FILT_CHANNEL_EST 0xF04B -+#define F367_OFDM_USE_FILT_PILOT 0xF04B0080 -+#define F367_OFDM_FILT_CHANNEL 0xF04B007F -+ -+/* ALPHA_NOPISE_FREQ */ -+#define R367_OFDM_ALPHA_NOPISE_FREQ 0xF04C -+#define F367_OFDM_NOISE_FREQ_FILT 0xF04C0040 -+#define F367_OFDM_ALPHA_NOISE_FREQ 0xF04C003F -+ -+/* RATIO_PILOT */ -+#define R367_OFDM_RATIO_PILOT 0xF04D -+#define F367_OFDM_RATIO_MEAN_SP 0xF04D00F0 -+#define F367_OFDM_RATIO_MEAN_CP 0xF04D000F -+ -+/* CHC_CTL */ -+#define R367_OFDM_CHC_CTL 0xF04E -+#define F367_OFDM_TRACK_EN 0xF04E0080 -+#define F367_OFDM_NOISE_NORM_EN 0xF04E0040 -+#define F367_OFDM_FORCE_CHC_RESET 0xF04E0020 -+#define F367_OFDM_SHORT_TIME 0xF04E0010 -+#define F367_OFDM_FORCE_STATE_EN 0xF04E0008 -+#define F367_OFDM_FORCE_STATE 0xF04E0007 -+ -+/* EPQ_ADJUST */ -+#define R367_OFDM_EPQ_ADJUST 0xF04F -+#define F367_OFDM_ADJUST_SCAT_IND 0xF04F00C0 -+#define F367_OFDM_ONE_SYMBOL 0xF04F0010 -+#define F367_OFDM_EPQ_DECAY 0xF04F000E -+#define F367_OFDM_HOLD_SLOPE 0xF04F0001 -+ -+/* EPQ_THRES */ -+#define R367_OFDM_EPQ_THRES 0xF050 -+#define F367_OFDM_EPQ_THR 0xF05000FF -+ -+/* OMEGA_CTL */ -+#define R367_OFDM_OMEGA_CTL 0xF051 -+#define F367_OFDM_OMEGA_RST 0xF0510080 -+#define F367_OFDM_FREEZE_OMEGA 0xF0510040 -+#define F367_OFDM_OMEGA_SEL 0xF051003F -+ -+/* GP_CTL */ -+#define R367_OFDM_GP_CTL 0xF052 -+#define F367_OFDM_CHC_STATE 0xF05200E0 -+#define F367_OFDM_FREEZE_GP 0xF0520010 -+#define F367_OFDM_GP_SEL 0xF052000F -+ -+/* MUMSB */ -+#define R367_OFDM_MUMSB 0xF053 -+#define F367_OFDM_MU_MSB 0xF053007F -+ -+/* MULSB */ -+#define R367_OFDM_MULSB 0xF054 -+#define F367_OFDM_MU_LSB 0xF05400FF -+ -+/* GPMSB */ -+#define R367_OFDM_GPMSB 0xF055 -+#define F367_OFDM_CSI_THRESHOLD 0xF05500E0 -+#define F367_OFDM_GP_MSB 0xF055000F -+ -+/* GPLSB */ -+#define R367_OFDM_GPLSB 0xF056 -+#define F367_OFDM_GP_LSB 0xF05600FF -+ -+/* OMEGAMSB */ -+#define R367_OFDM_OMEGAMSB 0xF057 -+#define F367_OFDM_OMEGA_MSB 0xF057007F -+ -+/* OMEGALSB */ -+#define R367_OFDM_OMEGALSB 0xF058 -+#define F367_OFDM_OMEGA_LSB 0xF05800FF -+ -+/* SCAT_NB */ -+#define R367_OFDM_SCAT_NB 0xF059 -+#define F367_OFDM_CHC_TEST 0xF05900F8 -+#define F367_OFDM_SCAT_NUMB 0xF0590003 -+ -+/* CHC_DUMMY */ -+#define R367_OFDM_CHC_DUMMY 0xF05A -+#define F367_OFDM_CHC_DUM 0xF05A00FF -+ -+/* INC_CTL */ -+#define R367_OFDM_INC_CTL 0xF05B -+#define F367_OFDM_INC_BYPASS 0xF05B0080 -+#define F367_OFDM_INC_NDEPTH 0xF05B000C -+#define F367_OFDM_INC_MADEPTH 0xF05B0003 -+ -+/* INCTHRES_COR1 */ -+#define R367_OFDM_INCTHRES_COR1 0xF05C -+#define F367_OFDM_INC_THRES_COR1 0xF05C00FF -+ -+/* INCTHRES_COR2 */ -+#define R367_OFDM_INCTHRES_COR2 0xF05D -+#define F367_OFDM_INC_THRES_COR2 0xF05D00FF -+ -+/* INCTHRES_DET1 */ -+#define R367_OFDM_INCTHRES_DET1 0xF05E -+#define F367_OFDM_INC_THRES_DET1 0xF05E003F -+ -+/* INCTHRES_DET2 */ -+#define R367_OFDM_INCTHRES_DET2 0xF05F -+#define F367_OFDM_INC_THRES_DET2 0xF05F003F -+ -+/* IIR_CELLNB */ -+#define R367_OFDM_IIR_CELLNB 0xF060 -+#define F367_OFDM_NRST_IIR 0xF0600080 -+#define F367_OFDM_IIR_CELL_NB 0xF0600007 -+ -+/* IIRCX_COEFF1_MSB */ -+#define R367_OFDM_IIRCX_COEFF1_MSB 0xF061 -+#define F367_OFDM_IIR_CX_COEFF1_MSB 0xF06100FF -+ -+/* IIRCX_COEFF1_LSB */ -+#define R367_OFDM_IIRCX_COEFF1_LSB 0xF062 -+#define F367_OFDM_IIR_CX_COEFF1_LSB 0xF06200FF -+ -+/* IIRCX_COEFF2_MSB */ -+#define R367_OFDM_IIRCX_COEFF2_MSB 0xF063 -+#define F367_OFDM_IIR_CX_COEFF2_MSB 0xF06300FF -+ -+/* IIRCX_COEFF2_LSB */ -+#define R367_OFDM_IIRCX_COEFF2_LSB 0xF064 -+#define F367_OFDM_IIR_CX_COEFF2_LSB 0xF06400FF -+ -+/* IIRCX_COEFF3_MSB */ -+#define R367_OFDM_IIRCX_COEFF3_MSB 0xF065 -+#define F367_OFDM_IIR_CX_COEFF3_MSB 0xF06500FF -+ -+/* IIRCX_COEFF3_LSB */ -+#define R367_OFDM_IIRCX_COEFF3_LSB 0xF066 -+#define F367_OFDM_IIR_CX_COEFF3_LSB 0xF06600FF -+ -+/* IIRCX_COEFF4_MSB */ -+#define R367_OFDM_IIRCX_COEFF4_MSB 0xF067 -+#define F367_OFDM_IIR_CX_COEFF4_MSB 0xF06700FF -+ -+/* IIRCX_COEFF4_LSB */ -+#define R367_OFDM_IIRCX_COEFF4_LSB 0xF068 -+#define F367_OFDM_IIR_CX_COEFF4_LSB 0xF06800FF -+ -+/* IIRCX_COEFF5_MSB */ -+#define R367_OFDM_IIRCX_COEFF5_MSB 0xF069 -+#define F367_OFDM_IIR_CX_COEFF5_MSB 0xF06900FF -+ -+/* IIRCX_COEFF5_LSB */ -+#define R367_OFDM_IIRCX_COEFF5_LSB 0xF06A -+#define F367_OFDM_IIR_CX_COEFF5_LSB 0xF06A00FF -+ -+/* FEPATH_CFG */ -+#define R367_OFDM_FEPATH_CFG 0xF06B -+#define F367_OFDM_DEMUX_SWAP 0xF06B0004 -+#define F367_OFDM_DIGAGC_SWAP 0xF06B0002 -+#define F367_OFDM_LONGPATH_IF 0xF06B0001 -+ -+/* PMC1_FUNC */ -+#define R367_OFDM_PMC1_FUNC 0xF06C -+#define F367_OFDM_SOFT_RSTN 0xF06C0080 -+#define F367_OFDM_PMC1_AVERAGE_TIME 0xF06C0078 -+#define F367_OFDM_PMC1_WAIT_TIME 0xF06C0006 -+#define F367_OFDM_PMC1_2N_SEL 0xF06C0001 -+ -+/* PMC1_FOR */ -+#define R367_OFDM_PMC1_FOR 0xF06D -+#define F367_OFDM_PMC1_FORCE 0xF06D0080 -+#define F367_OFDM_PMC1_FORCE_VALUE 0xF06D007C -+ -+/* PMC2_FUNC */ -+#define R367_OFDM_PMC2_FUNC 0xF06E -+#define F367_OFDM_PMC2_SOFT_STN 0xF06E0080 -+#define F367_OFDM_PMC2_ACCU_TIME 0xF06E0070 -+#define F367_OFDM_PMC2_CMDP_MN 0xF06E0008 -+#define F367_OFDM_PMC2_SWAP 0xF06E0004 -+ -+/* STATUS_ERR_DA */ -+#define R367_OFDM_STATUS_ERR_DA 0xF06F -+#define F367_OFDM_COM_USEGAINTRK 0xF06F0080 -+#define F367_OFDM_COM_AGCLOCK 0xF06F0040 -+#define F367_OFDM_AUT_AGCLOCK 0xF06F0020 -+#define F367_OFDM_MIN_ERR_X_LSB 0xF06F000F -+ -+/* DIG_AGC_R */ -+#define R367_OFDM_DIG_AGC_R 0xF070 -+#define F367_OFDM_COM_SOFT_RSTN 0xF0700080 -+#define F367_OFDM_COM_AGC_ON 0xF0700040 -+#define F367_OFDM_COM_EARLY 0xF0700020 -+#define F367_OFDM_AUT_SOFT_RESETN 0xF0700010 -+#define F367_OFDM_AUT_AGC_ON 0xF0700008 -+#define F367_OFDM_AUT_EARLY 0xF0700004 -+#define F367_OFDM_AUT_ROT_EN 0xF0700002 -+#define F367_OFDM_LOCK_SOFT_RESETN 0xF0700001 -+ -+/* COMAGC_TARMSB */ -+#define R367_OFDM_COMAGC_TARMSB 0xF071 -+#define F367_OFDM_COM_AGC_TARGET_MSB 0xF07100FF -+ -+/* COM_AGC_TAR_ENMODE */ -+#define R367_OFDM_COM_AGC_TAR_ENMODE 0xF072 -+#define F367_OFDM_COM_AGC_TARGET_LSB 0xF07200F0 -+#define F367_OFDM_COM_ENMODE 0xF072000F -+ -+/* COM_AGC_CFG */ -+#define R367_OFDM_COM_AGC_CFG 0xF073 -+#define F367_OFDM_COM_N 0xF07300F8 -+#define F367_OFDM_COM_STABMODE 0xF0730006 -+#define F367_OFDM_ERR_SEL 0xF0730001 -+ -+/* COM_AGC_GAIN1 */ -+#define R367_OFDM_COM_AGC_GAIN1 0xF074 -+#define F367_OFDM_COM_GAIN1ACK 0xF07400F0 -+#define F367_OFDM_COM_GAIN1TRK 0xF074000F -+ -+/* AUT_AGC_TARGETMSB */ -+#define R367_OFDM_AUT_AGC_TARGETMSB 0xF075 -+#define F367_OFDM_AUT_AGC_TARGET_MSB 0xF07500FF -+ -+/* LOCK_DET_MSB */ -+#define R367_OFDM_LOCK_DET_MSB 0xF076 -+#define F367_OFDM_LOCK_DETECT_MSB 0xF07600FF -+ -+/* AGCTAR_LOCK_LSBS */ -+#define R367_OFDM_AGCTAR_LOCK_LSBS 0xF077 -+#define F367_OFDM_AUT_AGC_TARGET_LSB 0xF07700F0 -+#define F367_OFDM_LOCK_DETECT_LSB 0xF077000F -+ -+/* AUT_GAIN_EN */ -+#define R367_OFDM_AUT_GAIN_EN 0xF078 -+#define F367_OFDM_AUT_ENMODE 0xF07800F0 -+#define F367_OFDM_AUT_GAIN2 0xF078000F -+ -+/* AUT_CFG */ -+#define R367_OFDM_AUT_CFG 0xF079 -+#define F367_OFDM_AUT_N 0xF07900F8 -+#define F367_OFDM_INT_CHOICE 0xF0790006 -+#define F367_OFDM_INT_LOAD 0xF0790001 -+ -+/* LOCKN */ -+#define R367_OFDM_LOCKN 0xF07A -+#define F367_OFDM_LOCK_N 0xF07A00F8 -+#define F367_OFDM_SEL_IQNTAR 0xF07A0004 -+#define F367_OFDM_LOCK_DETECT_CHOICE 0xF07A0003 -+ -+/* INT_X_3 */ -+#define R367_OFDM_INT_X_3 0xF07B -+#define F367_OFDM_INT_X3 0xF07B00FF -+ -+/* INT_X_2 */ -+#define R367_OFDM_INT_X_2 0xF07C -+#define F367_OFDM_INT_X2 0xF07C00FF -+ -+/* INT_X_1 */ -+#define R367_OFDM_INT_X_1 0xF07D -+#define F367_OFDM_INT_X1 0xF07D00FF -+ -+/* INT_X_0 */ -+#define R367_OFDM_INT_X_0 0xF07E -+#define F367_OFDM_INT_X0 0xF07E00FF -+ -+/* MIN_ERRX_MSB */ -+#define R367_OFDM_MIN_ERRX_MSB 0xF07F -+#define F367_OFDM_MIN_ERR_X_MSB 0xF07F00FF -+ -+/* COR_CTL */ -+#define R367_OFDM_COR_CTL 0xF080 -+#define F367_OFDM_CORE_ACTIVE 0xF0800020 -+#define F367_OFDM_HOLD 0xF0800010 -+#define F367_OFDM_CORE_STATE_CTL 0xF080000F -+ -+/* COR_STAT */ -+#define R367_OFDM_COR_STAT 0xF081 -+#define F367_OFDM_SCATT_LOCKED 0xF0810080 -+#define F367_OFDM_TPS_LOCKED 0xF0810040 -+#define F367_OFDM_SYR_LOCKED_COR 0xF0810020 -+#define F367_OFDM_AGC_LOCKED_STAT 0xF0810010 -+#define F367_OFDM_CORE_STATE_STAT 0xF081000F -+ -+/* COR_INTEN */ -+#define R367_OFDM_COR_INTEN 0xF082 -+#define F367_OFDM_INTEN 0xF0820080 -+#define F367_OFDM_INTEN_SYR 0xF0820020 -+#define F367_OFDM_INTEN_FFT 0xF0820010 -+#define F367_OFDM_INTEN_AGC 0xF0820008 -+#define F367_OFDM_INTEN_TPS1 0xF0820004 -+#define F367_OFDM_INTEN_TPS2 0xF0820002 -+#define F367_OFDM_INTEN_TPS3 0xF0820001 -+ -+/* COR_INTSTAT */ -+#define R367_OFDM_COR_INTSTAT 0xF083 -+#define F367_OFDM_INTSTAT_SYR 0xF0830020 -+#define F367_OFDM_INTSTAT_FFT 0xF0830010 -+#define F367_OFDM_INTSAT_AGC 0xF0830008 -+#define F367_OFDM_INTSTAT_TPS1 0xF0830004 -+#define F367_OFDM_INTSTAT_TPS2 0xF0830002 -+#define F367_OFDM_INTSTAT_TPS3 0xF0830001 -+ -+/* COR_MODEGUARD */ -+#define R367_OFDM_COR_MODEGUARD 0xF084 -+#define F367_OFDM_FORCE 0xF0840010 -+#define F367_OFDM_MODE 0xF084000C -+#define F367_OFDM_GUARD 0xF0840003 -+ -+/* AGC_CTL */ -+#define R367_OFDM_AGC_CTL 0xF085 -+#define F367_OFDM_AGC_TIMING_FACTOR 0xF08500E0 -+#define F367_OFDM_AGC_LAST 0xF0850010 -+#define F367_OFDM_AGC_GAIN 0xF085000C -+#define F367_OFDM_AGC_NEG 0xF0850002 -+#define F367_OFDM_AGC_SET 0xF0850001 -+ -+/* AGC_MANUAL1 */ -+#define R367_OFDM_AGC_MANUAL1 0xF086 -+#define F367_OFDM_AGC_VAL_LO 0xF08600FF -+ -+/* AGC_MANUAL2 */ -+#define R367_OFDM_AGC_MANUAL2 0xF087 -+#define F367_OFDM_AGC_VAL_HI 0xF087000F -+ -+/* AGC_TARG */ -+#define R367_OFDM_AGC_TARG 0xF088 -+#define F367_OFDM_AGC_TARGET 0xF08800FF -+ -+/* AGC_GAIN1 */ -+#define R367_OFDM_AGC_GAIN1 0xF089 -+#define F367_OFDM_AGC_GAIN_LO 0xF08900FF -+ -+/* AGC_GAIN2 */ -+#define R367_OFDM_AGC_GAIN2 0xF08A -+#define F367_OFDM_AGC_LOCKED_GAIN2 0xF08A0010 -+#define F367_OFDM_AGC_GAIN_HI 0xF08A000F -+ -+/* RESERVED_1 */ -+#define R367_OFDM_RESERVED_1 0xF08B -+#define F367_OFDM_RESERVED1 0xF08B00FF -+ -+/* RESERVED_2 */ -+#define R367_OFDM_RESERVED_2 0xF08C -+#define F367_OFDM_RESERVED2 0xF08C00FF -+ -+/* RESERVED_3 */ -+#define R367_OFDM_RESERVED_3 0xF08D -+#define F367_OFDM_RESERVED3 0xF08D00FF -+ -+/* CAS_CTL */ -+#define R367_OFDM_CAS_CTL 0xF08E -+#define F367_OFDM_CCS_ENABLE 0xF08E0080 -+#define F367_OFDM_ACS_DISABLE 0xF08E0040 -+#define F367_OFDM_DAGC_DIS 0xF08E0020 -+#define F367_OFDM_DAGC_GAIN 0xF08E0018 -+#define F367_OFDM_CCSMU 0xF08E0007 -+ -+/* CAS_FREQ */ -+#define R367_OFDM_CAS_FREQ 0xF08F -+#define F367_OFDM_CCS_FREQ 0xF08F00FF -+ -+/* CAS_DAGCGAIN */ -+#define R367_OFDM_CAS_DAGCGAIN 0xF090 -+#define F367_OFDM_CAS_DAGC_GAIN 0xF09000FF -+ -+/* SYR_CTL */ -+#define R367_OFDM_SYR_CTL 0xF091 -+#define F367_OFDM_SICTH_ENABLE 0xF0910080 -+#define F367_OFDM_LONG_ECHO 0xF0910078 -+#define F367_OFDM_AUTO_LE_EN 0xF0910004 -+#define F367_OFDM_SYR_BYPASS 0xF0910002 -+#define F367_OFDM_SYR_TR_DIS 0xF0910001 -+ -+/* SYR_STAT */ -+#define R367_OFDM_SYR_STAT 0xF092 -+#define F367_OFDM_SYR_LOCKED_STAT 0xF0920010 -+#define F367_OFDM_SYR_MODE 0xF092000C -+#define F367_OFDM_SYR_GUARD 0xF0920003 -+ -+/* SYR_NCO1 */ -+#define R367_OFDM_SYR_NCO1 0xF093 -+#define F367_OFDM_SYR_NCO_LO 0xF09300FF -+ -+/* SYR_NCO2 */ -+#define R367_OFDM_SYR_NCO2 0xF094 -+#define F367_OFDM_SYR_NCO_HI 0xF094003F -+ -+/* SYR_OFFSET1 */ -+#define R367_OFDM_SYR_OFFSET1 0xF095 -+#define F367_OFDM_SYR_OFFSET_LO 0xF09500FF -+ -+/* SYR_OFFSET2 */ -+#define R367_OFDM_SYR_OFFSET2 0xF096 -+#define F367_OFDM_SYR_OFFSET_HI 0xF096003F -+ -+/* FFT_CTL */ -+#define R367_OFDM_FFT_CTL 0xF097 -+#define F367_OFDM_SHIFT_FFT_TRIG 0xF0970018 -+#define F367_OFDM_FFT_TRIGGER 0xF0970004 -+#define F367_OFDM_FFT_MANUAL 0xF0970002 -+#define F367_OFDM_IFFT_MODE 0xF0970001 -+ -+/* SCR_CTL */ -+#define R367_OFDM_SCR_CTL 0xF098 -+#define F367_OFDM_SYRADJDECAY 0xF0980070 -+#define F367_OFDM_SCR_CPEDIS 0xF0980002 -+#define F367_OFDM_SCR_DIS 0xF0980001 -+ -+/* PPM_CTL1 */ -+#define R367_OFDM_PPM_CTL1 0xF099 -+#define F367_OFDM_PPM_MAXFREQ 0xF0990030 -+#define F367_OFDM_PPM_MAXTIM 0xF0990008 -+#define F367_OFDM_PPM_INVSEL 0xF0990004 -+#define F367_OFDM_PPM_SCATDIS 0xF0990002 -+#define F367_OFDM_PPM_BYP 0xF0990001 -+ -+/* TRL_CTL */ -+#define R367_OFDM_TRL_CTL 0xF09A -+#define F367_OFDM_TRL_NOMRATE_LSB 0xF09A0080 -+#define F367_OFDM_TRL_GAIN_FACTOR 0xF09A0078 -+#define F367_OFDM_TRL_LOOPGAIN 0xF09A0007 -+ -+/* TRL_NOMRATE1 */ -+#define R367_OFDM_TRL_NOMRATE1 0xF09B -+#define F367_OFDM_TRL_NOMRATE_LO 0xF09B00FF -+ -+/* TRL_NOMRATE2 */ -+#define R367_OFDM_TRL_NOMRATE2 0xF09C -+#define F367_OFDM_TRL_NOMRATE_HI 0xF09C00FF -+ -+/* TRL_TIME1 */ -+#define R367_OFDM_TRL_TIME1 0xF09D -+#define F367_OFDM_TRL_TOFFSET_LO 0xF09D00FF -+ -+/* TRL_TIME2 */ -+#define R367_OFDM_TRL_TIME2 0xF09E -+#define F367_OFDM_TRL_TOFFSET_HI 0xF09E00FF -+ -+/* CRL_CTL */ -+#define R367_OFDM_CRL_CTL 0xF09F -+#define F367_OFDM_CRL_DIS 0xF09F0080 -+#define F367_OFDM_CRL_GAIN_FACTOR 0xF09F0078 -+#define F367_OFDM_CRL_LOOPGAIN 0xF09F0007 -+ -+/* CRL_FREQ1 */ -+#define R367_OFDM_CRL_FREQ1 0xF0A0 -+#define F367_OFDM_CRL_FOFFSET_LO 0xF0A000FF -+ -+/* CRL_FREQ2 */ -+#define R367_OFDM_CRL_FREQ2 0xF0A1 -+#define F367_OFDM_CRL_FOFFSET_HI 0xF0A100FF -+ -+/* CRL_FREQ3 */ -+#define R367_OFDM_CRL_FREQ3 0xF0A2 -+#define F367_OFDM_CRL_FOFFSET_VHI 0xF0A200FF -+ -+/* TPS_SFRAME_CTL */ -+#define R367_OFDM_TPS_SFRAME_CTL 0xF0A3 -+#define F367_OFDM_TPS_SFRAME_SYNC 0xF0A30001 -+ -+/* CHC_SNR */ -+#define R367_OFDM_CHC_SNR 0xF0A4 -+#define F367_OFDM_CHCSNR 0xF0A400FF -+ -+/* BDI_CTL */ -+#define R367_OFDM_BDI_CTL 0xF0A5 -+#define F367_OFDM_BDI_LPSEL 0xF0A50002 -+#define F367_OFDM_BDI_SERIAL 0xF0A50001 -+ -+/* DMP_CTL */ -+#define R367_OFDM_DMP_CTL 0xF0A6 -+#define F367_OFDM_DMP_SCALING_FACTOR 0xF0A6001E -+#define F367_OFDM_DMP_SDDIS 0xF0A60001 -+ -+/* TPS_RCVD1 */ -+#define R367_OFDM_TPS_RCVD1 0xF0A7 -+#define F367_OFDM_TPS_CHANGE 0xF0A70040 -+#define F367_OFDM_BCH_OK 0xF0A70020 -+#define F367_OFDM_TPS_SYNC 0xF0A70010 -+#define F367_OFDM_TPS_FRAME 0xF0A70003 -+ -+/* TPS_RCVD2 */ -+#define R367_OFDM_TPS_RCVD2 0xF0A8 -+#define F367_OFDM_TPS_HIERMODE 0xF0A80070 -+#define F367_OFDM_TPS_CONST 0xF0A80003 -+ -+/* TPS_RCVD3 */ -+#define R367_OFDM_TPS_RCVD3 0xF0A9 -+#define F367_OFDM_TPS_LPCODE 0xF0A90070 -+#define F367_OFDM_TPS_HPCODE 0xF0A90007 -+ -+/* TPS_RCVD4 */ -+#define R367_OFDM_TPS_RCVD4 0xF0AA -+#define F367_OFDM_TPS_GUARD 0xF0AA0030 -+#define F367_OFDM_TPS_MODE 0xF0AA0003 -+ -+/* TPS_ID_CELL1 */ -+#define R367_OFDM_TPS_ID_CELL1 0xF0AB -+#define F367_OFDM_TPS_ID_CELL_LO 0xF0AB00FF -+ -+/* TPS_ID_CELL2 */ -+#define R367_OFDM_TPS_ID_CELL2 0xF0AC -+#define F367_OFDM_TPS_ID_CELL_HI 0xF0AC00FF -+ -+/* TPS_RCVD5_SET1 */ -+#define R367_OFDM_TPS_RCVD5_SET1 0xF0AD -+#define F367_OFDM_TPS_NA 0xF0AD00FC -+#define F367_OFDM_TPS_SETFRAME 0xF0AD0003 -+ -+/* TPS_SET2 */ -+#define R367_OFDM_TPS_SET2 0xF0AE -+#define F367_OFDM_TPS_SETHIERMODE 0xF0AE0070 -+#define F367_OFDM_TPS_SETCONST 0xF0AE0003 -+ -+/* TPS_SET3 */ -+#define R367_OFDM_TPS_SET3 0xF0AF -+#define F367_OFDM_TPS_SETLPCODE 0xF0AF0070 -+#define F367_OFDM_TPS_SETHPCODE 0xF0AF0007 -+ -+/* TPS_CTL */ -+#define R367_OFDM_TPS_CTL 0xF0B0 -+#define F367_OFDM_TPS_IMM 0xF0B00004 -+#define F367_OFDM_TPS_BCHDIS 0xF0B00002 -+#define F367_OFDM_TPS_UPDDIS 0xF0B00001 -+ -+/* CTL_FFTOSNUM */ -+#define R367_OFDM_CTL_FFTOSNUM 0xF0B1 -+#define F367_OFDM_SYMBOL_NUMBER 0xF0B1007F -+ -+/* TESTSELECT */ -+#define R367_OFDM_TESTSELECT 0xF0B2 -+#define F367_OFDM_TEST_SELECT 0xF0B2001F -+ -+/* MSC_REV */ -+#define R367_OFDM_MSC_REV 0xF0B3 -+#define F367_OFDM_REV_NUMBER 0xF0B300FF -+ -+/* PIR_CTL */ -+#define R367_OFDM_PIR_CTL 0xF0B4 -+#define F367_OFDM_FREEZE 0xF0B40001 -+ -+/* SNR_CARRIER1 */ -+#define R367_OFDM_SNR_CARRIER1 0xF0B5 -+#define F367_OFDM_SNR_CARRIER_LO 0xF0B500FF -+ -+/* SNR_CARRIER2 */ -+#define R367_OFDM_SNR_CARRIER2 0xF0B6 -+#define F367_OFDM_MEAN 0xF0B600C0 -+#define F367_OFDM_SNR_CARRIER_HI 0xF0B6001F -+ -+/* PPM_CPAMP */ -+#define R367_OFDM_PPM_CPAMP 0xF0B7 -+#define F367_OFDM_PPM_CPC 0xF0B700FF -+ -+/* TSM_AP0 */ -+#define R367_OFDM_TSM_AP0 0xF0B8 -+#define F367_OFDM_ADDRESS_BYTE_0 0xF0B800FF -+ -+/* TSM_AP1 */ -+#define R367_OFDM_TSM_AP1 0xF0B9 -+#define F367_OFDM_ADDRESS_BYTE_1 0xF0B900FF -+ -+/* TSM_AP2 */ -+#define R367_OFDM_TSM_AP2 0xF0BA -+#define F367_OFDM_DATA_BYTE_0 0xF0BA00FF -+ -+/* TSM_AP3 */ -+#define R367_OFDM_TSM_AP3 0xF0BB -+#define F367_OFDM_DATA_BYTE_1 0xF0BB00FF -+ -+/* TSM_AP4 */ -+#define R367_OFDM_TSM_AP4 0xF0BC -+#define F367_OFDM_DATA_BYTE_2 0xF0BC00FF -+ -+/* TSM_AP5 */ -+#define R367_OFDM_TSM_AP5 0xF0BD -+#define F367_OFDM_DATA_BYTE_3 0xF0BD00FF -+ -+/* TSM_AP6 */ -+#define R367_OFDM_TSM_AP6 0xF0BE -+#define F367_OFDM_TSM_AP_6 0xF0BE00FF -+ -+/* TSM_AP7 */ -+#define R367_OFDM_TSM_AP7 0xF0BF -+#define F367_OFDM_MEM_SELECT_BYTE 0xF0BF00FF -+ -+/* TSTRES */ -+#define R367_TSTRES 0xF0C0 -+#define F367_FRES_DISPLAY 0xF0C00080 -+#define F367_FRES_FIFO_AD 0xF0C00020 -+#define F367_FRESRS 0xF0C00010 -+#define F367_FRESACS 0xF0C00008 -+#define F367_FRESFEC 0xF0C00004 -+#define F367_FRES_PRIF 0xF0C00002 -+#define F367_FRESCORE 0xF0C00001 -+ -+/* ANACTRL */ -+#define R367_ANACTRL 0xF0C1 -+#define F367_BYPASS_XTAL 0xF0C10040 -+#define F367_BYPASS_PLLXN 0xF0C1000C -+#define F367_DIS_PAD_OSC 0xF0C10002 -+#define F367_STDBY_PLLXN 0xF0C10001 -+ -+/* TSTBUS */ -+#define R367_TSTBUS 0xF0C2 -+#define F367_TS_BYTE_CLK_INV 0xF0C20080 -+#define F367_CFG_IP 0xF0C20070 -+#define F367_CFG_TST 0xF0C2000F -+ -+/* TSTRATE */ -+#define R367_TSTRATE 0xF0C6 -+#define F367_FORCEPHA 0xF0C60080 -+#define F367_FNEWPHA 0xF0C60010 -+#define F367_FROT90 0xF0C60008 -+#define F367_FR 0xF0C60007 -+ -+/* CONSTMODE */ -+#define R367_OFDM_CONSTMODE 0xF0CB -+#define F367_OFDM_TST_PRIF 0xF0CB00E0 -+#define F367_OFDM_CAR_TYPE 0xF0CB0018 -+#define F367_OFDM_CONST_MODE 0xF0CB0003 -+ -+/* CONSTCARR1 */ -+#define R367_OFDM_CONSTCARR1 0xF0CC -+#define F367_OFDM_CONST_CARR_LO 0xF0CC00FF -+ -+/* CONSTCARR2 */ -+#define R367_OFDM_CONSTCARR2 0xF0CD -+#define F367_OFDM_CONST_CARR_HI 0xF0CD001F -+ -+/* ICONSTEL */ -+#define R367_OFDM_ICONSTEL 0xF0CE -+#define F367_OFDM_PICONSTEL 0xF0CE00FF -+ -+/* QCONSTEL */ -+#define R367_OFDM_QCONSTEL 0xF0CF -+#define F367_OFDM_PQCONSTEL 0xF0CF00FF -+ -+/* TSTBISTRES0 */ -+#define R367_OFDM_TSTBISTRES0 0xF0D0 -+#define F367_OFDM_BEND_PPM 0xF0D00080 -+#define F367_OFDM_BBAD_PPM 0xF0D00040 -+#define F367_OFDM_BEND_FFTW 0xF0D00020 -+#define F367_OFDM_BBAD_FFTW 0xF0D00010 -+#define F367_OFDM_BEND_FFT_BUF 0xF0D00008 -+#define F367_OFDM_BBAD_FFT_BUF 0xF0D00004 -+#define F367_OFDM_BEND_SYR 0xF0D00002 -+#define F367_OFDM_BBAD_SYR 0xF0D00001 -+ -+/* TSTBISTRES1 */ -+#define R367_OFDM_TSTBISTRES1 0xF0D1 -+#define F367_OFDM_BEND_CHC_CP 0xF0D10080 -+#define F367_OFDM_BBAD_CHC_CP 0xF0D10040 -+#define F367_OFDM_BEND_CHCI 0xF0D10020 -+#define F367_OFDM_BBAD_CHCI 0xF0D10010 -+#define F367_OFDM_BEND_BDI 0xF0D10008 -+#define F367_OFDM_BBAD_BDI 0xF0D10004 -+#define F367_OFDM_BEND_SDI 0xF0D10002 -+#define F367_OFDM_BBAD_SDI 0xF0D10001 -+ -+/* TSTBISTRES2 */ -+#define R367_OFDM_TSTBISTRES2 0xF0D2 -+#define F367_OFDM_BEND_CHC_INC 0xF0D20080 -+#define F367_OFDM_BBAD_CHC_INC 0xF0D20040 -+#define F367_OFDM_BEND_CHC_SPP 0xF0D20020 -+#define F367_OFDM_BBAD_CHC_SPP 0xF0D20010 -+#define F367_OFDM_BEND_CHC_CPP 0xF0D20008 -+#define F367_OFDM_BBAD_CHC_CPP 0xF0D20004 -+#define F367_OFDM_BEND_CHC_SP 0xF0D20002 -+#define F367_OFDM_BBAD_CHC_SP 0xF0D20001 -+ -+/* TSTBISTRES3 */ -+#define R367_OFDM_TSTBISTRES3 0xF0D3 -+#define F367_OFDM_BEND_QAM 0xF0D30080 -+#define F367_OFDM_BBAD_QAM 0xF0D30040 -+#define F367_OFDM_BEND_SFEC_VIT 0xF0D30020 -+#define F367_OFDM_BBAD_SFEC_VIT 0xF0D30010 -+#define F367_OFDM_BEND_SFEC_DLINE 0xF0D30008 -+#define F367_OFDM_BBAD_SFEC_DLINE 0xF0D30004 -+#define F367_OFDM_BEND_SFEC_HW 0xF0D30002 -+#define F367_OFDM_BBAD_SFEC_HW 0xF0D30001 -+ -+/* RF_AGC1 */ -+#define R367_RF_AGC1 0xF0D4 -+#define F367_RF_AGC1_LEVEL_HI 0xF0D400FF -+ -+/* RF_AGC2 */ -+#define R367_RF_AGC2 0xF0D5 -+#define F367_REF_ADGP 0xF0D50080 -+#define F367_STDBY_ADCGP 0xF0D50020 -+#define F367_CHANNEL_SEL 0xF0D5001C -+#define F367_RF_AGC1_LEVEL_LO 0xF0D50003 -+ -+/* ANADIGCTRL */ -+#define R367_ANADIGCTRL 0xF0D7 -+#define F367_SEL_CLKDEM 0xF0D70020 -+#define F367_EN_BUFFER_Q 0xF0D70010 -+#define F367_EN_BUFFER_I 0xF0D70008 -+#define F367_ADC_RIS_EGDE 0xF0D70004 -+#define F367_SGN_ADC 0xF0D70002 -+#define F367_SEL_AD12_SYNC 0xF0D70001 -+ -+/* PLLMDIV */ -+#define R367_PLLMDIV 0xF0D8 -+#define F367_PLL_MDIV 0xF0D800FF -+ -+/* PLLNDIV */ -+#define R367_PLLNDIV 0xF0D9 -+#define F367_PLL_NDIV 0xF0D900FF -+ -+/* PLLSETUP */ -+#define R367_PLLSETUP 0xF0DA -+#define F367_PLL_PDIV 0xF0DA0070 -+#define F367_PLL_KDIV 0xF0DA000F -+ -+/* DUAL_AD12 */ -+#define R367_DUAL_AD12 0xF0DB -+#define F367_FS20M 0xF0DB0020 -+#define F367_FS50M 0xF0DB0010 -+#define F367_INMODE0 0xF0DB0008 -+#define F367_POFFQ 0xF0DB0004 -+#define F367_POFFI 0xF0DB0002 -+#define F367_INMODE1 0xF0DB0001 -+ -+/* TSTBIST */ -+#define R367_TSTBIST 0xF0DC -+#define F367_TST_BYP_CLK 0xF0DC0080 -+#define F367_TST_GCLKENA_STD 0xF0DC0040 -+#define F367_TST_GCLKENA 0xF0DC0020 -+#define F367_TST_MEMBIST 0xF0DC001F -+ -+/* PAD_COMP_CTRL */ -+#define R367_PAD_COMP_CTRL 0xF0DD -+#define F367_COMPTQ 0xF0DD0010 -+#define F367_COMPEN 0xF0DD0008 -+#define F367_FREEZE2 0xF0DD0004 -+#define F367_SLEEP_INHBT 0xF0DD0002 -+#define F367_CHIP_SLEEP 0xF0DD0001 -+ -+/* PAD_COMP_WR */ -+#define R367_PAD_COMP_WR 0xF0DE -+#define F367_WR_ASRC 0xF0DE007F -+ -+/* PAD_COMP_RD */ -+#define R367_PAD_COMP_RD 0xF0DF -+#define F367_COMPOK 0xF0DF0080 -+#define F367_RD_ASRC 0xF0DF007F -+ -+/* SYR_TARGET_FFTADJT_MSB */ -+#define R367_OFDM_SYR_TARGET_FFTADJT_MSB 0xF100 -+#define F367_OFDM_SYR_START 0xF1000080 -+#define F367_OFDM_SYR_TARGET_FFTADJ_HI 0xF100000F -+ -+/* SYR_TARGET_FFTADJT_LSB */ -+#define R367_OFDM_SYR_TARGET_FFTADJT_LSB 0xF101 -+#define F367_OFDM_SYR_TARGET_FFTADJ_LO 0xF10100FF -+ -+/* SYR_TARGET_CHCADJT_MSB */ -+#define R367_OFDM_SYR_TARGET_CHCADJT_MSB 0xF102 -+#define F367_OFDM_SYR_TARGET_CHCADJ_HI 0xF102000F -+ -+/* SYR_TARGET_CHCADJT_LSB */ -+#define R367_OFDM_SYR_TARGET_CHCADJT_LSB 0xF103 -+#define F367_OFDM_SYR_TARGET_CHCADJ_LO 0xF10300FF -+ -+/* SYR_FLAG */ -+#define R367_OFDM_SYR_FLAG 0xF104 -+#define F367_OFDM_TRIG_FLG1 0xF1040080 -+#define F367_OFDM_TRIG_FLG0 0xF1040040 -+#define F367_OFDM_FFT_FLG1 0xF1040008 -+#define F367_OFDM_FFT_FLG0 0xF1040004 -+#define F367_OFDM_CHC_FLG1 0xF1040002 -+#define F367_OFDM_CHC_FLG0 0xF1040001 -+ -+/* CRL_TARGET1 */ -+#define R367_OFDM_CRL_TARGET1 0xF105 -+#define F367_OFDM_CRL_START 0xF1050080 -+#define F367_OFDM_CRL_TARGET_VHI 0xF105000F -+ -+/* CRL_TARGET2 */ -+#define R367_OFDM_CRL_TARGET2 0xF106 -+#define F367_OFDM_CRL_TARGET_HI 0xF10600FF -+ -+/* CRL_TARGET3 */ -+#define R367_OFDM_CRL_TARGET3 0xF107 -+#define F367_OFDM_CRL_TARGET_LO 0xF10700FF -+ -+/* CRL_TARGET4 */ -+#define R367_OFDM_CRL_TARGET4 0xF108 -+#define F367_OFDM_CRL_TARGET_VLO 0xF10800FF -+ -+/* CRL_FLAG */ -+#define R367_OFDM_CRL_FLAG 0xF109 -+#define F367_OFDM_CRL_FLAG1 0xF1090002 -+#define F367_OFDM_CRL_FLAG0 0xF1090001 -+ -+/* TRL_TARGET1 */ -+#define R367_OFDM_TRL_TARGET1 0xF10A -+#define F367_OFDM_TRL_TARGET_HI 0xF10A00FF -+ -+/* TRL_TARGET2 */ -+#define R367_OFDM_TRL_TARGET2 0xF10B -+#define F367_OFDM_TRL_TARGET_LO 0xF10B00FF -+ -+/* TRL_CHC */ -+#define R367_OFDM_TRL_CHC 0xF10C -+#define F367_OFDM_TRL_START 0xF10C0080 -+#define F367_OFDM_CHC_START 0xF10C0040 -+#define F367_OFDM_TRL_FLAG1 0xF10C0002 -+#define F367_OFDM_TRL_FLAG0 0xF10C0001 -+ -+/* CHC_SNR_TARG */ -+#define R367_OFDM_CHC_SNR_TARG 0xF10D -+#define F367_OFDM_CHC_SNR_TARGET 0xF10D00FF -+ -+/* TOP_TRACK */ -+#define R367_OFDM_TOP_TRACK 0xF10E -+#define F367_OFDM_TOP_START 0xF10E0080 -+#define F367_OFDM_FIRST_FLAG 0xF10E0070 -+#define F367_OFDM_TOP_FLAG1 0xF10E0008 -+#define F367_OFDM_TOP_FLAG0 0xF10E0004 -+#define F367_OFDM_CHC_FLAG1 0xF10E0002 -+#define F367_OFDM_CHC_FLAG0 0xF10E0001 -+ -+/* TRACKER_FREE1 */ -+#define R367_OFDM_TRACKER_FREE1 0xF10F -+#define F367_OFDM_TRACKER_FREE_1 0xF10F00FF -+ -+/* ERROR_CRL1 */ -+#define R367_OFDM_ERROR_CRL1 0xF110 -+#define F367_OFDM_ERROR_CRL_VHI 0xF11000FF -+ -+/* ERROR_CRL2 */ -+#define R367_OFDM_ERROR_CRL2 0xF111 -+#define F367_OFDM_ERROR_CRL_HI 0xF11100FF -+ -+/* ERROR_CRL3 */ -+#define R367_OFDM_ERROR_CRL3 0xF112 -+#define F367_OFDM_ERROR_CRL_LOI 0xF11200FF -+ -+/* ERROR_CRL4 */ -+#define R367_OFDM_ERROR_CRL4 0xF113 -+#define F367_OFDM_ERROR_CRL_VLO 0xF11300FF -+ -+/* DEC_NCO1 */ -+#define R367_OFDM_DEC_NCO1 0xF114 -+#define F367_OFDM_DEC_NCO_VHI 0xF11400FF -+ -+/* DEC_NCO2 */ -+#define R367_OFDM_DEC_NCO2 0xF115 -+#define F367_OFDM_DEC_NCO_HI 0xF11500FF -+ -+/* DEC_NCO3 */ -+#define R367_OFDM_DEC_NCO3 0xF116 -+#define F367_OFDM_DEC_NCO_LO 0xF11600FF -+ -+/* SNR */ -+#define R367_OFDM_SNR 0xF117 -+#define F367_OFDM_SNRATIO 0xF11700FF -+ -+/* SYR_FFTADJ1 */ -+#define R367_OFDM_SYR_FFTADJ1 0xF118 -+#define F367_OFDM_SYR_FFTADJ_HI 0xF11800FF -+ -+/* SYR_FFTADJ2 */ -+#define R367_OFDM_SYR_FFTADJ2 0xF119 -+#define F367_OFDM_SYR_FFTADJ_LO 0xF11900FF -+ -+/* SYR_CHCADJ1 */ -+#define R367_OFDM_SYR_CHCADJ1 0xF11A -+#define F367_OFDM_SYR_CHCADJ_HI 0xF11A00FF -+ -+/* SYR_CHCADJ2 */ -+#define R367_OFDM_SYR_CHCADJ2 0xF11B -+#define F367_OFDM_SYR_CHCADJ_LO 0xF11B00FF -+ -+/* SYR_OFF */ -+#define R367_OFDM_SYR_OFF 0xF11C -+#define F367_OFDM_SYR_OFFSET 0xF11C00FF -+ -+/* PPM_OFFSET1 */ -+#define R367_OFDM_PPM_OFFSET1 0xF11D -+#define F367_OFDM_PPM_OFFSET_HI 0xF11D00FF -+ -+/* PPM_OFFSET2 */ -+#define R367_OFDM_PPM_OFFSET2 0xF11E -+#define F367_OFDM_PPM_OFFSET_LO 0xF11E00FF -+ -+/* TRACKER_FREE2 */ -+#define R367_OFDM_TRACKER_FREE2 0xF11F -+#define F367_OFDM_TRACKER_FREE_2 0xF11F00FF -+ -+/* DEBG_LT10 */ -+#define R367_OFDM_DEBG_LT10 0xF120 -+#define F367_OFDM_DEBUG_LT10 0xF12000FF -+ -+/* DEBG_LT11 */ -+#define R367_OFDM_DEBG_LT11 0xF121 -+#define F367_OFDM_DEBUG_LT11 0xF12100FF -+ -+/* DEBG_LT12 */ -+#define R367_OFDM_DEBG_LT12 0xF122 -+#define F367_OFDM_DEBUG_LT12 0xF12200FF -+ -+/* DEBG_LT13 */ -+#define R367_OFDM_DEBG_LT13 0xF123 -+#define F367_OFDM_DEBUG_LT13 0xF12300FF -+ -+/* DEBG_LT14 */ -+#define R367_OFDM_DEBG_LT14 0xF124 -+#define F367_OFDM_DEBUG_LT14 0xF12400FF -+ -+/* DEBG_LT15 */ -+#define R367_OFDM_DEBG_LT15 0xF125 -+#define F367_OFDM_DEBUG_LT15 0xF12500FF -+ -+/* DEBG_LT16 */ -+#define R367_OFDM_DEBG_LT16 0xF126 -+#define F367_OFDM_DEBUG_LT16 0xF12600FF -+ -+/* DEBG_LT17 */ -+#define R367_OFDM_DEBG_LT17 0xF127 -+#define F367_OFDM_DEBUG_LT17 0xF12700FF -+ -+/* DEBG_LT18 */ -+#define R367_OFDM_DEBG_LT18 0xF128 -+#define F367_OFDM_DEBUG_LT18 0xF12800FF -+ -+/* DEBG_LT19 */ -+#define R367_OFDM_DEBG_LT19 0xF129 -+#define F367_OFDM_DEBUG_LT19 0xF12900FF -+ -+/* DEBG_LT1A */ -+#define R367_OFDM_DEBG_LT1A 0xF12A -+#define F367_OFDM_DEBUG_LT1A 0xF12A00FF -+ -+/* DEBG_LT1B */ -+#define R367_OFDM_DEBG_LT1B 0xF12B -+#define F367_OFDM_DEBUG_LT1B 0xF12B00FF -+ -+/* DEBG_LT1C */ -+#define R367_OFDM_DEBG_LT1C 0xF12C -+#define F367_OFDM_DEBUG_LT1C 0xF12C00FF -+ -+/* DEBG_LT1D */ -+#define R367_OFDM_DEBG_LT1D 0xF12D -+#define F367_OFDM_DEBUG_LT1D 0xF12D00FF -+ -+/* DEBG_LT1E */ -+#define R367_OFDM_DEBG_LT1E 0xF12E -+#define F367_OFDM_DEBUG_LT1E 0xF12E00FF -+ -+/* DEBG_LT1F */ -+#define R367_OFDM_DEBG_LT1F 0xF12F -+#define F367_OFDM_DEBUG_LT1F 0xF12F00FF -+ -+/* RCCFGH */ -+#define R367_OFDM_RCCFGH 0xF200 -+#define F367_OFDM_TSRCFIFO_DVBCI 0xF2000080 -+#define F367_OFDM_TSRCFIFO_SERIAL 0xF2000040 -+#define F367_OFDM_TSRCFIFO_DISABLE 0xF2000020 -+#define F367_OFDM_TSFIFO_2TORC 0xF2000010 -+#define F367_OFDM_TSRCFIFO_HSGNLOUT 0xF2000008 -+#define F367_OFDM_TSRCFIFO_ERRMODE 0xF2000006 -+#define F367_OFDM_RCCFGH_0 0xF2000001 -+ -+/* RCCFGM */ -+#define R367_OFDM_RCCFGM 0xF201 -+#define F367_OFDM_TSRCFIFO_MANSPEED 0xF20100C0 -+#define F367_OFDM_TSRCFIFO_PERMDATA 0xF2010020 -+#define F367_OFDM_TSRCFIFO_NONEWSGNL 0xF2010010 -+#define F367_OFDM_RCBYTE_OVERSAMPLING 0xF201000E -+#define F367_OFDM_TSRCFIFO_INVDATA 0xF2010001 -+ -+/* RCCFGL */ -+#define R367_OFDM_RCCFGL 0xF202 -+#define F367_OFDM_TSRCFIFO_BCLKDEL1CK 0xF20200C0 -+#define F367_OFDM_RCCFGL_5 0xF2020020 -+#define F367_OFDM_TSRCFIFO_DUTY50 0xF2020010 -+#define F367_OFDM_TSRCFIFO_NSGNL2DATA 0xF2020008 -+#define F367_OFDM_TSRCFIFO_DISSERMUX 0xF2020004 -+#define F367_OFDM_RCCFGL_1 0xF2020002 -+#define F367_OFDM_TSRCFIFO_STOPCKDIS 0xF2020001 -+ -+/* RCINSDELH */ -+#define R367_OFDM_RCINSDELH 0xF203 -+#define F367_OFDM_TSRCDEL_SYNCBYTE 0xF2030080 -+#define F367_OFDM_TSRCDEL_XXHEADER 0xF2030040 -+#define F367_OFDM_TSRCDEL_BBHEADER 0xF2030020 -+#define F367_OFDM_TSRCDEL_DATAFIELD 0xF2030010 -+#define F367_OFDM_TSRCINSDEL_ISCR 0xF2030008 -+#define F367_OFDM_TSRCINSDEL_NPD 0xF2030004 -+#define F367_OFDM_TSRCINSDEL_RSPARITY 0xF2030002 -+#define F367_OFDM_TSRCINSDEL_CRC8 0xF2030001 -+ -+/* RCINSDELM */ -+#define R367_OFDM_RCINSDELM 0xF204 -+#define F367_OFDM_TSRCINS_BBPADDING 0xF2040080 -+#define F367_OFDM_TSRCINS_BCHFEC 0xF2040040 -+#define F367_OFDM_TSRCINS_LDPCFEC 0xF2040020 -+#define F367_OFDM_TSRCINS_EMODCOD 0xF2040010 -+#define F367_OFDM_TSRCINS_TOKEN 0xF2040008 -+#define F367_OFDM_TSRCINS_XXXERR 0xF2040004 -+#define F367_OFDM_TSRCINS_MATYPE 0xF2040002 -+#define F367_OFDM_TSRCINS_UPL 0xF2040001 -+ -+/* RCINSDELL */ -+#define R367_OFDM_RCINSDELL 0xF205 -+#define F367_OFDM_TSRCINS_DFL 0xF2050080 -+#define F367_OFDM_TSRCINS_SYNCD 0xF2050040 -+#define F367_OFDM_TSRCINS_BLOCLEN 0xF2050020 -+#define F367_OFDM_TSRCINS_SIGPCOUNT 0xF2050010 -+#define F367_OFDM_TSRCINS_FIFO 0xF2050008 -+#define F367_OFDM_TSRCINS_REALPACK 0xF2050004 -+#define F367_OFDM_TSRCINS_TSCONFIG 0xF2050002 -+#define F367_OFDM_TSRCINS_LATENCY 0xF2050001 -+ -+/* RCSTATUS */ -+#define R367_OFDM_RCSTATUS 0xF206 -+#define F367_OFDM_TSRCFIFO_LINEOK 0xF2060080 -+#define F367_OFDM_TSRCFIFO_ERROR 0xF2060040 -+#define F367_OFDM_TSRCFIFO_DATA7 0xF2060020 -+#define F367_OFDM_RCSTATUS_4 0xF2060010 -+#define F367_OFDM_TSRCFIFO_DEMODSEL 0xF2060008 -+#define F367_OFDM_TSRC1FIFOSPEED_STORE 0xF2060004 -+#define F367_OFDM_RCSTATUS_1 0xF2060002 -+#define F367_OFDM_TSRCSERIAL_IMPOSSIBLE 0xF2060001 -+ -+/* RCSPEED */ -+#define R367_OFDM_RCSPEED 0xF207 -+#define F367_OFDM_TSRCFIFO_OUTSPEED 0xF20700FF -+ -+/* RCDEBUGM */ -+#define R367_OFDM_RCDEBUGM 0xF208 -+#define F367_OFDM_SD_UNSYNC 0xF2080080 -+#define F367_OFDM_ULFLOCK_DETECTM 0xF2080040 -+#define F367_OFDM_SUL_SELECTOS 0xF2080020 -+#define F367_OFDM_DILUL_NOSCRBLE 0xF2080010 -+#define F367_OFDM_NUL_SCRB 0xF2080008 -+#define F367_OFDM_UL_SCRB 0xF2080004 -+#define F367_OFDM_SCRAULBAD 0xF2080002 -+#define F367_OFDM_SCRAUL_UNSYNC 0xF2080001 -+ -+/* RCDEBUGL */ -+#define R367_OFDM_RCDEBUGL 0xF209 -+#define F367_OFDM_RS_ERR 0xF2090080 -+#define F367_OFDM_LLFLOCK_DETECTM 0xF2090040 -+#define F367_OFDM_NOT_SUL_SELECTOS 0xF2090020 -+#define F367_OFDM_DILLL_NOSCRBLE 0xF2090010 -+#define F367_OFDM_NLL_SCRB 0xF2090008 -+#define F367_OFDM_LL_SCRB 0xF2090004 -+#define F367_OFDM_SCRALLBAD 0xF2090002 -+#define F367_OFDM_SCRALL_UNSYNC 0xF2090001 -+ -+/* RCOBSCFG */ -+#define R367_OFDM_RCOBSCFG 0xF20A -+#define F367_OFDM_TSRCFIFO_OBSCFG 0xF20A00FF -+ -+/* RCOBSM */ -+#define R367_OFDM_RCOBSM 0xF20B -+#define F367_OFDM_TSRCFIFO_OBSDATA_HI 0xF20B00FF -+ -+/* RCOBSL */ -+#define R367_OFDM_RCOBSL 0xF20C -+#define F367_OFDM_TSRCFIFO_OBSDATA_LO 0xF20C00FF -+ -+/* RCFECSPY */ -+#define R367_OFDM_RCFECSPY 0xF210 -+#define F367_OFDM_SPYRC_ENABLE 0xF2100080 -+#define F367_OFDM_RCNO_SYNCBYTE 0xF2100040 -+#define F367_OFDM_RCSERIAL_MODE 0xF2100020 -+#define F367_OFDM_RCUNUSUAL_PACKET 0xF2100010 -+#define F367_OFDM_BERRCMETER_DATAMODE 0xF210000C -+#define F367_OFDM_BERRCMETER_LMODE 0xF2100002 -+#define F367_OFDM_BERRCMETER_RESET 0xF2100001 -+ -+/* RCFSPYCFG */ -+#define R367_OFDM_RCFSPYCFG 0xF211 -+#define F367_OFDM_FECSPYRC_INPUT 0xF21100C0 -+#define F367_OFDM_RCRST_ON_ERROR 0xF2110020 -+#define F367_OFDM_RCONE_SHOT 0xF2110010 -+#define F367_OFDM_RCI2C_MODE 0xF211000C -+#define F367_OFDM_SPYRC_HSTERESIS 0xF2110003 -+ -+/* RCFSPYDATA */ -+#define R367_OFDM_RCFSPYDATA 0xF212 -+#define F367_OFDM_SPYRC_STUFFING 0xF2120080 -+#define F367_OFDM_RCNOERR_PKTJITTER 0xF2120040 -+#define F367_OFDM_SPYRC_CNULLPKT 0xF2120020 -+#define F367_OFDM_SPYRC_OUTDATA_MODE 0xF212001F -+ -+/* RCFSPYOUT */ -+#define R367_OFDM_RCFSPYOUT 0xF213 -+#define F367_OFDM_FSPYRC_DIRECT 0xF2130080 -+#define F367_OFDM_RCFSPYOUT_6 0xF2130040 -+#define F367_OFDM_SPYRC_OUTDATA_BUS 0xF2130038 -+#define F367_OFDM_RCSTUFF_MODE 0xF2130007 -+ -+/* RCFSTATUS */ -+#define R367_OFDM_RCFSTATUS 0xF214 -+#define F367_OFDM_SPYRC_ENDSIM 0xF2140080 -+#define F367_OFDM_RCVALID_SIM 0xF2140040 -+#define F367_OFDM_RCFOUND_SIGNAL 0xF2140020 -+#define F367_OFDM_RCDSS_SYNCBYTE 0xF2140010 -+#define F367_OFDM_RCRESULT_STATE 0xF214000F -+ -+/* RCFGOODPACK */ -+#define R367_OFDM_RCFGOODPACK 0xF215 -+#define F367_OFDM_RCGOOD_PACKET 0xF21500FF -+ -+/* RCFPACKCNT */ -+#define R367_OFDM_RCFPACKCNT 0xF216 -+#define F367_OFDM_RCPACKET_COUNTER 0xF21600FF -+ -+/* RCFSPYMISC */ -+#define R367_OFDM_RCFSPYMISC 0xF217 -+#define F367_OFDM_RCLABEL_COUNTER 0xF21700FF -+ -+/* RCFBERCPT4 */ -+#define R367_OFDM_RCFBERCPT4 0xF218 -+#define F367_OFDM_FBERRCMETER_CPT_MMMMSB 0xF21800FF -+ -+/* RCFBERCPT3 */ -+#define R367_OFDM_RCFBERCPT3 0xF219 -+#define F367_OFDM_FBERRCMETER_CPT_MMMSB 0xF21900FF -+ -+/* RCFBERCPT2 */ -+#define R367_OFDM_RCFBERCPT2 0xF21A -+#define F367_OFDM_FBERRCMETER_CPT_MMSB 0xF21A00FF -+ -+/* RCFBERCPT1 */ -+#define R367_OFDM_RCFBERCPT1 0xF21B -+#define F367_OFDM_FBERRCMETER_CPT_MSB 0xF21B00FF -+ -+/* RCFBERCPT0 */ -+#define R367_OFDM_RCFBERCPT0 0xF21C -+#define F367_OFDM_FBERRCMETER_CPT_LSB 0xF21C00FF -+ -+/* RCFBERERR2 */ -+#define R367_OFDM_RCFBERERR2 0xF21D -+#define F367_OFDM_FBERRCMETER_ERR_HI 0xF21D00FF -+ -+/* RCFBERERR1 */ -+#define R367_OFDM_RCFBERERR1 0xF21E -+#define F367_OFDM_FBERRCMETER_ERR 0xF21E00FF -+ -+/* RCFBERERR0 */ -+#define R367_OFDM_RCFBERERR0 0xF21F -+#define F367_OFDM_FBERRCMETER_ERR_LO 0xF21F00FF -+ -+/* RCFSTATESM */ -+#define R367_OFDM_RCFSTATESM 0xF220 -+#define F367_OFDM_RCRSTATE_F 0xF2200080 -+#define F367_OFDM_RCRSTATE_E 0xF2200040 -+#define F367_OFDM_RCRSTATE_D 0xF2200020 -+#define F367_OFDM_RCRSTATE_C 0xF2200010 -+#define F367_OFDM_RCRSTATE_B 0xF2200008 -+#define F367_OFDM_RCRSTATE_A 0xF2200004 -+#define F367_OFDM_RCRSTATE_9 0xF2200002 -+#define F367_OFDM_RCRSTATE_8 0xF2200001 -+ -+/* RCFSTATESL */ -+#define R367_OFDM_RCFSTATESL 0xF221 -+#define F367_OFDM_RCRSTATE_7 0xF2210080 -+#define F367_OFDM_RCRSTATE_6 0xF2210040 -+#define F367_OFDM_RCRSTATE_5 0xF2210020 -+#define F367_OFDM_RCRSTATE_4 0xF2210010 -+#define F367_OFDM_RCRSTATE_3 0xF2210008 -+#define F367_OFDM_RCRSTATE_2 0xF2210004 -+#define F367_OFDM_RCRSTATE_1 0xF2210002 -+#define F367_OFDM_RCRSTATE_0 0xF2210001 -+ -+/* RCFSPYBER */ -+#define R367_OFDM_RCFSPYBER 0xF222 -+#define F367_OFDM_RCFSPYBER_7 0xF2220080 -+#define F367_OFDM_SPYRCOBS_XORREAD 0xF2220040 -+#define F367_OFDM_FSPYRCBER_OBSMODE 0xF2220020 -+#define F367_OFDM_FSPYRCBER_SYNCBYT 0xF2220010 -+#define F367_OFDM_FSPYRCBER_UNSYNC 0xF2220008 -+#define F367_OFDM_FSPYRCBER_CTIME 0xF2220007 -+ -+/* RCFSPYDISTM */ -+#define R367_OFDM_RCFSPYDISTM 0xF223 -+#define F367_OFDM_RCPKTTIME_DISTANCE_HI 0xF22300FF -+ -+/* RCFSPYDISTL */ -+#define R367_OFDM_RCFSPYDISTL 0xF224 -+#define F367_OFDM_RCPKTTIME_DISTANCE_LO 0xF22400FF -+ -+/* RCFSPYOBS7 */ -+#define R367_OFDM_RCFSPYOBS7 0xF228 -+#define F367_OFDM_RCSPYOBS_SPYFAIL 0xF2280080 -+#define F367_OFDM_RCSPYOBS_SPYFAIL1 0xF2280040 -+#define F367_OFDM_RCSPYOBS_ERROR 0xF2280020 -+#define F367_OFDM_RCSPYOBS_STROUT 0xF2280010 -+#define F367_OFDM_RCSPYOBS_RESULTSTATE1 0xF228000F -+ -+/* RCFSPYOBS6 */ -+#define R367_OFDM_RCFSPYOBS6 0xF229 -+#define F367_OFDM_RCSPYOBS_RESULTSTATE0 0xF22900F0 -+#define F367_OFDM_RCSPYOBS_RESULTSTATEM1 0xF229000F -+ -+/* RCFSPYOBS5 */ -+#define R367_OFDM_RCFSPYOBS5 0xF22A -+#define F367_OFDM_RCSPYOBS_BYTEOFPACKET1 0xF22A00FF -+ -+/* RCFSPYOBS4 */ -+#define R367_OFDM_RCFSPYOBS4 0xF22B -+#define F367_OFDM_RCSPYOBS_BYTEVALUE1 0xF22B00FF -+ -+/* RCFSPYOBS3 */ -+#define R367_OFDM_RCFSPYOBS3 0xF22C -+#define F367_OFDM_RCSPYOBS_DATA1 0xF22C00FF -+ -+/* RCFSPYOBS2 */ -+#define R367_OFDM_RCFSPYOBS2 0xF22D -+#define F367_OFDM_RCSPYOBS_DATA0 0xF22D00FF -+ -+/* RCFSPYOBS1 */ -+#define R367_OFDM_RCFSPYOBS1 0xF22E -+#define F367_OFDM_RCSPYOBS_DATAM1 0xF22E00FF -+ -+/* RCFSPYOBS0 */ -+#define R367_OFDM_RCFSPYOBS0 0xF22F -+#define F367_OFDM_RCSPYOBS_DATAM2 0xF22F00FF -+ -+/* TSGENERAL */ -+#define R367_TSGENERAL 0xF230 -+#define F367_TSGENERAL_7 0xF2300080 -+#define F367_TSGENERAL_6 0xF2300040 -+#define F367_TSFIFO_BCLK1ALL 0xF2300020 -+#define F367_TSGENERAL_4 0xF2300010 -+#define F367_MUXSTREAM_OUTMODE 0xF2300008 -+#define F367_TSFIFO_PERMPARAL 0xF2300006 -+#define F367_RST_REEDSOLO 0xF2300001 -+ -+/* RC1SPEED */ -+#define R367_RC1SPEED 0xF231 -+#define F367_TSRCFIFO1_OUTSPEED 0xF23100FF -+ -+/* TSGSTATUS */ -+#define R367_TSGSTATUS 0xF232 -+#define F367_TSGSTATUS_7 0xF2320080 -+#define F367_TSGSTATUS_6 0xF2320040 -+#define F367_RSMEM_FULL 0xF2320020 -+#define F367_RS_MULTCALC 0xF2320010 -+#define F367_RSIN_OVERTIME 0xF2320008 -+#define F367_TSFIFO3_DEMODSEL 0xF2320004 -+#define F367_TSFIFO2_DEMODSEL 0xF2320002 -+#define F367_TSFIFO1_DEMODSEL 0xF2320001 -+ -+ -+/* FECM */ -+#define R367_OFDM_FECM 0xF233 -+#define F367_OFDM_DSS_DVB 0xF2330080 -+#define F367_OFDM_DEMOD_BYPASS 0xF2330040 -+#define F367_OFDM_CMP_SLOWMODE 0xF2330020 -+#define F367_OFDM_DSS_SRCH 0xF2330010 -+#define F367_OFDM_FECM_3 0xF2330008 -+#define F367_OFDM_DIFF_MODEVIT 0xF2330004 -+#define F367_OFDM_SYNCVIT 0xF2330002 -+#define F367_OFDM_I2CSYM 0xF2330001 -+ -+/* VTH12 */ -+#define R367_OFDM_VTH12 0xF234 -+#define F367_OFDM_VTH_12 0xF23400FF -+ -+/* VTH23 */ -+#define R367_OFDM_VTH23 0xF235 -+#define F367_OFDM_VTH_23 0xF23500FF -+ -+/* VTH34 */ -+#define R367_OFDM_VTH34 0xF236 -+#define F367_OFDM_VTH_34 0xF23600FF -+ -+/* VTH56 */ -+#define R367_OFDM_VTH56 0xF237 -+#define F367_OFDM_VTH_56 0xF23700FF -+ -+/* VTH67 */ -+#define R367_OFDM_VTH67 0xF238 -+#define F367_OFDM_VTH_67 0xF23800FF -+ -+/* VTH78 */ -+#define R367_OFDM_VTH78 0xF239 -+#define F367_OFDM_VTH_78 0xF23900FF -+ -+/* VITCURPUN */ -+#define R367_OFDM_VITCURPUN 0xF23A -+#define F367_OFDM_VIT_MAPPING 0xF23A00E0 -+#define F367_OFDM_VIT_CURPUN 0xF23A001F -+ -+/* VERROR */ -+#define R367_OFDM_VERROR 0xF23B -+#define F367_OFDM_REGERR_VIT 0xF23B00FF -+ -+/* PRVIT */ -+#define R367_OFDM_PRVIT 0xF23C -+#define F367_OFDM_PRVIT_7 0xF23C0080 -+#define F367_OFDM_DIS_VTHLOCK 0xF23C0040 -+#define F367_OFDM_E7_8VIT 0xF23C0020 -+#define F367_OFDM_E6_7VIT 0xF23C0010 -+#define F367_OFDM_E5_6VIT 0xF23C0008 -+#define F367_OFDM_E3_4VIT 0xF23C0004 -+#define F367_OFDM_E2_3VIT 0xF23C0002 -+#define F367_OFDM_E1_2VIT 0xF23C0001 -+ -+/* VAVSRVIT */ -+#define R367_OFDM_VAVSRVIT 0xF23D -+#define F367_OFDM_AMVIT 0xF23D0080 -+#define F367_OFDM_FROZENVIT 0xF23D0040 -+#define F367_OFDM_SNVIT 0xF23D0030 -+#define F367_OFDM_TOVVIT 0xF23D000C -+#define F367_OFDM_HYPVIT 0xF23D0003 -+ -+/* VSTATUSVIT */ -+#define R367_OFDM_VSTATUSVIT 0xF23E -+#define F367_OFDM_VITERBI_ON 0xF23E0080 -+#define F367_OFDM_END_LOOPVIT 0xF23E0040 -+#define F367_OFDM_VITERBI_DEPRF 0xF23E0020 -+#define F367_OFDM_PRFVIT 0xF23E0010 -+#define F367_OFDM_LOCKEDVIT 0xF23E0008 -+#define F367_OFDM_VITERBI_DELOCK 0xF23E0004 -+#define F367_OFDM_VIT_DEMODSEL 0xF23E0002 -+#define F367_OFDM_VITERBI_COMPOUT 0xF23E0001 -+ -+/* VTHINUSE */ -+#define R367_OFDM_VTHINUSE 0xF23F -+#define F367_OFDM_VIT_INUSE 0xF23F00FF -+ -+/* KDIV12 */ -+#define R367_OFDM_KDIV12 0xF240 -+#define F367_OFDM_KDIV12_MANUAL 0xF2400080 -+#define F367_OFDM_K_DIVIDER_12 0xF240007F -+ -+/* KDIV23 */ -+#define R367_OFDM_KDIV23 0xF241 -+#define F367_OFDM_KDIV23_MANUAL 0xF2410080 -+#define F367_OFDM_K_DIVIDER_23 0xF241007F -+ -+/* KDIV34 */ -+#define R367_OFDM_KDIV34 0xF242 -+#define F367_OFDM_KDIV34_MANUAL 0xF2420080 -+#define F367_OFDM_K_DIVIDER_34 0xF242007F -+ -+/* KDIV56 */ -+#define R367_OFDM_KDIV56 0xF243 -+#define F367_OFDM_KDIV56_MANUAL 0xF2430080 -+#define F367_OFDM_K_DIVIDER_56 0xF243007F -+ -+/* KDIV67 */ -+#define R367_OFDM_KDIV67 0xF244 -+#define F367_OFDM_KDIV67_MANUAL 0xF2440080 -+#define F367_OFDM_K_DIVIDER_67 0xF244007F -+ -+/* KDIV78 */ -+#define R367_OFDM_KDIV78 0xF245 -+#define F367_OFDM_KDIV78_MANUAL 0xF2450080 -+#define F367_OFDM_K_DIVIDER_78 0xF245007F -+ -+/* SIGPOWER */ -+#define R367_OFDM_SIGPOWER 0xF246 -+#define F367_OFDM_SIGPOWER_MANUAL 0xF2460080 -+#define F367_OFDM_SIG_POWER 0xF246007F -+ -+/* DEMAPVIT */ -+#define R367_OFDM_DEMAPVIT 0xF247 -+#define F367_OFDM_DEMAPVIT_7 0xF2470080 -+#define F367_OFDM_K_DIVIDER_VIT 0xF247007F -+ -+/* VITSCALE */ -+#define R367_OFDM_VITSCALE 0xF248 -+#define F367_OFDM_NVTH_NOSRANGE 0xF2480080 -+#define F367_OFDM_VERROR_MAXMODE 0xF2480040 -+#define F367_OFDM_KDIV_MODE 0xF2480030 -+#define F367_OFDM_NSLOWSN_LOCKED 0xF2480008 -+#define F367_OFDM_DELOCK_PRFLOSS 0xF2480004 -+#define F367_OFDM_DIS_RSFLOCK 0xF2480002 -+#define F367_OFDM_VITSCALE_0 0xF2480001 -+ -+/* FFEC1PRG */ -+#define R367_OFDM_FFEC1PRG 0xF249 -+#define F367_OFDM_FDSS_DVB 0xF2490080 -+#define F367_OFDM_FDSS_SRCH 0xF2490040 -+#define F367_OFDM_FFECPROG_5 0xF2490020 -+#define F367_OFDM_FFECPROG_4 0xF2490010 -+#define F367_OFDM_FFECPROG_3 0xF2490008 -+#define F367_OFDM_FFECPROG_2 0xF2490004 -+#define F367_OFDM_FTS1_DISABLE 0xF2490002 -+#define F367_OFDM_FTS2_DISABLE 0xF2490001 -+ -+/* FVITCURPUN */ -+#define R367_OFDM_FVITCURPUN 0xF24A -+#define F367_OFDM_FVIT_MAPPING 0xF24A00E0 -+#define F367_OFDM_FVIT_CURPUN 0xF24A001F -+ -+/* FVERROR */ -+#define R367_OFDM_FVERROR 0xF24B -+#define F367_OFDM_FREGERR_VIT 0xF24B00FF -+ -+/* FVSTATUSVIT */ -+#define R367_OFDM_FVSTATUSVIT 0xF24C -+#define F367_OFDM_FVITERBI_ON 0xF24C0080 -+#define F367_OFDM_F1END_LOOPVIT 0xF24C0040 -+#define F367_OFDM_FVITERBI_DEPRF 0xF24C0020 -+#define F367_OFDM_FPRFVIT 0xF24C0010 -+#define F367_OFDM_FLOCKEDVIT 0xF24C0008 -+#define F367_OFDM_FVITERBI_DELOCK 0xF24C0004 -+#define F367_OFDM_FVIT_DEMODSEL 0xF24C0002 -+#define F367_OFDM_FVITERBI_COMPOUT 0xF24C0001 -+ -+/* DEBUG_LT1 */ -+#define R367_OFDM_DEBUG_LT1 0xF24D -+#define F367_OFDM_DBG_LT1 0xF24D00FF -+ -+/* DEBUG_LT2 */ -+#define R367_OFDM_DEBUG_LT2 0xF24E -+#define F367_OFDM_DBG_LT2 0xF24E00FF -+ -+/* DEBUG_LT3 */ -+#define R367_OFDM_DEBUG_LT3 0xF24F -+#define F367_OFDM_DBG_LT3 0xF24F00FF -+ -+ /* TSTSFMET */ -+#define R367_OFDM_TSTSFMET 0xF250 -+#define F367_OFDM_TSTSFEC_METRIQUES 0xF25000FF -+ -+ /* SELOUT */ -+#define R367_OFDM_SELOUT 0xF252 -+#define F367_OFDM_EN_SYNC 0xF2520080 -+#define F367_OFDM_EN_TBUSDEMAP 0xF2520040 -+#define F367_OFDM_SELOUT_5 0xF2520020 -+#define F367_OFDM_SELOUT_4 0xF2520010 -+#define F367_OFDM_TSTSYNCHRO_MODE 0xF2520002 -+ -+ /* TSYNC */ -+#define R367_OFDM_TSYNC 0xF253 -+#define F367_OFDM_CURPUN_INCMODE 0xF2530080 -+#define F367_OFDM_CERR_TSTMODE 0xF2530040 -+#define F367_OFDM_SHIFTSOF_MODE 0xF2530030 -+#define F367_OFDM_SLOWPHA_MODE 0xF2530008 -+#define F367_OFDM_PXX_BYPALL 0xF2530004 -+#define F367_OFDM_FROTA45_FIRST 0xF2530002 -+#define F367_OFDM_TST_BCHERROR 0xF2530001 -+ -+ /* TSTERR */ -+#define R367_OFDM_TSTERR 0xF254 -+#define F367_OFDM_TST_LONGPKT 0xF2540080 -+#define F367_OFDM_TST_ISSYION 0xF2540040 -+#define F367_OFDM_TST_NPDON 0xF2540020 -+#define F367_OFDM_TSTERR_4 0xF2540010 -+#define F367_OFDM_TRACEBACK_MODE 0xF2540008 -+#define F367_OFDM_TST_RSPARITY 0xF2540004 -+#define F367_OFDM_METRIQUE_MODE 0xF2540003 -+ -+ /* TSFSYNC */ -+#define R367_OFDM_TSFSYNC 0xF255 -+#define F367_OFDM_EN_SFECSYNC 0xF2550080 -+#define F367_OFDM_EN_SFECDEMAP 0xF2550040 -+#define F367_OFDM_SFCERR_TSTMODE 0xF2550020 -+#define F367_OFDM_SFECPXX_BYPALL 0xF2550010 -+#define F367_OFDM_SFECTSTSYNCHRO_MODE 0xF255000F -+ -+ /* TSTSFERR */ -+#define R367_OFDM_TSTSFERR 0xF256 -+#define F367_OFDM_TSTSTERR_7 0xF2560080 -+#define F367_OFDM_TSTSTERR_6 0xF2560040 -+#define F367_OFDM_TSTSTERR_5 0xF2560020 -+#define F367_OFDM_TSTSTERR_4 0xF2560010 -+#define F367_OFDM_SFECTRACEBACK_MODE 0xF2560008 -+#define F367_OFDM_SFEC_NCONVPROG 0xF2560004 -+#define F367_OFDM_SFECMETRIQUE_MODE 0xF2560003 -+ -+ /* TSTTSSF1 */ -+#define R367_OFDM_TSTTSSF1 0xF258 -+#define F367_OFDM_TSTERSSF 0xF2580080 -+#define F367_OFDM_TSTTSSFEN 0xF2580040 -+#define F367_OFDM_SFEC_OUTMODE 0xF2580030 -+#define F367_OFDM_XLSF_NOFTHRESHOLD 0xF2580008 -+#define F367_OFDM_TSTTSSF_STACKSEL 0xF2580007 -+ -+ /* TSTTSSF2 */ -+#define R367_OFDM_TSTTSSF2 0xF259 -+#define F367_OFDM_DILSF_DBBHEADER 0xF2590080 -+#define F367_OFDM_TSTTSSF_DISBUG 0xF2590040 -+#define F367_OFDM_TSTTSSF_NOBADSTART 0xF2590020 -+#define F367_OFDM_TSTTSSF_SELECT 0xF259001F -+ -+ /* TSTTSSF3 */ -+#define R367_OFDM_TSTTSSF3 0xF25A -+#define F367_OFDM_TSTTSSF3_7 0xF25A0080 -+#define F367_OFDM_TSTTSSF3_6 0xF25A0040 -+#define F367_OFDM_TSTTSSF3_5 0xF25A0020 -+#define F367_OFDM_TSTTSSF3_4 0xF25A0010 -+#define F367_OFDM_TSTTSSF3_3 0xF25A0008 -+#define F367_OFDM_TSTTSSF3_2 0xF25A0004 -+#define F367_OFDM_TSTTSSF3_1 0xF25A0002 -+#define F367_OFDM_DISSF_CLKENABLE 0xF25A0001 -+ -+ /* TSTTS1 */ -+#define R367_OFDM_TSTTS1 0xF25C -+#define F367_OFDM_TSTERS 0xF25C0080 -+#define F367_OFDM_TSFIFO_DSSSYNCB 0xF25C0040 -+#define F367_OFDM_TSTTS_FSPYBEFRS 0xF25C0020 -+#define F367_OFDM_NFORCE_SYNCBYTE 0xF25C0010 -+#define F367_OFDM_XL_NOFTHRESHOLD 0xF25C0008 -+#define F367_OFDM_TSTTS_FRFORCEPKT 0xF25C0004 -+#define F367_OFDM_DESCR_NOTAUTO 0xF25C0002 -+#define F367_OFDM_TSTTSEN 0xF25C0001 -+ -+ /* TSTTS2 */ -+#define R367_OFDM_TSTTS2 0xF25D -+#define F367_OFDM_DIL_DBBHEADER 0xF25D0080 -+#define F367_OFDM_TSTTS_NOBADXXX 0xF25D0040 -+#define F367_OFDM_TSFIFO_DELSPEEDUP 0xF25D0020 -+#define F367_OFDM_TSTTS_SELECT 0xF25D001F -+ -+ /* TSTTS3 */ -+#define R367_OFDM_TSTTS3 0xF25E -+#define F367_OFDM_TSTTS_NOPKTGAIN 0xF25E0080 -+#define F367_OFDM_TSTTS_NOPKTENE 0xF25E0040 -+#define F367_OFDM_TSTTS_ISOLATION 0xF25E0020 -+#define F367_OFDM_TSTTS_DISBUG 0xF25E0010 -+#define F367_OFDM_TSTTS_NOBADSTART 0xF25E0008 -+#define F367_OFDM_TSTTS_STACKSEL 0xF25E0007 -+ -+ /* TSTTS4 */ -+#define R367_OFDM_TSTTS4 0xF25F -+#define F367_OFDM_TSTTS4_7 0xF25F0080 -+#define F367_OFDM_TSTTS4_6 0xF25F0040 -+#define F367_OFDM_TSTTS4_5 0xF25F0020 -+#define F367_OFDM_TSTTS_DISDSTATE 0xF25F0010 -+#define F367_OFDM_TSTTS_FASTNOSYNC 0xF25F0008 -+#define F367_OFDM_EXT_FECSPYIN 0xF25F0004 -+#define F367_OFDM_TSTTS_NODPZERO 0xF25F0002 -+#define F367_OFDM_TSTTS_NODIV3 0xF25F0001 -+ -+ /* TSTTSRC */ -+#define R367_OFDM_TSTTSRC 0xF26C -+#define F367_OFDM_TSTTSRC_7 0xF26C0080 -+#define F367_OFDM_TSRCFIFO_DSSSYNCB 0xF26C0040 -+#define F367_OFDM_TSRCFIFO_DPUNACTIVE 0xF26C0020 -+#define F367_OFDM_TSRCFIFO_DELSPEEDUP 0xF26C0010 -+#define F367_OFDM_TSTTSRC_NODIV3 0xF26C0008 -+#define F367_OFDM_TSTTSRC_FRFORCEPKT 0xF26C0004 -+#define F367_OFDM_SAT25_SDDORIGINE 0xF26C0002 -+#define F367_OFDM_TSTTSRC_INACTIVE 0xF26C0001 -+ -+ /* TSTTSRS */ -+#define R367_OFDM_TSTTSRS 0xF26D -+#define F367_OFDM_TSTTSRS_7 0xF26D0080 -+#define F367_OFDM_TSTTSRS_6 0xF26D0040 -+#define F367_OFDM_TSTTSRS_5 0xF26D0020 -+#define F367_OFDM_TSTTSRS_4 0xF26D0010 -+#define F367_OFDM_TSTTSRS_3 0xF26D0008 -+#define F367_OFDM_TSTTSRS_2 0xF26D0004 -+#define F367_OFDM_TSTRS_DISRS2 0xF26D0002 -+#define F367_OFDM_TSTRS_DISRS1 0xF26D0001 -+ -+/* TSSTATEM */ -+#define R367_OFDM_TSSTATEM 0xF270 -+#define F367_OFDM_TSDIL_ON 0xF2700080 -+#define F367_OFDM_TSSKIPRS_ON 0xF2700040 -+#define F367_OFDM_TSRS_ON 0xF2700020 -+#define F367_OFDM_TSDESCRAMB_ON 0xF2700010 -+#define F367_OFDM_TSFRAME_MODE 0xF2700008 -+#define F367_OFDM_TS_DISABLE 0xF2700004 -+#define F367_OFDM_TSACM_MODE 0xF2700002 -+#define F367_OFDM_TSOUT_NOSYNC 0xF2700001 -+ -+/* TSSTATEL */ -+#define R367_OFDM_TSSTATEL 0xF271 -+#define F367_OFDM_TSNOSYNCBYTE 0xF2710080 -+#define F367_OFDM_TSPARITY_ON 0xF2710040 -+#define F367_OFDM_TSSYNCOUTRS_ON 0xF2710020 -+#define F367_OFDM_TSDVBS2_MODE 0xF2710010 -+#define F367_OFDM_TSISSYI_ON 0xF2710008 -+#define F367_OFDM_TSNPD_ON 0xF2710004 -+#define F367_OFDM_TSCRC8_ON 0xF2710002 -+#define F367_OFDM_TSDSS_PACKET 0xF2710001 -+ -+/* TSCFGH */ -+#define R367_OFDM_TSCFGH 0xF272 -+#define F367_OFDM_TSFIFO_DVBCI 0xF2720080 -+#define F367_OFDM_TSFIFO_SERIAL 0xF2720040 -+#define F367_OFDM_TSFIFO_TEIUPDATE 0xF2720020 -+#define F367_OFDM_TSFIFO_DUTY50 0xF2720010 -+#define F367_OFDM_TSFIFO_HSGNLOUT 0xF2720008 -+#define F367_OFDM_TSFIFO_ERRMODE 0xF2720006 -+#define F367_OFDM_RST_HWARE 0xF2720001 -+ -+/* TSCFGM */ -+#define R367_OFDM_TSCFGM 0xF273 -+#define F367_OFDM_TSFIFO_MANSPEED 0xF27300C0 -+#define F367_OFDM_TSFIFO_PERMDATA 0xF2730020 -+#define F367_OFDM_TSFIFO_NONEWSGNL 0xF2730010 -+#define F367_OFDM_TSFIFO_BITSPEED 0xF2730008 -+#define F367_OFDM_NPD_SPECDVBS2 0xF2730004 -+#define F367_OFDM_TSFIFO_STOPCKDIS 0xF2730002 -+#define F367_OFDM_TSFIFO_INVDATA 0xF2730001 -+ -+/* TSCFGL */ -+#define R367_OFDM_TSCFGL 0xF274 -+#define F367_OFDM_TSFIFO_BCLKDEL1CK 0xF27400C0 -+#define F367_OFDM_BCHERROR_MODE 0xF2740030 -+#define F367_OFDM_TSFIFO_NSGNL2DATA 0xF2740008 -+#define F367_OFDM_TSFIFO_EMBINDVB 0xF2740004 -+#define F367_OFDM_TSFIFO_DPUNACT 0xF2740002 -+#define F367_OFDM_TSFIFO_NPDOFF 0xF2740001 -+ -+/* TSSYNC */ -+#define R367_OFDM_TSSYNC 0xF275 -+#define F367_OFDM_TSFIFO_PERMUTE 0xF2750080 -+#define F367_OFDM_TSFIFO_FISCR3B 0xF2750060 -+#define F367_OFDM_TSFIFO_SYNCMODE 0xF2750018 -+#define F367_OFDM_TSFIFO_SYNCSEL 0xF2750007 -+ -+/* TSINSDELH */ -+#define R367_OFDM_TSINSDELH 0xF276 -+#define F367_OFDM_TSDEL_SYNCBYTE 0xF2760080 -+#define F367_OFDM_TSDEL_XXHEADER 0xF2760040 -+#define F367_OFDM_TSDEL_BBHEADER 0xF2760020 -+#define F367_OFDM_TSDEL_DATAFIELD 0xF2760010 -+#define F367_OFDM_TSINSDEL_ISCR 0xF2760008 -+#define F367_OFDM_TSINSDEL_NPD 0xF2760004 -+#define F367_OFDM_TSINSDEL_RSPARITY 0xF2760002 -+#define F367_OFDM_TSINSDEL_CRC8 0xF2760001 -+ -+/* TSINSDELM */ -+#define R367_OFDM_TSINSDELM 0xF277 -+#define F367_OFDM_TSINS_BBPADDING 0xF2770080 -+#define F367_OFDM_TSINS_BCHFEC 0xF2770040 -+#define F367_OFDM_TSINS_LDPCFEC 0xF2770020 -+#define F367_OFDM_TSINS_EMODCOD 0xF2770010 -+#define F367_OFDM_TSINS_TOKEN 0xF2770008 -+#define F367_OFDM_TSINS_XXXERR 0xF2770004 -+#define F367_OFDM_TSINS_MATYPE 0xF2770002 -+#define F367_OFDM_TSINS_UPL 0xF2770001 -+ -+/* TSINSDELL */ -+#define R367_OFDM_TSINSDELL 0xF278 -+#define F367_OFDM_TSINS_DFL 0xF2780080 -+#define F367_OFDM_TSINS_SYNCD 0xF2780040 -+#define F367_OFDM_TSINS_BLOCLEN 0xF2780020 -+#define F367_OFDM_TSINS_SIGPCOUNT 0xF2780010 -+#define F367_OFDM_TSINS_FIFO 0xF2780008 -+#define F367_OFDM_TSINS_REALPACK 0xF2780004 -+#define F367_OFDM_TSINS_TSCONFIG 0xF2780002 -+#define F367_OFDM_TSINS_LATENCY 0xF2780001 -+ -+/* TSDIVN */ -+#define R367_OFDM_TSDIVN 0xF279 -+#define F367_OFDM_TSFIFO_LOWSPEED 0xF2790080 -+#define F367_OFDM_BYTE_OVERSAMPLING 0xF2790070 -+#define F367_OFDM_TSMANUAL_PACKETNBR 0xF279000F -+ -+/* TSDIVPM */ -+#define R367_OFDM_TSDIVPM 0xF27A -+#define F367_OFDM_TSMANUAL_P_HI 0xF27A00FF -+ -+/* TSDIVPL */ -+#define R367_OFDM_TSDIVPL 0xF27B -+#define F367_OFDM_TSMANUAL_P_LO 0xF27B00FF -+ -+/* TSDIVQM */ -+#define R367_OFDM_TSDIVQM 0xF27C -+#define F367_OFDM_TSMANUAL_Q_HI 0xF27C00FF -+ -+/* TSDIVQL */ -+#define R367_OFDM_TSDIVQL 0xF27D -+#define F367_OFDM_TSMANUAL_Q_LO 0xF27D00FF -+ -+/* TSDILSTKM */ -+#define R367_OFDM_TSDILSTKM 0xF27E -+#define F367_OFDM_TSFIFO_DILSTK_HI 0xF27E00FF -+ -+/* TSDILSTKL */ -+#define R367_OFDM_TSDILSTKL 0xF27F -+#define F367_OFDM_TSFIFO_DILSTK_LO 0xF27F00FF -+ -+/* TSSPEED */ -+#define R367_OFDM_TSSPEED 0xF280 -+#define F367_OFDM_TSFIFO_OUTSPEED 0xF28000FF -+ -+/* TSSTATUS */ -+#define R367_OFDM_TSSTATUS 0xF281 -+#define F367_OFDM_TSFIFO_LINEOK 0xF2810080 -+#define F367_OFDM_TSFIFO_ERROR 0xF2810040 -+#define F367_OFDM_TSFIFO_DATA7 0xF2810020 -+#define F367_OFDM_TSFIFO_NOSYNC 0xF2810010 -+#define F367_OFDM_ISCR_INITIALIZED 0xF2810008 -+#define F367_OFDM_ISCR_UPDATED 0xF2810004 -+#define F367_OFDM_SOFFIFO_UNREGUL 0xF2810002 -+#define F367_OFDM_DIL_READY 0xF2810001 -+ -+/* TSSTATUS2 */ -+#define R367_OFDM_TSSTATUS2 0xF282 -+#define F367_OFDM_TSFIFO_DEMODSEL 0xF2820080 -+#define F367_OFDM_TSFIFOSPEED_STORE 0xF2820040 -+#define F367_OFDM_DILXX_RESET 0xF2820020 -+#define F367_OFDM_TSSERIAL_IMPOSSIBLE 0xF2820010 -+#define F367_OFDM_TSFIFO_UNDERSPEED 0xF2820008 -+#define F367_OFDM_BITSPEED_EVENT 0xF2820004 -+#define F367_OFDM_UL_SCRAMBDETECT 0xF2820002 -+#define F367_OFDM_ULDTV67_FALSELOCK 0xF2820001 -+ -+/* TSBITRATEM */ -+#define R367_OFDM_TSBITRATEM 0xF283 -+#define F367_OFDM_TSFIFO_BITRATE_HI 0xF28300FF -+ -+/* TSBITRATEL */ -+#define R367_OFDM_TSBITRATEL 0xF284 -+#define F367_OFDM_TSFIFO_BITRATE_LO 0xF28400FF -+ -+/* TSPACKLENM */ -+#define R367_OFDM_TSPACKLENM 0xF285 -+#define F367_OFDM_TSFIFO_PACKCPT 0xF28500E0 -+#define F367_OFDM_DIL_RPLEN_HI 0xF285001F -+ -+/* TSPACKLENL */ -+#define R367_OFDM_TSPACKLENL 0xF286 -+#define F367_OFDM_DIL_RPLEN_LO 0xF28600FF -+ -+/* TSBLOCLENM */ -+#define R367_OFDM_TSBLOCLENM 0xF287 -+#define F367_OFDM_TSFIFO_PFLEN_HI 0xF28700FF -+ -+/* TSBLOCLENL */ -+#define R367_OFDM_TSBLOCLENL 0xF288 -+#define F367_OFDM_TSFIFO_PFLEN_LO 0xF28800FF -+ -+/* TSDLYH */ -+#define R367_OFDM_TSDLYH 0xF289 -+#define F367_OFDM_SOFFIFO_TSTIMEVALID 0xF2890080 -+#define F367_OFDM_SOFFIFO_SPEEDUP 0xF2890040 -+#define F367_OFDM_SOFFIFO_STOP 0xF2890020 -+#define F367_OFDM_SOFFIFO_REGULATED 0xF2890010 -+#define F367_OFDM_SOFFIFO_REALSBOFF_HI 0xF289000F -+ -+/* TSDLYM */ -+#define R367_OFDM_TSDLYM 0xF28A -+#define F367_OFDM_SOFFIFO_REALSBOFF_MED 0xF28A00FF -+ -+/* TSDLYL */ -+#define R367_OFDM_TSDLYL 0xF28B -+#define F367_OFDM_SOFFIFO_REALSBOFF_LO 0xF28B00FF -+ -+/* TSNPDAV */ -+#define R367_OFDM_TSNPDAV 0xF28C -+#define F367_OFDM_TSNPD_AVERAGE 0xF28C00FF -+ -+/* TSBUFSTATH */ -+#define R367_OFDM_TSBUFSTATH 0xF28D -+#define F367_OFDM_TSISCR_3BYTES 0xF28D0080 -+#define F367_OFDM_TSISCR_NEWDATA 0xF28D0040 -+#define F367_OFDM_TSISCR_BUFSTAT_HI 0xF28D003F -+ -+/* TSBUFSTATM */ -+#define R367_OFDM_TSBUFSTATM 0xF28E -+#define F367_OFDM_TSISCR_BUFSTAT_MED 0xF28E00FF -+ -+/* TSBUFSTATL */ -+#define R367_OFDM_TSBUFSTATL 0xF28F -+#define F367_OFDM_TSISCR_BUFSTAT_LO 0xF28F00FF -+ -+/* TSDEBUGM */ -+#define R367_OFDM_TSDEBUGM 0xF290 -+#define F367_OFDM_TSFIFO_ILLPACKET 0xF2900080 -+#define F367_OFDM_DIL_NOSYNC 0xF2900040 -+#define F367_OFDM_DIL_ISCR 0xF2900020 -+#define F367_OFDM_DILOUT_BSYNCB 0xF2900010 -+#define F367_OFDM_TSFIFO_EMPTYPKT 0xF2900008 -+#define F367_OFDM_TSFIFO_EMPTYRD 0xF2900004 -+#define F367_OFDM_SOFFIFO_STOPM 0xF2900002 -+#define F367_OFDM_SOFFIFO_SPEEDUPM 0xF2900001 -+ -+/* TSDEBUGL */ -+#define R367_OFDM_TSDEBUGL 0xF291 -+#define F367_OFDM_TSFIFO_PACKLENFAIL 0xF2910080 -+#define F367_OFDM_TSFIFO_SYNCBFAIL 0xF2910040 -+#define F367_OFDM_TSFIFO_VITLIBRE 0xF2910020 -+#define F367_OFDM_TSFIFO_BOOSTSPEEDM 0xF2910010 -+#define F367_OFDM_TSFIFO_UNDERSPEEDM 0xF2910008 -+#define F367_OFDM_TSFIFO_ERROR_EVNT 0xF2910004 -+#define F367_OFDM_TSFIFO_FULL 0xF2910002 -+#define F367_OFDM_TSFIFO_OVERFLOWM 0xF2910001 -+ -+/* TSDLYSETH */ -+#define R367_OFDM_TSDLYSETH 0xF292 -+#define F367_OFDM_SOFFIFO_OFFSET 0xF29200E0 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_HI 0xF292001F -+ -+/* TSDLYSETM */ -+#define R367_OFDM_TSDLYSETM 0xF293 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_MED 0xF29300FF -+ -+/* TSDLYSETL */ -+#define R367_OFDM_TSDLYSETL 0xF294 -+#define F367_OFDM_SOFFIFO_SYMBOFFSET_LO 0xF29400FF -+ -+/* TSOBSCFG */ -+#define R367_OFDM_TSOBSCFG 0xF295 -+#define F367_OFDM_TSFIFO_OBSCFG 0xF29500FF -+ -+/* TSOBSM */ -+#define R367_OFDM_TSOBSM 0xF296 -+#define F367_OFDM_TSFIFO_OBSDATA_HI 0xF29600FF -+ -+/* TSOBSL */ -+#define R367_OFDM_TSOBSL 0xF297 -+#define F367_OFDM_TSFIFO_OBSDATA_LO 0xF29700FF -+ -+/* ERRCTRL1 */ -+#define R367_OFDM_ERRCTRL1 0xF298 -+#define F367_OFDM_ERR_SRC1 0xF29800F0 -+#define F367_OFDM_ERRCTRL1_3 0xF2980008 -+#define F367_OFDM_NUM_EVT1 0xF2980007 -+ -+/* ERRCNT1H */ -+#define R367_OFDM_ERRCNT1H 0xF299 -+#define F367_OFDM_ERRCNT1_OLDVALUE 0xF2990080 -+#define F367_OFDM_ERR_CNT1 0xF299007F -+ -+/* ERRCNT1M */ -+#define R367_OFDM_ERRCNT1M 0xF29A -+#define F367_OFDM_ERR_CNT1_HI 0xF29A00FF -+ -+/* ERRCNT1L */ -+#define R367_OFDM_ERRCNT1L 0xF29B -+#define F367_OFDM_ERR_CNT1_LO 0xF29B00FF -+ -+/* ERRCTRL2 */ -+#define R367_OFDM_ERRCTRL2 0xF29C -+#define F367_OFDM_ERR_SRC2 0xF29C00F0 -+#define F367_OFDM_ERRCTRL2_3 0xF29C0008 -+#define F367_OFDM_NUM_EVT2 0xF29C0007 -+ -+/* ERRCNT2H */ -+#define R367_OFDM_ERRCNT2H 0xF29D -+#define F367_OFDM_ERRCNT2_OLDVALUE 0xF29D0080 -+#define F367_OFDM_ERR_CNT2_HI 0xF29D007F -+ -+/* ERRCNT2M */ -+#define R367_OFDM_ERRCNT2M 0xF29E -+#define F367_OFDM_ERR_CNT2_MED 0xF29E00FF -+ -+/* ERRCNT2L */ -+#define R367_OFDM_ERRCNT2L 0xF29F -+#define F367_OFDM_ERR_CNT2_LO 0xF29F00FF -+ -+/* FECSPY */ -+#define R367_OFDM_FECSPY 0xF2A0 -+#define F367_OFDM_SPY_ENABLE 0xF2A00080 -+#define F367_OFDM_NO_SYNCBYTE 0xF2A00040 -+#define F367_OFDM_SERIAL_MODE 0xF2A00020 -+#define F367_OFDM_UNUSUAL_PACKET 0xF2A00010 -+#define F367_OFDM_BERMETER_DATAMODE 0xF2A0000C -+#define F367_OFDM_BERMETER_LMODE 0xF2A00002 -+#define F367_OFDM_BERMETER_RESET 0xF2A00001 -+ -+/* FSPYCFG */ -+#define R367_OFDM_FSPYCFG 0xF2A1 -+#define F367_OFDM_FECSPY_INPUT 0xF2A100C0 -+#define F367_OFDM_RST_ON_ERROR 0xF2A10020 -+#define F367_OFDM_ONE_SHOT 0xF2A10010 -+#define F367_OFDM_I2C_MOD 0xF2A1000C -+#define F367_OFDM_SPY_HYSTERESIS 0xF2A10003 -+ -+/* FSPYDATA */ -+#define R367_OFDM_FSPYDATA 0xF2A2 -+#define F367_OFDM_SPY_STUFFING 0xF2A20080 -+#define F367_OFDM_NOERROR_PKTJITTER 0xF2A20040 -+#define F367_OFDM_SPY_CNULLPKT 0xF2A20020 -+#define F367_OFDM_SPY_OUTDATA_MODE 0xF2A2001F -+ -+/* FSPYOUT */ -+#define R367_OFDM_FSPYOUT 0xF2A3 -+#define F367_OFDM_FSPY_DIRECT 0xF2A30080 -+#define F367_OFDM_FSPYOUT_6 0xF2A30040 -+#define F367_OFDM_SPY_OUTDATA_BUS 0xF2A30038 -+#define F367_OFDM_STUFF_MODE 0xF2A30007 -+ -+/* FSTATUS */ -+#define R367_OFDM_FSTATUS 0xF2A4 -+#define F367_OFDM_SPY_ENDSIM 0xF2A40080 -+#define F367_OFDM_VALID_SIM 0xF2A40040 -+#define F367_OFDM_FOUND_SIGNAL 0xF2A40020 -+#define F367_OFDM_DSS_SYNCBYTE 0xF2A40010 -+#define F367_OFDM_RESULT_STATE 0xF2A4000F -+ -+/* FGOODPACK */ -+#define R367_OFDM_FGOODPACK 0xF2A5 -+#define F367_OFDM_FGOOD_PACKET 0xF2A500FF -+ -+/* FPACKCNT */ -+#define R367_OFDM_FPACKCNT 0xF2A6 -+#define F367_OFDM_FPACKET_COUNTER 0xF2A600FF -+ -+/* FSPYMISC */ -+#define R367_OFDM_FSPYMISC 0xF2A7 -+#define F367_OFDM_FLABEL_COUNTER 0xF2A700FF -+ -+/* FBERCPT4 */ -+#define R367_OFDM_FBERCPT4 0xF2A8 -+#define F367_OFDM_FBERMETER_CPT5 0xF2A800FF -+ -+/* FBERCPT3 */ -+#define R367_OFDM_FBERCPT3 0xF2A9 -+#define F367_OFDM_FBERMETER_CPT4 0xF2A900FF -+ -+/* FBERCPT2 */ -+#define R367_OFDM_FBERCPT2 0xF2AA -+#define F367_OFDM_FBERMETER_CPT3 0xF2AA00FF -+ -+/* FBERCPT1 */ -+#define R367_OFDM_FBERCPT1 0xF2AB -+#define F367_OFDM_FBERMETER_CPT2 0xF2AB00FF -+ -+/* FBERCPT0 */ -+#define R367_OFDM_FBERCPT0 0xF2AC -+#define F367_OFDM_FBERMETER_CPT1 0xF2AC00FF -+ -+/* FBERERR2 */ -+#define R367_OFDM_FBERERR2 0xF2AD -+#define F367_OFDM_FBERMETER_ERR_HI 0xF2AD00FF -+ -+/* FBERERR1 */ -+#define R367_OFDM_FBERERR1 0xF2AE -+#define F367_OFDM_FBERMETER_ERR_MED 0xF2AE00FF -+ -+/* FBERERR0 */ -+#define R367_OFDM_FBERERR0 0xF2AF -+#define F367_OFDM_FBERMETER_ERR_LO 0xF2AF00FF -+ -+/* FSTATESM */ -+#define R367_OFDM_FSTATESM 0xF2B0 -+#define F367_OFDM_RSTATE_F 0xF2B00080 -+#define F367_OFDM_RSTATE_E 0xF2B00040 -+#define F367_OFDM_RSTATE_D 0xF2B00020 -+#define F367_OFDM_RSTATE_C 0xF2B00010 -+#define F367_OFDM_RSTATE_B 0xF2B00008 -+#define F367_OFDM_RSTATE_A 0xF2B00004 -+#define F367_OFDM_RSTATE_9 0xF2B00002 -+#define F367_OFDM_RSTATE_8 0xF2B00001 -+ -+/* FSTATESL */ -+#define R367_OFDM_FSTATESL 0xF2B1 -+#define F367_OFDM_RSTATE_7 0xF2B10080 -+#define F367_OFDM_RSTATE_6 0xF2B10040 -+#define F367_OFDM_RSTATE_5 0xF2B10020 -+#define F367_OFDM_RSTATE_4 0xF2B10010 -+#define F367_OFDM_RSTATE_3 0xF2B10008 -+#define F367_OFDM_RSTATE_2 0xF2B10004 -+#define F367_OFDM_RSTATE_1 0xF2B10002 -+#define F367_OFDM_RSTATE_0 0xF2B10001 -+ -+/* FSPYBER */ -+#define R367_OFDM_FSPYBER 0xF2B2 -+#define F367_OFDM_FSPYBER_7 0xF2B20080 -+#define F367_OFDM_FSPYOBS_XORREAD 0xF2B20040 -+#define F367_OFDM_FSPYBER_OBSMODE 0xF2B20020 -+#define F367_OFDM_FSPYBER_SYNCBYTE 0xF2B20010 -+#define F367_OFDM_FSPYBER_UNSYNC 0xF2B20008 -+#define F367_OFDM_FSPYBER_CTIME 0xF2B20007 -+ -+/* FSPYDISTM */ -+#define R367_OFDM_FSPYDISTM 0xF2B3 -+#define F367_OFDM_PKTTIME_DISTANCE_HI 0xF2B300FF -+ -+/* FSPYDISTL */ -+#define R367_OFDM_FSPYDISTL 0xF2B4 -+#define F367_OFDM_PKTTIME_DISTANCE_LO 0xF2B400FF -+ -+/* FSPYOBS7 */ -+#define R367_OFDM_FSPYOBS7 0xF2B8 -+#define F367_OFDM_FSPYOBS_SPYFAIL 0xF2B80080 -+#define F367_OFDM_FSPYOBS_SPYFAIL1 0xF2B80040 -+#define F367_OFDM_FSPYOBS_ERROR 0xF2B80020 -+#define F367_OFDM_FSPYOBS_STROUT 0xF2B80010 -+#define F367_OFDM_FSPYOBS_RESULTSTATE1 0xF2B8000F -+ -+/* FSPYOBS6 */ -+#define R367_OFDM_FSPYOBS6 0xF2B9 -+#define F367_OFDM_FSPYOBS_RESULTSTATE0 0xF2B900F0 -+#define F367_OFDM_FSPYOBS_RESULTSTATEM1 0xF2B9000F -+ -+/* FSPYOBS5 */ -+#define R367_OFDM_FSPYOBS5 0xF2BA -+#define F367_OFDM_FSPYOBS_BYTEOFPACKET1 0xF2BA00FF -+ -+/* FSPYOBS4 */ -+#define R367_OFDM_FSPYOBS4 0xF2BB -+#define F367_OFDM_FSPYOBS_BYTEVALUE1 0xF2BB00FF -+ -+/* FSPYOBS3 */ -+#define R367_OFDM_FSPYOBS3 0xF2BC -+#define F367_OFDM_FSPYOBS_DATA1 0xF2BC00FF -+ -+/* FSPYOBS2 */ -+#define R367_OFDM_FSPYOBS2 0xF2BD -+#define F367_OFDM_FSPYOBS_DATA0 0xF2BD00FF -+ -+/* FSPYOBS1 */ -+#define R367_OFDM_FSPYOBS1 0xF2BE -+#define F367_OFDM_FSPYOBS_DATAM1 0xF2BE00FF -+ -+/* FSPYOBS0 */ -+#define R367_OFDM_FSPYOBS0 0xF2BF -+#define F367_OFDM_FSPYOBS_DATAM2 0xF2BF00FF -+ -+/* SFDEMAP */ -+#define R367_OFDM_SFDEMAP 0xF2C0 -+#define F367_OFDM_SFDEMAP_7 0xF2C00080 -+#define F367_OFDM_SFEC_K_DIVIDER_VIT 0xF2C0007F -+ -+/* SFERROR */ -+#define R367_OFDM_SFERROR 0xF2C1 -+#define F367_OFDM_SFEC_REGERR_VIT 0xF2C100FF -+ -+/* SFAVSR */ -+#define R367_OFDM_SFAVSR 0xF2C2 -+#define F367_OFDM_SFEC_SUMERRORS 0xF2C20080 -+#define F367_OFDM_SERROR_MAXMODE 0xF2C20040 -+#define F367_OFDM_SN_SFEC 0xF2C20030 -+#define F367_OFDM_KDIV_MODE_SFEC 0xF2C2000C -+#define F367_OFDM_SFAVSR_1 0xF2C20002 -+#define F367_OFDM_SFAVSR_0 0xF2C20001 -+ -+/* SFECSTATUS */ -+#define R367_OFDM_SFECSTATUS 0xF2C3 -+#define F367_OFDM_SFEC_ON 0xF2C30080 -+#define F367_OFDM_SFSTATUS_6 0xF2C30040 -+#define F367_OFDM_SFSTATUS_5 0xF2C30020 -+#define F367_OFDM_SFSTATUS_4 0xF2C30010 -+#define F367_OFDM_LOCKEDSFEC 0xF2C30008 -+#define F367_OFDM_SFEC_DELOCK 0xF2C30004 -+#define F367_OFDM_SFEC_DEMODSEL1 0xF2C30002 -+#define F367_OFDM_SFEC_OVFON 0xF2C30001 -+ -+/* SFKDIV12 */ -+#define R367_OFDM_SFKDIV12 0xF2C4 -+#define F367_OFDM_SFECKDIV12_MAN 0xF2C40080 -+#define F367_OFDM_SFEC_K_DIVIDER_12 0xF2C4007F -+ -+/* SFKDIV23 */ -+#define R367_OFDM_SFKDIV23 0xF2C5 -+#define F367_OFDM_SFECKDIV23_MAN 0xF2C50080 -+#define F367_OFDM_SFEC_K_DIVIDER_23 0xF2C5007F -+ -+/* SFKDIV34 */ -+#define R367_OFDM_SFKDIV34 0xF2C6 -+#define F367_OFDM_SFECKDIV34_MAN 0xF2C60080 -+#define F367_OFDM_SFEC_K_DIVIDER_34 0xF2C6007F -+ -+/* SFKDIV56 */ -+#define R367_OFDM_SFKDIV56 0xF2C7 -+#define F367_OFDM_SFECKDIV56_MAN 0xF2C70080 -+#define F367_OFDM_SFEC_K_DIVIDER_56 0xF2C7007F -+ -+/* SFKDIV67 */ -+#define R367_OFDM_SFKDIV67 0xF2C8 -+#define F367_OFDM_SFECKDIV67_MAN 0xF2C80080 -+#define F367_OFDM_SFEC_K_DIVIDER_67 0xF2C8007F -+ -+/* SFKDIV78 */ -+#define R367_OFDM_SFKDIV78 0xF2C9 -+#define F367_OFDM_SFECKDIV78_MAN 0xF2C90080 -+#define F367_OFDM_SFEC_K_DIVIDER_78 0xF2C9007F -+ -+/* SFDILSTKM */ -+#define R367_OFDM_SFDILSTKM 0xF2CA -+#define F367_OFDM_SFEC_PACKCPT 0xF2CA00E0 -+#define F367_OFDM_SFEC_DILSTK_HI 0xF2CA001F -+ -+/* SFDILSTKL */ -+#define R367_OFDM_SFDILSTKL 0xF2CB -+#define F367_OFDM_SFEC_DILSTK_LO 0xF2CB00FF -+ -+/* SFSTATUS */ -+#define R367_OFDM_SFSTATUS 0xF2CC -+#define F367_OFDM_SFEC_LINEOK 0xF2CC0080 -+#define F367_OFDM_SFEC_ERROR 0xF2CC0040 -+#define F367_OFDM_SFEC_DATA7 0xF2CC0020 -+#define F367_OFDM_SFEC_OVERFLOW 0xF2CC0010 -+#define F367_OFDM_SFEC_DEMODSEL2 0xF2CC0008 -+#define F367_OFDM_SFEC_NOSYNC 0xF2CC0004 -+#define F367_OFDM_SFEC_UNREGULA 0xF2CC0002 -+#define F367_OFDM_SFEC_READY 0xF2CC0001 -+ -+/* SFDLYH */ -+#define R367_OFDM_SFDLYH 0xF2CD -+#define F367_OFDM_SFEC_TSTIMEVALID 0xF2CD0080 -+#define F367_OFDM_SFEC_SPEEDUP 0xF2CD0040 -+#define F367_OFDM_SFEC_STOP 0xF2CD0020 -+#define F367_OFDM_SFEC_REGULATED 0xF2CD0010 -+#define F367_OFDM_SFEC_REALSYMBOFFSET 0xF2CD000F -+ -+/* SFDLYM */ -+#define R367_OFDM_SFDLYM 0xF2CE -+#define F367_OFDM_SFEC_REALSYMBOFFSET_HI 0xF2CE00FF -+ -+/* SFDLYL */ -+#define R367_OFDM_SFDLYL 0xF2CF -+#define F367_OFDM_SFEC_REALSYMBOFFSET_LO 0xF2CF00FF -+ -+/* SFDLYSETH */ -+#define R367_OFDM_SFDLYSETH 0xF2D0 -+#define F367_OFDM_SFEC_OFFSET 0xF2D000E0 -+#define F367_OFDM_SFECDLYSETH_4 0xF2D00010 -+#define F367_OFDM_RST_SFEC 0xF2D00008 -+#define F367_OFDM_SFECDLYSETH_2 0xF2D00004 -+#define F367_OFDM_SFEC_DISABLE 0xF2D00002 -+#define F367_OFDM_SFEC_UNREGUL 0xF2D00001 -+ -+/* SFDLYSETM */ -+#define R367_OFDM_SFDLYSETM 0xF2D1 -+#define F367_OFDM_SFECDLYSETM_7 0xF2D10080 -+#define F367_OFDM_SFEC_SYMBOFFSET_HI 0xF2D1007F -+ -+/* SFDLYSETL */ -+#define R367_OFDM_SFDLYSETL 0xF2D2 -+#define F367_OFDM_SFEC_SYMBOFFSET_LO 0xF2D200FF -+ -+/* SFOBSCFG */ -+#define R367_OFDM_SFOBSCFG 0xF2D3 -+#define F367_OFDM_SFEC_OBSCFG 0xF2D300FF -+ -+/* SFOBSM */ -+#define R367_OFDM_SFOBSM 0xF2D4 -+#define F367_OFDM_SFEC_OBSDATA_HI 0xF2D400FF -+ -+/* SFOBSL */ -+#define R367_OFDM_SFOBSL 0xF2D5 -+#define F367_OFDM_SFEC_OBSDATA_LO 0xF2D500FF -+ -+/* SFECINFO */ -+#define R367_OFDM_SFECINFO 0xF2D6 -+#define F367_OFDM_SFECINFO_7 0xF2D60080 -+#define F367_OFDM_SFEC_SYNCDLSB 0xF2D60070 -+#define F367_OFDM_SFCE_S1CPHASE 0xF2D6000F -+ -+/* SFERRCTRL */ -+#define R367_OFDM_SFERRCTRL 0xF2D8 -+#define F367_OFDM_SFEC_ERR_SOURCE 0xF2D800F0 -+#define F367_OFDM_SFERRCTRL_3 0xF2D80008 -+#define F367_OFDM_SFEC_NUM_EVENT 0xF2D80007 -+ -+/* SFERRCNTH */ -+#define R367_OFDM_SFERRCNTH 0xF2D9 -+#define F367_OFDM_SFERRC_OLDVALUE 0xF2D90080 -+#define F367_OFDM_SFEC_ERR_CNT 0xF2D9007F -+ -+/* SFERRCNTM */ -+#define R367_OFDM_SFERRCNTM 0xF2DA -+#define F367_OFDM_SFEC_ERR_CNT_HI 0xF2DA00FF -+ -+/* SFERRCNTL */ -+#define R367_OFDM_SFERRCNTL 0xF2DB -+#define F367_OFDM_SFEC_ERR_CNT_LO 0xF2DB00FF -+ -+/* SYMBRATEM */ -+#define R367_OFDM_SYMBRATEM 0xF2E0 -+#define F367_OFDM_DEFGEN_SYMBRATE_HI 0xF2E000FF -+ -+/* SYMBRATEL */ -+#define R367_OFDM_SYMBRATEL 0xF2E1 -+#define F367_OFDM_DEFGEN_SYMBRATE_LO 0xF2E100FF -+ -+/* SYMBSTATUS */ -+#define R367_OFDM_SYMBSTATUS 0xF2E2 -+#define F367_OFDM_SYMBDLINE2_OFF 0xF2E20080 -+#define F367_OFDM_SDDL_REINIT1 0xF2E20040 -+#define F367_OFDM_SDD_REINIT1 0xF2E20020 -+#define F367_OFDM_TOKENID_ERROR 0xF2E20010 -+#define F367_OFDM_SYMBRATE_OVERFLOW 0xF2E20008 -+#define F367_OFDM_SYMBRATE_UNDERFLOW 0xF2E20004 -+#define F367_OFDM_TOKENID_RSTEVENT 0xF2E20002 -+#define F367_OFDM_TOKENID_RESET1 0xF2E20001 -+ -+/* SYMBCFG */ -+#define R367_OFDM_SYMBCFG 0xF2E3 -+#define F367_OFDM_SYMBCFG_7 0xF2E30080 -+#define F367_OFDM_SYMBCFG_6 0xF2E30040 -+#define F367_OFDM_SYMBCFG_5 0xF2E30020 -+#define F367_OFDM_SYMBCFG_4 0xF2E30010 -+#define F367_OFDM_SYMRATE_FSPEED 0xF2E3000C -+#define F367_OFDM_SYMRATE_SSPEED 0xF2E30003 -+ -+/* SYMBFIFOM */ -+#define R367_OFDM_SYMBFIFOM 0xF2E4 -+#define F367_OFDM_SYMBFIFOM_7 0xF2E40080 -+#define F367_OFDM_SYMBFIFOM_6 0xF2E40040 -+#define F367_OFDM_DEFGEN_SYMFIFO_HI 0xF2E4003F -+ -+/* SYMBFIFOL */ -+#define R367_OFDM_SYMBFIFOL 0xF2E5 -+#define F367_OFDM_DEFGEN_SYMFIFO_LO 0xF2E500FF -+ -+/* SYMBOFFSM */ -+#define R367_OFDM_SYMBOFFSM 0xF2E6 -+#define F367_OFDM_TOKENID_RESET2 0xF2E60080 -+#define F367_OFDM_SDDL_REINIT2 0xF2E60040 -+#define F367_OFDM_SDD_REINIT2 0xF2E60020 -+#define F367_OFDM_SYMBOFFSM_4 0xF2E60010 -+#define F367_OFDM_SYMBOFFSM_3 0xF2E60008 -+#define F367_OFDM_DEFGEN_SYMBOFFSET_HI 0xF2E60007 -+ -+/* SYMBOFFSL */ -+#define R367_OFDM_SYMBOFFSL 0xF2E7 -+#define F367_OFDM_DEFGEN_SYMBOFFSET_LO 0xF2E700FF -+ -+/* DEBUG_LT4 */ -+#define R367_DEBUG_LT4 0xF400 -+#define F367_F_DEBUG_LT4 0xF40000FF -+ -+/* DEBUG_LT5 */ -+#define R367_DEBUG_LT5 0xF401 -+#define F367_F_DEBUG_LT5 0xF40100FF -+ -+/* DEBUG_LT6 */ -+#define R367_DEBUG_LT6 0xF402 -+#define F367_F_DEBUG_LT6 0xF40200FF -+ -+/* DEBUG_LT7 */ -+#define R367_DEBUG_LT7 0xF403 -+#define F367_F_DEBUG_LT7 0xF40300FF -+ -+/* DEBUG_LT8 */ -+#define R367_DEBUG_LT8 0xF404 -+#define F367_F_DEBUG_LT8 0xF40400FF -+ -+/* DEBUG_LT9 */ -+#define R367_DEBUG_LT9 0xF405 -+#define F367_F_DEBUG_LT9 0xF40500FF -+ -+/* CTRL_1 */ -+#define R367_QAM_CTRL_1 0xF402 -+#define F367_QAM_SOFT_RST 0xF4020080 -+#define F367_QAM_EQU_RST 0xF4020008 -+#define F367_QAM_CRL_RST 0xF4020004 -+#define F367_QAM_TRL_RST 0xF4020002 -+#define F367_QAM_AGC_RST 0xF4020001 -+ -+/* CTRL_2 */ -+#define R367_QAM_CTRL_2 0xF403 -+#define F367_QAM_DEINT_RST 0xF4030008 -+#define F367_QAM_RS_RST 0xF4030004 -+ -+/* IT_STATUS1 */ -+#define R367_QAM_IT_STATUS1 0xF408 -+#define F367_QAM_SWEEP_OUT 0xF4080080 -+#define F367_QAM_FSM_CRL 0xF4080040 -+#define F367_QAM_CRL_LOCK 0xF4080020 -+#define F367_QAM_MFSM 0xF4080010 -+#define F367_QAM_TRL_LOCK 0xF4080008 -+#define F367_QAM_TRL_AGC_LIMIT 0xF4080004 -+#define F367_QAM_ADJ_AGC_LOCK 0xF4080002 -+#define F367_QAM_AGC_QAM_LOCK 0xF4080001 -+ -+/* IT_STATUS2 */ -+#define R367_QAM_IT_STATUS2 0xF409 -+#define F367_QAM_TSMF_CNT 0xF4090080 -+#define F367_QAM_TSMF_EOF 0xF4090040 -+#define F367_QAM_TSMF_RDY 0xF4090020 -+#define F367_QAM_FEC_NOCORR 0xF4090010 -+#define F367_QAM_SYNCSTATE 0xF4090008 -+#define F367_QAM_DEINT_LOCK 0xF4090004 -+#define F367_QAM_FADDING_FRZ 0xF4090002 -+#define F367_QAM_TAPMON_ALARM 0xF4090001 -+ -+/* IT_EN1 */ -+#define R367_QAM_IT_EN1 0xF40A -+#define F367_QAM_SWEEP_OUTE 0xF40A0080 -+#define F367_QAM_FSM_CRLE 0xF40A0040 -+#define F367_QAM_CRL_LOCKE 0xF40A0020 -+#define F367_QAM_MFSME 0xF40A0010 -+#define F367_QAM_TRL_LOCKE 0xF40A0008 -+#define F367_QAM_TRL_AGC_LIMITE 0xF40A0004 -+#define F367_QAM_ADJ_AGC_LOCKE 0xF40A0002 -+#define F367_QAM_AGC_LOCKE 0xF40A0001 -+ -+/* IT_EN2 */ -+#define R367_QAM_IT_EN2 0xF40B -+#define F367_QAM_TSMF_CNTE 0xF40B0080 -+#define F367_QAM_TSMF_EOFE 0xF40B0040 -+#define F367_QAM_TSMF_RDYE 0xF40B0020 -+#define F367_QAM_FEC_NOCORRE 0xF40B0010 -+#define F367_QAM_SYNCSTATEE 0xF40B0008 -+#define F367_QAM_DEINT_LOCKE 0xF40B0004 -+#define F367_QAM_FADDING_FRZE 0xF40B0002 -+#define F367_QAM_TAPMON_ALARME 0xF40B0001 -+ -+/* CTRL_STATUS */ -+#define R367_QAM_CTRL_STATUS 0xF40C -+#define F367_QAM_QAMFEC_LOCK 0xF40C0004 -+#define F367_QAM_TSMF_LOCK 0xF40C0002 -+#define F367_QAM_TSMF_ERROR 0xF40C0001 -+ -+/* TEST_CTL */ -+#define R367_QAM_TEST_CTL 0xF40F -+#define F367_QAM_TST_BLK_SEL 0xF40F0060 -+#define F367_QAM_TST_BUS_SEL 0xF40F001F -+ -+/* AGC_CTL */ -+#define R367_QAM_AGC_CTL 0xF410 -+#define F367_QAM_AGC_LCK_TH 0xF41000F0 -+#define F367_QAM_AGC_ACCUMRSTSEL 0xF4100007 -+ -+/* AGC_IF_CFG */ -+#define R367_QAM_AGC_IF_CFG 0xF411 -+#define F367_QAM_AGC_IF_BWSEL 0xF41100F0 -+#define F367_QAM_AGC_IF_FREEZE 0xF4110002 -+ -+/* AGC_RF_CFG */ -+#define R367_QAM_AGC_RF_CFG 0xF412 -+#define F367_QAM_AGC_RF_BWSEL 0xF4120070 -+#define F367_QAM_AGC_RF_FREEZE 0xF4120002 -+ -+/* AGC_PWM_CFG */ -+#define R367_QAM_AGC_PWM_CFG 0xF413 -+#define F367_QAM_AGC_RF_PWM_TST 0xF4130080 -+#define F367_QAM_AGC_RF_PWM_INV 0xF4130040 -+#define F367_QAM_AGC_IF_PWM_TST 0xF4130008 -+#define F367_QAM_AGC_IF_PWM_INV 0xF4130004 -+#define F367_QAM_AGC_PWM_CLKDIV 0xF4130003 -+ -+/* AGC_PWR_REF_L */ -+#define R367_QAM_AGC_PWR_REF_L 0xF414 -+#define F367_QAM_AGC_PWRREF_LO 0xF41400FF -+ -+/* AGC_PWR_REF_H */ -+#define R367_QAM_AGC_PWR_REF_H 0xF415 -+#define F367_QAM_AGC_PWRREF_HI 0xF4150003 -+ -+/* AGC_RF_TH_L */ -+#define R367_QAM_AGC_RF_TH_L 0xF416 -+#define F367_QAM_AGC_RF_TH_LO 0xF41600FF -+ -+/* AGC_RF_TH_H */ -+#define R367_QAM_AGC_RF_TH_H 0xF417 -+#define F367_QAM_AGC_RF_TH_HI 0xF417000F -+ -+/* AGC_IF_LTH_L */ -+#define R367_QAM_AGC_IF_LTH_L 0xF418 -+#define F367_QAM_AGC_IF_THLO_LO 0xF41800FF -+ -+/* AGC_IF_LTH_H */ -+#define R367_QAM_AGC_IF_LTH_H 0xF419 -+#define F367_QAM_AGC_IF_THLO_HI 0xF419000F -+ -+/* AGC_IF_HTH_L */ -+#define R367_QAM_AGC_IF_HTH_L 0xF41A -+#define F367_QAM_AGC_IF_THHI_LO 0xF41A00FF -+ -+/* AGC_IF_HTH_H */ -+#define R367_QAM_AGC_IF_HTH_H 0xF41B -+#define F367_QAM_AGC_IF_THHI_HI 0xF41B000F -+ -+/* AGC_PWR_RD_L */ -+#define R367_QAM_AGC_PWR_RD_L 0xF41C -+#define F367_QAM_AGC_PWR_WORD_LO 0xF41C00FF -+ -+/* AGC_PWR_RD_M */ -+#define R367_QAM_AGC_PWR_RD_M 0xF41D -+#define F367_QAM_AGC_PWR_WORD_ME 0xF41D00FF -+ -+/* AGC_PWR_RD_H */ -+#define R367_QAM_AGC_PWR_RD_H 0xF41E -+#define F367_QAM_AGC_PWR_WORD_HI 0xF41E0003 -+ -+/* AGC_PWM_IFCMD_L */ -+#define R367_QAM_AGC_PWM_IFCMD_L 0xF420 -+#define F367_QAM_AGC_IF_PWMCMD_LO 0xF42000FF -+ -+/* AGC_PWM_IFCMD_H */ -+#define R367_QAM_AGC_PWM_IFCMD_H 0xF421 -+#define F367_QAM_AGC_IF_PWMCMD_HI 0xF421000F -+ -+/* AGC_PWM_RFCMD_L */ -+#define R367_QAM_AGC_PWM_RFCMD_L 0xF422 -+#define F367_QAM_AGC_RF_PWMCMD_LO 0xF42200FF -+ -+/* AGC_PWM_RFCMD_H */ -+#define R367_QAM_AGC_PWM_RFCMD_H 0xF423 -+#define F367_QAM_AGC_RF_PWMCMD_HI 0xF423000F -+ -+/* IQDEM_CFG */ -+#define R367_QAM_IQDEM_CFG 0xF424 -+#define F367_QAM_IQDEM_CLK_SEL 0xF4240004 -+#define F367_QAM_IQDEM_INVIQ 0xF4240002 -+#define F367_QAM_IQDEM_A2DTYPE 0xF4240001 -+ -+/* MIX_NCO_LL */ -+#define R367_QAM_MIX_NCO_LL 0xF425 -+#define F367_QAM_MIX_NCO_INC_LL 0xF42500FF -+ -+/* MIX_NCO_HL */ -+#define R367_QAM_MIX_NCO_HL 0xF426 -+#define F367_QAM_MIX_NCO_INC_HL 0xF42600FF -+ -+/* MIX_NCO_HH */ -+#define R367_QAM_MIX_NCO_HH 0xF427 -+#define F367_QAM_MIX_NCO_INVCNST 0xF4270080 -+#define F367_QAM_MIX_NCO_INC_HH 0xF427007F -+ -+/* SRC_NCO_LL */ -+#define R367_QAM_SRC_NCO_LL 0xF428 -+#define F367_QAM_SRC_NCO_INC_LL 0xF42800FF -+ -+/* SRC_NCO_LH */ -+#define R367_QAM_SRC_NCO_LH 0xF429 -+#define F367_QAM_SRC_NCO_INC_LH 0xF42900FF -+ -+/* SRC_NCO_HL */ -+#define R367_QAM_SRC_NCO_HL 0xF42A -+#define F367_QAM_SRC_NCO_INC_HL 0xF42A00FF -+ -+/* SRC_NCO_HH */ -+#define R367_QAM_SRC_NCO_HH 0xF42B -+#define F367_QAM_SRC_NCO_INC_HH 0xF42B007F -+ -+/* IQDEM_GAIN_SRC_L */ -+#define R367_QAM_IQDEM_GAIN_SRC_L 0xF42C -+#define F367_QAM_GAIN_SRC_LO 0xF42C00FF -+ -+/* IQDEM_GAIN_SRC_H */ -+#define R367_QAM_IQDEM_GAIN_SRC_H 0xF42D -+#define F367_QAM_GAIN_SRC_HI 0xF42D0003 -+ -+/* IQDEM_DCRM_CFG_LL */ -+#define R367_QAM_IQDEM_DCRM_CFG_LL 0xF430 -+#define F367_QAM_DCRM0_DCIN_L 0xF43000FF -+ -+/* IQDEM_DCRM_CFG_LH */ -+#define R367_QAM_IQDEM_DCRM_CFG_LH 0xF431 -+#define F367_QAM_DCRM1_I_DCIN_L 0xF43100FC -+#define F367_QAM_DCRM0_DCIN_H 0xF4310003 -+ -+/* IQDEM_DCRM_CFG_HL */ -+#define R367_QAM_IQDEM_DCRM_CFG_HL 0xF432 -+#define F367_QAM_DCRM1_Q_DCIN_L 0xF43200F0 -+#define F367_QAM_DCRM1_I_DCIN_H 0xF432000F -+ -+/* IQDEM_DCRM_CFG_HH */ -+#define R367_QAM_IQDEM_DCRM_CFG_HH 0xF433 -+#define F367_QAM_DCRM1_FRZ 0xF4330080 -+#define F367_QAM_DCRM0_FRZ 0xF4330040 -+#define F367_QAM_DCRM1_Q_DCIN_H 0xF433003F -+ -+/* IQDEM_ADJ_COEFF0 */ -+#define R367_QAM_IQDEM_ADJ_COEFF0 0xF434 -+#define F367_QAM_ADJIIR_COEFF10_L 0xF43400FF -+ -+/* IQDEM_ADJ_COEFF1 */ -+#define R367_QAM_IQDEM_ADJ_COEFF1 0xF435 -+#define F367_QAM_ADJIIR_COEFF11_L 0xF43500FC -+#define F367_QAM_ADJIIR_COEFF10_H 0xF4350003 -+ -+/* IQDEM_ADJ_COEFF2 */ -+#define R367_QAM_IQDEM_ADJ_COEFF2 0xF436 -+#define F367_QAM_ADJIIR_COEFF12_L 0xF43600F0 -+#define F367_QAM_ADJIIR_COEFF11_H 0xF436000F -+ -+/* IQDEM_ADJ_COEFF3 */ -+#define R367_QAM_IQDEM_ADJ_COEFF3 0xF437 -+#define F367_QAM_ADJIIR_COEFF20_L 0xF43700C0 -+#define F367_QAM_ADJIIR_COEFF12_H 0xF437003F -+ -+/* IQDEM_ADJ_COEFF4 */ -+#define R367_QAM_IQDEM_ADJ_COEFF4 0xF438 -+#define F367_QAM_ADJIIR_COEFF20_H 0xF43800FF -+ -+/* IQDEM_ADJ_COEFF5 */ -+#define R367_QAM_IQDEM_ADJ_COEFF5 0xF439 -+#define F367_QAM_ADJIIR_COEFF21_L 0xF43900FF -+ -+/* IQDEM_ADJ_COEFF6 */ -+#define R367_QAM_IQDEM_ADJ_COEFF6 0xF43A -+#define F367_QAM_ADJIIR_COEFF22_L 0xF43A00FC -+#define F367_QAM_ADJIIR_COEFF21_H 0xF43A0003 -+ -+/* IQDEM_ADJ_COEFF7 */ -+#define R367_QAM_IQDEM_ADJ_COEFF7 0xF43B -+#define F367_QAM_ADJIIR_COEFF22_H 0xF43B000F -+ -+/* IQDEM_ADJ_EN */ -+#define R367_QAM_IQDEM_ADJ_EN 0xF43C -+#define F367_QAM_ALLPASSFILT_EN 0xF43C0008 -+#define F367_QAM_ADJ_AGC_EN 0xF43C0004 -+#define F367_QAM_ADJ_COEFF_FRZ 0xF43C0002 -+#define F367_QAM_ADJ_EN 0xF43C0001 -+ -+/* IQDEM_ADJ_AGC_REF */ -+#define R367_QAM_IQDEM_ADJ_AGC_REF 0xF43D -+#define F367_QAM_ADJ_AGC_REF 0xF43D00FF -+ -+/* ALLPASSFILT1 */ -+#define R367_QAM_ALLPASSFILT1 0xF440 -+#define F367_QAM_ALLPASSFILT_COEFF1_LO 0xF44000FF -+ -+/* ALLPASSFILT2 */ -+#define R367_QAM_ALLPASSFILT2 0xF441 -+#define F367_QAM_ALLPASSFILT_COEFF1_ME 0xF44100FF -+ -+/* ALLPASSFILT3 */ -+#define R367_QAM_ALLPASSFILT3 0xF442 -+#define F367_QAM_ALLPASSFILT_COEFF2_LO 0xF44200C0 -+#define F367_QAM_ALLPASSFILT_COEFF1_HI 0xF442003F -+ -+/* ALLPASSFILT4 */ -+#define R367_QAM_ALLPASSFILT4 0xF443 -+#define F367_QAM_ALLPASSFILT_COEFF2_MEL 0xF44300FF -+ -+/* ALLPASSFILT5 */ -+#define R367_QAM_ALLPASSFILT5 0xF444 -+#define F367_QAM_ALLPASSFILT_COEFF2_MEH 0xF44400FF -+ -+/* ALLPASSFILT6 */ -+#define R367_QAM_ALLPASSFILT6 0xF445 -+#define F367_QAM_ALLPASSFILT_COEFF3_LO 0xF44500F0 -+#define F367_QAM_ALLPASSFILT_COEFF2_HI 0xF445000F -+ -+/* ALLPASSFILT7 */ -+#define R367_QAM_ALLPASSFILT7 0xF446 -+#define F367_QAM_ALLPASSFILT_COEFF3_MEL 0xF44600FF -+ -+/* ALLPASSFILT8 */ -+#define R367_QAM_ALLPASSFILT8 0xF447 -+#define F367_QAM_ALLPASSFILT_COEFF3_MEH 0xF44700FF -+ -+/* ALLPASSFILT9 */ -+#define R367_QAM_ALLPASSFILT9 0xF448 -+#define F367_QAM_ALLPASSFILT_COEFF4_LO 0xF44800FC -+#define F367_QAM_ALLPASSFILT_COEFF3_HI 0xF4480003 -+ -+/* ALLPASSFILT10 */ -+#define R367_QAM_ALLPASSFILT10 0xF449 -+#define F367_QAM_ALLPASSFILT_COEFF4_ME 0xF44900FF -+ -+/* ALLPASSFILT11 */ -+#define R367_QAM_ALLPASSFILT11 0xF44A -+#define F367_QAM_ALLPASSFILT_COEFF4_HI 0xF44A00FF -+ -+/* TRL_AGC_CFG */ -+#define R367_QAM_TRL_AGC_CFG 0xF450 -+#define F367_QAM_TRL_AGC_FREEZE 0xF4500080 -+#define F367_QAM_TRL_AGC_REF 0xF450007F -+ -+/* TRL_LPF_CFG */ -+#define R367_QAM_TRL_LPF_CFG 0xF454 -+#define F367_QAM_NYQPOINT_INV 0xF4540040 -+#define F367_QAM_TRL_SHIFT 0xF4540030 -+#define F367_QAM_NYQ_COEFF_SEL 0xF454000C -+#define F367_QAM_TRL_LPF_FREEZE 0xF4540002 -+#define F367_QAM_TRL_LPF_CRT 0xF4540001 -+ -+/* TRL_LPF_ACQ_GAIN */ -+#define R367_QAM_TRL_LPF_ACQ_GAIN 0xF455 -+#define F367_QAM_TRL_GDIR_ACQ 0xF4550070 -+#define F367_QAM_TRL_GINT_ACQ 0xF4550007 -+ -+/* TRL_LPF_TRK_GAIN */ -+#define R367_QAM_TRL_LPF_TRK_GAIN 0xF456 -+#define F367_QAM_TRL_GDIR_TRK 0xF4560070 -+#define F367_QAM_TRL_GINT_TRK 0xF4560007 -+ -+/* TRL_LPF_OUT_GAIN */ -+#define R367_QAM_TRL_LPF_OUT_GAIN 0xF457 -+#define F367_QAM_TRL_GAIN_OUT 0xF4570007 -+ -+/* TRL_LOCKDET_LTH */ -+#define R367_QAM_TRL_LOCKDET_LTH 0xF458 -+#define F367_QAM_TRL_LCK_THLO 0xF4580007 -+ -+/* TRL_LOCKDET_HTH */ -+#define R367_QAM_TRL_LOCKDET_HTH 0xF459 -+#define F367_QAM_TRL_LCK_THHI 0xF45900FF -+ -+/* TRL_LOCKDET_TRGVAL */ -+#define R367_QAM_TRL_LOCKDET_TRGVAL 0xF45A -+#define F367_QAM_TRL_LCK_TRG 0xF45A00FF -+ -+/* IQ_QAM */ -+#define R367_QAM_IQ_QAM 0xF45C -+#define F367_QAM_IQ_INPUT 0xF45C0008 -+#define F367_QAM_DETECT_MODE 0xF45C0007 -+ -+/* FSM_STATE */ -+#define R367_QAM_FSM_STATE 0xF460 -+#define F367_QAM_CRL_DFE 0xF4600080 -+#define F367_QAM_DFE_START 0xF4600040 -+#define F367_QAM_CTRLG_START 0xF4600030 -+#define F367_QAM_FSM_FORCESTATE 0xF460000F -+ -+/* FSM_CTL */ -+#define R367_QAM_FSM_CTL 0xF461 -+#define F367_QAM_FEC2_EN 0xF4610040 -+#define F367_QAM_SIT_EN 0xF4610020 -+#define F367_QAM_TRL_AHEAD 0xF4610010 -+#define F367_QAM_TRL2_EN 0xF4610008 -+#define F367_QAM_FSM_EQA1_EN 0xF4610004 -+#define F367_QAM_FSM_BKP_DIS 0xF4610002 -+#define F367_QAM_FSM_FORCE_EN 0xF4610001 -+ -+/* FSM_STS */ -+#define R367_QAM_FSM_STS 0xF462 -+#define F367_QAM_FSM_STATUS 0xF462000F -+ -+/* FSM_SNR0_HTH */ -+#define R367_QAM_FSM_SNR0_HTH 0xF463 -+#define F367_QAM_SNR0_HTH 0xF46300FF -+ -+/* FSM_SNR1_HTH */ -+#define R367_QAM_FSM_SNR1_HTH 0xF464 -+#define F367_QAM_SNR1_HTH 0xF46400FF -+ -+/* FSM_SNR2_HTH */ -+#define R367_QAM_FSM_SNR2_HTH 0xF465 -+#define F367_QAM_SNR2_HTH 0xF46500FF -+ -+/* FSM_SNR0_LTH */ -+#define R367_QAM_FSM_SNR0_LTH 0xF466 -+#define F367_QAM_SNR0_LTH 0xF46600FF -+ -+/* FSM_SNR1_LTH */ -+#define R367_QAM_FSM_SNR1_LTH 0xF467 -+#define F367_QAM_SNR1_LTH 0xF46700FF -+ -+/* FSM_EQA1_HTH */ -+#define R367_QAM_FSM_EQA1_HTH 0xF468 -+#define F367_QAM_SNR3_HTH_LO 0xF46800F0 -+#define F367_QAM_EQA1_HTH 0xF468000F -+ -+/* FSM_TEMPO */ -+#define R367_QAM_FSM_TEMPO 0xF469 -+#define F367_QAM_SIT 0xF46900C0 -+#define F367_QAM_WST 0xF4690038 -+#define F367_QAM_ELT 0xF4690006 -+#define F367_QAM_SNR3_HTH_HI 0xF4690001 -+ -+/* FSM_CONFIG */ -+#define R367_QAM_FSM_CONFIG 0xF46A -+#define F367_QAM_FEC2_DFEOFF 0xF46A0004 -+#define F367_QAM_PRIT_STATE 0xF46A0002 -+#define F367_QAM_MODMAP_STATE 0xF46A0001 -+ -+/* EQU_I_TESTTAP_L */ -+#define R367_QAM_EQU_I_TESTTAP_L 0xF474 -+#define F367_QAM_I_TEST_TAP_L 0xF47400FF -+ -+/* EQU_I_TESTTAP_M */ -+#define R367_QAM_EQU_I_TESTTAP_M 0xF475 -+#define F367_QAM_I_TEST_TAP_M 0xF47500FF -+ -+/* EQU_I_TESTTAP_H */ -+#define R367_QAM_EQU_I_TESTTAP_H 0xF476 -+#define F367_QAM_I_TEST_TAP_H 0xF476001F -+ -+/* EQU_TESTAP_CFG */ -+#define R367_QAM_EQU_TESTAP_CFG 0xF477 -+#define F367_QAM_TEST_FFE_DFE_SEL 0xF4770040 -+#define F367_QAM_TEST_TAP_SELECT 0xF477003F -+ -+/* EQU_Q_TESTTAP_L */ -+#define R367_QAM_EQU_Q_TESTTAP_L 0xF478 -+#define F367_QAM_Q_TEST_TAP_L 0xF47800FF -+ -+/* EQU_Q_TESTTAP_M */ -+#define R367_QAM_EQU_Q_TESTTAP_M 0xF479 -+#define F367_QAM_Q_TEST_TAP_M 0xF47900FF -+ -+/* EQU_Q_TESTTAP_H */ -+#define R367_QAM_EQU_Q_TESTTAP_H 0xF47A -+#define F367_QAM_Q_TEST_TAP_H 0xF47A001F -+ -+/* EQU_TAP_CTRL */ -+#define R367_QAM_EQU_TAP_CTRL 0xF47B -+#define F367_QAM_MTAP_FRZ 0xF47B0010 -+#define F367_QAM_PRE_FREEZE 0xF47B0008 -+#define F367_QAM_DFE_TAPMON_EN 0xF47B0004 -+#define F367_QAM_FFE_TAPMON_EN 0xF47B0002 -+#define F367_QAM_MTAP_ONLY 0xF47B0001 -+ -+/* EQU_CTR_CRL_CONTROL_L */ -+#define R367_QAM_EQU_CTR_CRL_CONTROL_L 0xF47C -+#define F367_QAM_EQU_CTR_CRL_CONTROL_LO 0xF47C00FF -+ -+/* EQU_CTR_CRL_CONTROL_H */ -+#define R367_QAM_EQU_CTR_CRL_CONTROL_H 0xF47D -+#define F367_QAM_EQU_CTR_CRL_CONTROL_HI 0xF47D00FF -+ -+/* EQU_CTR_HIPOW_L */ -+#define R367_QAM_EQU_CTR_HIPOW_L 0xF47E -+#define F367_QAM_CTR_HIPOW_L 0xF47E00FF -+ -+/* EQU_CTR_HIPOW_H */ -+#define R367_QAM_EQU_CTR_HIPOW_H 0xF47F -+#define F367_QAM_CTR_HIPOW_H 0xF47F00FF -+ -+/* EQU_I_EQU_LO */ -+#define R367_QAM_EQU_I_EQU_LO 0xF480 -+#define F367_QAM_EQU_I_EQU_L 0xF48000FF -+ -+/* EQU_I_EQU_HI */ -+#define R367_QAM_EQU_I_EQU_HI 0xF481 -+#define F367_QAM_EQU_I_EQU_H 0xF4810003 -+ -+/* EQU_Q_EQU_LO */ -+#define R367_QAM_EQU_Q_EQU_LO 0xF482 -+#define F367_QAM_EQU_Q_EQU_L 0xF48200FF -+ -+/* EQU_Q_EQU_HI */ -+#define R367_QAM_EQU_Q_EQU_HI 0xF483 -+#define F367_QAM_EQU_Q_EQU_H 0xF4830003 -+ -+/* EQU_MAPPER */ -+#define R367_QAM_EQU_MAPPER 0xF484 -+#define F367_QAM_QUAD_AUTO 0xF4840080 -+#define F367_QAM_QUAD_INV 0xF4840040 -+#define F367_QAM_QAM_MODE 0xF4840007 -+ -+/* EQU_SWEEP_RATE */ -+#define R367_QAM_EQU_SWEEP_RATE 0xF485 -+#define F367_QAM_SNR_PER 0xF48500C0 -+#define F367_QAM_SWEEP_RATE 0xF485003F -+ -+/* EQU_SNR_LO */ -+#define R367_QAM_EQU_SNR_LO 0xF486 -+#define F367_QAM_SNR_LO 0xF48600FF -+ -+/* EQU_SNR_HI */ -+#define R367_QAM_EQU_SNR_HI 0xF487 -+#define F367_QAM_SNR_HI 0xF48700FF -+ -+/* EQU_GAMMA_LO */ -+#define R367_QAM_EQU_GAMMA_LO 0xF488 -+#define F367_QAM_GAMMA_LO 0xF48800FF -+ -+/* EQU_GAMMA_HI */ -+#define R367_QAM_EQU_GAMMA_HI 0xF489 -+#define F367_QAM_GAMMA_ME 0xF48900FF -+ -+/* EQU_ERR_GAIN */ -+#define R367_QAM_EQU_ERR_GAIN 0xF48A -+#define F367_QAM_EQA1MU 0xF48A0070 -+#define F367_QAM_CRL2MU 0xF48A000E -+#define F367_QAM_GAMMA_HI 0xF48A0001 -+ -+/* EQU_RADIUS */ -+#define R367_QAM_EQU_RADIUS 0xF48B -+#define F367_QAM_RADIUS 0xF48B00FF -+ -+/* EQU_FFE_MAINTAP */ -+#define R367_QAM_EQU_FFE_MAINTAP 0xF48C -+#define F367_QAM_FFE_MAINTAP_INIT 0xF48C00FF -+ -+/* EQU_FFE_LEAKAGE */ -+#define R367_QAM_EQU_FFE_LEAKAGE 0xF48E -+#define F367_QAM_LEAK_PER 0xF48E00F0 -+#define F367_QAM_EQU_OUTSEL 0xF48E0002 -+#define F367_QAM_PNT2DFE 0xF48E0001 -+ -+/* EQU_FFE_MAINTAP_POS */ -+#define R367_QAM_EQU_FFE_MAINTAP_POS 0xF48F -+#define F367_QAM_FFE_LEAK_EN 0xF48F0080 -+#define F367_QAM_DFE_LEAK_EN 0xF48F0040 -+#define F367_QAM_FFE_MAINTAP_POS 0xF48F003F -+ -+/* EQU_GAIN_WIDE */ -+#define R367_QAM_EQU_GAIN_WIDE 0xF490 -+#define F367_QAM_DFE_GAIN_WIDE 0xF49000F0 -+#define F367_QAM_FFE_GAIN_WIDE 0xF490000F -+ -+/* EQU_GAIN_NARROW */ -+#define R367_QAM_EQU_GAIN_NARROW 0xF491 -+#define F367_QAM_DFE_GAIN_NARROW 0xF49100F0 -+#define F367_QAM_FFE_GAIN_NARROW 0xF491000F -+ -+/* EQU_CTR_LPF_GAIN */ -+#define R367_QAM_EQU_CTR_LPF_GAIN 0xF492 -+#define F367_QAM_CTR_GTO 0xF4920080 -+#define F367_QAM_CTR_GDIR 0xF4920070 -+#define F367_QAM_SWEEP_EN 0xF4920008 -+#define F367_QAM_CTR_GINT 0xF4920007 -+ -+/* EQU_CRL_LPF_GAIN */ -+#define R367_QAM_EQU_CRL_LPF_GAIN 0xF493 -+#define F367_QAM_CRL_GTO 0xF4930080 -+#define F367_QAM_CRL_GDIR 0xF4930070 -+#define F367_QAM_SWEEP_DIR 0xF4930008 -+#define F367_QAM_CRL_GINT 0xF4930007 -+ -+/* EQU_GLOBAL_GAIN */ -+#define R367_QAM_EQU_GLOBAL_GAIN 0xF494 -+#define F367_QAM_CRL_GAIN 0xF49400F8 -+#define F367_QAM_CTR_INC_GAIN 0xF4940004 -+#define F367_QAM_CTR_FRAC 0xF4940003 -+ -+/* EQU_CRL_LD_SEN */ -+#define R367_QAM_EQU_CRL_LD_SEN 0xF495 -+#define F367_QAM_CTR_BADPOINT_EN 0xF4950080 -+#define F367_QAM_CTR_GAIN 0xF4950070 -+#define F367_QAM_LIMANEN 0xF4950008 -+#define F367_QAM_CRL_LD_SEN 0xF4950007 -+ -+/* EQU_CRL_LD_VAL */ -+#define R367_QAM_EQU_CRL_LD_VAL 0xF496 -+#define F367_QAM_CRL_BISTH_LIMIT 0xF4960080 -+#define F367_QAM_CARE_EN 0xF4960040 -+#define F367_QAM_CRL_LD_PER 0xF4960030 -+#define F367_QAM_CRL_LD_WST 0xF496000C -+#define F367_QAM_CRL_LD_TFS 0xF4960003 -+ -+/* EQU_CRL_TFR */ -+#define R367_QAM_EQU_CRL_TFR 0xF497 -+#define F367_QAM_CRL_LD_TFR 0xF49700FF -+ -+/* EQU_CRL_BISTH_LO */ -+#define R367_QAM_EQU_CRL_BISTH_LO 0xF498 -+#define F367_QAM_CRL_BISTH_LO 0xF49800FF -+ -+/* EQU_CRL_BISTH_HI */ -+#define R367_QAM_EQU_CRL_BISTH_HI 0xF499 -+#define F367_QAM_CRL_BISTH_HI 0xF49900FF -+ -+/* EQU_SWEEP_RANGE_LO */ -+#define R367_QAM_EQU_SWEEP_RANGE_LO 0xF49A -+#define F367_QAM_SWEEP_RANGE_LO 0xF49A00FF -+ -+/* EQU_SWEEP_RANGE_HI */ -+#define R367_QAM_EQU_SWEEP_RANGE_HI 0xF49B -+#define F367_QAM_SWEEP_RANGE_HI 0xF49B00FF -+ -+/* EQU_CRL_LIMITER */ -+#define R367_QAM_EQU_CRL_LIMITER 0xF49C -+#define F367_QAM_BISECTOR_EN 0xF49C0080 -+#define F367_QAM_PHEST128_EN 0xF49C0040 -+#define F367_QAM_CRL_LIM 0xF49C003F -+ -+/* EQU_MODULUS_MAP */ -+#define R367_QAM_EQU_MODULUS_MAP 0xF49D -+#define F367_QAM_PNT_DEPTH 0xF49D00E0 -+#define F367_QAM_MODULUS_CMP 0xF49D001F -+ -+/* EQU_PNT_GAIN */ -+#define R367_QAM_EQU_PNT_GAIN 0xF49E -+#define F367_QAM_PNT_EN 0xF49E0080 -+#define F367_QAM_MODULUSMAP_EN 0xF49E0040 -+#define F367_QAM_PNT_GAIN 0xF49E003F -+ -+/* FEC_AC_CTR_0 */ -+#define R367_QAM_FEC_AC_CTR_0 0xF4A8 -+#define F367_QAM_BE_BYPASS 0xF4A80020 -+#define F367_QAM_REFRESH47 0xF4A80010 -+#define F367_QAM_CT_NBST 0xF4A80008 -+#define F367_QAM_TEI_ENA 0xF4A80004 -+#define F367_QAM_DS_ENA 0xF4A80002 -+#define F367_QAM_TSMF_EN 0xF4A80001 -+ -+/* FEC_AC_CTR_1 */ -+#define R367_QAM_FEC_AC_CTR_1 0xF4A9 -+#define F367_QAM_DEINT_DEPTH 0xF4A900FF -+ -+/* FEC_AC_CTR_2 */ -+#define R367_QAM_FEC_AC_CTR_2 0xF4AA -+#define F367_QAM_DEINT_M 0xF4AA00F8 -+#define F367_QAM_DIS_UNLOCK 0xF4AA0004 -+#define F367_QAM_DESCR_MODE 0xF4AA0003 -+ -+/* FEC_AC_CTR_3 */ -+#define R367_QAM_FEC_AC_CTR_3 0xF4AB -+#define F367_QAM_DI_UNLOCK 0xF4AB0080 -+#define F367_QAM_DI_FREEZE 0xF4AB0040 -+#define F367_QAM_MISMATCH 0xF4AB0030 -+#define F367_QAM_ACQ_MODE 0xF4AB000C -+#define F367_QAM_TRK_MODE 0xF4AB0003 -+ -+/* FEC_STATUS */ -+#define R367_QAM_FEC_STATUS 0xF4AC -+#define F367_QAM_DEINT_SMCNTR 0xF4AC00E0 -+#define F367_QAM_DEINT_SYNCSTATE 0xF4AC0018 -+#define F367_QAM_DEINT_SYNLOST 0xF4AC0004 -+#define F367_QAM_DESCR_SYNCSTATE 0xF4AC0002 -+ -+/* RS_COUNTER_0 */ -+#define R367_QAM_RS_COUNTER_0 0xF4AE -+#define F367_QAM_BK_CT_L 0xF4AE00FF -+ -+/* RS_COUNTER_1 */ -+#define R367_QAM_RS_COUNTER_1 0xF4AF -+#define F367_QAM_BK_CT_H 0xF4AF00FF -+ -+/* RS_COUNTER_2 */ -+#define R367_QAM_RS_COUNTER_2 0xF4B0 -+#define F367_QAM_CORR_CT_L 0xF4B000FF -+ -+/* RS_COUNTER_3 */ -+#define R367_QAM_RS_COUNTER_3 0xF4B1 -+#define F367_QAM_CORR_CT_H 0xF4B100FF -+ -+/* RS_COUNTER_4 */ -+#define R367_QAM_RS_COUNTER_4 0xF4B2 -+#define F367_QAM_UNCORR_CT_L 0xF4B200FF -+ -+/* RS_COUNTER_5 */ -+#define R367_QAM_RS_COUNTER_5 0xF4B3 -+#define F367_QAM_UNCORR_CT_H 0xF4B300FF -+ -+/* BERT_0 */ -+#define R367_QAM_BERT_0 0xF4B4 -+#define F367_QAM_RS_NOCORR 0xF4B40004 -+#define F367_QAM_CT_HOLD 0xF4B40002 -+#define F367_QAM_CT_CLEAR 0xF4B40001 -+ -+/* BERT_1 */ -+#define R367_QAM_BERT_1 0xF4B5 -+#define F367_QAM_BERT_ON 0xF4B50020 -+#define F367_QAM_BERT_ERR_SRC 0xF4B50010 -+#define F367_QAM_BERT_ERR_MODE 0xF4B50008 -+#define F367_QAM_BERT_NBYTE 0xF4B50007 -+ -+/* BERT_2 */ -+#define R367_QAM_BERT_2 0xF4B6 -+#define F367_QAM_BERT_ERRCOUNT_L 0xF4B600FF -+ -+/* BERT_3 */ -+#define R367_QAM_BERT_3 0xF4B7 -+#define F367_QAM_BERT_ERRCOUNT_H 0xF4B700FF -+ -+/* OUTFORMAT_0 */ -+#define R367_QAM_OUTFORMAT_0 0xF4B8 -+#define F367_QAM_CLK_POLARITY 0xF4B80080 -+#define F367_QAM_FEC_TYPE 0xF4B80040 -+#define F367_QAM_SYNC_STRIP 0xF4B80008 -+#define F367_QAM_TS_SWAP 0xF4B80004 -+#define F367_QAM_OUTFORMAT 0xF4B80003 -+ -+/* OUTFORMAT_1 */ -+#define R367_QAM_OUTFORMAT_1 0xF4B9 -+#define F367_QAM_CI_DIVRANGE 0xF4B900FF -+ -+/* SMOOTHER_2 */ -+#define R367_QAM_SMOOTHER_2 0xF4BE -+#define F367_QAM_FIFO_BYPASS 0xF4BE0020 -+ -+/* TSMF_CTRL_0 */ -+#define R367_QAM_TSMF_CTRL_0 0xF4C0 -+#define F367_QAM_TS_NUMBER 0xF4C0001E -+#define F367_QAM_SEL_MODE 0xF4C00001 -+ -+/* TSMF_CTRL_1 */ -+#define R367_QAM_TSMF_CTRL_1 0xF4C1 -+#define F367_QAM_CHECK_ERROR_BIT 0xF4C10080 -+#define F367_QAM_CHCK_F_SYNC 0xF4C10040 -+#define F367_QAM_H_MODE 0xF4C10008 -+#define F367_QAM_D_V_MODE 0xF4C10004 -+#define F367_QAM_MODE 0xF4C10003 -+ -+/* TSMF_CTRL_3 */ -+#define R367_QAM_TSMF_CTRL_3 0xF4C3 -+#define F367_QAM_SYNC_IN_COUNT 0xF4C300F0 -+#define F367_QAM_SYNC_OUT_COUNT 0xF4C3000F -+ -+/* TS_ON_ID_0 */ -+#define R367_QAM_TS_ON_ID_0 0xF4C4 -+#define F367_QAM_TS_ID_L 0xF4C400FF -+ -+/* TS_ON_ID_1 */ -+#define R367_QAM_TS_ON_ID_1 0xF4C5 -+#define F367_QAM_TS_ID_H 0xF4C500FF -+ -+/* TS_ON_ID_2 */ -+#define R367_QAM_TS_ON_ID_2 0xF4C6 -+#define F367_QAM_ON_ID_L 0xF4C600FF -+ -+/* TS_ON_ID_3 */ -+#define R367_QAM_TS_ON_ID_3 0xF4C7 -+#define F367_QAM_ON_ID_H 0xF4C700FF -+ -+/* RE_STATUS_0 */ -+#define R367_QAM_RE_STATUS_0 0xF4C8 -+#define F367_QAM_RECEIVE_STATUS_L 0xF4C800FF -+ -+/* RE_STATUS_1 */ -+#define R367_QAM_RE_STATUS_1 0xF4C9 -+#define F367_QAM_RECEIVE_STATUS_LH 0xF4C900FF -+ -+/* RE_STATUS_2 */ -+#define R367_QAM_RE_STATUS_2 0xF4CA -+#define F367_QAM_RECEIVE_STATUS_HL 0xF4CA00FF -+ -+/* RE_STATUS_3 */ -+#define R367_QAM_RE_STATUS_3 0xF4CB -+#define F367_QAM_RECEIVE_STATUS_HH 0xF4CB003F -+ -+/* TS_STATUS_0 */ -+#define R367_QAM_TS_STATUS_0 0xF4CC -+#define F367_QAM_TS_STATUS_L 0xF4CC00FF -+ -+/* TS_STATUS_1 */ -+#define R367_QAM_TS_STATUS_1 0xF4CD -+#define F367_QAM_TS_STATUS_H 0xF4CD007F -+ -+/* TS_STATUS_2 */ -+#define R367_QAM_TS_STATUS_2 0xF4CE -+#define F367_QAM_ERROR 0xF4CE0080 -+#define F367_QAM_EMERGENCY 0xF4CE0040 -+#define F367_QAM_CRE_TS 0xF4CE0030 -+#define F367_QAM_VER 0xF4CE000E -+#define F367_QAM_M_LOCK 0xF4CE0001 -+ -+/* TS_STATUS_3 */ -+#define R367_QAM_TS_STATUS_3 0xF4CF -+#define F367_QAM_UPDATE_READY 0xF4CF0080 -+#define F367_QAM_END_FRAME_HEADER 0xF4CF0040 -+#define F367_QAM_CONTCNT 0xF4CF0020 -+#define F367_QAM_TS_IDENTIFIER_SEL 0xF4CF000F -+ -+/* T_O_ID_0 */ -+#define R367_QAM_T_O_ID_0 0xF4D0 -+#define F367_QAM_ON_ID_I_L 0xF4D000FF -+ -+/* T_O_ID_1 */ -+#define R367_QAM_T_O_ID_1 0xF4D1 -+#define F367_QAM_ON_ID_I_H 0xF4D100FF -+ -+/* T_O_ID_2 */ -+#define R367_QAM_T_O_ID_2 0xF4D2 -+#define F367_QAM_TS_ID_I_L 0xF4D200FF -+ -+/* T_O_ID_3 */ -+#define R367_QAM_T_O_ID_3 0xF4D3 -+#define F367_QAM_TS_ID_I_H 0xF4D300FF -+ -diff --git a/drivers/media/dvb-frontends/tda18212dd.c b/drivers/media/dvb-frontends/tda18212dd.c -new file mode 100644 -index 0000000..de2350b ---- /dev/null -+++ b/drivers/media/dvb-frontends/tda18212dd.c -@@ -0,0 +1,906 @@ -+/* -+ * tda18212: Driver for the TDA18212 tuner -+ * -+ * Copyright (C) 2011 Digital Devices GmbH -+ * -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "dvb_frontend.h" -+ -+#ifndef CHK_ERROR -+ #define CHK_ERROR(s) if ((status = s) < 0) break -+#endif -+ -+#define MASTER_PSM_AGC1 0 -+#define MASTER_AGC1_6_15dB 1 -+ -+#define SLAVE_PSM_AGC1 1 -+#define SLAVE_AGC1_6_15dB 0 -+ -+// 0 = 2 Vpp ... 2 = 1 Vpp, 7 = 0.5 Vpp -+#define IF_LEVEL_DVBC 2 -+#define IF_LEVEL_DVBT 2 -+ -+enum { -+ ID_1 = 0x00, -+ ID_2 = 0x01, -+ ID_3 = 0x02, -+ THERMO_1, -+ THERMO_2, -+ POWER_STATE_1, -+ POWER_STATE_2, -+ INPUT_POWER_LEVEL, -+ IRQ_STATUS, -+ IRQ_ENABLE, -+ IRQ_CLEAR, -+ IRQ_SET, -+ AGC1_1, -+ AGC2_1, -+ AGCK_1, -+ RF_AGC_1, -+ IR_MIXER_1 = 0x10, -+ AGC5_1, -+ IF_AGC, -+ IF_1, -+ REFERENCE, -+ IF_FREQUENCY_1, -+ RF_FREQUENCY_1, -+ RF_FREQUENCY_2, -+ RF_FREQUENCY_3, -+ MSM_1, -+ MSM_2, -+ PSM_1, -+ DCC_1, -+ FLO_MAX, -+ IR_CAL_1, -+ IR_CAL_2, -+ IR_CAL_3 = 0x20, -+ IR_CAL_4, -+ VSYNC_MGT, -+ IR_MIXER_2, -+ AGC1_2, -+ AGC5_2, -+ RF_CAL_1, -+ RF_CAL_2, -+ RF_CAL_3, -+ RF_CAL_4, -+ RF_CAL_5, -+ RF_CAL_6, -+ RF_FILTER_1, -+ RF_FILTER_2, -+ RF_FILTER_3, -+ RF_BAND_PASS_FILTER, -+ CP_CURRENT = 0x30, -+ AGC_DET_OUT = 0x31, -+ RF_AGC_GAIN_1 = 0x32, -+ RF_AGC_GAIN_2 = 0x33, -+ IF_AGC_GAIN = 0x34, -+ POWER_1 = 0x35, -+ POWER_2 = 0x36, -+ MISC_1, -+ RFCAL_LOG_1, -+ RFCAL_LOG_2, -+ RFCAL_LOG_3, -+ RFCAL_LOG_4, -+ RFCAL_LOG_5, -+ RFCAL_LOG_6, -+ RFCAL_LOG_7, -+ RFCAL_LOG_8, -+ RFCAL_LOG_9 = 0x40, -+ RFCAL_LOG_10 = 0x41, -+ RFCAL_LOG_11 = 0x42, -+ RFCAL_LOG_12 = 0x43, -+ REG_MAX, -+}; -+ -+enum HF_Standard { -+ HF_None=0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio, -+ HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ, -+ HF_DVBT, HF_ATSC, HF_DVBC_6MHZ, HF_DVBC_7MHZ, -+ HF_DVBC_8MHZ, HF_DVBC -+}; -+ -+struct SStandardParams { -+ s32 m_IFFrequency; -+ u32 m_BandWidth; -+ u8 m_IF_1; // FF IF_HP_fc:2 IF_Notch:1 LP_FC_Offset:2 LP_FC:3 -+ u8 m_IR_MIXER_2; // 03 :6 HI_Pass:1 DC_Notch:1 -+ u8 m_AGC1_1; // 0F :4 AGC1_Top:4 -+ u8 m_AGC2_1; // 0F :4 AGC2_Top:4 -+ u8 m_RF_AGC_1_Low; // EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1 RF_AGC_Top:3 -+ u8 m_RF_AGC_1_High;// EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1 RF_AGC_Top:3 -+ u8 m_IR_MIXER_1; // 0F :4 IR_mixer_Top:4 -+ u8 m_AGC5_1; // 1F :3 AGC5_Ana AGC5_Top:4 -+ u8 m_AGCK_1; // 0F :4 AGCK_Step:2 AGCK_Mode:2 -+ u8 m_PSM_1; // 20 :2 PSM_StoB:1 :5 -+ bool m_AGC1_Freeze; -+ bool m_LTO_STO_immune; -+}; -+ -+struct SStandardParams m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] = -+{ -+ { 3250000, 6000000, 0x20, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, // HF_DVBT_6MHZ -+ { 3500000, 7000000, 0x31, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, // HF_DVBT_7MHZ -+ { 4000000, 8000000, 0x22, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false }, // HF_DVBT_8MHZ -+ { 0, 0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, false, false }, // HF_DVBT (Unused) -+ { 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false }, // HF_ATSC -+ { 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_6MHZ -+// { 5000000, 7000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ) -+// { 5000000, 8000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_8MHZ -+ { 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ) -+ { 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true }, // HF_DVBC_8MHZ -+}; -+ -+struct tda_state { -+ struct i2c_adapter *i2c; -+ u8 adr; -+ -+ enum HF_Standard m_Standard; -+ u32 m_Frequency; -+ u32 IF; -+ -+ bool m_isMaster; -+ bool m_bPowerMeasurement; -+ bool m_bLTEnable; -+ bool m_bEnableFreeze; -+ -+ u16 m_ID; -+ -+ s32 m_SettlingTime; -+ -+ u8 m_IFLevelDVBC; -+ u8 m_IFLevelDVBT; -+ u8 m_Regs[REG_MAX]; -+ u8 m_LastPowerLevel; -+}; -+ -+static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -+ .buf = data, .len = len}}; -+ return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; -+} -+ -+static int i2c_read(struct i2c_adapter *adap, -+ u8 adr, u8 *msg, int len, u8 *answ, int alen) -+{ -+ struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0, -+ .buf = msg, .len = len}, -+ { .addr = adr, .flags = I2C_M_RD, -+ .buf = answ, .len = alen } }; -+ if (i2c_transfer(adap, msgs, 2) != 2) { -+ printk("tda18212dd: i2c_read error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, -+ .buf = data, .len = len}; -+ -+ if (i2c_transfer(adap, &msg, 1) != 1) { -+ printk("tda18212: i2c_write error\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int write_regs(struct tda_state *state, -+ u8 SubAddr, u8 *Regs, u16 nRegs) -+{ -+ u8 data[nRegs+1]; -+ -+ data[0] = SubAddr; -+ memcpy(data + 1, Regs, nRegs); -+ return i2c_write(state->i2c, state->adr, data, nRegs+1); -+} -+ -+static int write_reg(struct tda_state *state, u8 SubAddr,u8 Reg) -+{ -+ u8 msg[2] = {SubAddr, Reg}; -+ -+ return i2c_write(state->i2c, state->adr, msg, 2); -+} -+ -+static int Read(struct tda_state *state, u8 * Regs) -+{ -+ return i2c_readn(state->i2c, state->adr, Regs, REG_MAX); -+} -+ -+static int update_regs(struct tda_state *state, u8 RegFrom,u8 RegTo) -+{ -+ return write_regs(state, RegFrom, -+ &state->m_Regs[RegFrom], RegTo-RegFrom+1); -+} -+ -+static int update_reg(struct tda_state *state, u8 Reg) -+{ -+ return write_reg(state, Reg,state->m_Regs[Reg]); -+} -+ -+ -+static int read_regs(struct tda_state *state, -+ u8 SubAddr, u8 *Regs, u16 nRegs) -+{ -+ return i2c_read(state->i2c, state->adr, -+ &SubAddr, 1, Regs, nRegs); -+} -+ -+static int read_reg(struct tda_state *state, -+ u8 SubAddr, u8 *Reg) -+{ -+ return i2c_read(state->i2c, state->adr, -+ &SubAddr, 1, Reg, 1); -+} -+ -+static int read_reg1(struct tda_state *state, u8 Reg) -+{ -+ return read_reg(state, Reg, &state->m_Regs[Reg]); -+} -+ -+static void init_state(struct tda_state *state) -+{ -+ u32 ulIFLevelDVBC = IF_LEVEL_DVBC; -+ u32 ulIFLevelDVBT = IF_LEVEL_DVBT; -+ u32 ulPowerMeasurement = 1; -+ u32 ulLTEnable = 1; -+ u32 ulEnableFreeze = 0; -+ -+ state->m_Frequency = 0; -+ state->m_isMaster = true; -+ state->m_ID = 0; -+ state->m_LastPowerLevel = 0xFF; -+ state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07); -+ state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07); -+ state->m_bPowerMeasurement = (ulPowerMeasurement != 0); -+ state->m_bLTEnable = (ulLTEnable != 0); -+ state->m_bEnableFreeze = (ulEnableFreeze != 0); -+} -+ -+static int StartCalibration(struct tda_state *state) -+{ -+ int status = 0; -+ do { -+ state->m_Regs[POWER_2] &= ~0x02; // RSSI CK = 31.25 kHz -+ CHK_ERROR(update_reg(state, POWER_2)); -+ -+ state->m_Regs[AGC1_2] = (state->m_Regs[AGC1_2] & ~0x60) | 0x40; // AGC1 Do Step = 2 -+ CHK_ERROR(update_reg(state, AGC1_2)); // AGC -+ -+ state->m_Regs[RF_FILTER_3] = (state->m_Regs[RF_FILTER_3] & ~0xC0) | 0x40; // AGC2 Do Step = 1 -+ CHK_ERROR(update_reg(state, RF_FILTER_3)); -+ -+ state->m_Regs[AGCK_1] |= 0xC0; // AGCs Assym Up Step = 3 // Datasheet sets all bits to 1! -+ CHK_ERROR(update_reg(state, AGCK_1)); -+ -+ state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x60) | 0x40; // AGCs Assym Do Step = 2 -+ CHK_ERROR(update_reg(state, AGC5_1)); -+ -+ state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ -+ CHK_ERROR(update_reg(state, IRQ_CLEAR)); -+ -+ state->m_Regs[MSM_1] = 0x3B; // Set Calibration -+ state->m_Regs[MSM_2] = 0x01; // Start MSM -+ CHK_ERROR(update_regs(state, MSM_1,MSM_2)); -+ state->m_Regs[MSM_2] = 0x00; -+ -+ } while(0); -+ return status; -+} -+ -+static int FinishCalibration(struct tda_state *state) -+{ -+ int status = 0; -+ u8 RFCal_Log[12]; -+ -+ do { -+ u8 IRQ = 0; -+ int Timeout = 150; // 1.5 s -+ while(true) { -+ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); -+ if ((IRQ & 0x80) != 0 ) -+ break; -+ Timeout -= 1; -+ if (Timeout == 0) { -+ status = -1; -+ break; -+ } -+ msleep(10); -+ } -+ CHK_ERROR(status); -+ -+ state->m_Regs[FLO_MAX] = 0x0A; -+ CHK_ERROR(update_reg(state, FLO_MAX)); -+ -+ state->m_Regs[AGC1_1] &= ~0xC0; -+ if( state->m_bLTEnable ) state->m_Regs[AGC1_1] |= 0x80; // LTEnable -+ -+ state->m_Regs[AGC1_1] |= (state->m_isMaster ? MASTER_AGC1_6_15dB : SLAVE_AGC1_6_15dB ) << 6; -+ CHK_ERROR(update_reg(state, AGC1_1)); -+ -+ state->m_Regs[PSM_1] &= ~0xC0; -+ state->m_Regs[PSM_1] |= (state->m_isMaster ? MASTER_PSM_AGC1 : SLAVE_PSM_AGC1 ) << 6; -+ CHK_ERROR(update_reg(state, PSM_1)); -+ -+ state->m_Regs[REFERENCE] |= 0x03; // XTOUT = 3 -+ CHK_ERROR(update_reg(state, REFERENCE)); -+ -+ CHK_ERROR(read_regs(state, RFCAL_LOG_1,RFCal_Log,sizeof(RFCal_Log))); -+ } while(0); -+ return status; -+} -+ -+static int PowerOn(struct tda_state *state) -+{ -+ state->m_Regs[POWER_STATE_2] &= ~0x0F; -+ update_reg(state, POWER_STATE_2); -+ state->m_Regs[REFERENCE] |= 0x40; // Digital clock source = Sigma Delta -+ update_reg(state, REFERENCE); -+ return 0; -+} -+ -+static int Standby(struct tda_state *state) -+{ -+ int status = 0; -+ -+ do { -+ state->m_Regs[REFERENCE] &= ~0x40; // Digital clock source = Quarz -+ CHK_ERROR(update_reg(state, REFERENCE)); -+ -+ state->m_Regs[POWER_STATE_2] &= ~0x0F; -+ state->m_Regs[POWER_STATE_2] |= state->m_isMaster ? 0x08 : 0x0E; -+ CHK_ERROR(update_reg(state, POWER_STATE_2)); -+ } while(0); -+ return status; -+} -+ -+static int attach_init(struct tda_state *state) -+{ -+ int stat = 0; -+ u8 Id[2]; -+ u8 PowerState = 0x00; -+ -+ state->m_Standard = HF_None; -+ -+ /* first read after cold reset sometimes fails on some cards, -+ try twice */ -+ stat = read_regs(state, ID_1, Id, sizeof(Id)); -+ stat = read_regs(state, ID_1, Id, sizeof(Id)); -+ if (stat < 0) -+ return -1; -+ -+ state->m_ID = ((Id[0] & 0x7F) << 8) | Id[1]; -+ state->m_isMaster = ((Id[0] & 0x80) != 0); -+ if( !state->m_isMaster ) -+ state->m_bLTEnable = false; -+ -+ printk("tda18212dd: ChipID %04x\n", state->m_ID); -+ -+ if( state->m_ID != 18212 ) -+ return -1; -+ -+ stat = read_reg(state, POWER_STATE_1 ,&PowerState); -+ if (stat < 0) -+ return stat; -+ -+ printk("tda18212dd: PowerState %02x\n", PowerState); -+ -+ if (state->m_isMaster) { -+ if( PowerState & 0x02 ) { -+ // msleep for XTAL Calibration (on a PC this should be long done) -+ u8 IRQStatus = 0; -+ int Timeout = 10; -+ -+ while(Timeout > 0) { -+ read_reg(state, IRQ_STATUS, &IRQStatus); -+ if (IRQStatus & 0x20) -+ break; -+ Timeout -= 1; -+ msleep(10); -+ } -+ if( (IRQStatus & 0x20) == 0 ) { -+ stat = -ETIMEDOUT; -+ } -+ } -+ } else { -+ write_reg(state, FLO_MAX, 0x00); -+ write_reg(state, CP_CURRENT,0x68); -+ } -+ Read(state, state->m_Regs); -+ -+ PowerOn(state); -+ StartCalibration(state); -+ FinishCalibration(state); -+ Standby(state); -+ return stat; -+} -+ -+static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel) -+{ -+ int status = 0; -+ -+ do { -+ u8 IRQ = 0; -+ int Timeout = 70; // 700 ms -+ -+ state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ -+ CHK_ERROR(update_reg(state, IRQ_CLEAR)); -+ -+ state->m_Regs[MSM_1] = 0x80; // power measurement -+ state->m_Regs[MSM_2] = 0x01; // Start MSM -+ CHK_ERROR(update_regs(state, MSM_1,MSM_2)); -+ state->m_Regs[MSM_2] = 0x00; -+ -+ while(true) { -+ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); -+ if( (IRQ & 0x80) != 0 ) -+ break; -+ Timeout -= 1; -+ if( Timeout == 0 ) -+ { -+ status = -1; -+ break; -+ } -+ msleep(10); -+ } -+ CHK_ERROR(status); -+ -+ CHK_ERROR(read_reg1(state, INPUT_POWER_LEVEL)); -+ *pPowerLevel = state->m_Regs[INPUT_POWER_LEVEL] & 0x7F; -+ -+ -+ if( *pPowerLevel > 110 ) *pPowerLevel = 110; -+ } while(0); -+ /* printk("PL %d\n", *pPowerLevel); */ -+ return status; -+} -+ -+static int SetFrequency(struct tda_state *state, u32 Frequency, enum HF_Standard Standard) -+{ -+ int status = 0; -+ struct SStandardParams *StandardParams; -+ u32 f = Frequency / 1000; -+ u8 IRQ = 0; -+ int Timeout = 25; // 250 ms -+ u32 fRatio = Frequency / 16000000; -+ u32 fDelta = Frequency - fRatio * 16000000; -+ -+ if( Standard < HF_DVBT_6MHZ || Standard > HF_DVBC_8MHZ ) -+ return -EINVAL; -+ StandardParams = &m_StandardTable[Standard - HF_DVBT_6MHZ]; -+ -+ if( StandardParams->m_IFFrequency == 0 ) -+ return -EINVAL; -+ state->m_Standard = HF_None; -+ state->m_Frequency = 0; -+ -+ do { -+ // IF Level -+ state->m_Regs[IF_AGC] = (Standard >= HF_DVBC_6MHZ) ? state->m_IFLevelDVBC : state->m_IFLevelDVBT; -+ CHK_ERROR(update_reg(state, IF_AGC)); -+ -+ // --------------------------------------------------------------------------------- -+ // Standard setup -+ -+ state->m_Regs[IF_1] = StandardParams->m_IF_1; -+ CHK_ERROR(update_reg(state, IF_1)); -+ -+ state->m_Regs[IR_MIXER_2] = (state->m_Regs[IR_MIXER_2] & ~0x03) | StandardParams->m_IR_MIXER_2; -+ CHK_ERROR(update_reg(state, IR_MIXER_2)); -+ -+ state->m_Regs[AGC1_1] = (state->m_Regs[AGC1_1] & ~0x0F) | StandardParams->m_AGC1_1; -+ CHK_ERROR(update_reg(state, AGC1_1)); -+ -+ state->m_Regs[AGC2_1] = (state->m_Regs[AGC2_1] & ~0x0F) | StandardParams->m_AGC2_1; -+ CHK_ERROR(update_reg(state, AGC2_1)); -+ -+ state->m_Regs[RF_AGC_1] &= ~0xEF; -+ if( Frequency < 291000000 ) -+ state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_Low; -+ else -+ state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_High; -+ CHK_ERROR(update_reg(state, RF_AGC_1)); -+ -+ state->m_Regs[IR_MIXER_1] = (state->m_Regs[IR_MIXER_1] & ~0x0F) | StandardParams->m_IR_MIXER_1; -+ CHK_ERROR(update_reg(state, IR_MIXER_1)); -+ -+ state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x1F) | StandardParams->m_AGC5_1; -+ CHK_ERROR(update_reg(state, AGC5_1)); -+ -+ state->m_Regs[AGCK_1] = (state->m_Regs[AGCK_1] & ~0x0F) | StandardParams->m_AGCK_1; -+ CHK_ERROR(update_reg(state, AGCK_1)); -+ -+ state->m_Regs[PSM_1] = (state->m_Regs[PSM_1] & ~0x20) | StandardParams->m_PSM_1; -+ CHK_ERROR(update_reg(state, PSM_1)); -+ -+ state->m_Regs[IF_FREQUENCY_1] = ( StandardParams->m_IFFrequency / 50000 ); -+ CHK_ERROR(update_reg(state, IF_FREQUENCY_1)); -+ -+ if( state->m_isMaster && StandardParams->m_LTO_STO_immune ) -+ { -+ u8 tmp; -+ u8 RF_Filter_Gain; -+ -+ CHK_ERROR(read_reg(state, RF_AGC_GAIN_1,&tmp)); -+ RF_Filter_Gain = (tmp & 0x30) >> 4; -+ -+ state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2); -+ CHK_ERROR(update_reg(state, RF_FILTER_1)); -+ -+ state->m_Regs[RF_FILTER_1] |= 0x10; // Force -+ CHK_ERROR(update_reg(state, RF_FILTER_1)); -+ -+ while( RF_Filter_Gain != 0 ) -+ { -+ RF_Filter_Gain -= 1; -+ state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2); -+ CHK_ERROR(update_reg(state, RF_FILTER_1)); -+ msleep(10); -+ } -+ CHK_ERROR(status); -+ -+ state->m_Regs[RF_AGC_1] |= 0x08; -+ CHK_ERROR(update_reg(state, RF_AGC_1)); -+ } -+ -+ // --------------------------------------------------------------------------------- -+ -+ state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ -+ CHK_ERROR(update_reg(state, IRQ_CLEAR)); -+ -+ CHK_ERROR(PowerOn(state)); -+ -+ state->m_Regs[RF_FREQUENCY_1] = ((f >> 16) & 0xFF); -+ state->m_Regs[RF_FREQUENCY_2] = ((f >> 8) & 0xFF); -+ state->m_Regs[RF_FREQUENCY_3] = ((f ) & 0xFF); -+ CHK_ERROR(update_regs(state, RF_FREQUENCY_1,RF_FREQUENCY_3)); -+ -+ state->m_Regs[MSM_1] = 0x41; // Tune -+ state->m_Regs[MSM_2] = 0x01; // Start MSM -+ CHK_ERROR(update_regs(state, MSM_1, MSM_2)); -+ state->m_Regs[MSM_2] = 0x00; -+ -+ while(true) -+ { -+ CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ)); -+ if( (IRQ & 0x80) != 0 ) break; -+ Timeout -= 1; -+ if (Timeout == 0) { -+ status = -1; -+ break; -+ } -+ msleep(10); -+ } -+ CHK_ERROR(status); -+ -+ // --------------------------------------------------------------------------------- -+ -+ if( state->m_isMaster && StandardParams->m_LTO_STO_immune ) -+ { -+ state->m_Regs[RF_AGC_1] &= ~0x08; -+ CHK_ERROR(update_reg(state, RF_AGC_1)); -+ -+ msleep(50); -+ -+ state->m_Regs[RF_FILTER_1] &= ~0x10; // remove force -+ CHK_ERROR(update_reg(state, RF_FILTER_1)); -+ } -+ -+ // --------------------------------------------------------------------------------- -+ // Spur reduction -+ -+ if( Frequency < 72000000 ) -+ { -+ state->m_Regs[REFERENCE] |= 0x40; // Set digital clock -+ } -+ else if( Frequency < 104000000 ) -+ { -+ state->m_Regs[REFERENCE] &= ~0x40; // Clear digital clock -+ } -+ else if( Frequency < 120000000 ) -+ { -+ state->m_Regs[REFERENCE] |= 0x40; // Set digital clock -+ } -+ else -+ { -+ if( fDelta <= 8000000 ) -+ { -+ if( fRatio & 1 ) state->m_Regs[REFERENCE] &= ~0x40; // Clear digital clock -+ else state->m_Regs[REFERENCE] |= 0x40; // Set digital clock -+ } -+ else -+ { -+ if( fRatio & 1 ) state->m_Regs[REFERENCE] |= 0x40; // Set digital clock -+ else state->m_Regs[REFERENCE] &= ~0x40; // Clear digital clock -+ } -+ -+ } -+ CHK_ERROR(update_reg(state, REFERENCE)); -+ -+ if( StandardParams->m_AGC1_Freeze && state->m_bEnableFreeze ) -+ { -+ u8 tmp; -+ int AGC1GainMin = 0; -+ int nSteps = 10; -+ int Step = 0; -+ -+ CHK_ERROR(read_reg(state, AGC1_2,&tmp)); -+ -+ if( (tmp & 0x80) == 0 ) -+ { -+ state->m_Regs[AGC1_2] |= 0x80; // Loop off -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ state->m_Regs[AGC1_2] |= 0x10 ; // Force gain -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ } -+ // Adapt -+ if( state->m_Regs[AGC1_1] & 0x40 ) // AGC1_6_15dB set -+ { -+ AGC1GainMin = 6; -+ nSteps = 4; -+ } -+ while( Step < nSteps ) -+ { -+ int Down = 0; -+ int Up = 0, i; -+ u8 AGC1_Gain; -+ -+ Step = Step + 1; -+ -+ for (i = 0; i < 40; i += 1) { -+ CHK_ERROR(read_reg(state, AGC_DET_OUT, &tmp)); -+ Up += (tmp & 0x02) ? 1 : -4; -+ Down += (tmp & 0x01) ? 14 : -1; -+ msleep(1); -+ } -+ CHK_ERROR(status); -+ AGC1_Gain = (state->m_Regs[AGC1_2] & 0x0F); -+ if( Up >= 15 && AGC1_Gain != 9 ) -+ { -+ state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain + 1); -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ } -+ else if ( Down >= 10 && AGC1_Gain != AGC1GainMin ) -+ { -+ state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain - 1); -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ } -+ else -+ { -+ Step = nSteps; -+ } -+ } -+ } -+ else -+ { -+ state->m_Regs[AGC1_2] &= ~0x10 ; // unforce gain -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ state->m_Regs[AGC1_2] &= ~0x80; // Loop on -+ CHK_ERROR(update_reg(state, AGC1_2)); -+ } -+ -+ state->m_Standard = Standard; -+ state->m_Frequency = Frequency; -+ -+ if( state->m_bPowerMeasurement ) -+ PowerMeasurement(state, &state->m_LastPowerLevel); -+ } while(0); -+ -+ return status; -+} -+ -+static int sleep(struct dvb_frontend* fe) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ -+ Standby(state); -+ return 0; -+} -+ -+static int init(struct dvb_frontend* fe) -+{ -+ //struct tda_state *state = fe->tuner_priv; -+ return 0; -+} -+ -+static int release(struct dvb_frontend* fe) -+{ -+ kfree(fe->tuner_priv); -+ fe->tuner_priv = NULL; -+ return 0; -+} -+ -+#ifdef USE_API3 -+static int set_params(struct dvb_frontend *fe, -+ struct dvb_frontend_parameters *params) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ int status = 0; -+ int Standard; -+ -+ state->m_Frequency = params->frequency; -+ -+ if (fe->ops.info.type == FE_OFDM) -+ switch (params->u.ofdm.bandwidth) { -+ case BANDWIDTH_6_MHZ: -+ Standard = HF_DVBT_6MHZ; -+ break; -+ case BANDWIDTH_7_MHZ: -+ Standard = HF_DVBT_7MHZ; -+ break; -+ default: -+ case BANDWIDTH_8_MHZ: -+ Standard = HF_DVBT_8MHZ; -+ break; -+ } -+ else if (fe->ops.info.type == FE_QAM) { -+ Standard = HF_DVBC_8MHZ; -+ } else -+ return -EINVAL; -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ SetFrequency(state, state->m_Frequency, Standard); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ -+ return status; -+} -+#else -+static int set_params(struct dvb_frontend *fe) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ int status = 0; -+ int Standard; -+ -+ state->m_Frequency = p->frequency; -+ -+ if (p->delivery_system == SYS_DVBT) -+ switch (p->bandwidth_hz) { -+ case 6000000: -+ Standard = HF_DVBT_6MHZ; -+ break; -+ case 7000000: -+ Standard = HF_DVBT_7MHZ; -+ break; -+ default: -+ case 8000000: -+ Standard = HF_DVBT_8MHZ; -+ break; -+ } -+ else if (p->delivery_system == SYS_DVBC_ANNEX_A) { -+ Standard = HF_DVBC_8MHZ; -+ } else -+ return -EINVAL; -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ SetFrequency(state, state->m_Frequency, Standard); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ -+ return status; -+} -+#endif -+ -+static int get_frequency(struct dvb_frontend *fe, u32 *frequency) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ -+ *frequency = state->IF; -+ return 0; -+} -+ -+static int get_rf_strength(struct dvb_frontend *fe, u16 *st) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ -+ *st = state->m_LastPowerLevel; -+ return 0; -+} -+ -+static int get_if(struct dvb_frontend *fe, u32 *frequency) -+{ -+ struct tda_state *state = fe->tuner_priv; -+ -+ state->IF = 0; -+ if (state->m_Standard < HF_DVBT_6MHZ || -+ state->m_Standard > HF_DVBC_8MHZ) -+ return 0; -+ state->IF = m_StandardTable[state->m_Standard - HF_DVBT_6MHZ].m_IFFrequency; -+ *frequency = state->IF; -+ return 0; -+} -+ -+static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) -+{ -+ //struct tda_state *state = fe->tuner_priv; -+ //*bandwidth = priv->bandwidth; -+ return 0; -+} -+ -+ -+static struct dvb_tuner_ops tuner_ops = { -+ .info = { -+ .name = "NXP TDA18212", -+ .frequency_min = 47125000, -+ .frequency_max = 865000000, -+ .frequency_step = 62500 -+ }, -+ .init = init, -+ .sleep = sleep, -+ .set_params = set_params, -+ .release = release, -+ .get_frequency = get_frequency, -+ .get_if_frequency = get_if, -+ .get_bandwidth = get_bandwidth, -+ .get_rf_strength = get_rf_strength, -+}; -+ -+struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr) -+{ -+ struct tda_state *state; -+ int stat; -+ -+ state = kzalloc(sizeof(struct tda_state), GFP_KERNEL); -+ if (!state) -+ return NULL; -+ state->adr = adr; -+ state->i2c = i2c; -+ memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops)); -+ init_state(state); -+ -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 1); -+ stat = attach_init(state); -+ if (fe->ops.i2c_gate_ctrl) -+ fe->ops.i2c_gate_ctrl(fe, 0); -+ if (stat < 0) { -+ kfree(state); -+ return 0; -+ } -+ fe->tuner_priv = state; -+ return fe; -+} -+ -+EXPORT_SYMBOL_GPL(tda18212dd_attach); -+MODULE_DESCRIPTION("TDA18212 driver"); -+MODULE_AUTHOR("DD"); -+MODULE_LICENSE("GPL"); -+ -+/* -+ * Local variables: -+ * c-basic-offset: 8 -+ * End: -+ */ -diff --git a/drivers/media/dvb-frontends/tda18212dd.h b/drivers/media/dvb-frontends/tda18212dd.h -new file mode 100644 -index 0000000..687fab4 ---- /dev/null -+++ b/drivers/media/dvb-frontends/tda18212dd.h -@@ -0,0 +1,5 @@ -+#ifndef _TDA18212DD_H_ -+#define _TDA18212DD_H_ -+struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe, -+ struct i2c_adapter *i2c, u8 adr); -+#endif -diff --git a/drivers/media/pci/ddbridge/Kconfig b/drivers/media/pci/ddbridge/Kconfig -index 44e5dc1..0a4ae75 100644 ---- a/drivers/media/pci/ddbridge/Kconfig -+++ b/drivers/media/pci/ddbridge/Kconfig -@@ -1,11 +1,14 @@ - config DVB_DDBRIDGE - tristate "Digital Devices bridge support" - depends on DVB_CORE && PCI && I2C -- select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT -- select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT -- select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT -- select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT -- select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_CXD2099 -+ select DVB_LNBP21 if !DVB_FE_CUSTOMISE -+ select DVB_STV6110x if !DVB_FE_CUSTOMISE -+ select DVB_STV090x if !DVB_FE_CUSTOMISE -+ select DVB_DRXK if !DVB_FE_CUSTOMISE -+ select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE -+ select DVB_STV0367DD if !DVB_FE_CUSTOMISE -+ select DVB_TDA18212DD if !DVB_FE_CUSTOMISE - ---help--- - Support for cards with the Digital Devices PCI express bridge: - - Octopus PCIe Bridge -@@ -14,5 +17,6 @@ config DVB_DDBRIDGE - - DuoFlex S2 Octopus - - DuoFlex CT Octopus - - cineS2(v6) -+ - cineCT(v6) - - Say Y if you own such a card and want to use it. -diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c -index 36e3452..adff8cd 100644 ---- a/drivers/media/pci/ddbridge/ddbridge-core.c -+++ b/drivers/media/pci/ddbridge/ddbridge-core.c -@@ -31,11 +31,11 @@ - #include - #include - #include -+#include - #include - #include - #include - #include "ddbridge.h" -- - #include "ddbridge-regs.h" - - #include "tda18271c2dd.h" -@@ -43,14 +43,60 @@ - #include "stv090x.h" - #include "lnbh24.h" - #include "drxk.h" -+#if 0 -+#include "stv0367.h" -+#else -+#include "stv0367dd.h" -+#endif -+#if 0 -+#include "tda18212.h" -+#else -+#include "tda18212dd.h" -+#endif -+ -+static int adapter_alloc; -+module_param(adapter_alloc, int, 0444); -+MODULE_PARM_DESC(adapter_alloc, "0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all"); -+ -+static int ts_loop = -1; -+module_param(ts_loop, int, 0444); -+MODULE_PARM_DESC(ts_loop, "TS in/out on port ts_loop"); - - DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); - -+static struct ddb *ddbs[32]; -+ - /* MSI had problems with lost interrupts, fixed but needs testing */ --#undef CONFIG_PCI_MSI -+/* #undef CONFIG_PCI_MSI */ -+ -+/******************************************************************************/ -+ -+static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr) -+{ -+ writel(val, (char *) (dev->regs+(adr))); -+} -+ -+static inline u32 ddbreadl(struct ddb *dev, u32 adr) -+{ -+ return readl((char *) (dev->regs+(adr))); -+} -+ -+#define ddbcpyto(_dev, _adr, _src, _count) memcpy_toio((char *) \ -+ (_dev->regs + (_adr)), (_src), (_count)) -+ -+#define ddbcpyfrom(_dev, _dst, _adr, _count) memcpy_fromio((_dst), (char *) \ -+ (_dev->regs + (_adr)), (_count)) -+ - - /******************************************************************************/ - -+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len) -+{ -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len}; -+ -+ return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1; -+} -+ - static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) - { - struct i2c_msg msgs[1] = {{.addr = adr, .flags = I2C_M_RD, -@@ -58,10 +104,31 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val) - return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1; - } - -+static int i2c_read_regs(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u8 *val, u8 len) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = ®, .len = 1}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ -+static int i2c_read_regs16(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 *val, u8 len) -+{ -+ u8 reg16[2] = { reg >> 8, reg }; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = (u8 *)®16, .len = 2}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = val, .len = len } }; -+ return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -+} -+ - static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) - { - struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -- .buf = ®, .len = 1 }, -+ .buf = ®, .len = 1}, - {.addr = adr, .flags = I2C_M_RD, - .buf = val, .len = 1 } }; - return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; -@@ -70,14 +137,22 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val) - static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr, - u16 reg, u8 *val) - { -- u8 msg[2] = {reg>>8, reg&0xff}; -+ u8 msg[2] = {reg >> 8, reg & 0xff}; - struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, - .buf = msg, .len = 2}, - {.addr = adr, .flags = I2C_M_RD, -- .buf = val, .len = 1} }; -+ .buf = val, .len = 1 } }; - return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1; - } - -+static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr, -+ u16 reg, u8 val) -+{ -+ u8 msg[3] = {reg >> 8, reg & 0xff, val}; -+ -+ return i2c_write(adap, adr, msg, 3); -+} -+ - static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) - { - struct ddb *dev = i2c->dev; -@@ -85,18 +160,18 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) - u32 val; - - i2c->done = 0; -- ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND); -+ ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND); - stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ); - if (stat <= 0) { - printk(KERN_ERR "I2C timeout\n"); - { /* MSI debugging*/ -- u32 istat = ddbreadl(INTERRUPT_STATUS); -+ u32 istat = ddbreadl(dev, INTERRUPT_STATUS); - printk(KERN_ERR "IRS %08x\n", istat); -- ddbwritel(istat, INTERRUPT_ACK); -+ ddbwritel(dev, istat, INTERRUPT_ACK); - } - return -EIO; - } -- val = ddbreadl(i2c->regs+I2C_COMMAND); -+ val = ddbreadl(dev, i2c->regs+I2C_COMMAND); - if (val & 0x70000) - return -EIO; - return 0; -@@ -105,7 +180,7 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) - static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, - struct i2c_msg msg[], int num) - { -- struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter); -+ struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter); - struct ddb *dev = i2c->dev; - u8 addr = 0; - -@@ -116,8 +191,8 @@ static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, - !(msg[0].flags & I2C_M_RD)) { - memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf, - msg[0].buf, msg[0].len); -- ddbwritel(msg[0].len|(msg[1].len << 16), -- i2c->regs+I2C_TASKLENGTH); -+ ddbwritel(dev, msg[0].len|(msg[1].len << 16), -+ i2c->regs + I2C_TASKLENGTH); - if (!ddb_i2c_cmd(i2c, addr, 1)) { - memcpy_fromio(msg[1].buf, - dev->regs + I2C_TASKMEM_BASE + i2c->rbuf, -@@ -125,17 +200,16 @@ static int ddb_i2c_master_xfer(struct i2c_adapter *adapter, - return num; - } - } -- - if (num == 1 && !(msg[0].flags & I2C_M_RD)) { -- ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len); -- ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH); -+ ddbcpyto(dev, I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len); -+ ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH); - if (!ddb_i2c_cmd(i2c, addr, 2)) - return num; - } - if (num == 1 && (msg[0].flags & I2C_M_RD)) { -- ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); -+ ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH); - if (!ddb_i2c_cmd(i2c, addr, 3)) { -- ddbcpyfrom(msg[0].buf, -+ ddbcpyfrom(dev, msg[0].buf, - I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len); - return num; - } -@@ -160,7 +234,7 @@ static void ddb_i2c_release(struct ddb *dev) - struct ddb_i2c *i2c; - struct i2c_adapter *adap; - -- for (i = 0; i < dev->info->port_num; i++) { -+ for (i = 0; i < dev->info->i2c_num; i++) { - i2c = &dev->i2c[i]; - adap = &i2c->adap; - i2c_del_adapter(adap); -@@ -173,15 +247,15 @@ static int ddb_i2c_init(struct ddb *dev) - struct ddb_i2c *i2c; - struct i2c_adapter *adap; - -- for (i = 0; i < dev->info->port_num; i++) { -+ for (i = 0; i < dev->info->i2c_num; i++) { - i2c = &dev->i2c[i]; - i2c->dev = dev; - i2c->nr = i; - i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4); - i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8); - i2c->regs = 0x80 + i * 0x20; -- ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING); -- ddbwritel((i2c->rbuf << 16) | i2c->wbuf, -+ ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING); -+ ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf, - i2c->regs + I2C_TASKADDRESS); - init_waitqueue_head(&i2c->wq); - -@@ -216,69 +290,94 @@ static int ddb_i2c_init(struct ddb *dev) - /******************************************************************************/ - /******************************************************************************/ - --#if 0 --static void set_table(struct ddb *dev, u32 off, -- dma_addr_t *pbuf, u32 num) -+static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma) - { - u32 i, base; - u64 mem; - -- base = DMA_BASE_ADDRESS_TABLE + off; -- for (i = 0; i < num; i++) { -- mem = pbuf[i]; -- ddbwritel(mem & 0xffffffff, base + i * 8); -- ddbwritel(mem >> 32, base + i * 8 + 4); -+ if (!dma) -+ return; -+ base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100; -+ for (i = 0; i < dma->num; i++) { -+ mem = dma->pbuf[i]; -+ ddbwritel(dev, mem & 0xffffffff, base + i * 8); -+ ddbwritel(dev, mem >> 32, base + i * 8 + 4); - } -+ dma->bufreg = (dma->div << 16) | -+ ((dma->num & 0x1f) << 11) | -+ ((dma->size >> 7) & 0x7ff); - } --#endif - --static void ddb_address_table(struct ddb *dev) -+static void ddb_set_dma_tables(struct ddb *dev) - { -- u32 i, j, base; -- u64 mem; -- dma_addr_t *pbuf; -+ u32 i; - -- for (i = 0; i < dev->info->port_num * 2; i++) { -- base = DMA_BASE_ADDRESS_TABLE + i * 0x100; -- pbuf = dev->input[i].pbuf; -- for (j = 0; j < dev->input[i].dma_buf_num; j++) { -- mem = pbuf[j]; -- ddbwritel(mem & 0xffffffff, base + j * 8); -- ddbwritel(mem >> 32, base + j * 8 + 4); -- } -- } -- for (i = 0; i < dev->info->port_num; i++) { -- base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100; -- pbuf = dev->output[i].pbuf; -- for (j = 0; j < dev->output[i].dma_buf_num; j++) { -- mem = pbuf[j]; -- ddbwritel(mem & 0xffffffff, base + j * 8); -- ddbwritel(mem >> 32, base + j * 8 + 4); -- } -- } -+ for (i = 0; i < dev->info->port_num * 2; i++) -+ ddb_set_dma_table(dev, dev->input[i].dma); -+ for (i = 0; i < dev->info->port_num; i++) -+ ddb_set_dma_table(dev, dev->output[i].dma); - } - --static void io_free(struct pci_dev *pdev, u8 **vbuf, -- dma_addr_t *pbuf, u32 size, int num) -+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma) - { - int i; - -- for (i = 0; i < num; i++) { -- if (vbuf[i]) { -- pci_free_consistent(pdev, size, vbuf[i], pbuf[i]); -- vbuf[i] = 0; -+ if (!dma) -+ return; -+ for (i = 0; i < dma->num; i++) { -+ if (dma->vbuf[i]) { -+ pci_free_consistent(pdev, dma->size, -+ dma->vbuf[i], dma->pbuf[i]); -+ dma->vbuf[i] = 0; - } - } - } - --static int io_alloc(struct pci_dev *pdev, u8 **vbuf, -- dma_addr_t *pbuf, u32 size, int num) -+static void ddb_redirect_dma(struct ddb *dev, -+ struct ddb_dma *sdma, -+ struct ddb_dma *ddma) -+{ -+ u32 i, base; -+ u64 mem; -+ -+ sdma->bufreg = ddma->bufreg; -+ base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100; -+ for (i = 0; i < ddma->num; i++) { -+ mem = ddma->pbuf[i]; -+ ddbwritel(dev, mem & 0xffffffff, base + i * 8); -+ ddbwritel(dev, mem >> 32, base + i * 8 + 4); -+ } -+} -+ -+static void ddb_unredirect(struct ddb_port *port) -+{ -+ struct ddb_input *ored, *ired; -+ -+ ored = port->output->redirect; -+ ired = port->input[0]->redirect; -+ -+ if (!ored || !ired) -+ return; -+ if (ired->port->output->redirect == port->input[0]) { -+ ired->port->output->redirect = ored; -+ ddb_set_dma_table(port->dev, port->input[0]->dma); -+ ddb_redirect_dma(ored->port->dev, ored->dma, ired->port->output->dma); -+ } else -+ ddb_set_dma_table(ored->port->dev, ored->dma); -+ ored->redirect = ired; -+ port->input[0]->redirect = 0; -+ port->output->redirect = 0; -+} -+ -+static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma) - { - int i; - -- for (i = 0; i < num; i++) { -- vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]); -- if (!vbuf[i]) -+ if (!dma) -+ return 0; -+ for (i = 0; i < dma->num; i++) { -+ dma->vbuf[i] = pci_alloc_consistent(pdev, dma->size, &dma->pbuf[i]); -+ if (!dma->vbuf[i]) - return -ENOMEM; - } - return 0; -@@ -293,34 +392,23 @@ static int ddb_buffers_alloc(struct ddb *dev) - port = &dev->port[i]; - switch (port->class) { - case DDB_PORT_TUNER: -- if (io_alloc(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num) < 0) -+ if (dma_alloc(dev->pdev, port->input[0]->dma) < 0) - return -1; -- if (io_alloc(dev->pdev, port->input[1]->vbuf, -- port->input[1]->pbuf, -- port->input[1]->dma_buf_size, -- port->input[1]->dma_buf_num) < 0) -+ if (dma_alloc(dev->pdev, port->input[1]->dma) < 0) - return -1; - break; - case DDB_PORT_CI: -- if (io_alloc(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num) < 0) -+ case DDB_PORT_LOOP: -+ if (dma_alloc(dev->pdev, port->input[0]->dma) < 0) - return -1; -- if (io_alloc(dev->pdev, port->output->vbuf, -- port->output->pbuf, -- port->output->dma_buf_size, -- port->output->dma_buf_num) < 0) -+ if (dma_alloc(dev->pdev, port->output->dma) < 0) - return -1; - break; - default: - break; - } - } -- ddb_address_table(dev); -+ ddb_set_dma_tables(dev); - return 0; - } - -@@ -331,18 +419,11 @@ static void ddb_buffers_free(struct ddb *dev) - - for (i = 0; i < dev->info->port_num; i++) { - port = &dev->port[i]; -- io_free(dev->pdev, port->input[0]->vbuf, -- port->input[0]->pbuf, -- port->input[0]->dma_buf_size, -- port->input[0]->dma_buf_num); -- io_free(dev->pdev, port->input[1]->vbuf, -- port->input[1]->pbuf, -- port->input[1]->dma_buf_size, -- port->input[1]->dma_buf_num); -- io_free(dev->pdev, port->output->vbuf, -- port->output->pbuf, -- port->output->dma_buf_size, -- port->output->dma_buf_num); -+ -+ ddb_unredirect(port); -+ dma_free(dev->pdev, port->input[0]->dma); -+ dma_free(dev->pdev, port->input[1]->dma); -+ dma_free(dev->pdev, port->output->dma); - } - } - -@@ -350,90 +431,116 @@ static void ddb_input_start(struct ddb_input *input) - { - struct ddb *dev = input->port->dev; - -- spin_lock_irq(&input->lock); -- input->cbuf = 0; -- input->coff = 0; -+ spin_lock_irq(&input->dma->lock); -+ input->dma->cbuf = 0; -+ input->dma->coff = 0; - - /* reset */ -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(2, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); -+ ddbwritel(dev, 2, TS_INPUT_CONTROL(input->nr)); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); - -- ddbwritel((1 << 16) | -- (input->dma_buf_num << 11) | -- (input->dma_buf_size >> 7), -- DMA_BUFFER_SIZE(input->nr)); -- ddbwritel(0, DMA_BUFFER_ACK(input->nr)); -+ ddbwritel(dev, input->dma->bufreg, DMA_BUFFER_SIZE(input->dma->nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); - -- ddbwritel(1, DMA_BASE_WRITE); -- ddbwritel(3, DMA_BUFFER_CONTROL(input->nr)); -- ddbwritel(9, TS_INPUT_CONTROL(input->nr)); -- input->running = 1; -- spin_unlock_irq(&input->lock); -+ ddbwritel(dev, 1, DMA_BASE_WRITE); -+ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr)); -+ ddbwritel(dev, 9, TS_INPUT_CONTROL(input->nr)); -+ input->dma->running = 1; -+ spin_unlock_irq(&input->dma->lock); -+ /* printk(KERN_INFO "input_start %d\n", input->nr); */ - } - - static void ddb_input_stop(struct ddb_input *input) - { - struct ddb *dev = input->port->dev; - -- spin_lock_irq(&input->lock); -- ddbwritel(0, TS_INPUT_CONTROL(input->nr)); -- ddbwritel(0, DMA_BUFFER_CONTROL(input->nr)); -- input->running = 0; -- spin_unlock_irq(&input->lock); -+ spin_lock_irq(&input->dma->lock); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr)); -+ input->dma->running = 0; -+ spin_unlock_irq(&input->dma->lock); - } - - static void ddb_output_start(struct ddb_output *output) - { - struct ddb *dev = output->port->dev; - -- spin_lock_irq(&output->lock); -- output->cbuf = 0; -- output->coff = 0; -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(2, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel((1 << 16) | -- (output->dma_buf_num << 11) | -- (output->dma_buf_size >> 7), -- DMA_BUFFER_SIZE(output->nr + 8)); -- ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8)); -- -- ddbwritel(1, DMA_BASE_READ); -- ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8)); -- /* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */ -- ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr)); -- output->running = 1; -- spin_unlock_irq(&output->lock); -+ spin_lock_irq(&output->dma->lock); -+ output->dma->cbuf = 0; -+ output->dma->coff = 0; -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, output->dma->bufreg, DMA_BUFFER_SIZE(output->dma->nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr)); -+ -+ ddbwritel(dev, 1, DMA_BASE_READ); -+ ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr)); -+ if (output->port->input[0]->port->class == DDB_PORT_LOOP) -+ ddbwritel(dev, 0x05, TS_OUTPUT_CONTROL(output->nr)); -+ else -+ ddbwritel(dev, 0x1d, TS_OUTPUT_CONTROL(output->nr)); -+ output->dma->running = 1; -+ spin_unlock_irq(&output->dma->lock); -+ /* printk(KERN_INFO "output_start %d\n", output->nr); */ -+} -+ -+#if 0 -+static void ddb_input_start_all(struct ddb_input *input) -+{ -+ struct ddb_input *next; -+ -+ ddb_input_start(input); -+ while ((next = input->redirect) && -+ next != input) { -+ ddb_input_start(next); -+ ddb_output_start(next->port->output); -+ } - } -+#endif - - static void ddb_output_stop(struct ddb_output *output) - { - struct ddb *dev = output->port->dev; - -- spin_lock_irq(&output->lock); -- ddbwritel(0, TS_OUTPUT_CONTROL(output->nr)); -- ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8)); -- output->running = 0; -- spin_unlock_irq(&output->lock); -+ spin_lock_irq(&output->dma->lock); -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr)); -+ output->dma->running = 0; -+ spin_unlock_irq(&output->dma->lock); -+} -+ -+#if 0 -+static void ddb_input_stop_all(struct ddb_input *input) -+{ -+ struct ddb_input *next; -+ -+ ddb_input_stop(input); -+ while ((next = input->redirect) && -+ next != input) { -+ ddb_input_stop(next); -+ ddb_output_stop(next->port->output); -+ } - } -+#endif - - static u32 ddb_output_free(struct ddb_output *output) - { -- u32 idx, off, stat = output->stat; -+ u32 idx, off, stat = output->dma->stat; - s32 diff; - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - -- if (output->cbuf != idx) { -- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && -- (output->dma_buf_size - output->coff <= 188)) -+ if (output->dma->cbuf != idx) { -+ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && -+ (output->dma->size - output->dma->coff <= 188)) - return 0; - return 188; - } -- diff = off - output->coff; -+ diff = off - output->dma->coff; - if (diff <= 0 || diff > 188) - return 188; - return 0; -@@ -443,24 +550,24 @@ static ssize_t ddb_output_write(struct ddb_output *output, - const u8 *buf, size_t count) - { - struct ddb *dev = output->port->dev; -- u32 idx, off, stat = output->stat; -+ u32 idx, off, stat = output->dma->stat; - u32 left = count, len; - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - - while (left) { -- len = output->dma_buf_size - output->coff; -- if ((((output->cbuf + 1) % output->dma_buf_num) == idx) && -+ len = output->dma->size - output->dma->coff; -+ if ((((output->dma->cbuf + 1) % output->dma->num) == idx) && - (off == 0)) { - if (len <= 188) - break; - len -= 188; - } -- if (output->cbuf == idx) { -- if (off > output->coff) { -+ if (output->dma->cbuf == idx) { -+ if (off > output->dma->coff) { - #if 1 -- len = off - output->coff; -+ len = off - output->dma->coff; - len -= (len % 188); - if (len <= 188) - -@@ -471,68 +578,146 @@ static ssize_t ddb_output_write(struct ddb_output *output, - } - if (len > left) - len = left; -- if (copy_from_user(output->vbuf[output->cbuf] + output->coff, -+ if (copy_from_user(output->dma->vbuf[output->dma->cbuf] + -+ output->dma->coff, - buf, len)) - return -EIO; -+ /* printk("cfu %d %d %d\n", len, output->cbuf, output->coff); */ - left -= len; - buf += len; -- output->coff += len; -- if (output->coff == output->dma_buf_size) { -- output->coff = 0; -- output->cbuf = ((output->cbuf + 1) % output->dma_buf_num); -+ output->dma->coff += len; -+ if (output->dma->coff == output->dma->size) { -+ output->dma->coff = 0; -+ output->dma->cbuf = ((output->dma->cbuf + 1) % -+ output->dma->num); - } -- ddbwritel((output->cbuf << 11) | (output->coff >> 7), -- DMA_BUFFER_ACK(output->nr + 8)); -+ ddbwritel(dev, (output->dma->cbuf << 11) | (output->dma->coff >> 7), -+ DMA_BUFFER_ACK(output->dma->nr)); - } - return count - left; - } - -+#if 0 -+static u32 ddb_input_free_bytes(struct ddb_input *input) -+{ -+ struct ddb *dev = input->port->dev; -+ u32 idx, off, stat = input->dma->stat; -+ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); -+ -+ idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; -+ -+ if (ctrl & 4) -+ return 0; -+ if (input->dma->cbuf != idx) -+ return 1; -+ return 0; -+} -+ -+static s32 ddb_output_used_bufs(struct ddb_output *output) -+{ -+ u32 idx, off, stat, ctrl; -+ s32 diff; -+ -+ spin_lock_irq(&output->dma->lock); -+ stat = output->dma->stat; -+ ctrl = output->dma->ctrl; -+ spin_unlock_irq(&output->dma->lock); -+ -+ idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; -+ -+ if (ctrl & 4) -+ return 0; -+ diff = output->dma->cbuf - idx; -+ if (diff == 0 && off < output->dma->coff) -+ return 0; -+ if (diff <= 0) -+ diff += output->dma->num; -+ return diff; -+} -+ -+static s32 ddb_input_free_bufs(struct ddb_input *input) -+{ -+ u32 idx, off, stat, ctrl; -+ s32 free; -+ -+ spin_lock_irq(&input->dma->lock); -+ ctrl = input->dma->ctrl; -+ stat = input->dma->stat; -+ spin_unlock_irq(&input->dma->lock); -+ if (ctrl & 4) -+ return 0; -+ idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; -+ free = input->dma->cbuf - idx; -+ if (free == 0 && off < input->dma->coff) -+ return 0; -+ if (free <= 0) -+ free += input->dma->num; -+ return free - 1; -+} -+ -+static u32 ddb_output_ok(struct ddb_output *output) -+{ -+ struct ddb_input *input = output->port->input[0]; -+ s32 diff; -+ -+ diff = ddb_input_free_bufs(input) - ddb_output_used_bufs(output); -+ if (diff > 0) -+ return 1; -+ return 0; -+} -+#endif -+ - static u32 ddb_input_avail(struct ddb_input *input) - { - struct ddb *dev = input->port->dev; -- u32 idx, off, stat = input->stat; -- u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr)); -+ u32 idx, off, stat = input->dma->stat; -+ u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr)); - - idx = (stat >> 11) & 0x1f; - off = (stat & 0x7ff) << 7; - - if (ctrl & 4) { - printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl); -- ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr)); -+ ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr)); - return 0; - } -- if (input->cbuf != idx) -+ if (input->dma->cbuf != idx || off < input->dma->coff) - return 188; - return 0; - } - --static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count) -+static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count) - { - struct ddb *dev = input->port->dev; - u32 left = count; -- u32 idx, free, stat = input->stat; -+ u32 idx, off, free, stat = input->dma->stat; - int ret; - - idx = (stat >> 11) & 0x1f; -+ off = (stat & 0x7ff) << 7; - - while (left) { -- if (input->cbuf == idx) -+ if (input->dma->cbuf == idx) - return count - left; -- free = input->dma_buf_size - input->coff; -+ free = input->dma->size - input->dma->coff; - if (free > left) - free = left; -- ret = copy_to_user(buf, input->vbuf[input->cbuf] + -- input->coff, free); -+ ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] + -+ input->dma->coff, free); - if (ret) - return -EFAULT; -- input->coff += free; -- if (input->coff == input->dma_buf_size) { -- input->coff = 0; -- input->cbuf = (input->cbuf+1) % input->dma_buf_num; -+ input->dma->coff += free; -+ if (input->dma->coff == input->dma->size) { -+ input->dma->coff = 0; -+ input->dma->cbuf = (input->dma->cbuf+1) % -+ input->dma->num; - } - left -= free; -- ddbwritel((input->cbuf << 11) | (input->coff >> 7), -- DMA_BUFFER_ACK(input->nr)); -+ ddbwritel(dev, (input->dma->cbuf << 11) | (input->dma->coff >> 7), -+ DMA_BUFFER_ACK(input->dma->nr)); - } - return count; - } -@@ -554,7 +739,7 @@ static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe) - } - #endif - --static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) - { - struct ddb_input *input = fe->sec_priv; - struct ddb_port *port = input->port; -@@ -562,9 +747,9 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) - - if (enable) { - mutex_lock(&port->i2c_gate_lock); -- status = input->gate_ctrl(fe, 1); -+ status = input->dvb.gate_ctrl(fe, 1); - } else { -- status = input->gate_ctrl(fe, 0); -+ status = input->dvb.gate_ctrl(fe, 0); - mutex_unlock(&port->i2c_gate_lock); - } - return status; -@@ -577,18 +762,88 @@ static int demod_attach_drxk(struct ddb_input *input) - struct drxk_config config; - - memset(&config, 0, sizeof(config)); -- config.microcode_name = "drxk_a3.mc"; -- config.qam_demod_parameter_count = 4; - config.adr = 0x29 + (input->nr & 1); -+ config.microcode_name = "drxk_a3.mc"; - -- fe = input->fe = dvb_attach(drxk_attach, &config, i2c); -- if (!input->fe) { -+#ifdef USE_API3 -+ fe = input->dvb.fe = dvb_attach(drxk_attach, &config, i2c, &input->dvb.fe2); -+#else -+ fe = input->dvb.fe = dvb_attach(drxk_attach, &config, i2c); -+#endif -+ if (!input->dvb.fe) { - printk(KERN_ERR "No DRXK found!\n"); - return -ENODEV; - } - fe->sec_priv = input; -- input->gate_ctrl = fe->ops.i2c_gate_ctrl; -- fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; -+ input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+ -+#if 0 -+struct stv0367_config stv0367_0 = { -+ .demod_address = 0x1f, -+ .xtal = 27000000, -+ .if_khz = 5000, -+ .if_iq_mode = FE_TER_NORMAL_IF_TUNER, -+ .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, -+ .clk_pol = STV0367_RISINGEDGE_CLOCK, -+}; -+ -+struct stv0367_config stv0367_1 = { -+ .demod_address = 0x1e, -+ .xtal = 27000000, -+ .if_khz = 5000, -+ .if_iq_mode = FE_TER_NORMAL_IF_TUNER, -+ .ts_mode = STV0367_SERIAL_PUNCT_CLOCK, -+ .clk_pol = STV0367_RISINGEDGE_CLOCK, -+}; -+ -+ -+static int demod_attach_stv0367(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct dvb_frontend *fe; -+ -+ fe = input->dvb.fe = dvb_attach(stv0367ter_attach, -+ (input->nr & 1) ? &stv0367_1 : &stv0367_0, -+ i2c); -+ if (!input->dvb.fe) { -+ printk(KERN_ERR "No stv0367 found!\n"); -+ return -ENODEV; -+ } -+ fe->sec_priv = input; -+ input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+#endif -+ -+struct stv0367_cfg stv0367dd_0 = { -+ .adr = 0x1f, -+ .xtal = 27000000, -+}; -+ -+struct stv0367_cfg stv0367dd_1 = { -+ .adr = 0x1e, -+ .xtal = 27000000, -+}; -+ -+static int demod_attach_stv0367dd(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct dvb_frontend *fe; -+ -+ fe = input->dvb.fe = dvb_attach(stv0367_attach, i2c, -+ (input->nr & 1) ? &stv0367dd_1 : &stv0367dd_0, -+ &input->dvb.fe2); -+ if (!input->dvb.fe) { -+ printk(KERN_ERR "No stv0367 found!\n"); -+ return -ENODEV; -+ } -+ fe->sec_priv = input; -+ input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl; -+ fe->ops.i2c_gate_ctrl = locked_gate_ctrl; - return 0; - } - -@@ -597,18 +852,57 @@ static int tuner_attach_tda18271(struct ddb_input *input) - struct i2c_adapter *i2c = &input->port->i2c->adap; - struct dvb_frontend *fe; - -- if (input->fe->ops.i2c_gate_ctrl) -- input->fe->ops.i2c_gate_ctrl(input->fe, 1); -- fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60); -+ if (input->dvb.fe->ops.i2c_gate_ctrl) -+ input->dvb.fe->ops.i2c_gate_ctrl(input->dvb.fe, 1); -+ fe = dvb_attach(tda18271c2dd_attach, input->dvb.fe, i2c, 0x60); -+ if (input->dvb.fe->ops.i2c_gate_ctrl) -+ input->dvb.fe->ops.i2c_gate_ctrl(input->dvb.fe, 0); - if (!fe) { - printk(KERN_ERR "No TDA18271 found!\n"); - return -ENODEV; - } -- if (input->fe->ops.i2c_gate_ctrl) -- input->fe->ops.i2c_gate_ctrl(input->fe, 0); - return 0; - } - -+static int tuner_attach_tda18212dd(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct dvb_frontend *fe; -+ -+ fe = dvb_attach(tda18212dd_attach, input->dvb.fe, i2c, -+ (input->nr & 1) ? 0x63 : 0x60); -+ if (!fe) { -+ printk(KERN_ERR "No TDA18212 found!\n"); -+ return -ENODEV; -+ } -+ return 0; -+} -+ -+#if 0 -+struct tda18212_config tda18212_0 = { -+ .i2c_address = 0x60, -+}; -+ -+struct tda18212_config tda18212_1 = { -+ .i2c_address = 0x63, -+}; -+ -+static int tuner_attach_tda18212(struct ddb_input *input) -+{ -+ struct i2c_adapter *i2c = &input->port->i2c->adap; -+ struct dvb_frontend *fe; -+ struct tda18212_config *cfg; -+ -+ cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0; -+ fe = dvb_attach(tda18212_attach, input->dvb.fe, i2c, cfg); -+ if (!fe) { -+ printk(KERN_ERR "No TDA18212 found!\n"); -+ return -ENODEV; -+ } -+ return 0; -+} -+#endif -+ - /******************************************************************************/ - /******************************************************************************/ - /******************************************************************************/ -@@ -668,14 +962,14 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) - struct i2c_adapter *i2c = &input->port->i2c->adap; - struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; - -- input->fe = dvb_attach(stv090x_attach, feconf, i2c, -+ input->dvb.fe = dvb_attach(stv090x_attach, feconf, i2c, - (input->nr & 1) ? STV090x_DEMODULATOR_1 - : STV090x_DEMODULATOR_0); -- if (!input->fe) { -+ if (!input->dvb.fe) { - printk(KERN_ERR "No STV0900 found!\n"); - return -ENODEV; - } -- if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0, -+ if (!dvb_attach(lnbh24_attach, input->dvb.fe, i2c, 0, - 0, (input->nr & 1) ? - (0x09 - type) : (0x0b - type))) { - printk(KERN_ERR "No LNBH24 found!\n"); -@@ -692,7 +986,7 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) - &stv6110b : &stv6110a; - struct stv6110x_devctl *ctl; - -- ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); -+ ctl = dvb_attach(stv6110x_attach, input->dvb.fe, tunerconf, i2c); - if (!ctl) { - printk(KERN_ERR "No STV6110X found!\n"); - return -ENODEV; -@@ -760,10 +1054,10 @@ static int start_feed(struct dvb_demux_feed *dvbdmxfeed) - struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct ddb_input *input = dvbdmx->priv; - -- if (!input->users) -+ if (!input->dvb.users) - ddb_input_start(input); - -- return ++input->users; -+ return ++input->dvb.users; - } - - static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) -@@ -771,8 +1065,8 @@ static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) - struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct ddb_input *input = dvbdmx->priv; - -- if (--input->users) -- return input->users; -+ if (--input->dvb.users) -+ return input->dvb.users; - - ddb_input_stop(input); - return 0; -@@ -781,116 +1075,200 @@ static int stop_feed(struct dvb_demux_feed *dvbdmxfeed) - - static void dvb_input_detach(struct ddb_input *input) - { -- struct dvb_adapter *adap = &input->adap; -- struct dvb_demux *dvbdemux = &input->demux; -+ struct dvb_demux *dvbdemux = &input->dvb.demux; - -- switch (input->attached) { -+ switch (input->dvb.attached) { -+ case 6: -+ if (input->dvb.fe2) -+ dvb_unregister_frontend(input->dvb.fe2); -+ if (input->dvb.fe) -+ dvb_unregister_frontend(input->dvb.fe); - case 5: -- if (input->fe2) -- dvb_unregister_frontend(input->fe2); -- if (input->fe) { -- dvb_unregister_frontend(input->fe); -- dvb_frontend_detach(input->fe); -- input->fe = NULL; -- } -+ dvb_frontend_detach(input->dvb.fe); -+ input->dvb.fe = NULL; - case 4: -- dvb_net_release(&input->dvbnet); -- -+ dvb_net_release(&input->dvb.dvbnet); - case 3: - dvbdemux->dmx.close(&dvbdemux->dmx); - dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, -- &input->hw_frontend); -+ &input->dvb.hw_frontend); - dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, -- &input->mem_frontend); -- dvb_dmxdev_release(&input->dmxdev); -- -+ &input->dvb.mem_frontend); -+ dvb_dmxdev_release(&input->dvb.dmxdev); - case 2: -- dvb_dmx_release(&input->demux); -- -+ dvb_dmx_release(&input->dvb.demux); - case 1: -- dvb_unregister_adapter(adap); -+ break; - } -- input->attached = 0; -+ input->dvb.attached = 0; - } - -+static int dvb_register_adapters(struct ddb *dev) -+{ -+ int i, ret = 0; -+ struct ddb_port *port; -+ struct dvb_adapter *adap; -+ -+ if (adapter_alloc == 3) { -+ port = &dev->port[0]; -+ adap = port->input[0]->dvb.adap; -+ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -+ &port->dev->pdev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->input[0]->dvb.adap_registered = 1; -+ for (i = 0; i < dev->info->port_num; i++) { -+ port = &dev->port[i]; -+ port->input[0]->dvb.adap = adap; -+ port->input[1]->dvb.adap = adap; -+ } -+ return 0; -+ } -+ -+ for (i = 0; i < dev->info->port_num; i++) { -+ port = &dev->port[i]; -+ switch (port->class) { -+ case DDB_PORT_TUNER: -+ adap = port->input[0]->dvb.adap; -+ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -+ &port->dev->pdev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->input[0]->dvb.adap_registered = 1; -+ -+ if (adapter_alloc > 0) { -+ port->input[1]->dvb.adap = port->input[0]->dvb.adap; -+ break; -+ } -+ adap = port->input[1]->dvb.adap; -+ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -+ &port->dev->pdev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->input[1]->dvb.adap_registered = 1; -+ break; -+ -+ case DDB_PORT_CI: -+ case DDB_PORT_LOOP: -+ adap = port->input[0]->dvb.adap; -+ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -+ &port->dev->pdev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->input[0]->dvb.adap_registered = 1; -+ break; -+ default: -+ if (adapter_alloc < 2) -+ break; -+ adap = port->input[0]->dvb.adap; -+ ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -+ &port->dev->pdev->dev, -+ adapter_nr); -+ if (ret < 0) -+ return ret; -+ port->input[0]->dvb.adap_registered = 1; -+ break; -+ } -+ } -+ return ret; -+} -+ -+static void dvb_unregister_adapters(struct ddb *dev) -+{ -+ int i; -+ struct ddb_port *port; -+ struct ddb_input *input; -+ -+ for (i = 0; i < dev->info->port_num; i++) { -+ port = &dev->port[i]; -+ -+ input = port->input[0]; -+ if (input->dvb.adap_registered) -+ dvb_unregister_adapter(input->dvb.adap); -+ input->dvb.adap_registered = 0; -+ -+ input = port->input[1]; -+ if (input->dvb.adap_registered) -+ dvb_unregister_adapter(input->dvb.adap); -+ input->dvb.adap_registered = 0; -+ } -+} -+ -+ - static int dvb_input_attach(struct ddb_input *input) - { -- int ret; -+ int ret = 0; - struct ddb_port *port = input->port; -- struct dvb_adapter *adap = &input->adap; -- struct dvb_demux *dvbdemux = &input->demux; -- -- ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, -- &input->port->dev->pdev->dev, -- adapter_nr); -- if (ret < 0) { -- printk(KERN_ERR "ddbridge: Could not register adapter." -- "Check if you enabled enough adapters in dvb-core!\n"); -- return ret; -- } -- input->attached = 1; -+ struct dvb_adapter *adap = input->dvb.adap; -+ struct dvb_demux *dvbdemux = &input->dvb.demux; -+ -+ input->dvb.attached = 1; - - ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux", - start_feed, - stop_feed, input); - if (ret < 0) - return ret; -- input->attached = 2; -+ input->dvb.attached = 2; - -- ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux, -- &input->hw_frontend, -- &input->mem_frontend, adap); -+ ret = my_dvb_dmxdev_ts_card_init(&input->dvb.dmxdev, -+ &input->dvb.demux, -+ &input->dvb.hw_frontend, -+ &input->dvb.mem_frontend, adap); - if (ret < 0) - return ret; -- input->attached = 3; -+ input->dvb.attached = 3; - -- ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux); -+ ret = dvb_net_init(adap, &input->dvb.dvbnet, input->dvb.dmxdev.demux); - if (ret < 0) - return ret; -- input->attached = 4; -+ input->dvb.attached = 4; - -- input->fe = 0; -+ input->dvb.fe = 0; - switch (port->type) { - case DDB_TUNER_DVBS_ST: - if (demod_attach_stv0900(input, 0) < 0) - return -ENODEV; - if (tuner_attach_stv6110(input, 0) < 0) - return -ENODEV; -- if (input->fe) { -- if (dvb_register_frontend(adap, input->fe) < 0) -- return -ENODEV; -- } - break; - case DDB_TUNER_DVBS_ST_AA: - if (demod_attach_stv0900(input, 1) < 0) - return -ENODEV; - if (tuner_attach_stv6110(input, 1) < 0) - return -ENODEV; -- if (input->fe) { -- if (dvb_register_frontend(adap, input->fe) < 0) -- return -ENODEV; -- } - break; - case DDB_TUNER_DVBCT_TR: - if (demod_attach_drxk(input) < 0) - return -ENODEV; - if (tuner_attach_tda18271(input) < 0) - return -ENODEV; -- if (input->fe) { -- if (dvb_register_frontend(adap, input->fe) < 0) -- return -ENODEV; -- } -- if (input->fe2) { -- if (dvb_register_frontend(adap, input->fe2) < 0) -- return -ENODEV; -- input->fe2->tuner_priv = input->fe->tuner_priv; -- memcpy(&input->fe2->ops.tuner_ops, -- &input->fe->ops.tuner_ops, -- sizeof(struct dvb_tuner_ops)); -- } - break; -+ case DDB_TUNER_DVBCT_ST: -+ if (demod_attach_stv0367dd(input) < 0) -+ return -ENODEV; -+ if (tuner_attach_tda18212dd(input) < 0) -+ return -ENODEV; -+ break; -+ } -+ input->dvb.attached = 5; -+ if (input->dvb.fe) { -+ if (dvb_register_frontend(adap, input->dvb.fe) < 0) -+ return -ENODEV; - } -- input->attached = 5; -+ if (input->dvb.fe2) { -+ if (dvb_register_frontend(adap, input->dvb.fe2) < 0) -+ return -ENODEV; -+ input->dvb.fe2->tuner_priv = input->dvb.fe->tuner_priv; -+ memcpy(&input->dvb.fe2->ops.tuner_ops, -+ &input->dvb.fe->ops.tuner_ops, -+ sizeof(struct dvb_tuner_ops)); -+ } -+ input->dvb.attached = 6; - return 0; - } - -@@ -910,7 +1288,8 @@ static ssize_t ts_write(struct file *file, const char *buf, - if (file->f_flags & O_NONBLOCK) - break; - if (wait_event_interruptible( -- output->wq, ddb_output_free(output) >= 188) < 0) -+ output->dma->wq, -+ ddb_output_free(output) >= 188) < 0) - break; - } - stat = ddb_output_write(output, buf, left); -@@ -937,7 +1316,7 @@ static ssize_t ts_read(struct file *file, char *buf, - if (file->f_flags & O_NONBLOCK) - break; - if (wait_event_interruptible( -- input->wq, ddb_input_avail(input) >= 188) < 0) -+ input->dma->wq, ddb_input_avail(input) >= 188) < 0) - break; - } - read = ddb_input_read(input, buf, left); -@@ -970,21 +1349,53 @@ static unsigned int ts_poll(struct file *file, poll_table *wait) - return mask; - } - --static const struct file_operations ci_fops = { -- .owner = THIS_MODULE, -- .read = ts_read, -- .write = ts_write, -- .open = dvb_generic_open, -- .release = dvb_generic_release, -- .poll = ts_poll, -- .mmap = 0, --}; -- -+#if 0 -+static int ts_release(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; -+ -+ -+ return dvb_generic_release(inode, file); -+} -+ -+static unsigned int ts_open(struct inode *inode, struct file *file) -+{ -+ int err; -+ struct dvb_device *dvbdev = file->private_data; -+ struct ddb_output *output = dvbdev->priv; -+ struct ddb_input *input = output->port->input[0]; -+ -+ err = dvb_generic_open(inode, file); -+ if (err < 0) -+ return err; -+ -+#if 0 -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) -+ ddb_input_start(input); -+ else -+ ddb_output_start(output); -+#endif -+ return err; -+} -+#endif -+ -+static const struct file_operations ci_fops = { -+ .owner = THIS_MODULE, -+ .read = ts_read, -+ .write = ts_write, -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+ .poll = ts_poll, -+ .mmap = 0, -+}; -+ - static struct dvb_device dvbdev_ci = { - .priv = 0, -- .readers = -1, -- .writers = -1, -- .users = -1, -+ .readers = 1, -+ .writers = 1, -+ .users = 2, - .fops = &ci_fops, - }; - -@@ -992,53 +1403,297 @@ static struct dvb_device dvbdev_ci = { - /****************************************************************************/ - /****************************************************************************/ - -+static int set_redirect(u32 i, u32 p) -+{ -+ struct ddb *idev = ddbs[(i >> 4) & 0x1f]; -+ struct ddb_input *input; -+ struct ddb *pdev = ddbs[(p >> 4) & 0x1f]; -+ struct ddb_port *port; -+ -+ if (!idev || !pdev) -+ return -EINVAL; -+ -+ port = &pdev->port[p & 3]; -+ if (port->class != DDB_PORT_CI && port->class != DDB_PORT_LOOP) -+ return -EINVAL; -+ -+ ddb_unredirect(port); -+ if (i == 8) -+ return 0; -+ input = &idev->input[i & 7]; -+ if (input->port->class != DDB_PORT_TUNER) -+ port->input[0]->redirect = input->redirect; -+ else -+ port->input[0]->redirect = input; -+ input->redirect = port->input[0]; -+ port->output->redirect = input; -+ -+ ddb_redirect_dma(input->port->dev, input->dma, port->output->dma); -+ return 0; -+} -+ -+static void input_write_output(struct ddb_input *input, -+ struct ddb_output *output) -+{ -+ ddbwritel(output->port->dev, -+ input->dma->stat, DMA_BUFFER_ACK(output->dma->nr)); -+} -+ -+static void output_ack_input(struct ddb_output *output, -+ struct ddb_input *input) -+{ -+ ddbwritel(input->port->dev, -+ output->dma->stat, DMA_BUFFER_ACK(input->dma->nr)); -+} -+ -+static void input_write_dvb(struct ddb_input *input, struct ddb_dvb *dvb) -+{ -+ struct ddb_dma *dma = input->dma; -+ struct ddb *dev = input->port->dev; -+ -+ if (4 & ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr))) -+ printk(KERN_ERR "Overflow dma %d\n", dma->nr); -+ while (dma->cbuf != ((dma->stat >> 11) & 0x1f) -+ || (4 & ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)))) { -+ dvb_dmx_swfilter_packets(&dvb->demux, -+ dma->vbuf[dma->cbuf], -+ dma->size / 188); -+ dma->cbuf = (dma->cbuf + 1) % dma->num; -+ ddbwritel(dev, (dma->cbuf << 11), DMA_BUFFER_ACK(dma->nr)); -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ } -+} -+ - static void input_tasklet(unsigned long data) - { - struct ddb_input *input = (struct ddb_input *) data; -+ struct ddb_dma *dma = input->dma; - struct ddb *dev = input->port->dev; - -- spin_lock(&input->lock); -- if (!input->running) { -- spin_unlock(&input->lock); -+ spin_lock(&dma->lock); -+ if (!dma->running) { -+ spin_unlock(&dma->lock); - return; - } -- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); - - if (input->port->class == DDB_PORT_TUNER) { -- if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr))) -- printk(KERN_ERR "Overflow input %d\n", input->nr); -- while (input->cbuf != ((input->stat >> 11) & 0x1f) -- || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) { -- dvb_dmx_swfilter_packets(&input->demux, -- input->vbuf[input->cbuf], -- input->dma_buf_size / 188); -- -- input->cbuf = (input->cbuf + 1) % input->dma_buf_num; -- ddbwritel((input->cbuf << 11), -- DMA_BUFFER_ACK(input->nr)); -- input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr)); -- } -+ if (input->redirect) -+ input_write_output(input, -+ input->redirect->port->output); -+ else -+ input_write_dvb(input, &input->dvb); -+ } -+ if (input->port->class == DDB_PORT_CI || -+ input->port->class == DDB_PORT_LOOP) { -+ if (input->redirect) { -+ if (input->redirect->port->class == DDB_PORT_TUNER) -+ input_write_dvb(input, &input->redirect->dvb); -+ else -+ input_write_output(input, -+ input->redirect->port->output); -+ } else -+ wake_up(&dma->wq); - } -- if (input->port->class == DDB_PORT_CI) -- wake_up(&input->wq); -- spin_unlock(&input->lock); -+ spin_unlock(&dma->lock); - } - - static void output_tasklet(unsigned long data) - { - struct ddb_output *output = (struct ddb_output *) data; -+ struct ddb_dma *dma = output->dma; - struct ddb *dev = output->port->dev; - -- spin_lock(&output->lock); -- if (!output->running) { -- spin_unlock(&output->lock); -+ spin_lock(&dma->lock); -+ if (!dma->running) { -+ spin_unlock(&dma->lock); - return; - } -- output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8)); -- wake_up(&output->wq); -- spin_unlock(&output->lock); -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); -+ if (output->redirect) -+ output_ack_input(output, output->redirect); -+ wake_up(&dma->wq); -+ spin_unlock(&dma->lock); -+} -+ -+#if 0 -+static void io_tasklet(unsigned long data) -+{ -+ struct ddb_dma *dma = (struct ddb_dma *) data; -+ -+ spin_lock(&dma->lock); -+ if (!dma->running) { -+ spin_unlock(&dma->lock); -+ return; -+ } -+ dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr)); -+ dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)); -+ if (dma->nr & 8) -+ handle_output((struct ddb_output *) dma->io); -+ else -+ handle_input((struct ddb_input *) dma->io); -+ wake_up(&dma->wq); -+ spin_unlock(&dma->lock); -+} -+#endif -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ -+static int wait_ci_ready(struct ddb_ci *ci) -+{ -+ u32 count = 100; -+ -+ do { -+ if (ddbreadl(ci->port->dev, -+ CI_CONTROL(ci->nr)) & CI_READY) -+ break; -+ msleep(1); -+ if ((--count) == 0) -+ return -1; -+ } while (1); -+ return 0; -+} -+ -+static int read_attribute_mem(struct dvb_ca_en50221 *ca, -+ int slot, int address) -+{ -+ struct ddb_ci *ci = ca->data; -+ u32 val, off = (address >> 1) & (CI_BUFFER_SIZE-1); -+ -+ if (address > CI_BUFFER_SIZE) -+ return -1; -+ ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, -+ CI_DO_READ_ATTRIBUTES(ci->nr)); -+ wait_ci_ready(ci); -+ val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); -+ /* printk("%04x: %02x\n", address, val); */ -+ return val; -+} -+ -+static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, -+ int address, u8 value) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, -+ CI_DO_ATTRIBUTE_RW(ci->nr)); -+ wait_ci_ready(ci); -+ return 0; -+} -+ -+static int read_cam_control(struct dvb_ca_en50221 *ca, -+ int slot, u8 address) -+{ -+ u32 count = 100; -+ struct ddb_ci *ci = ca->data; -+ u32 res; -+ -+ ddbwritel(ci->port->dev, CI_READ_CMD | address, -+ CI_DO_IO_RW(ci->nr)); -+ do { -+ res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr)); -+ if (res & CI_READY) -+ break; -+ msleep(1); -+ if ((--count) == 0) -+ return -1; -+ } while (1); -+ return 0xff & res; -+} -+ -+static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, -+ u8 address, u8 value) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, -+ CI_DO_IO_RW(ci->nr)); -+ wait_ci_ready(ci); -+ return 0; -+} -+ -+static int slot_reset(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ printk(KERN_INFO "slot reset %d\n", ci->nr); -+ ddbwritel(ci->port->dev, CI_POWER_ON, -+ CI_CONTROL(ci->nr)); -+ msleep(300); -+ ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM, -+ CI_CONTROL(ci->nr)); -+ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM, -+ CI_CONTROL(ci->nr)); -+ udelay(20); -+ ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, -+ CI_CONTROL(ci->nr)); -+ return 0; -+} -+ -+static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ -+ printk(KERN_INFO "slot shutdown\n"); -+ ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); -+ return 0; -+} -+ -+static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) -+{ -+ struct ddb_ci *ci = ca->data; -+ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); -+ -+ ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, -+ CI_CONTROL(ci->nr)); -+ return 0; -+} -+ -+static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) -+{ -+ struct ddb_ci *ci = ca->data; -+ u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); -+ int stat = 0; -+ -+ if (val & CI_CAM_DETECT) -+ stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; -+ if (val & CI_CAM_READY) -+ stat |= DVB_CA_EN50221_POLL_CAM_READY; -+ return stat; - } - -+static struct dvb_ca_en50221 en_templ = { -+ .read_attribute_mem = read_attribute_mem, -+ .write_attribute_mem = write_attribute_mem, -+ .read_cam_control = read_cam_control, -+ .write_cam_control = write_cam_control, -+ .slot_reset = slot_reset, -+ .slot_shutdown = slot_shutdown, -+ .slot_ts_enable = slot_ts_enable, -+ .poll_slot_status = poll_slot_status, -+}; -+ -+static void ci_attach(struct ddb_port *port) -+{ -+ struct ddb_ci *ci = 0; -+ -+ ci = kzalloc(sizeof(*ci), GFP_KERNEL); -+ if (!ci) -+ return; -+ memcpy(&ci->en, &en_templ, sizeof(en_templ)); -+ ci->en.data = ci; -+ port->en = &ci->en; -+ ci->port = port; -+ ci->nr = port->nr - 2; -+} -+ -+/****************************************************************************/ -+/****************************************************************************/ -+/****************************************************************************/ -+ - - struct cxd2099_cfg cxd_cfg = { - .bitrate = 62000, -@@ -1049,28 +1704,22 @@ struct cxd2099_cfg cxd_cfg = { - - static int ddb_ci_attach(struct ddb_port *port) - { -- int ret; -- -- ret = dvb_register_adapter(&port->output->adap, -- "DDBridge", -- THIS_MODULE, -- &port->dev->pdev->dev, -- adapter_nr); -- if (ret < 0) -- return ret; -- port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); -- if (!port->en) { -- dvb_unregister_adapter(&port->output->adap); -- return -ENODEV; -+ if (port->type == DDB_CI_EXTERNAL_SONY) { -+ port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap); -+ if (!port->en) -+ return -ENODEV; -+ dvb_ca_en50221_init(port->input[0]->dvb.adap, -+ port->en, 0, 1); - } -- ddb_input_start(port->input[0]); -- ddb_output_start(port->output); -- dvb_ca_en50221_init(&port->output->adap, -- port->en, 0, 1); -- ret = dvb_register_device(&port->output->adap, &port->output->dev, -- &dvbdev_ci, (void *) port->output, -- DVB_DEVICE_SEC); -- return ret; -+#if 1 -+ if (port->type == DDB_CI_INTERNAL) { -+ ci_attach(port); -+ if (!port->en) -+ return -ENODEV; -+ dvb_ca_en50221_init(port->input[0]->dvb.adap, port->en, 0, 1); -+ } -+#endif -+ return 0; - } - - static int ddb_port_attach(struct ddb_port *port) -@@ -1086,6 +1735,15 @@ static int ddb_port_attach(struct ddb_port *port) - break; - case DDB_PORT_CI: - ret = ddb_ci_attach(port); -+ if (ret < 0) -+ break; -+ case DDB_PORT_LOOP: -+ ddb_input_start(port->input[0]); -+ ddb_output_start(port->output); -+ ret = dvb_register_device(port->input[0]->dvb.adap, -+ &port->input[0]->dvb.dev, -+ &dvbdev_ci, (void *) port->output, -+ DVB_DEVICE_SEC); - break; - default: - break; -@@ -1100,6 +1758,10 @@ static int ddb_ports_attach(struct ddb *dev) - int i, ret = 0; - struct ddb_port *port; - -+ ret = dvb_register_adapters(dev); -+ if (ret < 0) -+ return ret; -+ - for (i = 0; i < dev->info->port_num; i++) { - port = &dev->port[i]; - ret = ddb_port_attach(port); -@@ -1122,25 +1784,26 @@ static void ddb_ports_detach(struct ddb *dev) - dvb_input_detach(port->input[1]); - break; - case DDB_PORT_CI: -- if (port->output->dev) -- dvb_unregister_device(port->output->dev); -+ case DDB_PORT_LOOP: -+ if (port->input[0]->dvb.dev) -+ dvb_unregister_device(port->input[0]->dvb.dev); -+ ddb_input_stop(port->input[0]); -+ ddb_output_stop(port->output); - if (port->en) { -- ddb_input_stop(port->input[0]); -- ddb_output_stop(port->output); - dvb_ca_en50221_release(port->en); - kfree(port->en); - port->en = 0; -- dvb_unregister_adapter(&port->output->adap); - } - break; - } - } -+ dvb_unregister_adapters(dev); - } - - /****************************************************************************/ - /****************************************************************************/ - --static int port_has_ci(struct ddb_port *port) -+static int port_has_cxd(struct ddb_port *port) - { - u8 val; - return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1; -@@ -1172,6 +1835,21 @@ static int port_has_drxks(struct ddb_port *port) - return 1; - } - -+static int port_has_stv0367(struct ddb_port *port) -+{ -+ u8 val; -+ -+ if (i2c_read_reg16(&port->i2c->adap, 0x1e, 0xf000, &val) < 0) -+ return 0; -+ if (val != 0x60) -+ return 0; -+ if (i2c_read_reg16(&port->i2c->adap, 0x1f, 0xf000, &val) < 0) -+ return 0; -+ if (val != 0x60) -+ return 0; -+ return 1; -+} -+ - static void ddb_port_probe(struct ddb_port *port) - { - struct ddb *dev = port->dev; -@@ -1179,62 +1857,92 @@ static void ddb_port_probe(struct ddb_port *port) - - port->class = DDB_PORT_NONE; - -- if (port_has_ci(port)) { -+ if (port->nr > 1 && dev->info->type == DDB_OCTOPUS_CI) { -+ modname = "CI internal"; -+ port->class = DDB_PORT_CI; -+ port->type = DDB_CI_INTERNAL; -+ } else if (port_has_cxd(port)) { - modname = "CI"; - port->class = DDB_PORT_CI; -- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ port->type = DDB_CI_EXTERNAL_SONY; -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); - } else if (port_has_stv0900(port)) { - modname = "DUAL DVB-S2"; - port->class = DDB_PORT_TUNER; - port->type = DDB_TUNER_DVBS_ST; -- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); - } else if (port_has_stv0900_aa(port)) { - modname = "DUAL DVB-S2"; - port->class = DDB_PORT_TUNER; - port->type = DDB_TUNER_DVBS_ST_AA; -- ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); - } else if (port_has_drxks(port)) { - modname = "DUAL DVB-C/T"; - port->class = DDB_PORT_TUNER; - port->type = DDB_TUNER_DVBCT_TR; -- ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING); -+ } else if (port_has_stv0367(port)) { -+ modname = "DUAL DVB-C/T"; -+ port->class = DDB_PORT_TUNER; -+ port->type = DDB_TUNER_DVBCT_ST; -+ ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING); -+ } else if (port->nr == ts_loop) { -+ modname = "TS LOOP"; -+ port->class = DDB_PORT_LOOP; - } -- printk(KERN_INFO "Port %d (TAB %d): %s\n", -- port->nr, port->nr+1, modname); -+ printk(KERN_INFO "Port %d (TAB %d): %s\n", port->nr, port->nr+1, modname); - } - --static void ddb_input_init(struct ddb_port *port, int nr) -+static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io) -+{ -+ unsigned long priv = (unsigned long) io; -+ -+ dma->io = io; -+ dma->nr = nr; -+ spin_lock_init(&dma->lock); -+ init_waitqueue_head(&dma->wq); -+ if (nr & 8) { -+ tasklet_init(&dma->tasklet, output_tasklet, priv); -+ dma->num = OUTPUT_DMA_BUFS; -+ dma->size = OUTPUT_DMA_SIZE; -+ dma->div = OUTPUT_DMA_IRQ_DIV; -+ } else { -+ tasklet_init(&dma->tasklet, input_tasklet, priv); -+ dma->num = INPUT_DMA_BUFS; -+ dma->size = INPUT_DMA_SIZE; -+ dma->div = INPUT_DMA_IRQ_DIV; -+ } -+} -+ -+static void ddb_input_init(struct ddb_port *port, int nr, int pnr) - { - struct ddb *dev = port->dev; - struct ddb_input *input = &dev->input[nr]; - -+ port->input[pnr] = input; - input->nr = nr; - input->port = port; -- input->dma_buf_num = INPUT_DMA_BUFS; -- input->dma_buf_size = INPUT_DMA_SIZE; -- ddbwritel(0, TS_INPUT_CONTROL(nr)); -- ddbwritel(2, TS_INPUT_CONTROL(nr)); -- ddbwritel(0, TS_INPUT_CONTROL(nr)); -- ddbwritel(0, DMA_BUFFER_ACK(nr)); -- tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input); -- spin_lock_init(&input->lock); -- init_waitqueue_head(&input->wq); -+ input->dma = &dev->dma[nr]; -+ ddb_dma_init(input->dma, nr, (void *) input); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); -+ ddbwritel(dev, 2, TS_INPUT_CONTROL(nr)); -+ ddbwritel(dev, 0, TS_INPUT_CONTROL(nr)); -+ ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr)); -+ input->dvb.adap = &dev->adap[input->nr]; - } - - static void ddb_output_init(struct ddb_port *port, int nr) - { - struct ddb *dev = port->dev; - struct ddb_output *output = &dev->output[nr]; -+ port->output = output; - output->nr = nr; - output->port = port; -- output->dma_buf_num = OUTPUT_DMA_BUFS; -- output->dma_buf_size = OUTPUT_DMA_SIZE; -- -- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); -- ddbwritel(2, TS_OUTPUT_CONTROL(nr)); -- ddbwritel(0, TS_OUTPUT_CONTROL(nr)); -- tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output); -- init_waitqueue_head(&output->wq); -+ output->dma = &dev->dma[nr + 8]; -+ ddb_dma_init(output->dma, nr + 8, (void *) output); -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); -+ ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr)); -+ ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr)); - } - - static void ddb_ports_init(struct ddb *dev) -@@ -1247,14 +1955,16 @@ static void ddb_ports_init(struct ddb *dev) - port->dev = dev; - port->nr = i; - port->i2c = &dev->i2c[i]; -- port->input[0] = &dev->input[2 * i]; -- port->input[1] = &dev->input[2 * i + 1]; -- port->output = &dev->output[i]; - - mutex_init(&port->i2c_gate_lock); - ddb_port_probe(port); -- ddb_input_init(port, 2 * i); -- ddb_input_init(port, 2 * i + 1); -+ if (i >= 2 && dev->info->type == DDB_OCTOPUS_CI) { -+ ddb_input_init(port, 2 + i, 0); -+ ddb_input_init(port, 4 + i, 1); -+ } else { -+ ddb_input_init(port, 2 * i, 0); -+ ddb_input_init(port, 2 * i + 1, 1); -+ } - ddb_output_init(port, i); - } - } -@@ -1267,9 +1977,12 @@ static void ddb_ports_release(struct ddb *dev) - for (i = 0; i < dev->info->port_num; i++) { - port = &dev->port[i]; - port->dev = dev; -- tasklet_kill(&port->input[0]->tasklet); -- tasklet_kill(&port->input[1]->tasklet); -- tasklet_kill(&port->output->tasklet); -+ if (port->input[0]) -+ tasklet_kill(&port->input[0]->dma->tasklet); -+ if (port->input[1]) -+ tasklet_kill(&port->input[1]->dma->tasklet); -+ if (port->output) -+ tasklet_kill(&port->output->dma->tasklet); - } - } - -@@ -1288,13 +2001,18 @@ static void irq_handle_i2c(struct ddb *dev, int n) - static irqreturn_t irq_handler(int irq, void *dev_id) - { - struct ddb *dev = (struct ddb *) dev_id; -- u32 s = ddbreadl(INTERRUPT_STATUS); -+ u32 s = ddbreadl(dev, INTERRUPT_STATUS); - - if (!s) - return IRQ_NONE; - - do { -- ddbwritel(s, INTERRUPT_ACK); -+ ddbwritel(dev, s, INTERRUPT_ACK); -+ -+ if (s & 0x0000000f) -+ dev->i2c_irq++; -+ if (s & 0x000fff00) -+ dev->ts_irq++; - - if (s & 0x00000001) - irq_handle_i2c(dev, 0); -@@ -1306,33 +2024,32 @@ static irqreturn_t irq_handler(int irq, void *dev_id) - irq_handle_i2c(dev, 3); - - if (s & 0x00000100) -- tasklet_schedule(&dev->input[0].tasklet); -+ tasklet_schedule(&dev->dma[0].tasklet); - if (s & 0x00000200) -- tasklet_schedule(&dev->input[1].tasklet); -+ tasklet_schedule(&dev->dma[1].tasklet); - if (s & 0x00000400) -- tasklet_schedule(&dev->input[2].tasklet); -+ tasklet_schedule(&dev->dma[2].tasklet); - if (s & 0x00000800) -- tasklet_schedule(&dev->input[3].tasklet); -+ tasklet_schedule(&dev->dma[3].tasklet); - if (s & 0x00001000) -- tasklet_schedule(&dev->input[4].tasklet); -+ tasklet_schedule(&dev->dma[4].tasklet); - if (s & 0x00002000) -- tasklet_schedule(&dev->input[5].tasklet); -+ tasklet_schedule(&dev->dma[5].tasklet); - if (s & 0x00004000) -- tasklet_schedule(&dev->input[6].tasklet); -+ tasklet_schedule(&dev->dma[6].tasklet); - if (s & 0x00008000) -- tasklet_schedule(&dev->input[7].tasklet); -- -+ tasklet_schedule(&dev->dma[7].tasklet); - if (s & 0x00010000) -- tasklet_schedule(&dev->output[0].tasklet); -+ tasklet_schedule(&dev->dma[8].tasklet); - if (s & 0x00020000) -- tasklet_schedule(&dev->output[1].tasklet); -+ tasklet_schedule(&dev->dma[9].tasklet); - if (s & 0x00040000) -- tasklet_schedule(&dev->output[2].tasklet); -+ tasklet_schedule(&dev->dma[10].tasklet); - if (s & 0x00080000) -- tasklet_schedule(&dev->output[3].tasklet); -+ tasklet_schedule(&dev->dma[11].tasklet); - -- /* if (s & 0x000f0000) printk(KERN_DEBUG "%08x\n", istat); */ -- } while ((s = ddbreadl(INTERRUPT_STATUS))); -+ /* if (s & 0x000f0000) printk("%08x\n", istat); */ -+ } while ((s = ddbreadl(dev, INTERRUPT_STATUS))); - - return IRQ_HANDLED; - } -@@ -1346,21 +2063,21 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) - u32 data, shift; - - if (wlen > 4) -- ddbwritel(1, SPI_CONTROL); -+ ddbwritel(dev, 1, SPI_CONTROL); - while (wlen > 4) { - /* FIXME: check for big-endian */ - data = swab32(*(u32 *)wbuf); - wbuf += 4; - wlen -= 4; -- ddbwritel(data, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -+ ddbwritel(dev, data, SPI_DATA); -+ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) - ; - } - - if (rlen) -- ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); -+ ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); - else -- ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); -+ ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL); - - data = 0; - shift = ((4 - wlen) * 8); -@@ -1372,33 +2089,33 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) - } - if (shift) - data <<= shift; -- ddbwritel(data, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -+ ddbwritel(dev, data, SPI_DATA); -+ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) - ; - - if (!rlen) { -- ddbwritel(0, SPI_CONTROL); -+ ddbwritel(dev, 0, SPI_CONTROL); - return 0; - } - if (rlen > 4) -- ddbwritel(1, SPI_CONTROL); -+ ddbwritel(dev, 1, SPI_CONTROL); - - while (rlen > 4) { -- ddbwritel(0xffffffff, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -+ ddbwritel(dev, 0xffffffff, SPI_DATA); -+ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) - ; -- data = ddbreadl(SPI_DATA); -+ data = ddbreadl(dev, SPI_DATA); - *(u32 *) rbuf = swab32(data); - rbuf += 4; - rlen -= 4; - } -- ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); -- ddbwritel(0xffffffff, SPI_DATA); -- while (ddbreadl(SPI_CONTROL) & 0x0004) -+ ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); -+ ddbwritel(dev, 0xffffffff, SPI_DATA); -+ while (ddbreadl(dev, SPI_CONTROL) & 0x0004) - ; - -- data = ddbreadl(SPI_DATA); -- ddbwritel(0, SPI_CONTROL); -+ data = ddbreadl(dev, SPI_DATA); -+ ddbwritel(dev, 0, SPI_CONTROL); - - if (rlen < 4) - data <<= ((4 - rlen) * 8); -@@ -1421,14 +2138,21 @@ struct ddb_flashio { - __u32 read_len; - }; - -+struct ddb_gpio { -+ __u32 mask; -+ __u32 data; -+}; -+ -+ - #define IOCTL_DDB_FLASHIO _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio) -+#define IOCTL_DDB_GPIO_IN _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio) -+#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio) - - #define DDB_NAME "ddbridge" - - static u32 ddb_num; --static struct ddb *ddbs[32]; --static struct class *ddb_class; - static int ddb_major; -+static DEFINE_MUTEX(ddb_mutex); - - static int ddb_open(struct inode *inode, struct file *file) - { -@@ -1470,6 +2194,16 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) - return -EFAULT; - break; - } -+ case IOCTL_DDB_GPIO_OUT: -+ { -+ struct ddb_gpio gpio; -+ if (copy_from_user(&gpio, parg, sizeof(gpio))) -+ break; -+ ddbwritel(dev, gpio.mask, GPIO_DIRECTION); -+ ddbwritel(dev, gpio.data, GPIO_OUTPUT); -+ res = 0; -+ break; -+ } - default: - return -ENOTTY; - } -@@ -1481,52 +2215,336 @@ static const struct file_operations ddb_fops = { - .open = ddb_open, - }; - --static char *ddb_devnode(struct device *device, umode_t *mode) -+static char *ddb_devnode(struct device *device, mode_t *mode) - { - struct ddb *dev = dev_get_drvdata(device); - - return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr); - } - -+static ssize_t ports_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ -+ return sprintf(buf, "%d\n", dev->info->port_num); -+} -+ -+static ssize_t ts_irq_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ -+ return sprintf(buf, "%d\n", dev->ts_irq); -+} -+ -+static ssize_t i2c_irq_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ -+ return sprintf(buf, "%d\n", dev->i2c_irq); -+} -+ -+static char *class_name[] = { -+ "NONE", "CI", "TUNER", "LOOP" -+}; -+ -+static char *type_name[] = { -+ "NONE", "DVBS_ST", "DVBS_ST_AA", "DVBCT_TR", "DVBCT_ST", "INTERNAL", "CXD2099", -+}; -+ -+static ssize_t fan_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ u32 val; -+ -+ val = ddbreadl(dev, GPIO_OUTPUT) & 1; -+ return sprintf(buf, "%d\n", val); -+} -+ -+static ssize_t fan_store(struct device *device, struct device_attribute *d, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ unsigned val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ ddbwritel(dev, 1, GPIO_DIRECTION); -+ ddbwritel(dev, val & 1, GPIO_OUTPUT); -+ return count; -+} -+ -+static ssize_t temp_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int temp; -+ u8 tmp[2]; -+ -+ if (!dev->info->temp_num) -+ return sprintf(buf, "no sensor\n"); -+ if (i2c_read_regs(&dev->i2c[0].adap, 0x48, 0, tmp, 2) < 0) -+ return sprintf(buf, "read_error\n"); -+ temp = (tmp[0] << 3) | (tmp[1] >> 5); -+ temp *= 125; -+ return sprintf(buf, "%d\n", temp); -+} -+ -+static ssize_t mod_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ -+ return sprintf(buf, "%s:%s\n", -+ class_name[dev->port[num].class], -+ type_name[dev->port[num].type]); -+} -+ -+static ssize_t led_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ -+ return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0); -+} -+ -+ -+static void ddb_set_led(struct ddb *dev, int num, int val) -+{ -+ if (!dev->info->led_num) -+ return; -+ switch (dev->port[num].class) { -+ case DDB_PORT_TUNER: -+ switch (dev->port[num].type) { -+ case DDB_TUNER_DVBS_ST: -+ printk(KERN_INFO "LED %d %d\n", num, val); -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x69, 0xf14c, val ? 2 : 0); -+ break; -+ case DDB_TUNER_DVBCT_ST: -+ printk(KERN_INFO "LED %d %d\n", num, val); -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x1f, 0xf00e, 0); -+ i2c_write_reg16(&dev->i2c[num].adap, -+ 0x1f, 0xf00f, val ? 1 : 0); -+ break; -+ } -+ break; -+ default: -+ break; -+ } -+} -+ -+static ssize_t led_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ unsigned val; -+ -+ if (sscanf(buf, "%u\n", &val) != 1) -+ return -EINVAL; -+ if (val) -+ dev->leds |= (1 << num); -+ else -+ dev->leds &= ~(1 << num); -+ ddb_set_led(dev, num, val); -+ return count; -+} -+ -+static ssize_t snr_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ char snr[32]; -+ int num = attr->attr.name[3] - 0x30; -+ -+ /* serial number at 0x100-0x11f */ -+ if (i2c_read_regs16(&dev->i2c[num].adap, 0x57, 0x100, snr, 32) < 0) -+ return sprintf(buf, "NO SNR\n"); -+ snr[31] = 0; /* in case it is not terminated on EEPROM */ -+ return sprintf(buf, "%s\n", snr); -+} -+ -+ -+static ssize_t snr_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct ddb *dev = dev_get_drvdata(device); -+ int num = attr->attr.name[3] - 0x30; -+ u8 snr[34] = { 0x01, 0x00 }; -+ -+ if (count > 31) -+ return -EINVAL; -+ memcpy(snr + 2, buf, count); -+ i2c_write(&dev->i2c[num].adap, 0x57, snr, 34); -+ return count; -+} -+ -+static ssize_t redirect_show(struct device *device, struct device_attribute *attr, char *buf) -+{ -+ return 0; -+} -+ -+static ssize_t redirect_store(struct device *device, struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ unsigned int i, p; -+ int res; -+ -+ if (sscanf(buf, "%x %x\n", &i, &p) != 2) -+ return -EINVAL; -+ printk(KERN_INFO "redirect: %02x, %02x\n", i, p); -+ res = set_redirect(i, p); -+ if (res < 0) -+ return res; -+ return count; -+} -+ -+#define __ATTR_MRO(_name, _show) { \ -+ .attr = { .name = __stringify(_name), .mode = 0444 }, \ -+ .show = _show, \ -+} -+ -+struct device_attribute ddb_attrs[] = { -+ __ATTR_RO(ports), -+ __ATTR_RO(ts_irq), -+ __ATTR_RO(i2c_irq), -+ __ATTR(redirect, 0666, redirect_show, redirect_store), -+ __ATTR_NULL -+}; -+ -+static struct device_attribute ddb_mod[] = { -+ __ATTR_MRO(mod0, mod_show), -+ __ATTR_MRO(mod1, mod_show), -+ __ATTR_MRO(mod2, mod_show), -+ __ATTR_MRO(mod3, mod_show), -+}; -+ -+static struct device_attribute ddb_temp = -+ __ATTR_RO(temp); -+ -+static struct device_attribute ddb_fan = -+ __ATTR(fan, 0666, fan_show, fan_store); -+ -+static struct device_attribute ddb_led[] = { -+ __ATTR(led0, 0666, led_show, led_store), -+ __ATTR(led1, 0666, led_show, led_store), -+ __ATTR(led2, 0666, led_show, led_store), -+ __ATTR(led3, 0666, led_show, led_store), -+}; -+ -+static struct device_attribute ddb_snr[] = { -+ __ATTR(snr0, 0666, snr_show, snr_store), -+ __ATTR(snr1, 0666, snr_show, snr_store), -+ __ATTR(snr2, 0666, snr_show, snr_store), -+ __ATTR(snr3, 0666, snr_show, snr_store), -+}; -+ -+static struct class ddb_class = { -+ .name = "ddbridge", -+ .owner = THIS_MODULE, -+ .dev_attrs = ddb_attrs, -+ .devnode = ddb_devnode, -+}; -+ - static int ddb_class_create(void) - { - ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops); - if (ddb_major < 0) - return ddb_major; -- -- ddb_class = class_create(THIS_MODULE, DDB_NAME); -- if (IS_ERR(ddb_class)) { -- unregister_chrdev(ddb_major, DDB_NAME); -- return PTR_ERR(ddb_class); -- } -- ddb_class->devnode = ddb_devnode; -+ if (class_register(&ddb_class) < 0) -+ return -1; - return 0; - } - - static void ddb_class_destroy(void) - { -- class_destroy(ddb_class); -+ class_unregister(&ddb_class); - unregister_chrdev(ddb_major, DDB_NAME); - } - -+static int ddb_device_files_create(struct ddb *dev) -+{ -+ int i, error = 0; -+ -+ if (dev->info->temp_num > 0) -+ error = device_create_file(dev->ddb_dev, &ddb_temp); -+ -+ if (!error && dev->info->fan_num > 0) -+ error = device_create_file(dev->ddb_dev, &ddb_fan); -+ -+ for (i = 0; !error && (i < dev->info->led_num); i++) -+ error = device_create_file(dev->ddb_dev, &ddb_led[i]); -+ -+ for (i = 0; !error && (i < dev->info->port_num); i++) -+ error = device_create_file(dev->ddb_dev, &ddb_mod[i]); -+ -+ for (i = 0; !error && (i < dev->info->i2c_num); i++) -+ error = device_create_file(dev->ddb_dev, &ddb_snr[i]); -+ -+ return error; -+} -+ -+static void ddb_device_files_delete(struct ddb *dev) -+{ -+ int i; -+ -+ if (dev->info->temp_num > 0) -+ device_remove_file(dev->ddb_dev, &ddb_temp); -+ -+ if (dev->info->fan_num > 0) -+ device_remove_file(dev->ddb_dev, &ddb_fan); -+ -+ for (i = 0; i < dev->info->led_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_led[i]); -+ -+ for (i = 0; i < dev->info->port_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_mod[i]); -+ -+ for (i = 0; i < dev->info->i2c_num; i++) -+ device_remove_file(dev->ddb_dev, &ddb_snr[i]); -+} -+ - static int ddb_device_create(struct ddb *dev) - { -+ int error = -1; -+ -+ mutex_lock(&ddb_mutex); - dev->nr = ddb_num++; -- dev->ddb_dev = device_create(ddb_class, NULL, -+ ddbs[dev->nr] = dev; -+ mutex_unlock(&ddb_mutex); -+ dev->ddb_dev = device_create(&ddb_class, &dev->pdev->dev, - MKDEV(ddb_major, dev->nr), - dev, "ddbridge%d", dev->nr); -- ddbs[dev->nr] = dev; -- if (IS_ERR(dev->ddb_dev)) -- return -1; -+ if (IS_ERR(dev->ddb_dev)) { -+ printk(KERN_ERR ": Could not create ddbridge device\n"); -+ goto fail1; -+ } -+ error = ddb_device_files_create(dev); -+ if (error) { -+ printk(KERN_ERR ": Could not create ddbridge sysfs files\n"); -+ goto fail2; -+ } -+ - return 0; -+ -+fail2: -+ ddb_device_files_delete(dev); -+ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); -+ -+fail1: -+ mutex_lock(&ddb_mutex); -+ ddb_num--; -+ ddbs[dev->nr] = NULL; -+ mutex_unlock(&ddb_mutex); -+ -+ return error; - } - - static void ddb_device_destroy(struct ddb *dev) - { -- ddb_num--; - if (IS_ERR(dev->ddb_dev)) - return; -- device_destroy(ddb_class, MKDEV(ddb_major, 0)); -+ ddb_device_files_delete(dev); -+ device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr)); - } - - -@@ -1549,7 +2567,7 @@ static void ddb_remove(struct pci_dev *pdev) - ddb_ports_detach(dev); - ddb_i2c_release(dev); - -- ddbwritel(0, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0, INTERRUPT_ENABLE); - free_irq(dev->pdev->irq, dev); - #ifdef CONFIG_PCI_MSI - if (dev->msi) -@@ -1564,7 +2582,6 @@ static void ddb_remove(struct pci_dev *pdev) - pci_disable_device(pdev); - } - -- - static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) - { - struct ddb *dev; -@@ -1574,10 +2591,9 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) - if (pci_enable_device(pdev) < 0) - return -ENODEV; - -- dev = vmalloc(sizeof(struct ddb)); -+ dev = vzalloc(sizeof(struct ddb)); - if (dev == NULL) - return -ENOMEM; -- memset(dev, 0, sizeof(struct ddb)); - - dev->pdev = pdev; - pci_set_drvdata(pdev, dev); -@@ -1590,7 +2606,8 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) - stat = -ENOMEM; - goto fail; - } -- printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4)); -+ printk(KERN_INFO "HW %08x REG %08x\n", -+ ddbreadl(dev, 0), ddbreadl(dev, 4)); - - #ifdef CONFIG_PCI_MSI - if (pci_msi_enabled()) -@@ -1606,11 +2623,11 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) - irq_flag, "DDBridge", (void *) dev); - if (stat < 0) - goto fail1; -- ddbwritel(0, DMA_BASE_WRITE); -- ddbwritel(0, DMA_BASE_READ); -- ddbwritel(0xffffffff, INTERRUPT_ACK); -- ddbwritel(0xfff0f, INTERRUPT_ENABLE); -- ddbwritel(0, MSI1_ENABLE); -+ ddbwritel(dev, 0, DMA_BASE_WRITE); -+ ddbwritel(dev, 0, DMA_BASE_READ); -+ ddbwritel(dev, 0xffffffff, INTERRUPT_ACK); -+ ddbwritel(dev, 0x000fff0f, INTERRUPT_ENABLE); -+ ddbwritel(dev, 0, MSI1_ENABLE); - - if (ddb_i2c_init(dev) < 0) - goto fail1; -@@ -1621,7 +2638,14 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) - } - if (ddb_ports_attach(dev) < 0) - goto fail3; -- ddb_device_create(dev); -+ -+ if (ddb_device_create(dev) < 0) -+ goto fail3; -+ -+ if (dev->info->fan_num) { -+ ddbwritel(dev, 1, GPIO_DIRECTION); -+ ddbwritel(dev, 1, GPIO_OUTPUT); -+ } - return 0; - - fail3: -@@ -1631,11 +2655,14 @@ fail3: - fail2: - printk(KERN_ERR "fail2\n"); - ddb_buffers_free(dev); -+ ddb_i2c_release(dev); - fail1: - printk(KERN_ERR "fail1\n"); -+ free_irq(dev->pdev->irq, dev); -+#ifdef CONFIG_PCI_MSI - if (dev->msi) - pci_disable_msi(dev->pdev); -- free_irq(dev->pdev->irq, dev); -+#endif - fail: - printk(KERN_ERR "fail\n"); - ddb_unmap(dev); -@@ -1657,23 +2684,78 @@ static struct ddb_info ddb_octopus = { - .type = DDB_OCTOPUS, - .name = "Digital Devices Octopus DVB adapter", - .port_num = 4, -+ .i2c_num = 4, - }; - - static struct ddb_info ddb_octopus_le = { - .type = DDB_OCTOPUS, - .name = "Digital Devices Octopus LE DVB adapter", - .port_num = 2, -+ .i2c_num = 2, -+}; -+ -+static struct ddb_info ddb_octopus_oem = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus OEM", -+ .port_num = 4, -+ .i2c_num = 4, -+ .led_num = 1, -+ .fan_num = 1, -+ .temp_num = 1, -+}; -+ -+static struct ddb_info ddb_octopus_mini = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Octopus Mini", -+ .port_num = 4, -+ .i2c_num = 4, - }; - - static struct ddb_info ddb_v6 = { - .type = DDB_OCTOPUS, - .name = "Digital Devices Cine S2 V6 DVB adapter", - .port_num = 3, -+ .i2c_num = 3, -+}; -+ -+static struct ddb_info ddb_v6_5 = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices Cine S2 V6.5 DVB adapter", -+ .port_num = 4, -+ .i2c_num = 4, -+}; -+ -+static struct ddb_info ddb_dvbct = { -+ .type = DDB_OCTOPUS, -+ .name = "Digital Devices DVBCT V6.1 DVB adapter", -+ .port_num = 3, -+ .i2c_num = 3, -+}; -+ -+static struct ddb_info ddb_satixS2v3 = { -+ .type = DDB_OCTOPUS, -+ .name = "Mystique SaTiX-S2 V3 DVB adapter", -+ .port_num = 3, -+ .i2c_num = 3, -+}; -+ -+static struct ddb_info ddb_ci = { -+ .type = DDB_OCTOPUS_CI, -+ .name = "Digital Devices Octopus CI", -+ .port_num = 4, -+ .i2c_num = 2, -+}; -+ -+static struct ddb_info ddb_cis = { -+ .type = DDB_OCTOPUS_CI, -+ .name = "Digital Devices Octopus CI single", -+ .port_num = 3, -+ .i2c_num = 2, - }; - - #define DDVID 0xdd01 /* Digital Devices Vendor ID */ - --#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ -+#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \ - .vendor = _vend, .device = _dev, \ - .subvendor = _subvend, .subdevice = _subdev, \ - .driver_data = (unsigned long)&_driverdata } -@@ -1682,8 +2764,15 @@ static const struct pci_device_id ddb_id_tbl[] = { - DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus), - DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus), - DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le), -- DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini), - DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5), -+ DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct), -+ DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3), -+ DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopus), -+ DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci), -+ DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis), - /* in case sub-ids got deleted in flash */ - DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none), - {0} -@@ -1700,18 +2789,16 @@ static struct pci_driver ddb_pci_driver = { - - static __init int module_init_ddbridge(void) - { -- int ret; -+ int stat; - - printk(KERN_INFO "Digital Devices PCIE bridge driver, " - "Copyright (C) 2010-11 Digital Devices GmbH\n"); -- -- ret = ddb_class_create(); -- if (ret < 0) -- return ret; -- ret = pci_register_driver(&ddb_pci_driver); -- if (ret < 0) -+ if (ddb_class_create()) -+ return -1; -+ stat = pci_register_driver(&ddb_pci_driver); -+ if (stat < 0) - ddb_class_destroy(); -- return ret; -+ return stat; - } - - static __exit void module_exit_ddbridge(void) -@@ -1726,4 +2813,4 @@ module_exit(module_exit_ddbridge); - MODULE_DESCRIPTION("Digital Devices PCIe Bridge"); - MODULE_AUTHOR("Ralph Metzler"); - MODULE_LICENSE("GPL"); --MODULE_VERSION("0.5"); -+MODULE_VERSION("0.8"); -diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h -index a3ccb31..46e8a21 100644 ---- a/drivers/media/pci/ddbridge/ddbridge-regs.h -+++ b/drivers/media/pci/ddbridge/ddbridge-regs.h -@@ -21,11 +21,12 @@ - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - --/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */ -+/* DD-DVBBridgeV1.h 388 2011-07-13 20:47:08Z manfred */ - - /* Register Definitions */ - --#define CUR_REGISTERMAP_VERSION 0x10000 -+#define CUR_REGISTERMAP_VERSION 0x10003 -+#define CUR_REGISTERMAP_VERSION_CI 0x10000 - - #define HARDWARE_VERSION 0x00 - #define REGISTERMAP_VERSION 0x04 -@@ -36,8 +37,14 @@ - #define SPI_CONTROL 0x10 - #define SPI_DATA 0x14 - --/* ------------------------------------------------------------------------- */ -+/* -------------------------------------------------------------------------- */ -+/* GPIO */ -+ -+#define GPIO_OUTPUT 0x20 -+#define GPIO_INPUT 0x24 -+#define GPIO_DIRECTION 0x28 - -+/* -------------------------------------------------------------------------- */ - /* Interrupt controller */ - /* How many MSI's are available depends on HW (Min 2 max 8) */ - /* How many are usable also depends on Host platform */ -@@ -149,3 +156,46 @@ - #define DMA_BASE_ADDRESS_TABLE (0x2000) - #define DMA_BASE_ADDRESS_TABLE_ENTRIES (512) - -+/* -------------------------------------------------------------------------- */ -+/* CI Interface (only CI-Bridge) */ -+ -+#define CI_BASE (0x400) -+#define CI_CONTROL(i) (CI_BASE + (i) * 32 + 0x00) -+ -+#define CI_DO_ATTRIBUTE_RW(i) (CI_BASE + (i) * 32 + 0x04) -+#define CI_DO_IO_RW(i) (CI_BASE + (i) * 32 + 0x08) -+#define CI_READDATA(i) (CI_BASE + (i) * 32 + 0x0c) -+#define CI_DO_READ_ATTRIBUTES(i) (CI_BASE + (i) * 32 + 0x10) -+ -+#define CI_RESET_CAM (0x00000001) -+#define CI_POWER_ON (0x00000002) -+#define CI_ENABLE (0x00000004) -+#define CI_BLOCKIO_ENABLE (0x00000008) -+#define CI_BYPASS_DISABLE (0x00000010) -+#define CI_DISABLE_AUTO_OFF (0x00000020) -+ -+#define CI_CAM_READY (0x00010000) -+#define CI_CAM_DETECT (0x00020000) -+#define CI_READY (0x80000000) -+#define CI_BLOCKIO_ACTIVE (0x40000000) -+#define CI_BLOCKIO_RCVDATA (0x20000000) -+#define CI_BLOCKIO_SEND_PENDING (0x10000000) -+#define CI_BLOCKIO_SEND_COMPLETE (0x08000000) -+ -+#define CI_READ_CMD (0x40000000) -+#define CI_WRITE_CMD (0x80000000) -+ -+#define CI_BLOCKIO_SEND(i) (CI_BASE + (i) * 32 + 0x14) -+#define CI_BLOCKIO_RECEIVE(i) (CI_BASE + (i) * 32 + 0x18) -+ -+#define CI_BLOCKIO_SEND_COMMAND (0x80000000) -+#define CI_BLOCKIO_SEND_COMPLETE_ACK (0x40000000) -+#define CI_BLOCKIO_RCVDATA_ACK (0x40000000) -+ -+#define CI_BUFFER_BASE (0x3000) -+#define CI_BUFFER_SIZE (0x0800) -+#define CI_BLOCKIO_BUFFER_SIZE (CI_BUFFER_SIZE/2) -+ -+#define CI_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) -+#define CI_BLOCKIO_RECEIVE_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE) -+#define CI_BLOCKIO_SEND_BUFFER(i) (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE) -diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h -index 8b1b41d..ce2df00 100644 ---- a/drivers/media/pci/ddbridge/ddbridge.h -+++ b/drivers/media/pci/ddbridge/ddbridge.h -@@ -32,7 +32,10 @@ - #include - #include - #include -+#include -+#include - #include -+#include - - #include "dmxdev.h" - #include "dvbdev.h" -@@ -52,43 +55,53 @@ struct ddb_info { - int type; - #define DDB_NONE 0 - #define DDB_OCTOPUS 1 -+#define DDB_OCTOPUS_CI 2 - char *name; - int port_num; -- u32 port_type[DDB_MAX_PORT]; -+ int i2c_num; -+ int led_num; -+ int fan_num; -+ int temp_num; - }; - - /* DMA_SIZE MUST be divisible by 188 and 128 !!! */ - --#define INPUT_DMA_MAX_BUFS 32 /* hardware table limit */ -+#define DMA_MAX_BUFS 32 /* hardware table limit */ -+ - #define INPUT_DMA_BUFS 8 - #define INPUT_DMA_SIZE (128*47*21) -+#define INPUT_DMA_IRQ_DIV 1 - --#define OUTPUT_DMA_MAX_BUFS 32 - #define OUTPUT_DMA_BUFS 8 - #define OUTPUT_DMA_SIZE (128*47*21) -+#define OUTPUT_DMA_IRQ_DIV 1 - - struct ddb; - struct ddb_port; - --struct ddb_input { -- struct ddb_port *port; -+struct ddb_dma { -+ void *io; - u32 nr; -- int attached; -- -- dma_addr_t pbuf[INPUT_DMA_MAX_BUFS]; -- u8 *vbuf[INPUT_DMA_MAX_BUFS]; -- u32 dma_buf_num; -- u32 dma_buf_size; -+ dma_addr_t pbuf[DMA_MAX_BUFS]; -+ u8 *vbuf[DMA_MAX_BUFS]; -+ u32 num; -+ u32 size; -+ u32 div; -+ u32 bufreg; - - struct tasklet_struct tasklet; - spinlock_t lock; - wait_queue_head_t wq; - int running; - u32 stat; -+ u32 ctrl; - u32 cbuf; - u32 coff; -+}; - -- struct dvb_adapter adap; -+struct ddb_dvb { -+ struct dvb_adapter *adap; -+ int adap_registered; - struct dvb_device *dev; - struct dvb_frontend *fe; - struct dvb_frontend *fe2; -@@ -99,32 +112,36 @@ struct ddb_input { - struct dmx_frontend mem_frontend; - int users; - int (*gate_ctrl)(struct dvb_frontend *, int); -+ int attached; - }; - --struct ddb_output { -+struct ddb_ci { -+ struct dvb_ca_en50221 en; - struct ddb_port *port; - u32 nr; -- dma_addr_t pbuf[OUTPUT_DMA_MAX_BUFS]; -- u8 *vbuf[OUTPUT_DMA_MAX_BUFS]; -- u32 dma_buf_num; -- u32 dma_buf_size; -- struct tasklet_struct tasklet; -- spinlock_t lock; -- wait_queue_head_t wq; -- int running; -- u32 stat; -- u32 cbuf; -- u32 coff; -+}; - -- struct dvb_adapter adap; -- struct dvb_device *dev; -+ -+struct ddb_input { -+ struct ddb_port *port; -+ u32 nr; -+ struct ddb_dma *dma; -+ struct ddb_input *redirect; -+ -+ struct ddb_dvb dvb; -+}; -+ -+struct ddb_output { -+ struct ddb_port *port; -+ u32 nr; -+ struct ddb_dma *dma; -+ struct ddb_input *redirect; - }; - - struct ddb_i2c { - struct ddb *dev; - u32 nr; - struct i2c_adapter adap; -- struct i2c_adapter adap2; - u32 regs; - u32 rbuf; - u32 wbuf; -@@ -141,12 +158,15 @@ struct ddb_port { - #define DDB_PORT_NONE 0 - #define DDB_PORT_CI 1 - #define DDB_PORT_TUNER 2 -+#define DDB_PORT_LOOP 3 - u32 type; - #define DDB_TUNER_NONE 0 - #define DDB_TUNER_DVBS_ST 1 - #define DDB_TUNER_DVBS_ST_AA 2 --#define DDB_TUNER_DVBCT_TR 16 --#define DDB_TUNER_DVBCT_ST 17 -+#define DDB_TUNER_DVBCT_TR 3 -+#define DDB_TUNER_DVBCT_ST 4 -+#define DDB_CI_INTERNAL 5 -+#define DDB_CI_EXTERNAL_SONY 6 - u32 adr; - - struct ddb_input *input[2]; -@@ -161,25 +181,20 @@ struct ddb { - struct ddb_i2c i2c[DDB_MAX_I2C]; - struct ddb_input input[DDB_MAX_INPUT]; - struct ddb_output output[DDB_MAX_OUTPUT]; -+ struct dvb_adapter adap[DDB_MAX_INPUT]; -+ struct ddb_dma dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT]; - - struct device *ddb_dev; -- int nr; -+ u32 nr; - u8 iobuf[1028]; - - struct ddb_info *info; - int msi; --}; -- --/****************************************************************************/ - --#define ddbwritel(_val, _adr) writel((_val), \ -- (char *) (dev->regs+(_adr))) --#define ddbreadl(_adr) readl((char *) (dev->regs+(_adr))) --#define ddbcpyto(_adr, _src, _count) memcpy_toio((char *) \ -- (dev->regs+(_adr)), (_src), (_count)) --#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), (char *) \ -- (dev->regs+(_adr)), (_count)) -+ u8 leds; - --/****************************************************************************/ -+ u32 ts_irq; -+ u32 i2c_irq; -+}; - - #endif -diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig -index 637d506..14975c7 100644 ---- a/drivers/media/pci/ngene/Kconfig -+++ b/drivers/media/pci/ngene/Kconfig -@@ -1,13 +1,16 @@ - config DVB_NGENE - tristate "Micronas nGene support" - depends on DVB_CORE && PCI && I2C -- select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT -- select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT -- select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT -- select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT -- select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT -- select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT -- select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT -+ select DVB_CXD2099 -+ select DVB_LNBP21 if !DVB_FE_CUSTOMISE -+ select DVB_STV6110x if !DVB_FE_CUSTOMISE -+ select DVB_STV090x if !DVB_FE_CUSTOMISE -+ select DVB_LGDT330X if !DVB_FE_CUSTOMISE -+ select DVB_DRXK if !DVB_FE_CUSTOMISE -+ select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE -+ select DVB_STV0367DD if !DVB_FE_CUSTOMISE -+ select DVB_TDA18212DD if !DVB_FE_CUSTOMISE -+ select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE - ---help--- - Support for Micronas PCI express cards with nGene bridge. - -diff --git a/drivers/media/pci/ngene/Makefile b/drivers/media/pci/ngene/Makefile -index 5c0b5d6..42c036a 100644 ---- a/drivers/media/pci/ngene/Makefile -+++ b/drivers/media/pci/ngene/Makefile -@@ -2,7 +2,8 @@ - # Makefile for the nGene device driver - # - --ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o -+ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-av.o \ -+ ngene-eeprom.o ngene-dvb.o - - obj-$(CONFIG_DVB_NGENE) += ngene.o - -diff --git a/drivers/media/pci/ngene/ngene-av.c b/drivers/media/pci/ngene/ngene-av.c -new file mode 100644 -index 0000000..a86459e ---- /dev/null -+++ b/drivers/media/pci/ngene/ngene-av.c -@@ -0,0 +1,348 @@ -+/* -+ * ngene-av.c: nGene PCIe bridge driver - DVB video/audio support -+ * -+ * Copyright (C) 2005-2007 Micronas -+ * -+ * Copyright (C) 2008-2009 Ralph Metzler -+ * Modifications for new nGene firmware, -+ * support for EEPROM-copying, -+ * support for new dual DVB-S2 card prototype -+ * -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+/* This file provides the support functions for DVB audio/video devices -+ (/dev/dvb/adapter0/[video|audio]), not to be confused with V4L2 support */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "ngene.h" -+ -+#if 0 -+ -+static void *ain_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) -+{ -+ struct ngene_channel *chan = priv; -+ struct ngene *dev = chan->dev; -+ -+ if (dvb_ringbuffer_free(&dev->ain_rbuf) >= len) { -+ dvb_ringbuffer_write(&dev->ain_rbuf, buf, len); -+ wake_up_interruptible(&dev->ain_rbuf.queue); -+ } else -+ printk(KERN_INFO DEVICE_NAME ": Dropped ain packet.\n"); -+ -+ return 0; -+} -+ -+static void *vcap_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) -+{ -+ -+ struct ngene_channel *chan = priv; -+ struct ngene *dev = chan->dev; -+ -+ if (len >= 1920 * 1080) -+ len = 1920 * 1080; -+ if (dvb_ringbuffer_free(&dev->vin_rbuf) >= len) { -+ dvb_ringbuffer_write(&dev->vin_rbuf, buf, len); -+ wake_up_interruptible(&dev->vin_rbuf.queue); -+ } else { -+ ;/*printk(KERN_INFO DEVICE_NAME ": Dropped vcap packet.\n"); */ -+ } -+ return 0; -+} -+ -+static ssize_t audio_write(struct file *file, -+ const char *buf, size_t count, loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+ssize_t audio_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int left; -+ int avail; -+ -+ left = count; -+ while (left) { -+ if (wait_event_interruptible( -+ dev->ain_rbuf.queue, -+ dvb_ringbuffer_avail(&dev->ain_rbuf) > 0) < 0) -+ return -EAGAIN; -+ avail = dvb_ringbuffer_avail(&dev->ain_rbuf); -+ if (avail > left) -+ avail = left; -+ dvb_ringbuffer_read_user(&dev->ain_rbuf, buf, avail); -+ left -= avail; -+ buf += avail; -+ } -+ return count; -+} -+ -+static int audio_open(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ struct ngene_channel *chan2 = &chan->dev->channel[2]; -+ int ret; -+ -+ ret = dvb_generic_open(inode, file); -+ if (ret < 0) -+ return ret; -+ dvb_ringbuffer_flush(&dev->ain_rbuf); -+ -+ chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE; -+ chan2->pBufferExchange = ain_exchange; -+ ngene_command_stream_control(chan2->dev, chan2->number, 0x80, -+ SMODE_AUDIO_CAPTURE, 0); -+ return ret; -+} -+ -+static int audio_release(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ struct ngene_channel *chan2 = &chan->dev->channel[2]; -+ -+ ngene_command_stream_control(dev, 2, 0, 0, 0); -+ chan2->pBufferExchange = 0; -+ -+ return dvb_generic_release(inode, file); -+} -+ -+static const struct file_operations audio_fops = { -+ .owner = THIS_MODULE, -+ .read = audio_read, -+ .write = audio_write, -+ .open = audio_open, -+ .release = audio_release, -+}; -+ -+static struct dvb_device dvbdev_audio = { -+ .priv = 0, -+ .readers = -1, -+ .writers = 1, -+ .users = 1, -+ .fops = &audio_fops, -+}; -+ -+static int video_open(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ struct ngene_channel *chan0 = &chan->dev->channel[0]; -+ int ret; -+ -+ ret = dvb_generic_open(inode, file); -+ if (ret < 0) -+ return ret; -+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) -+ return ret; -+ dvb_ringbuffer_flush(&dev->vin_rbuf); -+ -+ chan0->nBytesPerLine = 1920 * 2; -+ chan0->nLines = 540; -+ chan0->Capture1Length = 1920 * 2 * 540; -+ chan0->pBufferExchange = vcap_exchange; -+ chan0->itumode = 2; -+ ngene_command_stream_control(chan0->dev, chan0->number, -+ 0x80, SMODE_VIDEO_CAPTURE, 0); -+ return ret; -+} -+ -+static int video_release(struct inode *inode, struct file *file) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ struct ngene_channel *chan0 = &chan->dev->channel[0]; -+ -+ ngene_command_stream_control(dev, 0, 0, 0, 0); -+ chan0->pBufferExchange = 0; -+ -+ return dvb_generic_release(inode, file); -+} -+ -+static ssize_t video_write(struct file *file, -+ const char *buf, size_t count, loff_t *ppos) -+{ -+ return -EINVAL; -+} -+ -+ssize_t video_read(struct file *file, char *buf, size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int left, avail; -+ -+ left = count; -+ while (left) { -+ if (wait_event_interruptible( -+ dev->vin_rbuf.queue, -+ dvb_ringbuffer_avail(&dev->vin_rbuf) > 0) < 0) -+ return -EAGAIN; -+ avail = dvb_ringbuffer_avail(&dev->vin_rbuf); -+ if (avail > left) -+ avail = left; -+ dvb_ringbuffer_read_user(&dev->vin_rbuf, buf, avail); -+ left -= avail; -+ buf += avail; -+ } -+ return count; -+} -+ -+/* Why is this not exported from dvb_core ?!?! */ -+ -+static int dvb_usercopy2(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg, -+ int (*func)(struct inode *inode, struct file *file, -+ unsigned int cmd, void *arg)) -+{ -+ char sbuf[128]; -+ void *mbuf = NULL; -+ void *parg = NULL; -+ int err = -EINVAL; -+ -+ /* Copy arguments into temp kernel buffer */ -+ switch (_IOC_DIR(cmd)) { -+ case _IOC_NONE: -+ /* -+ * For this command, the pointer is actually an integer -+ * argument. -+ */ -+ parg = (void *)arg; -+ break; -+ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ -+ case _IOC_WRITE: -+ case (_IOC_WRITE | _IOC_READ): -+ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { -+ parg = sbuf; -+ } else { -+ /* too big to allocate from stack */ -+ mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); -+ if (NULL == mbuf) -+ return -ENOMEM; -+ parg = mbuf; -+ } -+ -+ err = -EFAULT; -+ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) -+ goto out; -+ break; -+ } -+ -+ /* call driver */ -+ err = func(inode, file, cmd, parg); -+ if (err == -ENOIOCTLCMD) -+ err = -EINVAL; -+ -+ if (err < 0) -+ goto out; -+ -+ /* Copy results into user buffer */ -+ switch (_IOC_DIR(cmd)) { -+ case _IOC_READ: -+ case (_IOC_WRITE | _IOC_READ): -+ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ break; -+ } -+ -+out: -+ kfree(mbuf); -+ return err; -+} -+ -+static int video_do_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, void *parg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int ret = 0; -+ unsigned long arg = (unsigned long)parg; -+ -+ switch (cmd) { -+ case VIDEO_SET_STREAMTYPE: -+ switch (arg) { -+ case VIDEO_CAP_MPEG2: -+ /* printk(KERN_INFO DEVICE_NAME ": setting MPEG2\n"); */ -+ send_cli(dev, "vdec mpeg2\n"); -+ break; -+ case VIDEO_CAP_AVC: -+ /* printk(KERN_INFO DEVICE_NAME ": setting H264\n"); */ -+ send_cli(dev, "vdec h264\n"); -+ break; -+ case VIDEO_CAP_VC1: -+ /* printk(KERN_INFO DEVICE_NAME ": setting VC1\n"); */ -+ send_cli(dev, "vdec vc1\n"); -+ break; -+ default: -+ ret = -EINVAL; -+ break; -+ } -+ break; -+ default: -+ ret = -ENOIOCTLCMD; -+ return -EINVAL; -+ } -+ return ret; -+} -+ -+static int video_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ return dvb_usercopy2(inode, file, cmd, arg, video_do_ioctl); -+} -+ -+static const struct file_operations video_fops = { -+ .owner = THIS_MODULE, -+ .read = video_read, -+ .write = video_write, -+ .open = video_open, -+ .release = video_release, -+ .ioctl = video_ioctl, -+}; -+ -+static struct dvb_device dvbdev_video = { -+ .priv = 0, -+ .readers = -1, -+ .writers = 1, -+ .users = -1, -+ .fops = &video_fops, -+}; -+#endif -diff --git a/drivers/media/pci/ngene/ngene-cards.c b/drivers/media/pci/ngene/ngene-cards.c -index 9e82d21..c9b1bd4 100644 ---- a/drivers/media/pci/ngene/ngene-cards.c -+++ b/drivers/media/pci/ngene/ngene-cards.c -@@ -42,8 +42,8 @@ - #include "mt2131.h" - #include "tda18271c2dd.h" - #include "drxk.h" --#include "drxd.h" --#include "dvb-pll.h" -+#include "tda18212dd.h" -+#include "stv0367dd.h" - - - /****************************************************************************/ -@@ -86,8 +86,98 @@ static int tuner_attach_stv6110(struct ngene_channel *chan) - return 0; - } - -+#if 0 -+static int tuner_attach_mt2060(struct ngene_channel *chan) -+{ -+ struct ngene *dev = chan->dev; -+ void *tconf = dev->card_info->tuner_config[chan->number]; -+ u8 drxa = dev->card_info->demoda[chan->number]; -+ struct dvb_frontend *fe = chan->fe, *fe2; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ fe->misc_priv = chan; -+#else -+ fe->sec_priv = chan; -+#endif -+ fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; -+ -+ dev->card_info->gate_ctrl(fe, 1); -+ fe2 = mt2060_attach(fe, &chan->i2c_adapter, tconf, 1220); -+ dev->card_info->gate_ctrl(fe, 0); -+ -+ i2c_write_register(&chan->i2c_adapter, drxa, 3, 4); -+ write_demod(&chan->i2c_adapter, drxa, 0x1012, 15); -+ write_demod(&chan->i2c_adapter, drxa, 0x1007, 0xc27); -+ write_demod(&chan->i2c_adapter, drxa, 0x0020, 0x003); -+ -+ return fe2 ? 0 : -ENODEV; -+} -+ -+static int tuner_attach_xc3028(struct ngene_channel *chan) -+{ -+ struct ngene *dev = chan->dev; -+ void *tconf = dev->card_info->tuner_config[chan->number]; -+ struct dvb_frontend *fe = chan->fe, *fe2; -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ fe->misc_priv = chan; -+#else -+ fe->sec_priv = chan; -+#endif -+ fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl; -+ -+ dev->card_info->gate_ctrl(fe, 1); -+ fe2 = xc3028_attach(fe, &chan->i2c_adapter, tconf); -+ dev->card_info->gate_ctrl(fe, 0); -+ -+ /*chan->fe->ops.tuner_ops.set_frequency(chan->fe,231250000);*/ -+ -+ return fe2 ? 0 : -ENODEV; -+} -+ -+static int demod_attach_drxd(struct ngene_channel *chan) -+{ -+ void *feconf = chan->dev->card_info->fe_config[chan->number]; -+ -+ chan->fe = drxd_attach(feconf, -+ chan, &chan->i2c_adapter, -+ &chan->dev->pci_dev->dev); -+ return (chan->fe) ? 0 : -ENODEV; -+} -+ -+static int demod_attach_drxh(struct ngene_channel *chan) -+{ -+ void *feconf = chan->dev->card_info->fe_config[chan->number]; -+ -+ chan->fe = drxh_attach(feconf, chan, -+ &chan->i2c_adapter, &chan->dev->pci_dev->dev); -+ return (chan->fe) ? 0 : -ENODEV; -+} -+ -+static int demod_attach_stb0899(struct ngene_channel *chan) -+{ -+ void *feconf = chan->dev->card_info->fe_config[chan->number]; -+ -+ chan->fe = stb0899_attach(feconf, -+ chan, &chan->i2c_adapter, -+ &chan->dev->pci_dev->dev); -+ if (chan->fe) { -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -+ chan->set_tone = chan->fe->ops->set_tone; -+ chan->fe->ops->set_tone = lnbh21_set_tone; -+ chan->fe->ops->set_voltage = lnbh21_set_voltage; -+#else -+ chan->set_tone = chan->fe->ops.set_tone; -+ chan->fe->ops.set_tone = lnbh21_set_tone; -+ chan->fe->ops.set_voltage = lnbh21_set_voltage; -+#endif -+ } -+ -+ return (chan->fe) ? 0 : -ENODEV; -+} -+#endif - --static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) -+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable) - { - struct ngene_channel *chan = fe->sec_priv; - int status; -@@ -121,12 +211,29 @@ static int tuner_attach_tda18271(struct ngene_channel *chan) - return 0; - } - -+static int tuner_attach_tda18212dd(struct ngene_channel *chan) -+{ -+ struct i2c_adapter *i2c; -+ struct dvb_frontend *fe; -+ -+ i2c = &chan->dev->channel[0].i2c_adapter; -+ fe = dvb_attach(tda18212dd_attach, chan->fe, i2c, -+ (chan->number & 1) ? 0x63 : 0x60); -+ if (!fe) { -+ printk(KERN_ERR "No TDA18212 found!\n"); -+ return -ENODEV; -+ } -+ return 0; -+} -+ - static int tuner_attach_probe(struct ngene_channel *chan) - { - if (chan->demod_type == 0) - return tuner_attach_stv6110(chan); - if (chan->demod_type == 1) - return tuner_attach_tda18271(chan); -+ if (chan->demod_type == 2) -+ return tuner_attach_tda18212dd(chan); - return -EINVAL; - } - -@@ -218,18 +325,51 @@ static int demod_attach_drxk(struct ngene_channel *chan, - struct drxk_config config; - - memset(&config, 0, sizeof(config)); -- config.microcode_name = "drxk_a3.mc"; -- config.qam_demod_parameter_count = 4; - config.adr = 0x29 + (chan->number ^ 2); -+ config.microcode_name = "drxk_a3.mc"; - -+#ifdef USE_API3 -+ chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2); -+#else - chan->fe = dvb_attach(drxk_attach, &config, i2c); -+#endif - if (!chan->fe) { - printk(KERN_ERR "No DRXK found!\n"); - return -ENODEV; - } - chan->fe->sec_priv = chan; - chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; -- chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl; -+ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; -+ return 0; -+} -+ -+static int port_has_stv0367(struct i2c_adapter *i2c, int port) -+{ -+ u8 val; -+ -+ if (i2c_read_reg16(i2c, 0x1c + (port ^ 1), 0xf000, &val) < 0) -+ return 0; -+ if (val != 0x60) -+ return 0; -+ return 1; -+} -+ -+static int demod_attach_stv0367dd(struct ngene_channel *chan, -+ struct i2c_adapter *i2c) -+{ -+ struct stv0367_cfg cfg; -+ -+ memset(&cfg, 0, sizeof cfg); -+ cfg.adr = 0x1c + (chan->number ^ 1); -+ -+ chan->fe = dvb_attach(stv0367_attach, i2c, &cfg, &chan->fe2); -+ if (!chan->fe) { -+ printk(KERN_ERR "No stv0367 found!\n"); -+ return -ENODEV; -+ } -+ chan->fe->sec_priv = chan; -+ chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl; -+ chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl; - return 0; - } - -@@ -279,6 +419,9 @@ static int cineS2_probe(struct ngene_channel *chan) - } else if (port_has_drxk(i2c, chan->number^2)) { - chan->demod_type = 1; - demod_attach_drxk(chan, i2c); -+ } else if (port_has_stv0367(i2c, chan->number)) { -+ chan->demod_type = 2; -+ demod_attach_stv0367dd(chan, i2c); - } else { - printk(KERN_ERR "No demod found on chan %d\n", chan->number); - return -ENODEV; -@@ -315,249 +458,140 @@ static int demod_attach_lg330x(struct ngene_channel *chan) - return (chan->fe) ? 0 : -ENODEV; - } - --static int demod_attach_drxd(struct ngene_channel *chan) --{ -- struct drxd_config *feconf; -- -- feconf = chan->dev->card_info->fe_config[chan->number]; -- -- chan->fe = dvb_attach(drxd_attach, feconf, chan, -- &chan->i2c_adapter, &chan->dev->pci_dev->dev); -- if (!chan->fe) { -- pr_err("No DRXD found!\n"); -- return -ENODEV; -- } -- return 0; --} -+/****************************************************************************/ -+/* Switch control (I2C gates, etc.) *****************************************/ -+/****************************************************************************/ - --static int tuner_attach_dtt7520x(struct ngene_channel *chan) -+#if 0 -+static int avf_output(struct ngene_channel *chan, int state) - { -- struct drxd_config *feconf; -- -- feconf = chan->dev->card_info->fe_config[chan->number]; -- -- if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address, -- &chan->i2c_adapter, -- feconf->pll_type)) { -- pr_err("No pll(%d) found!\n", feconf->pll_type); -- return -ENODEV; -- } -+ if (chan->dev->card_info->avf[chan->number]) -+ i2c_write_register(&chan->i2c_adapter, -+ chan->dev->card_info->avf[chan->number], -+ 0xf2, state ? 0x89 : 0x80); - return 0; - } - --/****************************************************************************/ --/* EEPROM TAGS **************************************************************/ --/****************************************************************************/ -- --#define MICNG_EE_START 0x0100 --#define MICNG_EE_END 0x0FF0 -+/* Viper expander: sw11,sw12,sw21,sw22,i2csw1,i2csw2,tsen1,tsen2 */ - --#define MICNG_EETAG_END0 0x0000 --#define MICNG_EETAG_END1 0xFFFF -- --/* 0x0001 - 0x000F reserved for housekeeping */ --/* 0xFFFF - 0xFFFE reserved for housekeeping */ -- --/* Micronas assigned tags -- EEProm tags for hardware support */ -- --#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ --#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ -- --#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ --#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ -- --/* Tag range for OEMs */ -+static int exp_set(struct ngene *dev) -+{ -+ return i2c_write(&dev->channel[0].i2c_adapter, -+ dev->card_info->exp, dev->exp_val); -+} - --#define MICNG_EETAG_OEM_FIRST 0xC000 --#define MICNG_EETAG_OEM_LAST 0xFFEF -+static int exp_init(struct ngene *dev) -+{ -+ if (!dev->card_info->exp) -+ return 0; -+ dev->exp_val = dev->card_info->exp_init; -+ return exp_set(dev); -+} - --static int i2c_write_eeprom(struct i2c_adapter *adapter, -- u8 adr, u16 reg, u8 data) -+static int exp_set_bit(struct ngene *dev, int bit, int val) - { -- u8 m[3] = {(reg >> 8), (reg & 0xff), data}; -- struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, -- .len = sizeof(m)}; -+ if (val) -+ set_bit(bit, &dev->exp_val); -+ else -+ clear_bit(bit, &dev->exp_val); -+ return exp_set(dev); -+} - -- if (i2c_transfer(adapter, &msg, 1) != 1) { -- pr_err(DEVICE_NAME ": Error writing EEPROM!\n"); -- return -EIO; -+static int viper_switch_ctrl(struct ngene_channel *chan, int type, int val) -+{ -+ switch (type) { -+ case 0: /* I2C tuner gate on/off */ -+ return exp_set_bit(chan->dev, 4 + chan->number, val); -+ case 1: /* Stream: 0=TS 1=ITU */ -+ avf_output(chan, val); -+ return exp_set_bit(chan->dev, 6 + chan->number, val); -+ case 2: /* Input: 0=digital 1=analog antenna input */ -+ exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); -+ exp_set_bit(chan->dev, 1 + chan->number * 2, val ? 1 : 0); -+ break; - } - return 0; - } - --static int i2c_read_eeprom(struct i2c_adapter *adapter, -- u8 adr, u16 reg, u8 *data, int len) -+static int viper_switch_ctrl2(struct ngene_channel *chan, int type, int val) - { -- u8 msg[2] = {(reg >> 8), (reg & 0xff)}; -- struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -- .buf = msg, .len = 2 }, -- {.addr = adr, .flags = I2C_M_RD, -- .buf = data, .len = len} }; -- -- if (i2c_transfer(adapter, msgs, 2) != 2) { -- pr_err(DEVICE_NAME ": Error reading EEPROM\n"); -- return -EIO; -+ switch (type) { -+ case 0: /* I2C tuner gate on/off */ -+ return exp_set_bit(chan->dev, 4 + chan->number, val); -+ case 1: /* Stream: 0=TS 1=ITU */ -+ avf_output(chan, val); -+ return exp_set_bit(chan->dev, 6 + chan->number, val); -+ case 2: /* Input: 0=digital 1=analog antenna input */ -+ exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1); -+ exp_set_bit(chan->dev, 1 + chan->number * 2, 0); -+ break; - } - return 0; - } - --static int ReadEEProm(struct i2c_adapter *adapter, -- u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) -+static int viper_gate_ctrl(struct dvb_frontend *fe, int enable) - { -- int status = 0; -- u16 Addr = MICNG_EE_START, Length, tag = 0; -- u8 EETag[3]; -- -- while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { -- if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) -- return -1; -- tag = (EETag[0] << 8) | EETag[1]; -- if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) -- return -1; -- if (tag == Tag) -- break; -- Addr += sizeof(u16) + 1 + EETag[2]; -- } -- if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { -- pr_err(DEVICE_NAME -- ": Reached EOEE @ Tag = %04x Length = %3d\n", -- tag, EETag[2]); -- return -1; -- } -- Length = EETag[2]; -- if (Length > MaxLen) -- Length = (u16) MaxLen; -- if (Length > 0) { -- Addr += sizeof(u16) + 1; -- status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); -- if (!status) { -- *pLength = EETag[2]; --#if 0 -- if (Length < EETag[2]) -- status = STATUS_BUFFER_OVERFLOW; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ struct ngene_channel *chan = fe->misc_priv; -+#else /* Why is there no misc_priv available anymore !?!?! */ -+ /* Well, just abuse sec :-) */ -+ struct ngene_channel *chan = fe->sec_priv; - #endif -- } -- } -- return status; -+ struct ngene *dev = chan->dev; -+ -+ return dev->card_info->switch_ctrl(chan, 0, enable); - } - --static int WriteEEProm(struct i2c_adapter *adapter, -- u16 Tag, u32 Length, u8 *data) -+static int python_switch_ctrl(struct ngene_channel *chan, int type, int val) - { -- int status = 0; -- u16 Addr = MICNG_EE_START; -- u8 EETag[3]; -- u16 tag = 0; -- int retry, i; -- -- while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { -- if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) -- return -1; -- tag = (EETag[0] << 8) | EETag[1]; -- if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) -- return -1; -- if (tag == Tag) -- break; -- Addr += sizeof(u16) + 1 + EETag[2]; -- } -- if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { -- pr_err(DEVICE_NAME -- ": Reached EOEE @ Tag = %04x Length = %3d\n", -- tag, EETag[2]); -- return -1; -- } -- -- if (Length > EETag[2]) -- return -EINVAL; -- /* Note: We write the data one byte at a time to avoid -- issues with page sizes. (which are different for -- each manufacture and eeprom size) -- */ -- Addr += sizeof(u16) + 1; -- for (i = 0; i < Length; i++, Addr++) { -- status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); -- -- if (status) -- break; -- -- /* Poll for finishing write cycle */ -- retry = 10; -- while (retry) { -- u8 Tmp; -- -- msleep(50); -- status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); -- if (status) -- break; -- if (Tmp != data[i]) -- pr_err(DEVICE_NAME -- "eeprom write error\n"); -- retry -= 1; -- } -- if (status) { -- pr_err(DEVICE_NAME -- ": Timeout polling eeprom\n"); -- break; -- } -+ switch (type) { -+ case 0: /* I2C tuner gate on/off */ -+ if (chan->number > 1) -+ return -EINVAL; -+ return ngene_command_gpio_set(chan->dev, 3 + chan->number, val); -+ case 1: /* Stream: 0=TS 1=ITU */ -+ avf_output(chan, val); -+ return 0; - } -- return status; -+ return 0; - } - --static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) -+static int viper_reset_xc(struct dvb_frontend *fe) - { -- int stat; -- u8 buf[2]; -- u32 len = 0; -- -- stat = ReadEEProm(adapter, tag, 2, buf, &len); -- if (stat) -- return stat; -- if (len != 2) -- return -EINVAL; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ struct ngene_channel *chan = fe->misc_priv; -+#else -+ struct ngene_channel *chan = fe->sec_priv; -+#endif -+ struct ngene *dev = chan->dev; - -- *data = (buf[0] << 8) | buf[1]; -- return 0; --} -+ printk(KERN_INFO DEVICE_NAME ": Reset XC3028\n"); - --static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) --{ -- int stat; -- u8 buf[2]; -+ if (chan->number > 1) -+ return -EINVAL; - -- buf[0] = data >> 8; -- buf[1] = data & 0xff; -- stat = WriteEEProm(adapter, tag, 2, buf); -- if (stat) -- return stat; -+ ngene_command_gpio_set(dev, 3 + chan->number, 0); -+ msleep(150); -+ ngene_command_gpio_set(dev, 3 + chan->number, 1); - return 0; - } - --static s16 osc_deviation(void *priv, s16 deviation, int flag) -+static int python_gate_ctrl(struct dvb_frontend *fe, int enable) - { -- struct ngene_channel *chan = priv; -- struct i2c_adapter *adap = &chan->i2c_adapter; -- u16 data = 0; -- -- if (flag) { -- data = (u16) deviation; -- pr_info(DEVICE_NAME ": write deviation %d\n", -- deviation); -- eeprom_write_ushort(adap, 0x1000 + chan->number, data); -- } else { -- if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data)) -- data = 0; -- pr_info(DEVICE_NAME ": read deviation %d\n", -- (s16) data); -- } -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -+ struct ngene_channel *chan = fe->misc_priv; -+#else /* Why is there no misc_priv available anymore !?!?! */ -+ struct ngene_channel *chan = fe->sec_priv; -+#endif -+ struct ngene *dev = chan->dev; - -- return (s16) data; -+ if (chan->number == 0) -+ return ngene_command_gpio_set(dev, 3, enable); -+ if (chan->number == 1) -+ return ngene_command_gpio_set(dev, 4, enable); -+ return -EINVAL; - } -- --/****************************************************************************/ --/* Switch control (I2C gates, etc.) *****************************************/ --/****************************************************************************/ -- -+#endif - - static struct stv090x_config fe_cineS2 = { - .device = STV0900, -@@ -705,14 +739,18 @@ static struct ngene_info ngene_info_m780 = { - .fw_version = 15, - }; - -+/****************************************************************************/ -+ -+#if 0 - static struct drxd_config fe_terratec_dvbt_0 = { - .index = 0, - .demod_address = 0x70, - .demod_revision = 0xa2, - .demoda_address = 0x00, - .pll_address = 0x60, -- .pll_type = DVB_PLL_THOMSON_DTT7520X, -+ .pll_type = DRXD_PLL_DTT7520X, - .clock = 20000, -+ .pll_set = ngene_pll_set_th_dtt7520x, - .osc_deviation = osc_deviation, - }; - -@@ -722,8 +760,9 @@ static struct drxd_config fe_terratec_dvbt_1 = { - .demod_revision = 0xa2, - .demoda_address = 0x00, - .pll_address = 0x60, -- .pll_type = DVB_PLL_THOMSON_DTT7520X, -+ .pll_type = DRXD_PLL_DTT7520X, - .clock = 20000, -+ .pll_set = ngene_pll_set_th_dtt7520x, - .osc_deviation = osc_deviation, - }; - -@@ -732,13 +771,293 @@ static struct ngene_info ngene_info_terratec = { - .name = "Terratec Integra/Cinergy2400i Dual DVB-T", - .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, - .demod_attach = {demod_attach_drxd, demod_attach_drxd}, -- .tuner_attach = {tuner_attach_dtt7520x, tuner_attach_dtt7520x}, - .fe_config = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1}, - .i2c_access = 1, - }; - - /****************************************************************************/ - -+static struct mt2060_config tuner_python_0 = { -+ .i2c_address = 0x60, -+ .clock_out = 3, -+ .input = 0 -+}; -+ -+static struct mt2060_config tuner_python_1 = { -+ .i2c_address = 0x61, -+ .clock_out = 3, -+ .input = 1 -+}; -+ -+static struct drxd_config fe_python_0 = { -+ .index = 0, -+ .demod_address = 0x71, -+ .demod_revision = 0xb1, -+ .demoda_address = 0x41, -+ .clock = 16000, -+ .osc_deviation = osc_deviation, -+}; -+ -+static struct drxd_config fe_python_1 = { -+ .index = 1, -+ .demod_address = 0x70, -+ .demod_revision = 0xb1, -+ .demoda_address = 0x45, -+ .clock = 16000, -+ .osc_deviation = osc_deviation, -+}; -+ -+static struct ngene_info ngene_info_python = { -+ .type = NGENE_PYTHON, -+ .name = "Micronas MicPython/Hedgehog Dual DVB-T", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, -+ .tuner_attach = {tuner_attach_mt2060, tuner_attach_mt2060}, -+ .fe_config = {&fe_python_0, &fe_python_1}, -+ .tuner_config = {&tuner_python_0, &tuner_python_1}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .demoda = {0x41, 0x45}, -+ .gate_ctrl = python_gate_ctrl, -+ .switch_ctrl = python_switch_ctrl, -+}; -+ -+/****************************************************************************/ -+ -+static struct drxd_config fe_appb_dvbt_0 = { -+ .index = 0, -+ .demod_address = 0x71, -+ .demod_revision = 0xa2, -+ .demoda_address = 0x41, -+ .pll_address = 0x63, -+ .pll_type = DRXD_PLL_MT3X0823, -+ .clock = 20000, -+ .pll_set = ngene_pll_set_mt_3x0823, -+ .osc_deviation = osc_deviation, -+}; -+ -+static struct drxd_config fe_appb_dvbt_1 = { -+ .index = 1, -+ .demod_address = 0x70, -+ .demod_revision = 0xa2, -+ .demoda_address = 0x45, -+ .pll_address = 0x60, -+ .pll_type = DRXD_PLL_MT3X0823, -+ .clock = 20000, -+ .pll_set = ngene_pll_set_mt_3x0823, -+ .osc_deviation = osc_deviation, -+}; -+ -+static struct ngene_info ngene_info_appboard = { -+ .type = NGENE_APP, -+ .name = "Micronas Application Board Dual DVB-T", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, -+ .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, -+ .avf = {0x43, 0x47}, -+}; -+ -+static struct ngene_info ngene_info_appboard_ntsc = { -+ .type = NGENE_APP, -+ .name = "Micronas Application Board Dual DVB-T", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_drxd, demod_attach_drxd}, -+ .fe_config = {&fe_appb_dvbt_0, &fe_appb_dvbt_1}, -+ .avf = {0x43, 0x47}, -+ .ntsc = 1, -+}; -+ -+/****************************************************************************/ -+ -+static struct stb0899_config fe_sidewinder_0 = { -+ .demod_address = 0x68, -+ .pll_address = 0x63, -+}; -+ -+static struct stb0899_config fe_sidewinder_1 = { -+ .demod_address = 0x6b, -+ .pll_address = 0x60, -+}; -+ -+static struct ngene_info ngene_info_sidewinder = { -+ .type = NGENE_SIDEWINDER, -+ .name = "Micronas MicSquirrel/Sidewinder Dual DVB-S2", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_stb0899, demod_attach_stb0899}, -+ .fe_config = {&fe_sidewinder_0, &fe_sidewinder_1}, -+ .lnb = {0x0b, 0x08}, -+}; -+ -+/****************************************************************************/ -+/* Yet unnamed S2 card with dual DVB-S2 demod */ -+/****************************************************************************/ -+ -+static struct stv0900_config fe_s2_0 = { -+ .addr = 0x68, -+ .pll = 0x63, -+ .pll_type = 0, -+ .nr = 0, -+}; -+ -+static struct stv0900_config fe_s2_1 = { -+ .addr = 0x68, -+ .pll = 0x60, -+ .pll_type = 0, -+ .nr = 1, -+}; -+ -+static struct ngene_info ngene_info_s2 = { -+ .type = NGENE_SIDEWINDER, -+ .name = "S2", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, -+ NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, -+ .fe_config = {&fe_s2_0, &fe_s2_1}, -+ .lnb = {0x0b, 0x08}, -+ .tsf = {3, 3}, -+ .fw_version = 15, -+}; -+ -+static struct stv0900_config fe_s2b_0 = { -+ .addr = 0x68, -+ .pll = 0x60, -+ .pll_type = 0x10, -+ .nr = 0, -+}; -+ -+static struct stv0900_config fe_s2b_1 = { -+ .addr = 0x68, -+ .pll = 0x63, -+ .pll_type = 0x10, -+ .nr = 1, -+}; -+ -+static struct ngene_info ngene_info_s2_b = { -+ .type = NGENE_SIDEWINDER, -+ .name = "S2 V2", -+ .io_type = {NGENE_IO_TSIN, NGENE_IO_TSIN, -+ NGENE_IO_TSIN, NGENE_IO_TSIN}, -+ .demod_attach = {demod_attach_stv0900, demod_attach_stv0900}, -+ .fe_config = {&fe_s2b_0, &fe_s2b_1}, -+ .lnb = {0x0b, 0x08}, -+ .tsf = {3, 3}, -+ .fw_version = 17, -+}; -+ -+/****************************************************************************/ -+ -+static struct xc3028_config tuner_viper_0 = { -+ .adr = 0x61, -+ .reset = viper_reset_xc -+}; -+ -+static struct xc3028_config tuner_viper_1 = { -+ .adr = 0x64, -+ .reset = viper_reset_xc -+}; -+ -+static struct drxh_config fe_viper_h_0 = {.adr = 0x2b}; -+ -+static struct drxh_config fe_viper_h_1 = {.adr = 0x29}; -+ -+static struct drxh_config fe_viper_l_0 = {.adr = 0x2b, .type = 3931}; -+ -+static struct drxh_config fe_viper_l_1 = {.adr = 0x29, .type = 3931}; -+ -+static struct ngene_info ngene_info_viper_v1 = { -+ .type = NGENE_VIPER, -+ .name = "Micronas MicViper Dual ATSC DRXH", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, -+ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, -+ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, -+ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .exp = 0x20, -+ .exp_init = 0xf5, -+ .gate_ctrl = viper_gate_ctrl, -+ .switch_ctrl = viper_switch_ctrl, -+ .tsf = {2, 2}, -+}; -+ -+static struct ngene_info ngene_info_viper_v2 = { -+ .type = NGENE_VIPER, -+ .name = "Micronas MicViper Dual ATSC DRXL", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, -+ .fe_config = {&fe_viper_l_0, &fe_viper_l_1}, -+ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, -+ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .exp = 0x38, -+ .exp_init = 0xf5, -+ .gate_ctrl = viper_gate_ctrl, -+ .switch_ctrl = viper_switch_ctrl, -+ .tsf = {2, 2}, -+}; -+ -+/****************************************************************************/ -+ -+static struct ngene_info ngene_info_vbox_v1 = { -+ .type = NGENE_VBOX_V1, -+ .name = "VBox Cat's Eye 164E", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, -+ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, -+ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, -+ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .exp = 0x20, -+ .exp_init = 0xf5, -+ .gate_ctrl = viper_gate_ctrl, -+ .switch_ctrl = viper_switch_ctrl, -+ .tsf = {2, 2}, -+}; -+ -+/****************************************************************************/ -+ -+static struct ngene_info ngene_info_vbox_v2 = { -+ .type = NGENE_VBOX_V2, -+ .name = "VBox Cat's Eye 164E", -+ .io_type = {NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_TSIN | NGENE_IO_TV, -+ NGENE_IO_AIN, NGENE_IO_AIN}, -+ .demod_attach = {demod_attach_drxh, demod_attach_drxh}, -+ .fe_config = {&fe_viper_h_0, &fe_viper_h_1}, -+ .tuner_config = {&tuner_viper_0, &tuner_viper_1}, -+ .tuner_attach = {tuner_attach_xc3028, tuner_attach_xc3028}, -+ .avf = {0x43, 0x47}, -+ .msp = {0x40, 0x42}, -+ .exp = 0x20, -+ .exp_init = 0xf5, -+ .gate_ctrl = viper_gate_ctrl, -+ .switch_ctrl = viper_switch_ctrl2, -+ .tsf = {2, 2}, -+}; -+ -+/****************************************************************************/ -+ -+static struct ngene_info ngene_info_racer = { -+ .type = NGENE_RACER, -+ .name = "Micronas MicRacer HDTV Decoder Card", -+ .io_type = {NGENE_IO_HDTV, NGENE_IO_NONE, -+ NGENE_IO_AIN, NGENE_IO_NONE, -+ NGENE_IO_TSOUT}, -+ .i2s = {0, 0, 1, 0}, -+ .fw_version = 17, -+}; -+#endif - - - /****************************************************************************/ -@@ -753,6 +1072,8 @@ static struct ngene_info ngene_info_terratec = { - /****************************************************************************/ - - static const struct pci_device_id ngene_id_tbl[] = { -+ NGENE_ID(0x18c3, 0xab04, ngene_info_cineS2), -+ NGENE_ID(0x18c3, 0xab05, ngene_info_cineS2v5), - NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2), - NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2), - NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2), -@@ -761,7 +1082,32 @@ static const struct pci_device_id ngene_id_tbl[] = { - NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex), - NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex), - NGENE_ID(0x1461, 0x062e, ngene_info_m780), -+#if 0 /* not (yet?) supported */ -+ NGENE_ID(0x18c3, 0x0000, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x0004, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x8011, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x8015, ngene_info_appboard_ntsc), - NGENE_ID(0x153b, 0x1167, ngene_info_terratec), -+ NGENE_ID(0x18c3, 0x0030, ngene_info_python), -+ NGENE_ID(0x18c3, 0x0052, ngene_info_sidewinder), -+ NGENE_ID(0x18c3, 0x8f00, ngene_info_racer), -+ NGENE_ID(0x18c3, 0x0041, ngene_info_viper_v1), -+ NGENE_ID(0x18c3, 0x0042, ngene_info_viper_v2), -+ NGENE_ID(0x14f3, 0x0041, ngene_info_vbox_v1), -+ NGENE_ID(0x14f3, 0x0043, ngene_info_vbox_v2), -+ NGENE_ID(0x18c3, 0xabcd, ngene_info_s2), -+ NGENE_ID(0x18c3, 0xabc2, ngene_info_s2_b), -+ NGENE_ID(0x18c3, 0xabc3, ngene_info_s2_b), -+ NGENE_ID(0x18c3, 0x0001, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x0005, ngene_info_appboard), -+ NGENE_ID(0x18c3, 0x0009, ngene_info_appboard_atsc), -+ NGENE_ID(0x18c3, 0x000b, ngene_info_appboard_atsc), -+ NGENE_ID(0x18c3, 0x0010, ngene_info_shrek_50_fp), -+ NGENE_ID(0x18c3, 0x0011, ngene_info_shrek_60_fp), -+ NGENE_ID(0x18c3, 0x0012, ngene_info_shrek_50), -+ NGENE_ID(0x18c3, 0x0013, ngene_info_shrek_60), -+ NGENE_ID(0x18c3, 0x0000, ngene_info_hognose), -+#endif - {0} - }; - MODULE_DEVICE_TABLE(pci, ngene_id_tbl); -@@ -798,7 +1144,7 @@ static void ngene_resume(struct pci_dev *dev) - printk(KERN_INFO DEVICE_NAME ": resume\n"); - } - --static const struct pci_error_handlers ngene_errors = { -+static struct pci_error_handlers ngene_errors = { - .error_detected = ngene_error_detected, - .link_reset = ngene_link_reset, - .slot_reset = ngene_slot_reset, -diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c -index 37ebc42..84510db 100644 ---- a/drivers/media/pci/ngene/ngene-core.c -+++ b/drivers/media/pci/ngene/ngene-core.c -@@ -86,6 +86,14 @@ static void event_tasklet(unsigned long data) - if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify)) - dev->RxEventNotify(dev, Event.TimeStamp, - Event.RXCharacter); -+#if 0 -+ if ((Event.GPIOStatus & 0x80) && (dev->Gpio2EventNotify)) -+ dev->Gpio2EventNotify(dev, Event.TimeStamp, -+ Event.GPIOStatus & 0x1f); -+ if ((Event.GPIOStatus & 0x40) && (dev->Gpio3EventNotify)) -+ dev->Gpio3EventNotify(dev, Event.TimeStamp, -+ Event.GPIOStatus & 0x1f); -+#endif - } - } - -@@ -214,6 +222,13 @@ static irqreturn_t irq_handler(int irq, void *dev_id) - u8 nextWriteIndex = - (dev->EventQueueWriteIndex + 1) & - (EVENT_QUEUE_SIZE - 1); -+#if 0 -+ printk(KERN_ERR DEVICE_NAME -+ ": Event interrupt %02x Uart = %02x Gpio = %02x\n", -+ dev->EventBuffer->EventStatus, -+ dev->EventBuffer->UARTStatus, -+ dev->EventBuffer->GPIOStatus); -+#endif - if (nextWriteIndex != dev->EventQueueReadIndex) { - dev->EventQueue[dev->EventQueueWriteIndex] = - *(dev->EventBuffer); -@@ -258,16 +273,22 @@ static void dump_command_io(struct ngene *dev) - u8 buf[8], *b; - - ngcpyfrom(buf, HOST_TO_NGENE, 8); -- printk(KERN_ERR "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf); -+ printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3], -+ buf[4], buf[5], buf[6], buf[7]); - - ngcpyfrom(buf, NGENE_TO_HOST, 8); -- printk(KERN_ERR "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf); -+ printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3], -+ buf[4], buf[5], buf[6], buf[7]); - - b = dev->hosttongene; -- printk(KERN_ERR "dev->hosttongene (%p): %*ph\n", b, 8, b); -+ printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); - - b = dev->ngenetohost; -- printk(KERN_ERR "dev->ngenetohost (%p): %*ph\n", b, 8, b); -+ printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n", -+ b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); - } - - static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) -@@ -316,12 +337,24 @@ static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com) - ngwritel(1, FORCE_INT); - - ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ); -+#if 0 -+ if (ret < 0) -+ return ret; -+ if (!dev->cmd_done) -+ ; -+#endif - if (!ret) { - /*ngwritel(0, FORCE_NMI);*/ - - printk(KERN_ERR DEVICE_NAME - ": Command timeout cmd=%02x prev=%02x\n", - com->cmd.hdr.Opcode, dev->prev_cmd); -+#if 0 -+ printk(KERN_ERR DEVICE_NAME ": Icounts=%08x\n", -+ ngreadl(NGENE_INT_COUNTS)); -+ if (ngreadl(NGENE_INT_COUNTS) == 0xffffffff) -+ ngwritel(0, NGENE_INT_ENABLE); -+#endif - dump_command_io(dev); - return -1; - } -@@ -348,6 +381,19 @@ int ngene_command(struct ngene *dev, struct ngene_command *com) - return result; - } - -+#if 0 -+int ngene_command_nop(struct ngene *dev) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = CMD_NOP; -+ com.cmd.hdr.Length = 0; -+ com.in_len = 0; -+ com.out_len = 0; -+ -+ return ngene_command(dev, &com); -+} -+#endif - - static int ngene_command_load_firmware(struct ngene *dev, - u8 *ngene_fw, u32 size) -@@ -382,6 +428,83 @@ static int ngene_command_load_firmware(struct ngene *dev, - return ngene_command(dev, &com); - } - -+#if 0 -+int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = type ? CMD_SFR_READ : CMD_IRAM_READ; -+ com.cmd.hdr.Length = 1; -+ com.cmd.SfrIramRead.address = adr; -+ com.in_len = 1; -+ com.out_len = 2; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ *data = com.cmd.raw8[1]; -+ return 0; -+} -+ -+int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = type ? CMD_SFR_WRITE : CMD_IRAM_WRITE; -+ com.cmd.hdr.Length = 2; -+ com.cmd.SfrIramWrite.address = adr; -+ com.cmd.SfrIramWrite.data = data; -+ com.in_len = 2; -+ com.out_len = 1; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ return 0; -+} -+ -+static int ngene_command_config_uart(struct ngene *dev, u8 config, -+ tx_cb_t *tx_cb, rx_cb_t *rx_cb) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = CMD_CONFIGURE_UART; -+ com.cmd.hdr.Length = sizeof(struct FW_CONFIGURE_UART) - 2; -+ com.cmd.ConfigureUart.UartControl = config; -+ com.in_len = sizeof(struct FW_CONFIGURE_UART); -+ com.out_len = 0; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ dev->TxEventNotify = tx_cb; -+ dev->RxEventNotify = rx_cb; -+ -+ dprintk(KERN_DEBUG DEVICE_NAME ": Set UART config %02x.\n", config); -+ -+ return 0; -+} -+ -+static void tx_cb(struct ngene *dev, u32 ts) -+{ -+ dev->tx_busy = 0; -+ wake_up_interruptible(&dev->tx_wq); -+} -+ -+static void rx_cb(struct ngene *dev, u32 ts, u8 c) -+{ -+ int rp = dev->uart_rp; -+ int nwp, wp = dev->uart_wp; -+ -+ /* dprintk(KERN_DEBUG DEVICE_NAME ": %c\n", c); */ -+ nwp = (wp + 1) % (UART_RBUF_LEN); -+ if (nwp == rp) -+ return; -+ dev->uart_rbuf[wp] = c; -+ dev->uart_wp = nwp; -+ wake_up_interruptible(&dev->rx_wq); -+} -+#endif - - static int ngene_command_config_buf(struct ngene *dev, u8 config) - { -@@ -427,6 +550,18 @@ int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level) - return ngene_command(dev, &com); - } - -+#if 0 -+/* The reset is only wired to GPIO4 on MicRacer Revision 1.10 ! -+ Also better set bootdelay to 1 in nvram or less. */ -+static void ngene_reset_decypher(struct ngene *dev) -+{ -+ printk(KERN_INFO DEVICE_NAME ": Resetting Decypher.\n"); -+ ngene_command_gpio_set(dev, 4, 0); -+ msleep(1); -+ ngene_command_gpio_set(dev, 4, 1); -+ msleep(2000); -+} -+#endif - - /* - 02000640 is sample on rising edge. -@@ -512,6 +647,17 @@ void FillTSBuffer(void *Buffer, int Length, u32 Flags) - } - } - -+#if 0 -+static void clear_tsin(struct ngene_channel *chan) -+{ -+ struct SBufferHeader *Cur = chan->nextBuffer; -+ -+ do { -+ memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR)); -+ Cur = Cur->Next; -+ } while (Cur != chan->nextBuffer); -+} -+#endif - - static void flush_buffers(struct ngene_channel *chan) - { -@@ -732,6 +878,14 @@ void set_transfer(struct ngene_channel *chan, int state) - if (dev->card_info->switch_ctrl) - dev->card_info->switch_ctrl(chan, 1, state ^ 1); - -+#if 0 -+ /* Disable AVF output if present. */ -+ if (dev->card_info->avf[chan->number]) -+ i2c_write_register(&chan->i2c_adapter, -+ chan->dev->card_info->avf[chan->number], -+ 0xf2, state ? 0x80 : 0x89); -+ -+#endif - if (state) { - spin_lock_irq(&chan->state_lock); - -@@ -752,8 +906,8 @@ void set_transfer(struct ngene_channel *chan, int state) - if (chan->mode & NGENE_IO_TSIN) - chan->pBufferExchange = tsin_exchange; - spin_unlock_irq(&chan->state_lock); -- } -- /* else printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", -+ } else -+ ;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", - ngreadl(0x9310)); */ - - ret = ngene_command_stream_control(dev, chan->number, -@@ -771,6 +925,89 @@ void set_transfer(struct ngene_channel *chan, int state) - } - } - -+#if 0 -+/****************************************************************************/ -+/* Decypher firmware loading ************************************************/ -+/****************************************************************************/ -+ -+#define DECYPHER_FW "decypher.fw" -+ -+static int dec_ts_send(struct ngene *dev, u8 *buf, u32 len) -+{ -+#if 0 -+ if (wait_event_interruptible(dev->tsout_rbuf.queue, -+ dvb_ringbuffer_free -+ (&dev->tsout_rbuf) >= len) < 0) -+ return 0; -+#else -+ while (dvb_ringbuffer_free(&dev->tsout_rbuf) < len) -+ msleep(1); -+ -+#endif -+ -+ dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len); -+ -+ return len; -+} -+ -+u8 dec_fw_fill_ts[188] = { 0x47, 0x09, 0x0e, 0x10, 0xff, 0xff, 0x00, 0x00 }; -+ -+int dec_fw_send(struct ngene *dev, u8 *fw, u32 size) -+{ -+ struct ngene_channel *chan = &dev->channel[4]; -+ u32 len = 180, cc = 0; -+ u8 buf[8] = { 0x47, 0x09, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00 }; -+ -+ set_transfer(chan, 1); -+ msleep(100); -+ while (size) { -+ len = 180; -+ if (len > size) -+ len = size; -+ buf[3] = 0x10 | (cc & 0x0f); -+ buf[4] = (cc >> 8); -+ buf[5] = cc & 0xff; -+ buf[6] = len; -+ -+ dec_ts_send(dev, buf, 8); -+ dec_ts_send(dev, fw, len); -+ if (len < 180) -+ dec_ts_send(dev, dec_fw_fill_ts + len + 8, 180 - len); -+ cc++; -+ size -= len; -+ fw += len; -+ } -+ for (len = 0; len < 512; len++) -+ dec_ts_send(dev, dec_fw_fill_ts, 188); -+ while (dvb_ringbuffer_avail(&dev->tsout_rbuf)) -+ msleep(10); -+ msleep(100); -+ set_transfer(chan, 0); -+ return 0; -+} -+ -+int dec_fw_boot(struct ngene *dev) -+{ -+ u32 size; -+ const struct firmware *fw = NULL; -+ u8 *dec_fw; -+ -+ if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) { -+ printk(KERN_ERR DEVICE_NAME -+ ": %s not found. Check hotplug directory.\n", -+ DECYPHER_FW); -+ return -1; -+ } -+ printk(KERN_INFO DEVICE_NAME ": Booting decypher firmware file %s\n", -+ DECYPHER_FW); -+ -+ size = fw->size; -+ dec_fw = (u8 *)fw->data; -+ dec_fw_send(dev, dec_fw, size); -+ release_firmware(fw); -+ return 0; -+} -+#endif - - /****************************************************************************/ - /* nGene hardware init and release functions ********************************/ -@@ -1065,6 +1302,85 @@ static u32 Buffer2Sizes[MAX_STREAM] = { - 0 - }; - -+#if 0 -+static int allocate_buffer(struct pci_dev *pci_dev, dma_addr_t of, -+ struct SRingBufferDescriptor *rbuf, -+ u32 entries, u32 size1, u32 size2) -+{ -+ if (create_ring_buffer(pci_dev, rbuf, entries) < 0) -+ return -ENOMEM; -+ -+ if (AllocateRingBuffers(pci_dev, of, rbuf, size1, size2) < 0) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static int channel_allocate_buffers(struct ngene_channel *chan) -+{ -+ struct ngene *dev = chan->dev; -+ int type = dev->card_info->io_type[chan->number]; -+ int status; -+ -+ chan->State = KSSTATE_STOP; -+ -+ if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) { -+ status = create_ring_buffer(dev->pci_dev, -+ &chan->RingBuffer, -+ RingBufferSizes[chan->number]); -+ if (status < 0) -+ return -ENOMEM; -+ -+ if (type & (NGENE_IO_TV | NGENE_IO_AIN)) { -+ status = AllocateRingBuffers(dev->pci_dev, -+ dev->PAOverflowBuffer, -+ &chan->RingBuffer, -+ Buffer1Sizes[chan->number], -+ Buffer2Sizes[chan-> -+ number]); -+ if (status < 0) -+ return -ENOMEM; -+ } else if (type & NGENE_IO_HDTV) { -+ status = AllocateRingBuffers(dev->pci_dev, -+ dev->PAOverflowBuffer, -+ &chan->RingBuffer, -+ MAX_HDTV_BUFFER_SIZE, 0); -+ if (status < 0) -+ return -ENOMEM; -+ } -+ } -+ -+ if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) { -+ -+ status = create_ring_buffer(dev->pci_dev, -+ &chan->TSRingBuffer, RING_SIZE_TS); -+ if (status < 0) -+ return -ENOMEM; -+ -+ status = AllocateRingBuffers(dev->pci_dev, -+ dev->PAOverflowBuffer, -+ &chan->TSRingBuffer, -+ MAX_TS_BUFFER_SIZE, 0); -+ if (status) -+ return -ENOMEM; -+ } -+ -+ if (type & NGENE_IO_TSOUT) { -+ status = create_ring_buffer(dev->pci_dev, -+ &chan->TSIdleBuffer, 1); -+ if (status < 0) -+ return -ENOMEM; -+ status = AllocateRingBuffers(dev->pci_dev, -+ dev->PAOverflowBuffer, -+ &chan->TSIdleBuffer, -+ MAX_TS_BUFFER_SIZE, 0); -+ if (status) -+ return -ENOMEM; -+ FillTSIdleBuffer(&chan->TSIdleBuffer, &chan->TSRingBuffer); -+ } -+ return 0; -+} -+#endif - - static int AllocCommonBuffers(struct ngene *dev) - { -@@ -1318,6 +1634,10 @@ static int ngene_buffer_config(struct ngene *dev) - u8 tsin12_config[6] = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 }; - u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 }; - u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 }; -+#if 0 -+ u8 tsin34_config[6] = { 0x00, 0x00, 0x00, 0x60, 0x60, 0x00 }; -+ u8 tsio35_config[6] = { 0x00, 0x00, 0x00, 0x60, 0x00, 0x60 }; -+#endif - u8 *bconf = tsin12_config; - - if (dev->card_info->io_type[2]&NGENE_IO_TSIN && -@@ -1327,10 +1647,22 @@ static int ngene_buffer_config(struct ngene *dev) - dev->ci.en) - bconf = tsio1235_config; - } -+#if 0 -+ if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { -+ bconf = hdtv_config; -+ ngene_reset_decypher(dev); -+ } -+#endif - stat = ngene_command_config_free_buf(dev, bconf); - } else { - int bconf = BUFFER_CONFIG_4422; - -+#if 0 -+ if (dev->card_info->io_type[0] == NGENE_IO_HDTV) { -+ bconf = BUFFER_CONFIG_8022; -+ ngene_reset_decypher(dev); -+ } -+#endif - if (dev->card_info->io_type[3] == NGENE_IO_TSIN) - bconf = BUFFER_CONFIG_3333; - stat = ngene_command_config_buf(dev, bconf); -@@ -1403,8 +1735,10 @@ static int ngene_start(struct ngene *dev) - if (stat < 0) - goto fail; - -- return 0; -+ if (!stat) -+ return stat; - -+ /* otherwise error: fall through */ - fail: - ngwritel(0, NGENE_INT_ENABLE); - free_irq(dev->pci_dev->irq, dev); -@@ -1688,10 +2022,36 @@ int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) - - - dev->i2c_current_bus = -1; -+#if 0 -+ exp_init(dev); -+ -+ /* Disable analog TV decoder chips if present */ -+ if (dev->card_info->msp[0]) -+ i2c_write_msp_register(&dev->channel[0].i2c_adapter, -+ dev->card_info->msp[0], 0x00, 0x0000); -+ if (dev->card_info->msp[1]) -+ i2c_write_msp_register(&dev->channel[1].i2c_adapter, -+ dev->card_info->msp[1], 0x00, 0x0000); -+ { -+ u16 data; -+ read_msp(&dev->channel[0].i2c_adapter, -+ dev->card_info->msp[0], 0x00, &data); -+ } -+ if (dev->card_info->avf[0]) -+ i2c_write_register(&dev->channel[0].i2c_adapter, -+ dev->card_info->avf[0], 0xf2, 0x80); -+ if (dev->card_info->avf[1]) -+ i2c_write_register(&dev->channel[1].i2c_adapter, -+ dev->card_info->avf[1], 0xf2, 0x80); -+ if (copy_eeprom) { -+ i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52); -+ i2c_dump_eeprom(&dev->channel[0].i2c_adapter, 0x52); -+ } -+ /*i2c_check_eeprom(&dev->i2c_adapter);*/ -+#endif - - /* Register DVB adapters and devices for both channels */ -- stat = init_channels(dev); -- if (stat < 0) -+ if (init_channels(dev) < 0) - goto fail2; - - return 0; -diff --git a/drivers/media/pci/ngene/ngene-dvb.c b/drivers/media/pci/ngene/ngene-dvb.c -index fcb16a6..8049e2b 100644 ---- a/drivers/media/pci/ngene/ngene-dvb.c -+++ b/drivers/media/pci/ngene/ngene-dvb.c -@@ -42,10 +42,319 @@ - - #include "ngene.h" - -+#if 0 -+int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, -+ u16 lines, u16 bpl, u16 vblines, u16 vbibpl) -+{ -+ if (!(mode & SMODE_TRANSPORT_STREAM)) -+ return -EINVAL; -+ -+ if (lines * bpl > MAX_VIDEO_BUFFER_SIZE) -+ return -EINVAL; -+ -+ if ((mode & SMODE_TRANSPORT_STREAM) && (((bpl * lines) & 0xff) != 0)) -+ return -EINVAL; -+ -+ if ((mode & SMODE_VIDEO_CAPTURE) && (bpl & 7) != 0) -+ return -EINVAL; -+ -+ return ngene_command_stream_control(dev, stream, control, mode, 0); -+} -+#endif - - /****************************************************************************/ - /* COMMAND API interface ****************************************************/ - /****************************************************************************/ -+#if 0 -+ -+static int command_do_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, void *parg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int err = 0; -+ -+ switch (cmd) { -+ case IOCTL_MIC_NO_OP: -+ err = ngene_command_nop(dev); -+ break; -+ -+ case IOCTL_MIC_DOWNLOAD_FIRMWARE: -+ break; -+ -+ case IOCTL_MIC_I2C_READ: -+ { -+ MIC_I2C_READ *msg = parg; -+ -+ err = ngene_command_i2c_read(dev, msg->I2CAddress >> 1, -+ msg->OutData, msg->OutLength, -+ msg->OutData, msg->InLength, 1); -+ break; -+ } -+ -+ case IOCTL_MIC_I2C_WRITE: -+ { -+ MIC_I2C_WRITE *msg = parg; -+ -+ err = ngene_command_i2c_write(dev, msg->I2CAddress >> 1, -+ msg->Data, msg->Length); -+ break; -+ } -+ -+ case IOCTL_MIC_TEST_GETMEM: -+ { -+ MIC_MEM *m = parg; -+ -+ if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) -+ return -EINVAL; -+ -+ /* WARNING, only use this on x86, -+ other archs may not swallow this */ -+ err = copy_to_user(m->Data, dev->iomem + m->Start, m->Length); -+ break; -+ } -+ -+ case IOCTL_MIC_TEST_SETMEM: -+ { -+ MIC_MEM *m = parg; -+ -+ if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024) -+ return -EINVAL; -+ -+ err = copy_from_user(dev->iomem + m->Start, m->Data, m->Length); -+ break; -+ } -+ -+ case IOCTL_MIC_SFR_READ: -+ { -+ MIC_IMEM *m = parg; -+ -+ err = ngene_command_imem_read(dev, m->Address, &m->Data, 1); -+ break; -+ } -+ -+ case IOCTL_MIC_SFR_WRITE: -+ { -+ MIC_IMEM *m = parg; -+ -+ err = ngene_command_imem_write(dev, m->Address, m->Data, 1); -+ break; -+ } -+ -+ case IOCTL_MIC_IRAM_READ: -+ { -+ MIC_IMEM *m = parg; -+ -+ err = ngene_command_imem_read(dev, m->Address, &m->Data, 0); -+ break; -+ } -+ -+ case IOCTL_MIC_IRAM_WRITE: -+ { -+ MIC_IMEM *m = parg; -+ -+ err = ngene_command_imem_write(dev, m->Address, m->Data, 0); -+ break; -+ } -+ -+ case IOCTL_MIC_STREAM_CONTROL: -+ { -+ MIC_STREAM_CONTROL *m = parg; -+ -+ err = ngene_stream_control(dev, m->Stream, m->Control, m->Mode, -+ m->nLines, m->nBytesPerLine, -+ m->nVBILines, m->nBytesPerVBILine); -+ break; -+ } -+ -+ default: -+ err = -EINVAL; -+ break; -+ } -+ return err; -+} -+ -+static int command_ioctl(struct inode *inode, struct file *file, -+ unsigned int cmd, unsigned long arg) -+{ -+ void *parg = (void *)arg, *pbuf = NULL; -+ char buf[64]; -+ int res = -EFAULT; -+ -+ if (_IOC_DIR(cmd) & _IOC_WRITE) { -+ parg = buf; -+ if (_IOC_SIZE(cmd) > sizeof(buf)) { -+ pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); -+ if (!pbuf) -+ return -ENOMEM; -+ parg = pbuf; -+ } -+ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) -+ goto error; -+ } -+ res = command_do_ioctl(inode, file, cmd, parg); -+ if (res < 0) -+ goto error; -+ if (_IOC_DIR(cmd) & _IOC_READ) -+ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) -+ res = -EFAULT; -+error: -+ kfree(pbuf); -+ return res; -+} -+ -+struct page *ngene_nopage(struct vm_area_struct *vma, -+ unsigned long address, int *type) -+{ -+ return 0; -+} -+ -+static int ngene_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ -+ unsigned long size = vma->vm_end - vma->vm_start; -+ unsigned long off = vma->vm_pgoff << PAGE_SHIFT; -+ unsigned long padr = pci_resource_start(dev->pci_dev, 0) + off; -+ unsigned long psize = pci_resource_len(dev->pci_dev, 0) - off; -+ -+ if (size > psize) -+ return -EINVAL; -+ -+ if (io_remap_pfn_range(vma, vma->vm_start, padr >> PAGE_SHIFT, size, -+ vma->vm_page_prot)) -+ return -EAGAIN; -+ return 0; -+} -+ -+ -+static int write_uart(struct ngene *dev, u8 *data, int len) -+{ -+ struct ngene_command com; -+ -+ com.cmd.hdr.Opcode = CMD_WRITE_UART; -+ com.cmd.hdr.Length = len; -+ memcpy(com.cmd.WriteUart.Data, data, len); -+ com.cmd.WriteUart.Data[len] = 0; -+ com.cmd.WriteUart.Data[len + 1] = 0; -+ com.in_len = len; -+ com.out_len = 0; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ return 0; -+} -+ -+static int send_cli(struct ngene *dev, char *cmd) -+{ -+ /* printk(KERN_INFO DEVICE_NAME ": %s", cmd); */ -+ return write_uart(dev, cmd, strlen(cmd)); -+} -+ -+static int send_cli_val(struct ngene *dev, char *cmd, u32 val) -+{ -+ char s[32]; -+ -+ snprintf(s, 32, "%s %d\n", cmd, val); -+ /* printk(KERN_INFO DEVICE_NAME ": %s", s); */ -+ return write_uart(dev, s, strlen(s)); -+} -+ -+static int ngene_command_write_uart_user(struct ngene *dev, -+ const u8 *data, int len) -+{ -+ struct ngene_command com; -+ -+ dev->tx_busy = 1; -+ com.cmd.hdr.Opcode = CMD_WRITE_UART; -+ com.cmd.hdr.Length = len; -+ -+ if (copy_from_user(com.cmd.WriteUart.Data, data, len)) -+ return -EFAULT; -+ com.in_len = len; -+ com.out_len = 0; -+ -+ if (ngene_command(dev, &com) < 0) -+ return -EIO; -+ -+ return 0; -+} -+ -+static ssize_t uart_write(struct file *file, const char *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int len, ret = 0; -+ size_t left = count; -+ -+ while (left) { -+ len = left; -+ if (len > 250) -+ len = 250; -+ ret = wait_event_interruptible(dev->tx_wq, dev->tx_busy == 0); -+ if (ret < 0) -+ return ret; -+ ngene_command_write_uart_user(dev, buf, len); -+ left -= len; -+ buf += len; -+ } -+ return count; -+} -+ -+static ssize_t uart_read(struct file *file, char *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct ngene_channel *chan = dvbdev->priv; -+ struct ngene *dev = chan->dev; -+ int left; -+ int wp, rp, avail, len; -+ -+ if (!dev->uart_rbuf) -+ return -EINVAL; -+ if (count > 128) -+ count = 128; -+ left = count; -+ while (left) { -+ if (wait_event_interruptible(dev->rx_wq, -+ dev->uart_wp != dev->uart_rp) < 0) -+ return -EAGAIN; -+ wp = dev->uart_wp; -+ rp = dev->uart_rp; -+ avail = (wp - rp); -+ -+ if (avail < 0) -+ avail += UART_RBUF_LEN; -+ if (avail > left) -+ avail = left; -+ if (wp < rp) { -+ len = UART_RBUF_LEN - rp; -+ if (len > avail) -+ len = avail; -+ if (copy_to_user(buf, dev->uart_rbuf + rp, len)) -+ return -EFAULT; -+ if (len < avail) -+ if (copy_to_user(buf + len, dev->uart_rbuf, -+ avail - len)) -+ return -EFAULT; -+ } else { -+ if (copy_to_user(buf, dev->uart_rbuf + rp, avail)) -+ return -EFAULT; -+ } -+ dev->uart_rp = (rp + avail) % UART_RBUF_LEN; -+ left -= avail; -+ buf += avail; -+ } -+ return count; -+} -+ -+#endif - - static ssize_t ts_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -@@ -133,6 +442,11 @@ void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) - struct ngene_channel *chan = priv; - struct ngene *dev = chan->dev; - -+#if 0 -+ printk(KERN_INFO DEVICE_NAME ": tsin %08x %02x %02x %02x %02x\n", -+ len, ((u8 *) buf)[512 * 188], ((u8 *) buf)[0], -+ ((u8 *) buf)[1], ((u8 *) buf)[2]); -+#endif - - if (flags & DF_SWAP32) - swap_buffer(buf, len); -@@ -191,12 +505,49 @@ void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) - return buf; - } - -+#if 0 -+static void set_dto(struct ngene_channel *chan, u32 rate) -+{ -+ u64 val = rate * 0x89705f41ULL; /* times val for 2^26 Hz */ -+ -+ val = ((val >> 25) + 1) >> 1; -+ chan->AudioDTOValue = (u32) val; -+ /* chan->AudioDTOUpdated=1; */ -+ /* printk(KERN_INFO DEVICE_NAME ": Setting DTO to %08x\n", val); */ -+} -+#endif - - - int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) - { - struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct ngene_channel *chan = dvbdmx->priv; -+#if 0 -+ struct ngene *dev = chan->dev; -+ -+ if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { -+ switch (dvbdmxfeed->pes_type) { -+ case DMX_TS_PES_VIDEO: -+ send_cli_val(dev, "vpid", dvbdmxfeed->pid); -+ send_cli(dev, "res 1080i50\n"); -+ /* send_cli(dev, "vdec mpeg2\n"); */ -+ break; -+ -+ case DMX_TS_PES_AUDIO: -+ send_cli_val(dev, "apid", dvbdmxfeed->pid); -+ send_cli(dev, "start\n"); -+ break; -+ -+ case DMX_TS_PES_PCR: -+ send_cli_val(dev, "pcrpid", dvbdmxfeed->pid); -+ break; -+ -+ default: -+ break; -+ } -+ -+ } -+#endif - - if (chan->users == 0) { - if (!chan->dev->cmd_timeout_workaround || !chan->running) -@@ -210,6 +561,27 @@ int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) - { - struct dvb_demux *dvbdmx = dvbdmxfeed->demux; - struct ngene_channel *chan = dvbdmx->priv; -+#if 0 -+ struct ngene *dev = chan->dev; -+ -+ if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) { -+ switch (dvbdmxfeed->pes_type) { -+ case DMX_TS_PES_VIDEO: -+ send_cli(dev, "stop\n"); -+ break; -+ -+ case DMX_TS_PES_AUDIO: -+ break; -+ -+ case DMX_TS_PES_PCR: -+ break; -+ -+ default: -+ break; -+ } -+ -+ } -+#endif - - if (--chan->users) - return chan->users; -diff --git a/drivers/media/pci/ngene/ngene-eeprom.c b/drivers/media/pci/ngene/ngene-eeprom.c -new file mode 100644 -index 0000000..281d9f9 ---- /dev/null -+++ b/drivers/media/pci/ngene/ngene-eeprom.c -@@ -0,0 +1,284 @@ -+/* -+ * ngene-eeprom.c: nGene PCIe bridge driver - eeprom support -+ * -+ * Copyright (C) 2005-2007 Micronas -+ * -+ * Copyright (C) 2008-2009 Ralph Metzler -+ * Modifications for new nGene firmware, -+ * support for EEPROM-copying, -+ * support for new dual DVB-S2 card prototype -+ * -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * version 2 only, as published by the Free Software Foundation. -+ * -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ */ -+ -+#if 0 -+static int copy_eeprom; -+module_param(copy_eeprom, int, 0444); -+MODULE_PARM_DESC(copy_eeprom, "Copy eeprom."); -+ -+#define MICNG_EE_START 0x0100 -+#define MICNG_EE_END 0x0FF0 -+ -+#define MICNG_EETAG_END0 0x0000 -+#define MICNG_EETAG_END1 0xFFFF -+ -+/* 0x0001 - 0x000F reserved for housekeeping */ -+/* 0xFFFF - 0xFFFE reserved for housekeeping */ -+ -+/* Micronas assigned tags -+ EEProm tags for hardware support */ -+ -+#define MICNG_EETAG_DRXD1_OSCDEVIATION 0x1000 /* 2 Bytes data */ -+#define MICNG_EETAG_DRXD2_OSCDEVIATION 0x1001 /* 2 Bytes data */ -+ -+#define MICNG_EETAG_MT2060_1_1STIF 0x1100 /* 2 Bytes data */ -+#define MICNG_EETAG_MT2060_2_1STIF 0x1101 /* 2 Bytes data */ -+ -+/* Tag range for OEMs */ -+ -+#define MICNG_EETAG_OEM_FIRST 0xC000 -+#define MICNG_EETAG_OEM_LAST 0xFFEF -+ -+static int i2c_write_eeprom(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 data) -+{ -+ u8 m[3] = {(reg >> 8), (reg & 0xff), data}; -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, -+ .len = sizeof(m)}; -+ -+ if (i2c_transfer(adapter, &msg, 1) != 1) { -+ dprintk(KERN_ERR DEVICE_NAME ": Error writing EEPROM!\n"); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static int i2c_read_eeprom(struct i2c_adapter *adapter, -+ u8 adr, u16 reg, u8 *data, int len) -+{ -+ u8 msg[2] = {(reg >> 8), (reg & 0xff)}; -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = msg, .len = 2 }, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = data, .len = len} }; -+ -+ if (i2c_transfer(adapter, msgs, 2) != 2) { -+ dprintk(KERN_ERR DEVICE_NAME ": Error reading EEPROM\n"); -+ return -EIO; -+ } -+ return 0; -+} -+ -+static int ReadEEProm(struct i2c_adapter *adapter, -+ u16 Tag, u32 MaxLen, u8 *data, u32 *pLength) -+{ -+ int status = 0; -+ u16 Addr = MICNG_EE_START, Length, tag = 0; -+ u8 EETag[3]; -+ -+ while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { -+ if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) -+ return -1; -+ tag = (EETag[0] << 8) | EETag[1]; -+ if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) -+ return -1; -+ if (tag == Tag) -+ break; -+ Addr += sizeof(u16) + 1 + EETag[2]; -+ } -+ if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Reached EOEE @ Tag = %04x Length = %3d\n", -+ tag, EETag[2]); -+ return -1; -+ } -+ Length = EETag[2]; -+ if (Length > MaxLen) -+ Length = (u16) MaxLen; -+ if (Length > 0) { -+ Addr += sizeof(u16) + 1; -+ status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length); -+ if (!status) { -+ *pLength = EETag[2]; -+ if (Length < EETag[2]) -+ ; /*status=STATUS_BUFFER_OVERFLOW; */ -+ } -+ } -+ return status; -+} -+ -+static int WriteEEProm(struct i2c_adapter *adapter, -+ u16 Tag, u32 Length, u8 *data) -+{ -+ int status = 0; -+ u16 Addr = MICNG_EE_START; -+ u8 EETag[3]; -+ u16 tag = 0; -+ int retry, i; -+ -+ while (Addr + sizeof(u16) + 1 < MICNG_EE_END) { -+ if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag))) -+ return -1; -+ tag = (EETag[0] << 8) | EETag[1]; -+ if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1) -+ return -1; -+ if (tag == Tag) -+ break; -+ Addr += sizeof(u16) + 1 + EETag[2]; -+ } -+ if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Reached EOEE @ Tag = %04x Length = %3d\n", -+ tag, EETag[2]); -+ return -1; -+ } -+ -+ if (Length > EETag[2]) -+ return -EINVAL; -+ /* Note: We write the data one byte at a time to avoid -+ issues with page sizes. (which are different for -+ each manufacture and eeprom size) -+ */ -+ Addr += sizeof(u16) + 1; -+ for (i = 0; i < Length; i++, Addr++) { -+ status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]); -+ -+ if (status) -+ break; -+ -+ /* Poll for finishing write cycle */ -+ retry = 10; -+ while (retry) { -+ u8 Tmp; -+ -+ msleep(50); -+ status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1); -+ if (status) -+ break; -+ if (Tmp != data[i]) -+ printk(KERN_ERR DEVICE_NAME -+ "eeprom write error\n"); -+ retry -= 1; -+ } -+ if (status) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Timeout polling eeprom\n"); -+ break; -+ } -+ } -+ return status; -+} -+ -+static void i2c_init_eeprom(struct i2c_adapter *adapter) -+{ -+ u8 tags[] = {0x10, 0x00, 0x02, 0x00, 0x00, -+ 0x10, 0x01, 0x02, 0x00, 0x00, -+ 0x00, 0x00, 0x00}; -+ -+ int i; -+ -+ for (i = 0; i < sizeof(tags); i++) -+ i2c_write_eeprom(adapter, 0x50, 0x0100 + i, tags[i]); -+} -+ -+int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data) -+{ -+ int stat; -+ u8 buf[2]; -+ u32 len = 0; -+ -+ stat = ReadEEProm(adapter, tag, 2, buf, &len); -+ if (stat) -+ return stat; -+ if (len != 2) -+ return -EINVAL; -+ -+ *data = (buf[0] << 8) | buf[1]; -+ return 0; -+} -+ -+static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data) -+{ -+ int stat; -+ u8 buf[2]; -+ -+ buf[0] = data >> 8; -+ buf[1] = data & 0xff; -+ stat = WriteEEProm(adapter, tag, 2, buf); -+ if (stat) -+ return stat; -+ return 0; -+} -+ -+int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr) -+{ -+ u8 buf[64]; -+ int i; -+ -+ if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { -+ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); -+ return -1; -+ } -+ for (i = 0; i < sizeof(buf); i++) { -+ if (!(i & 15)) -+ printk(KERN_DEBUG "\n"); -+ printk(KERN_DEBUG "%02x ", buf[i]); -+ } -+ printk("\n"); -+ -+ return 0; -+} -+ -+int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2) -+{ -+ u8 buf[64]; -+ int i; -+ -+ if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) { -+ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); -+ return -1; -+ } -+ buf[36] = 0xc3; -+ buf[39] = 0xab; -+ for (i = 0; i < sizeof(buf); i++) { -+ i2c_write_eeprom(adapter, adr2, i, buf[i]); -+ msleep(10); -+ } -+ return 0; -+} -+ -+int i2c_check_eeprom(struct i2c_adapter *adapter) -+{ -+ u8 buf[13]; -+ -+ i2c_dump_eeprom(adapter); -+ -+ if (i2c_read_eeprom(adapter, 0x50, 0x0100, buf, sizeof(buf))) { -+ printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n"); -+ return -1; -+ } -+ if (buf[0] != 0x10 || buf[1] != 0x00) { -+ printk(KERN_INFO DEVICE_NAME -+ ": Initializing EEPROM TAG area\n"); -+ i2c_init_eeprom(adapter); -+ } -+ return 0; -+} -+ -+#endif -diff --git a/drivers/media/pci/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c -index d28554f..601bea4 100644 ---- a/drivers/media/pci/ngene/ngene-i2c.c -+++ b/drivers/media/pci/ngene/ngene-i2c.c -@@ -77,6 +77,11 @@ static int ngene_command_i2c_write(struct ngene *dev, u8 adr, - { - struct ngene_command com; - -+#if 0 -+ /* Probing by writing 0 bytes does not work */ -+ if (!outlen) -+ outlen++; -+#endif - - com.cmd.hdr.Opcode = CMD_I2C_WRITE; - com.cmd.hdr.Length = outlen + 1; -@@ -148,6 +153,39 @@ done: - return num; - } - -+#if 0 -+static int ngene_i2c_algo_control(struct i2c_adapter *adap, -+ unsigned int cmd, unsigned long arg) -+{ -+ struct ngene_channel *chan = -+ (struct ngene_channel *)i2c_get_adapdata(adap); -+ -+ switch (cmd) { -+ case IOCTL_MIC_TUN_RDY: -+ chan->tun_rdy = 1; -+ if (chan->dec_rdy == 1) -+ chan->tun_dec_rdy = 1; -+ break; -+ -+ case IOCTL_MIC_DEC_RDY: -+ chan->dec_rdy = 1; -+ if (chan->tun_rdy == 1) -+ chan->tun_dec_rdy = 1; -+ break; -+ -+ case IOCTL_MIC_TUN_DETECT: -+ { -+ int *palorbtsc = (int *)arg; -+ *palorbtsc = chan->dev->card_info->ntsc; -+ break; -+ } -+ -+ default: -+ break; -+ } -+ return 0; -+} -+#endif - - static u32 ngene_i2c_functionality(struct i2c_adapter *adap) - { -@@ -174,3 +212,78 @@ int ngene_i2c_init(struct ngene *dev, int dev_nr) - return i2c_add_adapter(adap); - } - -+#if 0 -+int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data) -+{ -+ u8 m[1] = {data}; -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 1}; -+ -+ if (i2c_transfer(adapter, &msg, 1) != 1) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Failed to write to I2C adr %02x!\n", adr); -+ return -1; -+ } -+ return 0; -+} -+ -+static int i2c_write_register(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u8 data) -+{ -+ u8 m[2] = {reg, data}; -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; -+ -+ if (i2c_transfer(adapter, &msg, 1) != 1) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Failed to write to I2C register %02x@%02x!\n", -+ reg, adr); -+ return -1; -+ } -+ return 0; -+} -+ -+static int i2c_write_read(struct i2c_adapter *adapter, -+ u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen) -+{ -+ struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, -+ .buf = w, .len = wlen}, -+ {.addr = adr, .flags = I2C_M_RD, -+ .buf = r, .len = rlen} }; -+ -+ if (i2c_transfer(adapter, msgs, 2) != 2) { -+ printk(KERN_ERR DEVICE_NAME ": error in i2c_write_read\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int test_dec_i2c(struct i2c_adapter *adapter, int reg) -+{ -+ u8 data[256] = { reg, 0x00, 0x93, 0x78, 0x43, 0x45 }; -+ u8 data2[256]; -+ int i; -+ -+ memset(data2, 0, 256); -+ i2c_write_read(adapter, 0x66, data, 2, data2, 4); -+ for (i = 0; i < 4; i++) -+ printk(KERN_DEBUG "%02x ", data2[i]); -+ printk(KERN_DEBUG "\n"); -+ -+ return 0; -+} -+ -+static int i2c_write_msp_register(struct i2c_adapter *adapter, -+ u8 adr, u8 reg, u16 data) -+{ -+ u8 m[3] = {reg, (data >> 8) & 0xff, data & 0xff}; -+ struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 3 }; -+ -+ if (i2c_transfer(adapter, &msg, 1) != 1) { -+ printk(KERN_ERR DEVICE_NAME -+ ": Failed to write to I2C register %02x@%02x!\n", -+ reg, adr); -+ return -1; -+ } -+ return 0; -+} -+ -+#endif -diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h -index 22c39ff..e3ae00c 100644 ---- a/drivers/media/pci/ngene/ngene.h -+++ b/drivers/media/pci/ngene/ngene.h -@@ -653,6 +653,11 @@ struct ngene_channel { - struct dmx_frontend mem_frontend; - int users; - struct video_device *v4l_dev; -+#if 0 -+ struct dvb_device *command_dev; -+ struct dvb_device *audio_dev; -+ struct dvb_device *video_dev; -+#endif - struct dvb_device *ci_dev; - struct tasklet_struct demux_tasklet; - -@@ -691,6 +696,9 @@ struct ngene_channel { - struct mychip *mychip; - struct snd_card *soundcard; - u8 *evenbuffer; -+#if 0 -+ u8 *soundbuffer; -+#endif - u8 dma_on; - int soundstreamon; - int audiomute; -@@ -849,6 +857,10 @@ struct ngene_info { - u8 lnb[4]; - int i2c_access; - u8 ntsc; -+#if 0 -+ u8 exp; -+ u8 exp_init; -+#endif - u8 tsf[4]; - u8 i2s[4]; - -@@ -885,6 +897,25 @@ struct ngene_buffer { - }; - #endif - -+#if 0 -+int ngene_command_stream_control(struct ngene *dev, -+ u8 stream, u8 control, u8 mode, u8 flags); -+int ngene_command_nop(struct ngene *dev); -+int ngene_command_i2c_read(struct ngene *dev, u8 adr, -+ u8 *out, u8 outlen, u8 *in, u8 inlen, int flag); -+int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen); -+int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type); -+int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type); -+int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode, -+ u16 lines, u16 bpl, u16 vblines, u16 vbibpl); -+ -+int ngene_v4l2_init(struct ngene_channel *chan); -+void ngene_v4l2_remove(struct ngene_channel *chan); -+int ngene_snd_exit(struct ngene_channel *chan); -+int ngene_snd_init(struct ngene_channel *chan); -+ -+struct i2c_client *avf4910a_attach(struct i2c_adapter *adap, int addr); -+#endif - - /* Provided by ngene-core.c */ - int ngene_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); -@@ -914,6 +945,15 @@ int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, - struct dmx_frontend *mem_frontend, - struct dvb_adapter *dvb_adapter); - -+/* Provided by ngene-eeprom.c */ -+#if 0 -+int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2); -+int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr); -+int i2c_check_eeprom(struct i2c_adapter *adapter); -+int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data); -+int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data); -+#endif -+ - #endif - - /* LocalWords: Endif -diff --git a/drivers/staging/media/cxd2099/TODO b/drivers/staging/media/cxd2099/TODO -deleted file mode 100644 -index 375bb6f..0000000 ---- a/drivers/staging/media/cxd2099/TODO -+++ /dev/null -@@ -1,12 +0,0 @@ --For now, data is passed through '/dev/dvb/adapterX/sec0': -- - Encrypted data must be written to 'sec0'. -- - Decrypted data can be read from 'sec0'. -- - Setup the CAM using device 'ca0'. -- --But this is wrong. There are some discussions about the proper way for --doing it, as seen at: -- http://www.mail-archive.com/linux-media@vger.kernel.org/msg22196.html -- --While there's no proper fix for it, the driver should be kept in staging. -- --Patches should be submitted to: linux-media@vger.kernel.org. -diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c -index 822c487..6d54b01 100644 ---- a/drivers/staging/media/cxd2099/cxd2099.c -+++ b/drivers/staging/media/cxd2099/cxd2099.c -@@ -66,9 +66,8 @@ static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, - struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2}; - - if (i2c_transfer(adapter, &msg, 1) != 1) { -- dev_err(&adapter->dev, -- "Failed to write to I2C register %02x@%02x!\n", -- reg, adr); -+ printk(KERN_ERR "Failed to write to I2C register %02x@%02x!\n", -+ reg, adr); - return -1; - } - return 0; -@@ -80,7 +79,7 @@ static int i2c_write(struct i2c_adapter *adapter, u8 adr, - struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len}; - - if (i2c_transfer(adapter, &msg, 1) != 1) { -- dev_err(&adapter->dev, "Failed to write to I2C!\n"); -+ printk(KERN_ERR "Failed to write to I2C!\n"); - return -1; - } - return 0; -@@ -95,7 +94,7 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, - .buf = val, .len = 1} }; - - if (i2c_transfer(adapter, msgs, 2) != 2) { -- dev_err(&adapter->dev, "error in i2c_read_reg\n"); -+ printk(KERN_ERR "error in i2c_read_reg\n"); - return -1; - } - return 0; -@@ -110,7 +109,7 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, - .buf = data, .len = n} }; - - if (i2c_transfer(adapter, msgs, 2) != 2) { -- dev_err(&adapter->dev, "error in i2c_read\n"); -+ printk(KERN_ERR "error in i2c_read\n"); - return -1; - } - return 0; -@@ -118,9 +117,10 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, - - static int read_block(struct cxd *ci, u8 adr, u8 *data, u8 n) - { -- int status; -+ int status = 0; - -- status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); -+ if (ci->lastaddress != adr) -+ status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); - if (!status) { - ci->lastaddress = adr; - status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, n); -@@ -278,7 +278,7 @@ static void cam_mode(struct cxd *ci, int mode) - #ifdef BUFFER_MODE - if (!ci->en.read_data) - return; -- dev_info(&ci->i2c->dev, "enable cam buffer mode\n"); -+ printk(KERN_INFO "enable cam buffer mode\n"); - /* write_reg(ci, 0x0d, 0x00); */ - /* write_reg(ci, 0x0e, 0x01); */ - write_regm(ci, 0x08, 0x40, 0x40); -@@ -525,7 +525,7 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) - msleep(10); - #if 0 - read_reg(ci, 0x06, &val); -- dev_info(&ci->i2c->dev, "%d:%02x\n", i, val); -+ printk(KERN_INFO "%d:%02x\n", i, val); - if (!(val&0x10)) - break; - #else -@@ -543,7 +543,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) - { - struct cxd *ci = ca->data; - -- dev_info(&ci->i2c->dev, "slot_shutdown\n"); -+ printk(KERN_INFO "slot_shutdown\n"); - mutex_lock(&ci->lock); - write_regm(ci, 0x09, 0x08, 0x08); - write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */ -@@ -579,10 +579,10 @@ static int campoll(struct cxd *ci) - - if (istat&0x40) { - ci->dr = 1; -- dev_info(&ci->i2c->dev, "DR\n"); -+ printk(KERN_INFO "DR\n"); - } - if (istat&0x20) -- dev_info(&ci->i2c->dev, "WC\n"); -+ printk(KERN_INFO "WC\n"); - - if (istat&2) { - u8 slotstat; -@@ -598,7 +598,7 @@ static int campoll(struct cxd *ci) - if (ci->slot_stat) { - ci->slot_stat = 0; - write_regm(ci, 0x03, 0x00, 0x08); -- dev_info(&ci->i2c->dev, "NO CAM\n"); -+ printk(KERN_INFO "NO CAM\n"); - ci->ready = 0; - } - } -@@ -635,7 +635,7 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) - campoll(ci); - mutex_unlock(&ci->lock); - -- dev_info(&ci->i2c->dev, "read_data\n"); -+ printk(KERN_INFO "read_data\n"); - if (!ci->dr) - return 0; - -@@ -684,29 +684,30 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, - void *priv, - struct i2c_adapter *i2c) - { -- struct cxd *ci; -+ struct cxd *ci = 0; - u8 val; - - if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) { -- dev_info(&i2c->dev, "No CXD2099 detected at %02x\n", cfg->adr); -- return NULL; -+ printk(KERN_INFO "No CXD2099 detected at %02x\n", cfg->adr); -+ return 0; - } - -- ci = kzalloc(sizeof(struct cxd), GFP_KERNEL); -+ ci = kmalloc(sizeof(struct cxd), GFP_KERNEL); - if (!ci) -- return NULL; -+ return 0; -+ memset(ci, 0, sizeof(*ci)); - - mutex_init(&ci->lock); -- ci->cfg = *cfg; -+ memcpy(&ci->cfg, cfg, sizeof(struct cxd2099_cfg)); - ci->i2c = i2c; - ci->lastaddress = 0xff; - ci->clk_reg_b = 0x4a; - ci->clk_reg_f = 0x1b; - -- ci->en = en_templ; -+ memcpy(&ci->en, &en_templ, sizeof(en_templ)); - ci->en.data = ci; - init(ci); -- dev_info(&i2c->dev, "Attached CXD2099AR at %02x\n", ci->cfg.adr); -+ printk(KERN_INFO "Attached CXD2099AR at %02x\n", ci->cfg.adr); - return &ci->en; - } - EXPORT_SYMBOL(cxd2099_attach); -diff --git a/drivers/staging/media/cxd2099/cxd2099.h b/drivers/staging/media/cxd2099/cxd2099.h -index 0eb607c..19c588a 100644 ---- a/drivers/staging/media/cxd2099/cxd2099.h -+++ b/drivers/staging/media/cxd2099/cxd2099.h -@@ -43,7 +43,7 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, - static inline struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, - void *priv, struct i2c_adapter *i2c) - { -- dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__); -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return NULL; - } - #endif --- -1.7.2.5 - diff --git a/packages/linux/patches/3.9.8/linux-222-stb0899_signal_quality.patch b/packages/linux/patches/3.9.8/linux-222-stb0899_signal_quality.patch deleted file mode 100644 index fd6539d2bf..0000000000 --- a/packages/linux/patches/3.9.8/linux-222-stb0899_signal_quality.patch +++ /dev/null @@ -1,62 +0,0 @@ -diff -Naur linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c ---- linux-3.7.2/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/dvb-frontends/stb0899_drv.c 2013-01-16 10:33:10.323380937 +0100 -@@ -971,6 +971,16 @@ - - *strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val); - *strength += 750; -+ -+ const int MIN_STRENGTH_DVBS = 0; -+ const int MAX_STRENGTH_DVBS = 680; -+ if (*strength < MIN_STRENGTH_DVBS) -+ *strength = 0; -+ else if(*strength > MAX_STRENGTH_DVBS) -+ *strength = 0xFFFF; -+ else -+ *strength = (*strength - MIN_STRENGTH_DVBS) * 0xFFFF / (MAX_STRENGTH_DVBS - MIN_STRENGTH_DVBS); -+ - dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm", - val & 0xff, *strength); - } -@@ -983,6 +993,7 @@ - - *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); - *strength += 950; -+ *strength = *strength << 4; - dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", - val & 0x3fff, *strength); - } -@@ -1016,6 +1027,16 @@ - val = MAKEWORD16(buf[0], buf[1]); - - *snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val); -+ -+ const int MIN_SNR_DVBS = 0; -+ const int MAX_SNR_DVBS = 200; -+ if (*snr < MIN_SNR_DVBS) -+ *snr = 0; -+ else if(*snr > MAX_SNR_DVBS) -+ *snr = 0xFFFF; -+ else -+ *snr = (*snr - MIN_SNR_DVBS) * 0xFFFF / (MAX_SNR_DVBS - MIN_SNR_DVBS); -+ - dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n", - buf[0], buf[1], val, *snr); - } -@@ -1040,6 +1061,16 @@ - val = (quantn - estn) / 10; - } - *snr = val; -+ -+ const int MIN_SNR_DVBS2 = 10; -+ const int MAX_SNR_DVBS2 = 70; -+ if (*snr < MIN_SNR_DVBS2) -+ *snr = 0; -+ else if(*snr > MAX_SNR_DVBS2) -+ *snr = 0xFFFF; -+ else -+ *snr = (*snr - MIN_SNR_DVBS2) * 0xFFFF / (MAX_SNR_DVBS2 - MIN_SNR_DVBS2); -+ - dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm", - quant, quantn, est, estn, val); - } diff --git a/packages/linux/patches/3.9.8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch b/packages/linux/patches/3.9.8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch deleted file mode 100644 index 7aaabc48c0..0000000000 --- a/packages/linux/patches/3.9.8/linux-223-Fix-video-artifacts-with-tt-3600-s2-usb.patch +++ /dev/null @@ -1,17 +0,0 @@ -diff -Naur linux-3.7.9/drivers/media/usb/dvb-usb/pctv452e.c linux-3.7.9.patch/drivers/media/usb/dvb-usb/pctv452e.c ---- linux-3.7.9/drivers/media/usb/dvb-usb/pctv452e.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.9.patch/drivers/media/usb/dvb-usb/pctv452e.c 2013-01-16 10:35:01.131342123 +0100 -@@ -995,11 +995,11 @@ - /* parameter for the MPEG2-data transfer */ - .stream = { - .type = USB_ISOC, -- .count = 7, -+ .count = 4, - .endpoint = 0x02, - .u = { - .isoc = { -- .framesperurb = 4, -+ .framesperurb = 64, - .framesize = 940, - .interval = 1 - } diff --git a/packages/linux/patches/3.9.8/linux-700-jmicron_1_0_8_5.patch b/packages/linux/patches/3.9.8/linux-700-jmicron_1_0_8_5.patch deleted file mode 100644 index 80a2c8195f..0000000000 --- a/packages/linux/patches/3.9.8/linux-700-jmicron_1_0_8_5.patch +++ /dev/null @@ -1,1603 +0,0 @@ -diff -Naur linux-3.7.2/drivers/net/ethernet/jme.c linux-3.7.2.patch/drivers/net/ethernet/jme.c ---- linux-3.7.2/drivers/net/ethernet/jme.c 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/net/ethernet/jme.c 2013-01-16 10:16:40.087516337 +0100 -@@ -22,7 +22,10 @@ - * - */ - -+#include -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+#endif - - #include - #include -@@ -48,6 +51,7 @@ - static int force_pseudohp = -1; - static int no_pseudohp = -1; - static int no_extplug = -1; -+static int delay_time = 11; - module_param(force_pseudohp, int, 0); - MODULE_PARM_DESC(force_pseudohp, - "Enable pseudo hot-plug feature manually by driver instead of BIOS."); -@@ -56,6 +60,24 @@ - module_param(no_extplug, int, 0); - MODULE_PARM_DESC(no_extplug, - "Do not use external plug signal for pseudo hot-plug."); -+module_param(delay_time, uint, 0); -+MODULE_PARM_DESC(delay_time, -+ "Seconds to delay before switching lower speed; default = 11 seconds(3 trials)"); -+ -+#ifndef JME_NEW_PM_API -+static void -+jme_pci_wakeup_enable(struct jme_adapter *jme, int enable) -+{ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27) -+ pci_enable_wake(jme->pdev, PCI_D1, enable); -+ pci_enable_wake(jme->pdev, PCI_D2, enable); -+ pci_enable_wake(jme->pdev, PCI_D3hot, enable); -+ pci_enable_wake(jme->pdev, PCI_D3cold, enable); -+#else -+ pci_pme_active(jme->pdev, enable); -+#endif -+} -+#endif - - static int - jme_mdio_read(struct net_device *netdev, int phy, int reg) -@@ -758,6 +780,9 @@ - jme->dev->mtu + RX_EXTRA_LEN); - if (unlikely(!skb)) - return -ENOMEM; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -+ skb->dev = jme->dev; -+#endif - - mapping = pci_map_page(jme->pdev, virt_to_page(skb->data), - offset_in_page(skb->data), skb_tailroom(skb), -@@ -967,11 +992,29 @@ - jme_udpsum(struct sk_buff *skb) - { - u16 csum = 0xFFFFu; -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) -+ struct iphdr *iph; -+ int iphlen; -+ struct udphdr *udph; -+#endif - - if (skb->len < (ETH_HLEN + sizeof(struct iphdr))) - return csum; - if (skb->protocol != htons(ETH_P_IP)) - return csum; -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) -+ iph = (struct iphdr *)skb_pull(skb, ETH_HLEN); -+ iphlen = (iph->ihl << 2); -+ if ((iph->protocol != IPPROTO_UDP) || -+ (skb->len < (iphlen + sizeof(struct udphdr)))) { -+ skb_push(skb, ETH_HLEN); -+ return csum; -+ } -+ udph = (struct udphdr *)skb_pull(skb, iphlen); -+ csum = udph->check; -+ skb_push(skb, iphlen); -+ skb_push(skb, ETH_HLEN); -+#else - skb_set_network_header(skb, ETH_HLEN); - if ((ip_hdr(skb)->protocol != IPPROTO_UDP) || - (skb->len < (ETH_HLEN + -@@ -985,6 +1028,7 @@ - csum = udp_hdr(skb)->check; - skb_reset_transport_header(skb); - skb_reset_network_header(skb); -+#endif - - return csum; - } -@@ -1054,8 +1098,24 @@ - if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb)) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) -+ skb->ip_summed = CHECKSUM_NONE; -+#else - skb_checksum_none_assert(skb); -- -+#endif -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) -+ if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) { -+ if (jme->vlgrp) { -+ jme->jme_vlan_rx(skb, jme->vlgrp, -+ le16_to_cpu(rxdesc->descwb.vlan)); -+ NET_STAT(jme).rx_bytes += 4; -+ } else { -+ dev_kfree_skb(skb); -+ } -+ } else { -+ jme->jme_rx(skb); -+ } -+#else - if (rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_TAGON)) { - u16 vid = le16_to_cpu(rxdesc->descwb.vlan); - -@@ -1064,6 +1124,7 @@ - } - jme->jme_rx(skb); - -+#endif - if ((rxdesc->descwb.flags & cpu_to_le16(RXWBFLAG_DEST)) == - cpu_to_le16(RXWBFLAG_DEST_MUL)) - ++(NET_STAT(jme).multicast); -@@ -1292,6 +1353,223 @@ - } - - static void -+jme_set_physpeed_capability(struct jme_adapter *jme, u16 speed) -+{ -+ u32 advert, advert2; -+ -+// spin_lock_bh(&jme->phy_lock); -+ advert = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE); -+ advert2 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); -+ switch (speed) { -+ case SPEED_1000: -+ advert = (advert|ADVERTISE_100HALF|ADVERTISE_100FULL); -+ advert2 = (advert2|ADVERTISE_1000HALF|ADVERTISE_1000FULL); -+ break; -+ case SPEED_100: -+ advert = (advert|ADVERTISE_100HALF|ADVERTISE_100FULL); -+ advert2 = advert2 & ~(ADVERTISE_1000HALF|ADVERTISE_1000FULL); -+ break; -+ default: -+ advert = advert & ~(ADVERTISE_100HALF|ADVERTISE_100FULL); -+ advert2 = advert2 & ~(ADVERTISE_1000HALF|ADVERTISE_1000FULL); -+ } -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE, advert); -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, advert2); -+// spin_unlock_bh(&jme->phy_lock); -+ return; -+} -+ -+/* -+ PHY reg: MII_FCSCOUNTER is read and clear, we have to -+ continuing read until RJ45 is attached, then cache -+ this result. -+*/ -+static int -+jme_check_ANcomplete(struct jme_adapter *jme) -+{ -+ u32 val; -+ -+ val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_FCSCOUNTER); -+ return ((val&(PHY_SPEC_STATUS_AN_FAIL|PHY_SPEC_STATUS_AN_COMPLETE)) -+ == PHY_SPEC_STATUS_AN_COMPLETE) ? true : false; -+} -+ -+static int -+jme_media_connected(struct jme_adapter *jme) -+{ -+ if (jme->media_cnct == true) -+ return true; -+ -+ jme->media_cnct = jme_check_ANcomplete(jme); -+ return jme->media_cnct; -+} -+ -+static inline void -+jme_slowspeed_tune(struct jme_adapter *jme, u16 speed) -+{ -+ if (jme_check_ANcomplete(jme)) -+ jme_set_physpeed_capability(jme, speed); -+ else { -+ jme->media_cnct = false; -+ jme->media_cnct_sec = 0; -+ } -+} -+ -+static void -+asd_polling_func(unsigned long data) -+{ -+ struct jme_adapter *jme = (struct jme_adapter *)data; -+ unsigned long flags; -+ /* -+ check condition term by term. -+ 1. link is up() -+ ==> reset all thing, exit the process. -+ 2. there is no RJ45 cable attached -+ ==> do nothing but polling -+ 3. RJ45 cable attached. but link is down -+ ==> downspeed if the timeing is over 3.5 second. -+ */ -+ spin_lock_irqsave(&jme->asd_lock, flags); -+ if (jme->flag_run_asd == true) { -+ if (jme_media_connected(jme)) { -+ jme->media_cnct_sec++; -+ if (jme->media_cnct_sec == (delay_time*3-5)) { -+ /* Unable to link anyway, it can NOT be resolved -+ by slower speed, restore the capability */ -+ jme_set_physpeed_capability(jme, SPEED_1000); -+ jme->media_cnct = false; -+ jme->media_cnct_sec = 0; -+ } else if (jme->media_cnct_sec == (delay_time*2-5)) -+ jme_slowspeed_tune(jme, SPEED_10); -+ else if (jme->media_cnct_sec == delay_time-5) -+ jme_slowspeed_tune(jme, SPEED_100); -+ } -+ mod_timer(&jme->asd_timer, jiffies+HZ); -+ spin_unlock_irqrestore(&jme->asd_lock, flags); -+ return ; -+ } -+ jme->media_cnct = false; -+ jme->media_cnct_sec = 0; -+ spin_unlock_irqrestore(&jme->asd_lock, flags); -+ return; -+} -+ -+static int jme_check_linkup(struct jme_adapter *jme) -+{ -+ u32 phylink; -+ -+ if (jme->fpgaver) -+ phylink = jme_linkstat_from_phy(jme); -+ else -+ phylink = jread32(jme, JME_PHY_LINK); -+ -+ return (phylink & PHY_LINK_UP) ? true : false; -+} -+ -+static void jme_LC_task(struct work_struct *work) -+{ -+ struct jme_adapter *jme; -+ struct net_device *netdev; -+ int rc; -+ unsigned long flags; -+ -+ jme = container_of(work, struct jme_adapter, LC_task); -+ netdev = jme->dev; -+ -+ -+ msleep(500); -+ while (!atomic_dec_and_test(&jme->link_changing)) { -+ atomic_inc(&jme->link_changing); -+ netif_info(jme, intr, jme->dev, "Get link change lock failed\n"); -+ while (atomic_read(&jme->link_changing) != 1) -+ netif_info(jme, intr, jme->dev, "Waiting link change lock\n"); -+ } -+ spin_lock_irqsave(&jme->asd_lock, flags); -+ if (jme_check_linkup(jme)) { -+ if (jme->flag_run_asd) { -+ jme->flag_run_asd = false; -+ del_timer_sync(&jme->asd_timer); -+ } -+ } else { -+ if (!jme->flag_run_asd) { -+ jme_set_physpeed_capability(jme, SPEED_1000); -+ jme_check_ANcomplete(jme); -+ jme->media_cnct = false; -+ jme->flag_run_asd = true; -+ jme->media_cnct_sec = 0; -+ jme->asd_timer.expires = jiffies + 4*HZ; -+ jme->asd_timer.function = &asd_polling_func; -+ jme->asd_timer.data = (unsigned long)jme; -+ add_timer(&jme->asd_timer); -+ } -+ } -+ spin_unlock_irqrestore(&jme->asd_lock, flags); -+ if (jme_check_link(netdev, 1) && jme->old_mtu == netdev->mtu) -+ goto out; -+ -+ jme->old_mtu = netdev->mtu; -+ netif_stop_queue(netdev); -+ if (jme_pseudo_hotplug_enabled(jme)) -+ jme_stop_shutdown_timer(jme); -+ -+ jme_stop_pcc_timer(jme); -+ tasklet_disable(&jme->txclean_task); -+ tasklet_disable(&jme->rxclean_task); -+ tasklet_disable(&jme->rxempty_task); -+ -+ if (netif_carrier_ok(netdev)) { -+ jme_disable_rx_engine(jme); -+ jme_disable_tx_engine(jme); -+ jme_reset_mac_processor(jme); -+ jme_free_rx_resources(jme); -+ jme_free_tx_resources(jme); -+ -+ if (test_bit(JME_FLAG_POLL, &jme->flags)) -+ jme_polling_mode(jme); -+ -+ netif_carrier_off(netdev); -+ } -+ -+ jme_check_link(netdev, 0); -+ if (netif_carrier_ok(netdev)) { -+ rc = jme_setup_rx_resources(jme); -+ if (rc) { -+ pr_err("Allocating resources for RX error, Device STOPPED!\n"); -+ goto out_enable_tasklet; -+ } -+ -+ rc = jme_setup_tx_resources(jme); -+ if (rc) { -+ pr_err("Allocating resources for TX error, Device STOPPED!\n"); -+ goto err_out_free_rx_resources; -+ } -+ -+ jme_enable_rx_engine(jme); -+ jme_enable_tx_engine(jme); -+ -+ netif_start_queue(netdev); -+ -+ if (test_bit(JME_FLAG_POLL, &jme->flags)) -+ jme_interrupt_mode(jme); -+ -+ jme_start_pcc_timer(jme); -+ } else if (jme_pseudo_hotplug_enabled(jme)) { -+ jme_start_shutdown_timer(jme); -+ } -+ -+ goto out_enable_tasklet; -+ -+err_out_free_rx_resources: -+ jme_free_rx_resources(jme); -+out_enable_tasklet: -+ tasklet_enable(&jme->txclean_task); -+ tasklet_hi_enable(&jme->rxclean_task); -+ tasklet_hi_enable(&jme->rxempty_task); -+out: -+ atomic_inc(&jme->link_changing); -+} -+ -+static void - jme_link_change_tasklet(unsigned long arg) - { - struct jme_adapter *jme = (struct jme_adapter *)arg; -@@ -1385,6 +1663,7 @@ - jme_poll(JME_NAPI_HOLDER(holder), JME_NAPI_WEIGHT(budget)) - { - struct jme_adapter *jme = jme_napi_priv(holder); -+ DECLARE_NETDEV - int rest; - - rest = jme_process_receive(jme, JME_NAPI_WEIGHT_VAL(budget)); -@@ -1538,7 +1817,7 @@ - * all other events are ignored - */ - jwrite32(jme, JME_IEVE, intrstat); -- tasklet_schedule(&jme->linkch_task); -+ schedule_work(&jme->LC_task); - goto out_reenable; - } - -@@ -1585,8 +1864,13 @@ - jwrite32f(jme, JME_IENS, INTR_ENABLE); - } - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) -+static irqreturn_t -+jme_intr(int irq, void *dev_id, struct pt_regs *regs) -+#else - static irqreturn_t - jme_intr(int irq, void *dev_id) -+#endif - { - struct net_device *netdev = dev_id; - struct jme_adapter *jme = netdev_priv(netdev); -@@ -1611,8 +1895,13 @@ - return IRQ_HANDLED; - } - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) -+static irqreturn_t -+jme_msi(int irq, void *dev_id, struct pt_regs *regs) -+#else - static irqreturn_t - jme_msi(int irq, void *dev_id) -+#endif - { - struct net_device *netdev = dev_id; - struct jme_adapter *jme = netdev_priv(netdev); -@@ -1648,8 +1937,13 @@ - { - int rc; - struct net_device *netdev = jme->dev; -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) -+ irqreturn_t (*handler)(int, void *, struct pt_regs *) = jme_intr; -+ int irq_flags = SA_SHIRQ; -+#else - irq_handler_t handler = jme_intr; - int irq_flags = IRQF_SHARED; -+#endif - - if (!pci_enable_msi(jme->pdev)) { - set_bit(JME_FLAG_MSI, &jme->flags); -@@ -1746,55 +2040,60 @@ - } - - static int --jme_phy_specreg_read(struct jme_adapter *jme, u32 specreg) --{ -- u32 phy_addr; -- -- phy_addr = JM_PHY_SPEC_REG_READ | specreg; -- jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, -- phy_addr); -- return jme_mdio_read(jme->dev, jme->mii_if.phy_id, -- JM_PHY_SPEC_DATA_REG); --} -- --static void --jme_phy_specreg_write(struct jme_adapter *jme, u32 ext_reg, u32 phy_data) --{ -- u32 phy_addr; -- -- phy_addr = JM_PHY_SPEC_REG_WRITE | ext_reg; -- jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG, -- phy_data); -- jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, -- phy_addr); --} -- --static int - jme_phy_calibration(struct jme_adapter *jme) - { -- u32 ctrl1000, phy_data; -+ u32 ctrl1000, bmcr, phy_addr, phy_data; - -- jme_phy_off(jme); -- jme_phy_on(jme); -- /* Enabel PHY test mode 1 */ -+ // Turn PHY off -+ bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); -+ bmcr |= BMCR_PDOWN; -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); -+ // Turn PHY on -+ bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); -+ bmcr &= ~BMCR_PDOWN; -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); -+ // Enabel PHY test mode 1 - ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); - ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK; - ctrl1000 |= PHY_GAD_TEST_MODE_1; -- jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); -- -- phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG); -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); -+ -+ -+ phy_addr = JM_PHY_SPEC_REG_READ | JM_PHY_EXT_COMM_2_REG; -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, -+ phy_addr); -+ phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id, -+ JM_PHY_SPEC_DATA_REG); -+ - phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0; - phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH | - JM_PHY_EXT_COMM_2_CALI_ENABLE; -- jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data); -+ -+ phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_2_REG; -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG, -+ phy_data); -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, -+ phy_addr); -+ - msleep(20); -- phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG); -+ -+ phy_addr = JM_PHY_SPEC_REG_READ | JM_PHY_EXT_COMM_2_REG; -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, -+ phy_addr); -+ phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id, -+ JM_PHY_SPEC_DATA_REG); -+ - phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE | - JM_PHY_EXT_COMM_2_CALI_MODE_0 | - JM_PHY_EXT_COMM_2_CALI_LATCH); -- jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data); - -- /* Disable PHY test mode */ -+ phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_2_REG; -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG, -+ phy_data); -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG, -+ phy_addr); -+ -+ // Disable PHY test mode - ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000); - ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK; - jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000); -@@ -1804,11 +2103,11 @@ - static int - jme_phy_setEA(struct jme_adapter *jme) - { -- u32 phy_comm0 = 0, phy_comm1 = 0; -+ u32 phy_addr, phy_comm0 = 0, phy_comm1 = 0; - u8 nic_ctrl; - - pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl); -- if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE) -+ if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE) - return 0; - - switch (jme->pdev->device) { -@@ -1840,14 +2139,23 @@ - if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2)) - phy_comm0 = 0x408A; - break; -- default: -+ default: - return -ENODEV; - } -- if (phy_comm0) -- jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_0_REG, phy_comm0); -- if (phy_comm1) -- jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_1_REG, phy_comm1); -- -+ if (phy_comm0){ -+ phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_0_REG; -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, -+ JM_PHY_SPEC_DATA_REG, phy_comm0); -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, -+ JM_PHY_SPEC_ADDR_REG, phy_addr); -+ } -+ if (phy_comm1){ -+ phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_1_REG; -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, -+ JM_PHY_SPEC_DATA_REG, phy_comm1); -+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, -+ JM_PHY_SPEC_ADDR_REG, phy_addr); -+ } - return 0; - } - -@@ -1995,7 +2303,7 @@ - struct page *page, - u32 page_offset, - u32 len, -- bool hidma) -+ u8 hidma) - { - dma_addr_t dmaaddr; - -@@ -2029,20 +2337,24 @@ - struct jme_ring *txring = &(jme->txring[0]); - struct txdesc *txdesc = txring->desc, *ctxdesc; - struct jme_buffer_info *txbi = txring->bufinf, *ctxbi; -- bool hidma = jme->dev->features & NETIF_F_HIGHDMA; -+ u8 hidma = jme->dev->features & NETIF_F_HIGHDMA; - int i, nr_frags = skb_shinfo(skb)->nr_frags; - int mask = jme->tx_ring_mask; -- const struct skb_frag_struct *frag; -+ struct skb_frag_struct *frag; - u32 len; - - for (i = 0 ; i < nr_frags ; ++i) { - frag = &skb_shinfo(skb)->frags[i]; - ctxdesc = txdesc + ((idx + i + 2) & (mask)); - ctxbi = txbi + ((idx + i + 2) & (mask)); -- -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) -+ jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, frag->page, -+ frag->page_offset, frag->size, hidma); -+#else - jme_fill_tx_map(jme->pdev, ctxdesc, ctxbi, - skb_frag_page(frag), - frag->page_offset, skb_frag_size(frag), hidma); -+#endif - } - - len = skb_is_nonlinear(skb) ? skb_headlen(skb) : skb->len; -@@ -2056,8 +2368,13 @@ - static int - jme_expand_header(struct jme_adapter *jme, struct sk_buff *skb) - { -- if (unlikely(skb_shinfo(skb)->gso_size && -- skb_header_cloned(skb) && -+ if (unlikely( -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) -+ skb_shinfo(skb)->tso_size -+#else -+ skb_shinfo(skb)->gso_size -+#endif -+ && skb_header_cloned(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) { - dev_kfree_skb(skb); - return -1; -@@ -2069,7 +2386,11 @@ - static int - jme_tx_tso(struct sk_buff *skb, __le16 *mss, u8 *flags) - { -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,17) -+ *mss = cpu_to_le16(skb_shinfo(skb)->tso_size << TXDESC_MSS_SHIFT); -+#else - *mss = cpu_to_le16(skb_shinfo(skb)->gso_size << TXDESC_MSS_SHIFT); -+#endif - if (*mss) { - *flags |= TXFLAG_LSEN; - -@@ -2099,9 +2420,22 @@ - static void - jme_tx_csum(struct jme_adapter *jme, struct sk_buff *skb, u8 *flags) - { -- if (skb->ip_summed == CHECKSUM_PARTIAL) { -+#ifdef CHECKSUM_PARTIAL -+ if (skb->ip_summed == CHECKSUM_PARTIAL) -+#else -+ if (skb->ip_summed == CHECKSUM_HW) -+#endif -+ { - u8 ip_proto; - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) -+ if (skb->protocol == htons(ETH_P_IP)) -+ ip_proto = ip_hdr(skb)->protocol; -+ else if (skb->protocol == htons(ETH_P_IPV6)) -+ ip_proto = ipv6_hdr(skb)->nexthdr; -+ else -+ ip_proto = 0; -+#else - switch (skb->protocol) { - case htons(ETH_P_IP): - ip_proto = ip_hdr(skb)->protocol; -@@ -2113,6 +2447,7 @@ - ip_proto = 0; - break; - } -+#endif - - switch (ip_proto) { - case IPPROTO_TCP: -@@ -2219,7 +2554,11 @@ - * This function is already protected by netif_tx_lock() - */ - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,31) -+static int -+#else - static netdev_tx_t -+#endif - jme_start_xmit(struct sk_buff *skb, struct net_device *netdev) - { - struct jme_adapter *jme = netdev_priv(netdev); -@@ -2246,6 +2585,9 @@ - TXCS_SELECT_QUEUE0 | - TXCS_QUEUE0S | - TXCS_ENABLE); -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,29) -+ netdev->trans_start = jiffies; -+#endif - - tx_dbg(jme, "xmit: %d+%d@%lu\n", - idx, skb_shinfo(skb)->nr_frags + 2, jiffies); -@@ -2292,6 +2634,9 @@ - { - struct jme_adapter *jme = netdev_priv(netdev); - u32 mc_hash[2] = {}; -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,33) -+ int i; -+#endif - - spin_lock_bh(&jme->rxmcs_lock); - -@@ -2302,12 +2647,28 @@ - } else if (netdev->flags & IFF_ALLMULTI) { - jme->reg_rxmcs |= RXMCS_ALLMULFRAME; - } else if (netdev->flags & IFF_MULTICAST) { -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34) -+ struct dev_mc_list *mclist; -+#else - struct netdev_hw_addr *ha; -+#endif - int bit_nr; - - jme->reg_rxmcs |= RXMCS_MULFRAME | RXMCS_MULFILTERED; -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,33) -+ for (i = 0, mclist = netdev->mc_list; -+ mclist && i < netdev->mc_count; -+ ++i, mclist = mclist->next) { -+#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34) -+ netdev_for_each_mc_addr(mclist, netdev) { -+#else - netdev_for_each_mc_addr(ha, netdev) { -+#endif -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,34) -+ bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) & 0x3F; -+#else - bit_nr = ether_crc(ETH_ALEN, ha->addr) & 0x3F; -+#endif - mc_hash[bit_nr >> 5] |= 1 << (bit_nr & 0x1F); - } - -@@ -2333,11 +2694,27 @@ - ((new_mtu) < IPV6_MIN_MTU)) - return -EINVAL; - -+ if (new_mtu > 4000) { -+ jme->reg_rxcs &= ~RXCS_FIFOTHNP; -+ jme->reg_rxcs |= RXCS_FIFOTHNP_64QW; -+ jme_restart_rx_engine(jme); -+ } else { -+ jme->reg_rxcs &= ~RXCS_FIFOTHNP; -+ jme->reg_rxcs |= RXCS_FIFOTHNP_128QW; -+ jme_restart_rx_engine(jme); -+ } -+ -+ if (new_mtu > 1900) { -+ netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | -+ NETIF_F_TSO | NETIF_F_TSO6); -+ } else { -+ if (test_bit(JME_FLAG_TXCSUM, &jme->flags)) -+ netdev->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; -+ if (test_bit(JME_FLAG_TSO, &jme->flags)) -+ netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; -+ } - - netdev->mtu = new_mtu; -- netdev_update_features(netdev); -- -- jme_restart_rx_engine(jme); - jme_reset_link(jme); - - return 0; -@@ -2390,15 +2767,45 @@ - atomic_inc(&jme->link_changing); - } - -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) -+static void -+jme_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) -+{ -+ struct jme_adapter *jme = netdev_priv(netdev); -+ -+ jme_pause_rx(jme); -+ jme->vlgrp = grp; -+ jme_resume_rx(jme); -+} -+#endif -+ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) -+static void -+jme_vlan_rx_kill_vid(struct net_device *netdev, unsigned short vid) -+{ -+ struct jme_adapter *jme = netdev_priv(netdev); -+ -+ if(jme->vlgrp) { -+ jme_pause_rx(jme); -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,20) -+ jme->vlgrp->vlan_devices[vid] = NULL; -+#else -+ vlan_group_set_device(jme->vlgrp, vid, NULL); -+#endif -+ jme_resume_rx(jme); -+ } -+} -+#endif -+ - static void - jme_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *info) - { - struct jme_adapter *jme = netdev_priv(netdev); - -- strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); -- strlcpy(info->version, DRV_VERSION, sizeof(info->version)); -- strlcpy(info->bus_info, pci_name(jme->pdev), sizeof(info->bus_info)); -+ strcpy(info->driver, DRV_NAME); -+ strcpy(info->version, DRV_VERSION); -+ strcpy(info->bus_info, pci_name(jme->pdev)); - } - - static int -@@ -2500,6 +2907,9 @@ - test_bit(JME_FLAG_POLL, &jme->flags)) { - clear_bit(JME_FLAG_POLL, &jme->flags); - jme->jme_rx = netif_rx; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) -+ jme->jme_vlan_rx = vlan_hwaccel_rx; -+#endif - dpi->cur = PCC_P1; - dpi->attempt = PCC_P1; - dpi->cnt = 0; -@@ -2509,6 +2919,9 @@ - !(test_bit(JME_FLAG_POLL, &jme->flags))) { - set_bit(JME_FLAG_POLL, &jme->flags); - jme->jme_rx = netif_receive_skb; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) -+ jme->jme_vlan_rx = vlan_hwaccel_receive_skb; -+#endif - jme_interrupt_mode(jme); - } - -@@ -2622,7 +3035,12 @@ - jme->reg_pmcs |= PMCS_MFEN; - - jwrite32(jme, JME_PMCS, jme->reg_pmcs); -+#ifndef JME_NEW_PM_API -+ jme_pci_wakeup_enable(jme, !!(jme->reg_pmcs)); -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs)); -+#endif - - return 0; - } -@@ -2724,21 +3142,21 @@ - jme->msg_enable = value; - } - --static netdev_features_t --jme_fix_features(struct net_device *netdev, netdev_features_t features) -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) -+static u32 -+jme_get_rx_csum(struct net_device *netdev) - { -- if (netdev->mtu > 1900) -- features &= ~(NETIF_F_ALL_TSO | NETIF_F_ALL_CSUM); -- return features; -+ struct jme_adapter *jme = netdev_priv(netdev); -+ return jme->reg_rxmcs & RXMCS_CHECKSUM; - } - - static int --jme_set_features(struct net_device *netdev, netdev_features_t features) -+jme_set_rx_csum(struct net_device *netdev, u32 on) - { - struct jme_adapter *jme = netdev_priv(netdev); - - spin_lock_bh(&jme->rxmcs_lock); -- if (features & NETIF_F_RXCSUM) -+ if (on) - jme->reg_rxmcs |= RXMCS_CHECKSUM; - else - jme->reg_rxmcs &= ~RXMCS_CHECKSUM; -@@ -2748,14 +3166,40 @@ - return 0; - } - --#ifdef CONFIG_NET_POLL_CONTROLLER --static void jme_netpoll(struct net_device *dev) -+static int -+jme_set_tx_csum(struct net_device *netdev, u32 on) - { -- unsigned long flags; -+ struct jme_adapter *jme = netdev_priv(netdev); -+ -+ if (on) { -+ set_bit(JME_FLAG_TXCSUM, &jme->flags); -+ if (netdev->mtu <= 1900) -+ netdev->features |= -+ NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; -+ } else { -+ clear_bit(JME_FLAG_TXCSUM, &jme->flags); -+ netdev->features &= -+ ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -+ } -+ -+ return 0; -+} -+ -+static int -+jme_set_tso(struct net_device *netdev, u32 on) -+{ -+ struct jme_adapter *jme = netdev_priv(netdev); -+ -+ if (on) { -+ set_bit(JME_FLAG_TSO, &jme->flags); -+ if (netdev->mtu <= 1900) -+ netdev->features |= NETIF_F_TSO | NETIF_F_TSO6; -+ } else { -+ clear_bit(JME_FLAG_TSO, &jme->flags); -+ netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); -+ } - -- local_irq_save(flags); -- jme_intr(dev->irq, dev); -- local_irq_restore(flags); -+ return 0; - } - #endif - -@@ -2885,7 +3329,11 @@ - return 0; - } - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) -+static struct ethtool_ops jme_ethtool_ops = { -+#else - static const struct ethtool_ops jme_ethtool_ops = { -+#endif - .get_drvinfo = jme_get_drvinfo, - .get_regs_len = jme_get_regs_len, - .get_regs = jme_get_regs, -@@ -2900,6 +3348,13 @@ - .get_link = jme_get_link, - .get_msglevel = jme_get_msglevel, - .set_msglevel = jme_set_msglevel, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) -+ .get_rx_csum = jme_get_rx_csum, -+ .set_rx_csum = jme_set_rx_csum, -+ .set_tx_csum = jme_set_tx_csum, -+ .set_tso = jme_set_tso, -+ .set_sg = ethtool_op_set_sg, -+#endif - .nway_reset = jme_nway_reset, - .get_eeprom_len = jme_get_eeprom_len, - .get_eeprom = jme_get_eeprom, -@@ -2910,17 +3365,40 @@ - jme_pci_dma64(struct pci_dev *pdev) - { - if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && -- !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -+ !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) -+#else -+ !pci_set_dma_mask(pdev, DMA_64BIT_MASK) -+#endif -+ ) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) -+#else -+ if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) -+#endif - return 1; - - if (pdev->device == PCI_DEVICE_ID_JMICRON_JMC250 && -- !pci_set_dma_mask(pdev, DMA_BIT_MASK(40))) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -+ !pci_set_dma_mask(pdev, DMA_BIT_MASK(40)) -+#else -+ !pci_set_dma_mask(pdev, DMA_40BIT_MASK) -+#endif -+ ) -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(40))) -+#else -+ if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK)) -+#endif - return 1; - -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) - if (!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) -+#else -+ if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) -+ if (!pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) -+#endif - return 0; - - return -1; -@@ -2948,6 +3426,7 @@ - jme->chip_sub_rev = (jme->chiprev >> 4) & 0xF; - } - -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - static const struct net_device_ops jme_netdev_ops = { - .ndo_open = jme_open, - .ndo_stop = jme_close, -@@ -2955,15 +3434,16 @@ - .ndo_do_ioctl = jme_ioctl, - .ndo_start_xmit = jme_start_xmit, - .ndo_set_mac_address = jme_set_macaddr, -- .ndo_set_rx_mode = jme_set_multi, -+ .ndo_set_rx_mode = jme_set_multi, -+ -+ - .ndo_change_mtu = jme_change_mtu, - .ndo_tx_timeout = jme_tx_timeout, -- .ndo_fix_features = jme_fix_features, -- .ndo_set_features = jme_set_features, --#ifdef CONFIG_NET_POLL_CONTROLLER -- .ndo_poll_controller = jme_netpoll, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) -+ .ndo_vlan_rx_register = jme_vlan_rx_register, - #endif - }; -+#endif - - static int __devinit - jme_init_one(struct pci_dev *pdev, -@@ -3013,18 +3493,29 @@ - */ - netdev = alloc_etherdev(sizeof(*jme)); - if (!netdev) { -+ pr_err("Cannot allocate netdev structure\n"); - rc = -ENOMEM; - goto err_out_release_regions; - } -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - netdev->netdev_ops = &jme_netdev_ops; -+#else -+ netdev->open = jme_open; -+ netdev->stop = jme_close; -+ netdev->do_ioctl = jme_ioctl; -+ netdev->hard_start_xmit = jme_start_xmit; -+ netdev->set_mac_address = jme_set_macaddr; -+ netdev->set_multicast_list = jme_set_multi; -+ netdev->change_mtu = jme_change_mtu; -+ netdev->tx_timeout = jme_tx_timeout; -+ netdev->vlan_rx_register = jme_vlan_rx_register; -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) -+ netdev->vlan_rx_kill_vid = jme_vlan_rx_kill_vid; -+#endif -+ NETDEV_GET_STATS(netdev, &jme_get_stats); -+#endif - netdev->ethtool_ops = &jme_ethtool_ops; - netdev->watchdog_timeo = TX_TIMEOUT; -- netdev->hw_features = NETIF_F_IP_CSUM | -- NETIF_F_IPV6_CSUM | -- NETIF_F_SG | -- NETIF_F_TSO | -- NETIF_F_TSO6 | -- NETIF_F_RXCSUM; - netdev->features = NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | - NETIF_F_SG | -@@ -3045,6 +3536,9 @@ - jme->pdev = pdev; - jme->dev = netdev; - jme->jme_rx = netif_rx; -+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) -+ jme->jme_vlan_rx = vlan_hwaccel_rx; -+#endif - jme->old_mtu = netdev->mtu = 1500; - jme->phylink = 0; - jme->tx_ring_size = 1 << 10; -@@ -3083,6 +3577,9 @@ - tasklet_init(&jme->pcc_task, - jme_pcc_tasklet, - (unsigned long) jme); -+ -+ INIT_WORK(&jme->LC_task, jme_LC_task); -+ - jme->dpi.cur = PCC_P1; - - jme->reg_ghc = 0; -@@ -3091,9 +3588,8 @@ - jme->reg_txpfc = 0; - jme->reg_pmcs = PMCS_MFEN; - jme->reg_gpreg1 = GPREG1_DEFAULT; -- -- if (jme->reg_rxmcs & RXMCS_CHECKSUM) -- netdev->features |= NETIF_F_RXCSUM; -+ set_bit(JME_FLAG_TXCSUM, &jme->flags); -+ set_bit(JME_FLAG_TSO, &jme->flags); - - /* - * Get Max Read Req Size from PCI Config Space -@@ -3149,10 +3645,19 @@ - - jme_clear_pm(jme); - pci_set_power_state(jme->pdev, PCI_D0); -+#ifndef JME_NEW_PM_API -+ jme_pci_wakeup_enable(jme, true); -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - device_set_wakeup_enable(&pdev->dev, true); -+#endif - - jme_set_phyfifo_5level(jme); -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) -+ pci_read_config_byte(pdev, PCI_REVISION_ID, &jme->pcirev); -+#else - jme->pcirev = pdev->revision; -+#endif - if (!jme->fpgaver) - jme_phy_init(jme); - jme_phy_off(jme); -@@ -3179,14 +3684,26 @@ - goto err_out_unmap; - } - -- netif_info(jme, probe, jme->dev, "%s%s chiprev:%x pcirev:%x macaddr:%pM\n", -+ init_timer(&(jme->asd_timer)); -+ jme->media_cnct_sec = 0; -+ jme->flag_run_asd = false; -+ jme->media_cnct = false; -+ -+ netif_info(jme, probe, jme->dev, "%s%s chipver:%x pcirev:%x " -+ "macaddr: %02x:%02x:%02x:%02x:%02x:%02x\n", - (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ? - "JMC250 Gigabit Ethernet" : - (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ? - "JMC260 Fast Ethernet" : "Unknown", - (jme->fpgaver != 0) ? " (FPGA)" : "", - (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev, -- jme->pcirev, netdev->dev_addr); -+ jme->pcirev, -+ netdev->dev_addr[0], -+ netdev->dev_addr[1], -+ netdev->dev_addr[2], -+ netdev->dev_addr[3], -+ netdev->dev_addr[4], -+ netdev->dev_addr[5]); - - return 0; - -@@ -3209,6 +3726,8 @@ - struct net_device *netdev = pci_get_drvdata(pdev); - struct jme_adapter *jme = netdev_priv(netdev); - -+ del_timer_sync(&jme->asd_timer); -+ cancel_work_sync(&jme->LC_task); - unregister_netdev(netdev); - iounmap(jme->regs); - pci_set_drvdata(pdev, NULL); -@@ -3225,26 +3744,48 @@ - struct jme_adapter *jme = netdev_priv(netdev); - - jme_powersave_phy(jme); -- pci_pme_active(pdev, true); -+#ifndef JME_NEW_PM_API -+ jme_pci_wakeup_enable(jme, !!(jme->reg_pmcs)); -+#endif -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -+ device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs)); -+#endif - } - --#ifdef CONFIG_PM_SLEEP -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) -+ #ifdef CONFIG_PM -+ #define JME_HAVE_PM -+ #endif -+#else -+ #ifdef CONFIG_PM_SLEEP -+ #define JME_HAVE_PM -+ #endif -+#endif -+ -+#ifdef JME_HAVE_PM - static int -+#ifdef JME_NEW_PM_API - jme_suspend(struct device *dev) -+#else -+jme_suspend(struct pci_dev *pdev, pm_message_t state) -+#endif - { -+#ifdef JME_NEW_PM_API - struct pci_dev *pdev = to_pci_dev(dev); -+#endif - struct net_device *netdev = pci_get_drvdata(pdev); - struct jme_adapter *jme = netdev_priv(netdev); -- -- if (!netif_running(netdev)) -- return 0; -- -+ unsigned long flags; -+ - atomic_dec(&jme->link_changing); - - netif_device_detach(netdev); - netif_stop_queue(netdev); - jme_stop_irq(jme); -- -+ spin_lock_irqsave(&jme->asd_lock, flags); -+ if (jme->flag_run_asd) -+ del_timer_sync(&jme->asd_timer); -+ spin_unlock_irqrestore(&jme->asd_lock, flags); - tasklet_disable(&jme->txclean_task); - tasklet_disable(&jme->rxclean_task); - tasklet_disable(&jme->rxempty_task); -@@ -3268,21 +3809,37 @@ - tasklet_hi_enable(&jme->rxempty_task); - - jme_powersave_phy(jme); -+ jme->media_cnct_sec = 0; -+ jme->media_cnct = false; -+#ifndef JME_NEW_PM_API -+ pci_save_state(pdev); -+ jme_pci_wakeup_enable(jme, !!(jme->reg_pmcs)); -+ pci_set_power_state(pdev, PCI_D3hot); -+#endif - - return 0; - } - - static int -+#ifdef JME_NEW_PM_API - jme_resume(struct device *dev) -+#else -+jme_resume(struct pci_dev *pdev) -+#endif - { -+#ifdef JME_NEW_PM_API - struct pci_dev *pdev = to_pci_dev(dev); -+#endif - struct net_device *netdev = pci_get_drvdata(pdev); - struct jme_adapter *jme = netdev_priv(netdev); -- -- if (!netif_running(netdev)) -- return 0; -+ unsigned long flags; - - jme_clear_pm(jme); -+#ifndef JME_NEW_PM_API -+ pci_set_power_state(pdev, PCI_D0); -+ pci_restore_state(pdev); -+#endif -+ - jme_phy_on(jme); - if (test_bit(JME_FLAG_SSET, &jme->flags)) - jme_set_settings(netdev, &jme->old_ecmd); -@@ -3296,19 +3853,35 @@ - atomic_inc(&jme->link_changing); - - jme_reset_link(jme); -- -+ spin_lock_irqsave(&jme->asd_lock, flags); -+ if (jme->flag_run_asd) { -+ jme_check_ANcomplete(jme); -+ jme->asd_timer.expires = jiffies + 4*HZ; -+ jme->asd_timer.function = &asd_polling_func; -+ jme->asd_timer.data = (unsigned long)jme; -+ add_timer(&jme->asd_timer); -+ } -+ spin_unlock_irqrestore(&jme->asd_lock, flags); - return 0; - } - -+#ifdef JME_NEW_PM_API - static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume); - #define JME_PM_OPS (&jme_pm_ops) -+#endif - - #else - -+#ifdef JME_NEW_PM_API - #define JME_PM_OPS NULL - #endif -+#endif - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24) -+static struct pci_device_id jme_pci_tbl[] = { -+#else - static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = { -+#endif - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC250) }, - { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMC260) }, - { } -@@ -3320,7 +3893,12 @@ - .probe = jme_init_one, - .remove = __devexit_p(jme_remove_one), - .shutdown = jme_shutdown, -+#ifndef JME_NEW_PM_API -+ .suspend = jme_suspend, -+ .resume = jme_resume -+#else - .driver.pm = JME_PM_OPS, -+#endif - }; - - static int __init -@@ -3344,3 +3922,4 @@ - MODULE_LICENSE("GPL"); - MODULE_VERSION(DRV_VERSION); - MODULE_DEVICE_TABLE(pci, jme_pci_tbl); -+ -diff -Naur linux-3.7.2/drivers/net/ethernet/jme.h linux-3.7.2.patch/drivers/net/ethernet/jme.h ---- linux-3.7.2/drivers/net/ethernet/jme.h 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/net/ethernet/jme.h 2013-01-16 10:11:32.534765166 +0100 -@@ -27,7 +27,7 @@ - #include - - #define DRV_NAME "jme" --#define DRV_VERSION "1.0.8" -+#define DRV_VERSION "1.0.8.5-jmmod" - #define PFX DRV_NAME ": " - - #define PCI_DEVICE_ID_JMICRON_JMC250 0x0250 -@@ -43,6 +43,15 @@ - NETIF_MSG_TX_ERR | \ - NETIF_MSG_HW) - -+#ifndef pr_err -+#define pr_err(fmt, arg...) \ -+ printk(KERN_ERR fmt, ##arg) -+#endif -+#ifndef netdev_err -+#define netdev_err(netdev, fmt, arg...) \ -+ pr_err(fmt, ##arg) -+#endif -+ - #ifdef TX_DEBUG - #define tx_dbg(priv, fmt, args...) \ - printk(KERN_DEBUG "%s: " fmt, (priv)->dev->name, ##args) -@@ -54,6 +63,55 @@ - } while (0) - #endif - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,33) -+#define jme_msg(msglvl, type, priv, fmt, args...) \ -+ if (netif_msg_##type(priv)) \ -+ printk(msglvl "%s: " fmt, (priv)->dev->name, ## args) -+ -+#define msg_probe(priv, fmt, args...) \ -+ jme_msg(KERN_INFO, probe, priv, fmt, ## args) -+ -+#define msg_link(priv, fmt, args...) \ -+ jme_msg(KERN_INFO, link, priv, fmt, ## args) -+ -+#define msg_intr(priv, fmt, args...) \ -+ jme_msg(KERN_INFO, intr, priv, fmt, ## args) -+ -+#define msg_rx_err(priv, fmt, args...) \ -+ jme_msg(KERN_ERR, rx_err, priv, fmt, ## args) -+ -+#define msg_rx_status(priv, fmt, args...) \ -+ jme_msg(KERN_INFO, rx_status, priv, fmt, ## args) -+ -+#define msg_tx_err(priv, fmt, args...) \ -+ jme_msg(KERN_ERR, tx_err, priv, fmt, ## args) -+ -+#define msg_tx_done(priv, fmt, args...) \ -+ jme_msg(KERN_INFO, tx_done, priv, fmt, ## args) -+ -+#define msg_tx_queued(priv, fmt, args...) \ -+ jme_msg(KERN_INFO, tx_queued, priv, fmt, ## args) -+ -+#define msg_hw(priv, fmt, args...) \ -+ jme_msg(KERN_ERR, hw, priv, fmt, ## args) -+ -+#ifndef netif_info -+#define netif_info(priv, type, dev, fmt, args...) \ -+ msg_ ## type(priv, fmt, ## args) -+#endif -+#ifndef netif_err -+#define netif_err(priv, type, dev, fmt, args...) \ -+ msg_ ## type(priv, fmt, ## args) -+#endif -+#endif -+ -+#ifndef NETIF_F_TSO6 -+#define NETIF_F_TSO6 0 -+#endif -+#ifndef NETIF_F_IPV6_CSUM -+#define NETIF_F_IPV6_CSUM 0 -+#endif -+ - /* - * Extra PCI Configuration space interface - */ -@@ -102,6 +160,7 @@ - }; - - #define HALF_US 500 /* 500 ns */ -+#define JMESPIIOCTL SIOCDEVPRIVATE - - #define PCI_PRIV_PE1 0xE4 - -@@ -388,10 +447,75 @@ - atomic_t nr_free; - }; - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,18) -+#define false 0 -+#define true 0 -+#define netdev_alloc_skb(dev, len) dev_alloc_skb(len) -+#define PCI_VENDOR_ID_JMICRON 0x197B -+#endif -+ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,19) -+#define PCI_VDEVICE(vendor, device) \ -+ PCI_VENDOR_ID_##vendor, (device), \ -+ PCI_ANY_ID, PCI_ANY_ID, 0, 0 -+#endif -+ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) -+#define NET_STAT(priv) priv->stats -+#define NETDEV_GET_STATS(netdev, fun_ptr) \ -+ netdev->get_stats = fun_ptr -+#define DECLARE_NET_DEVICE_STATS struct net_device_stats stats; -+/* -+ * CentOS 5.2 have *_hdr helpers back-ported -+ */ -+#ifdef RHEL_RELEASE_CODE -+#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,2) -+#define __DEFINE_IPHDR_HELPERS__ -+#endif -+#else -+#define __DEFINE_IPHDR_HELPERS__ -+#endif -+#else - #define NET_STAT(priv) (priv->dev->stats) - #define NETDEV_GET_STATS(netdev, fun_ptr) - #define DECLARE_NET_DEVICE_STATS -+#endif -+ -+#ifdef __DEFINE_IPHDR_HELPERS__ -+static inline struct iphdr *ip_hdr(const struct sk_buff *skb) -+{ -+ return skb->nh.iph; -+} -+ -+static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb) -+{ -+ return skb->nh.ipv6h; -+} - -+static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb) -+{ -+ return skb->h.th; -+} -+#endif -+ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) -+#define DECLARE_NAPI_STRUCT -+#define NETIF_NAPI_SET(dev, napis, pollfn, q) \ -+ dev->poll = pollfn; \ -+ dev->weight = q; -+#define JME_NAPI_HOLDER(holder) struct net_device *holder -+#define JME_NAPI_WEIGHT(w) int *w -+#define JME_NAPI_WEIGHT_VAL(w) *w -+#define JME_NAPI_WEIGHT_SET(w, r) *w = r -+#define DECLARE_NETDEV struct net_device *netdev = jme->dev; -+#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(dev) -+#define JME_NAPI_ENABLE(priv) netif_poll_enable(priv->dev); -+#define JME_NAPI_DISABLE(priv) netif_poll_disable(priv->dev); -+#define JME_RX_SCHEDULE_PREP(priv) \ -+ netif_rx_schedule_prep(priv->dev) -+#define JME_RX_SCHEDULE(priv) \ -+ __netif_rx_schedule(priv->dev); -+#else - #define DECLARE_NAPI_STRUCT struct napi_struct napi; - #define NETIF_NAPI_SET(dev, napis, pollfn, q) \ - netif_napi_add(dev, napis, pollfn, q); -@@ -399,6 +523,7 @@ - #define JME_NAPI_WEIGHT(w) int w - #define JME_NAPI_WEIGHT_VAL(w) w - #define JME_NAPI_WEIGHT_SET(w, r) -+#define DECLARE_NETDEV - #define JME_RX_COMPLETE(dev, napis) napi_complete(napis) - #define JME_NAPI_ENABLE(priv) napi_enable(&priv->napi); - #define JME_NAPI_DISABLE(priv) \ -@@ -408,6 +533,18 @@ - napi_schedule_prep(&priv->napi) - #define JME_RX_SCHEDULE(priv) \ - __napi_schedule(&priv->napi); -+#endif -+ -+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38) -+#define JME_NEW_PM_API -+#endif -+ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,26) -+static inline __u32 ethtool_cmd_speed(struct ethtool_cmd *ep) -+{ -+ return ep->speed; -+} -+#endif - - /* - * Jmac Adapter Private data -@@ -427,6 +564,7 @@ - struct tasklet_struct txclean_task; - struct tasklet_struct linkch_task; - struct tasklet_struct pcc_task; -+ struct work_struct LC_task; - unsigned long flags; - u32 reg_txcs; - u32 reg_txpfc; -@@ -450,6 +588,7 @@ - u32 msg_enable; - struct ethtool_cmd old_ecmd; - unsigned int old_mtu; -+ struct vlan_group *vlgrp; - struct dynpcc_info dpi; - atomic_t intr_sem; - atomic_t link_changing; -@@ -457,13 +596,32 @@ - atomic_t rx_cleaning; - atomic_t rx_empty; - int (*jme_rx)(struct sk_buff *skb); -+ spinlock_t asd_lock; -+ u8 flag_run_asd; -+ u32 media_cnct_sec; -+ u8 media_cnct; -+ struct timer_list asd_timer; -+ int (*jme_vlan_rx)(struct sk_buff *skb, -+ struct vlan_group *grp, -+ unsigned short vlan_tag); - DECLARE_NAPI_STRUCT - DECLARE_NET_DEVICE_STATS - }; - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21) -+static struct net_device_stats * -+jme_get_stats(struct net_device *netdev) -+{ -+ struct jme_adapter *jme = netdev_priv(netdev); -+ return &jme->stats; -+} -+#endif -+ - enum jme_flags_bits { - JME_FLAG_MSI = 1, - JME_FLAG_SSET = 2, -+ JME_FLAG_TXCSUM = 3, -+ JME_FLAG_TSO = 4, - JME_FLAG_POLL = 5, - JME_FLAG_SHUTDOWN = 6, - }; -@@ -472,6 +630,15 @@ - #define JME_REG_LEN 0x500 - #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9216 - -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) -+static inline struct jme_adapter* -+jme_napi_priv(struct net_device *holder) -+{ -+ struct jme_adapter *jme; -+ jme = netdev_priv(holder); -+ return jme; -+} -+#else - static inline struct jme_adapter* - jme_napi_priv(struct napi_struct *napi) - { -@@ -479,6 +646,7 @@ - jme = container_of(napi, struct jme_adapter, napi); - return jme; - } -+#endif - - /* - * MMaped I/O Resters -@@ -730,7 +898,7 @@ - RXCS_RETRYCNT_60 = 0x00000F00, - - RXCS_DEFAULT = RXCS_FIFOTHTP_128T | -- RXCS_FIFOTHNP_16QW | -+ RXCS_FIFOTHNP_128QW | - RXCS_DMAREQSZ_128B | - RXCS_RETRYGAP_256ns | - RXCS_RETRYCNT_32, -@@ -762,20 +930,20 @@ - - /* Extern PHY common register 2 */ - --#define PHY_GAD_TEST_MODE_1 0x00002000 --#define PHY_GAD_TEST_MODE_MSK 0x0000E000 --#define JM_PHY_SPEC_REG_READ 0x00004000 --#define JM_PHY_SPEC_REG_WRITE 0x00008000 --#define PHY_CALIBRATION_DELAY 20 -+#define PHY_GAD_TEST_MODE_1 0x00002000 //BIT_13 GIGA Test mode 1 -+#define PHY_GAD_TEST_MODE_MSK 0x0000E000 //BIT_13_15 GIGA Test mode mask -+#define JM_PHY_SPEC_REG_READ 0x00004000 //BIT_14 -+#define JM_PHY_SPEC_REG_WRITE 0x00008000 //BIT_15 -+#define PHY_CALIBRATION_DELAY 20 // 20 milliseconds - #define JM_PHY_SPEC_ADDR_REG 0x1E - #define JM_PHY_SPEC_DATA_REG 0x1F - - #define JM_PHY_EXT_COMM_0_REG 0x30 --#define JM_PHY_EXT_COMM_1_REG 0x31 -+#define JM_PHY_EXT_COMM_1_REG 0x31 - #define JM_PHY_EXT_COMM_2_REG 0x32 --#define JM_PHY_EXT_COMM_2_CALI_ENABLE 0x01 --#define JM_PHY_EXT_COMM_2_CALI_MODE_0 0x02 --#define JM_PHY_EXT_COMM_2_CALI_LATCH 0x10 -+#define JM_PHY_EXT_COMM_2_CALI_ENABLE 0x01 //BIT_0 -+#define JM_PHY_EXT_COMM_2_CALI_MODE_0 0x02 //BIT_1 -+#define JM_PHY_EXT_COMM_2_CALI_LATCH 0x10 //BIT_4 - #define PCI_PRIV_SHARE_NICCTRL 0xF5 - #define JME_FLAG_PHYEA_ENABLE 0x2 - -@@ -908,6 +1076,14 @@ - }; - - /* -+ * False carrier Counter -+ */ -+enum jme_phy_an_status { -+ PHY_SPEC_STATUS_AN_COMPLETE = 0x00000800, -+ PHY_SPEC_STATUS_AN_FAIL = 0x00008000, -+}; -+ -+/* - * Giga PHY Status Registers - */ - enum jme_phy_link_bit_mask { -@@ -1277,3 +1453,4 @@ - static void jme_set_multi(struct net_device *netdev); - - #endif -+ diff --git a/packages/linux/patches/3.9.8/linux-900-hide_tsc_error.patch b/packages/linux/patches/3.9.8/linux-900-hide_tsc_error.patch deleted file mode 100644 index 61b73b69b0..0000000000 --- a/packages/linux/patches/3.9.8/linux-900-hide_tsc_error.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -uNr linux-3.6.4-orig/arch/x86/kernel/tsc.c linux-3.6.4-new/arch/x86/kernel/tsc.c ---- linux-3.6.4-orig/arch/x86/kernel/tsc.c 2012-11-03 14:19:55.000000000 +0100 -+++ linux-3.6.4-new/arch/x86/kernel/tsc.c 2012-11-03 14:23:05.000000000 +0100 -@@ -374,7 +374,7 @@ - goto success; - } - } -- pr_err("Fast TSC calibration failed\n"); -+ pr_info("Fast TSC calibration failed\n"); - return 0; - - success: diff --git a/packages/linux/patches/3.9.8/linux-950-saa716x_PCIe_interface_chipset.patch b/packages/linux/patches/3.9.8/linux-950-saa716x_PCIe_interface_chipset.patch deleted file mode 100644 index d2ee6111cc..0000000000 --- a/packages/linux/patches/3.9.8/linux-950-saa716x_PCIe_interface_chipset.patch +++ /dev/null @@ -1,12914 +0,0 @@ -diff -Naur linux-3.7.2/drivers/media/common/Kconfig linux-3.7.2.patch/drivers/media/common/Kconfig ---- linux-3.7.2/drivers/media/common/Kconfig 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/Kconfig 2013-01-16 10:52:04.586923233 +0100 -@@ -1,3 +1,4 @@ - source "drivers/media/common/b2c2/Kconfig" - source "drivers/media/common/saa7146/Kconfig" -+source "drivers/media/common/saa716x/Kconfig" - source "drivers/media/common/siano/Kconfig" -diff -Naur linux-3.7.2/drivers/media/common/Makefile linux-3.7.2.patch/drivers/media/common/Makefile ---- linux-3.7.2/drivers/media/common/Makefile 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/Makefile 2013-01-16 10:52:15.443844483 +0100 -@@ -1 +1 @@ --obj-y += b2c2/ saa7146/ siano/ -+obj-y += b2c2/ saa7146/ saa716x/ siano/ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/Kconfig linux-3.7.2.patch/drivers/media/common/saa716x/Kconfig ---- linux-3.7.2/drivers/media/common/saa716x/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/Kconfig 2013-01-16 10:41:10.906798319 +0100 -@@ -0,0 +1,67 @@ -+menuconfig SAA716X_SUPPORT -+ bool "Support for SAA716x family from NXP/Philips" -+ depends on PCI && I2C -+ help -+ support for saa716x -+ -+if SAA716X_SUPPORT -+config SAA716X_CORE -+ tristate "SAA7160/1/2 PCI Express bridge based devices" -+ depends on PCI && I2C -+ -+ help -+ Support for PCI cards based on the SAA7160/1/2 PCI Express bridge. -+ -+ Say Y if you own such a device and want to use it. -+ -+config DVB_SAA716X_BUDGET -+ tristate "SAA7160/1/2 based Budget PCIe cards (DVB only)" -+ depends on SAA716X_CORE && DVB_CORE -+ select DVB_DS3000 if !DVB_FE_CUSTOMISE -+ select DVB_DS3103 if !DVB_FE_CUSTOMISE -+ select DVB_TS2022 if !DVB_FE_CUSTOMISE -+ -+ help -+ Support for the SAA7160/1/2 based Budget PCIe DVB cards -+ Currently supported devices are: -+ -+ * KNC1 Dual S2 (DVB-S, DVB-S/S2) -+ * Twinhan/Azurewave VP-1028 (DVB-S) -+ * Twinhan/Azurewave VP-3071 (DVB-T x2) -+ * Twinhan/Azurewave VP-6002 (DVB-S) -+ -+ Say Y if you own such a device and want to use it. -+ -+config DVB_SAA716X_HYBRID -+ tristate "SAA7160/1/2 based Hybrid PCIe cards (DVB + Analog)" -+ depends on SAA716X_CORE && DVB_CORE -+ -+ help -+ Support for the SAA7160/1/2 based Hybrid PCIe DVB cards -+ Currently supported devices are: -+ -+ * Avermedia H-788 (DVB-T) -+ * Avermedia HC-82 (DVB-T) -+ * NXP Reference (Atlantis) (DVB-T x2) -+ * NXP Reference (Nemo) (DVB-T) -+ * Twinhan/Azurewave VP-6090 (DVB-S x2, DVB-T x2) -+ -+ Say Y if you own such a device and want to use it. -+ -+#config DVB_SAA716X_FF -+# tristate "SAA7160/1/2 based Full Fledged PCIe cards" -+# depends on SAA716X_CORE && DVB_CORE -+# depends on INPUT # IR -+# default n -+ -+# help -+# Support for the SAA7160/1/2 based Full fledged PCIe DVB cards -+# These cards do feature a hardware MPEG decoder and other -+# peripherals. Also known as Premium cards. -+# Currently supported devices are: -+ -+# * Technotrend S2 6400 Dual S2 HD (DVB-S/S2 x2) -+ -+# Say Y if you own such a device and want to use it. -+ -+endif # SAA716X_SUPPORT -diff -Naur linux-3.7.2/drivers/media/common/saa716x/Makefile linux-3.7.2.patch/drivers/media/common/saa716x/Makefile ---- linux-3.7.2/drivers/media/common/saa716x/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/Makefile 2013-01-16 10:54:20.634929700 +0100 -@@ -0,0 +1,26 @@ -+saa716x_core-objs := saa716x_pci.o \ -+ saa716x_i2c.o \ -+ saa716x_cgu.o \ -+ saa716x_msi.o \ -+ saa716x_dma.o \ -+ saa716x_vip.o \ -+ saa716x_aip.o \ -+ saa716x_phi.o \ -+ saa716x_boot.o \ -+ saa716x_fgpi.o \ -+ saa716x_adap.o \ -+ saa716x_gpio.o \ -+ saa716x_greg.o \ -+ saa716x_rom.o \ -+ saa716x_spi.o -+ -+#saa716x_ff-objs := saa716x_ff_main.o \ -+# saa716x_ff_cmd.o \ -+# saa716x_ff_ir.o -+ -+obj-$(CONFIG_SAA716X_CORE) += saa716x_core.o -+obj-$(CONFIG_DVB_SAA716X_BUDGET) += saa716x_budget.o -+obj-$(CONFIG_DVB_SAA716X_HYBRID) += saa716x_hybrid.o -+#obj-$(CONFIG_DVB_SAA716X_FF) += saa716x_ff.o -+ -+EXTRA_CFLAGS = -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/ -Idrivers/media/tuners/ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_adap.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_adap.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_adap.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_adap.c 2013-01-16 10:41:10.907798312 +0100 -@@ -0,0 +1,274 @@ -+#include -+ -+#include "dmxdev.h" -+#include "dvbdev.h" -+#include "dvb_demux.h" -+#include "dvb_frontend.h" -+ -+#include "saa716x_mod.h" -+#include "saa716x_spi.h" -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_gpio.h" -+#include "saa716x_priv.h" -+#include "saa716x_budget.h" -+ -+ -+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); -+ -+ -+void saa716x_dma_start(struct saa716x_dev *saa716x, u8 adapter) -+{ -+ struct fgpi_stream_params params; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Start DMA engine for Adapter:%d", adapter); -+ -+ params.bits = 8; -+ params.samples = 188; -+ params.lines = 348; -+ params.pitch = 188; -+ params.offset = 0; -+ params.page_tables = 0; -+ params.stream_type = FGPI_TRANSPORT_STREAM; -+ params.stream_flags = 0; -+ -+ saa716x_fgpi_start(saa716x, saa716x->config->adap_config[adapter].ts_port, ¶ms); -+} -+ -+void saa716x_dma_stop(struct saa716x_dev *saa716x, u8 adapter) -+{ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Stop DMA engine for Adapter:%d", adapter); -+ -+ saa716x_fgpi_stop(saa716x, saa716x->config->adap_config[adapter].ts_port); -+} -+ -+static int saa716x_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed) -+{ -+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -+ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; -+ struct saa716x_dev *saa716x = saa716x_adap->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Start feed"); -+ if (!dvbdmx->dmx.frontend) { -+ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); -+ return -EINVAL; -+ } -+ saa716x_adap->feeds++; -+ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed, feeds=%d", -+ saa716x_adap->feeds); -+ -+ if (saa716x_adap->feeds == 1) { -+ dprintk(SAA716x_DEBUG, 1, "SAA716x start feed & dma"); -+ saa716x_dma_start(saa716x, saa716x_adap->count); -+ } -+ -+ return saa716x_adap->feeds; -+} -+ -+static int saa716x_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed) -+{ -+ struct dvb_demux *dvbdmx = dvbdmxfeed->demux; -+ struct saa716x_adapter *saa716x_adap = dvbdmx->priv; -+ struct saa716x_dev *saa716x = saa716x_adap->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA716x DVB Stop feed"); -+ if (!dvbdmx->dmx.frontend) { -+ dprintk(SAA716x_DEBUG, 1, "no frontend ?"); -+ return -EINVAL; -+ } -+ saa716x_adap->feeds--; -+ if (saa716x_adap->feeds == 0) { -+ dprintk(SAA716x_DEBUG, 1, "saa716x stop feed and dma"); -+ saa716x_dma_stop(saa716x, saa716x_adap->count); -+ } -+ -+ return 0; -+} -+ -+int saa716x_dvb_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct saa716x_config *config = saa716x->config; -+ int result, i; -+ -+ mutex_init(&saa716x->adap_lock); -+ -+ for (i = 0; i < config->adapters; i++) { -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_register_adapter"); -+ if (dvb_register_adapter(&saa716x_adap->dvb_adapter, -+ "SAA716x dvb adapter", -+ THIS_MODULE, -+ &saa716x->pdev->dev, -+ adapter_nr) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "Error registering adapter"); -+ return -ENODEV; -+ } -+ -+ saa716x_adap->count = i; -+ -+ saa716x_adap->dvb_adapter.priv = saa716x_adap; -+ saa716x_adap->demux.dmx.capabilities = DMX_TS_FILTERING | -+ DMX_SECTION_FILTERING | -+ DMX_MEMORY_BASED_FILTERING; -+ -+ saa716x_adap->demux.priv = saa716x_adap; -+ saa716x_adap->demux.filternum = 256; -+ saa716x_adap->demux.feednum = 256; -+ saa716x_adap->demux.start_feed = saa716x_dvb_start_feed; -+ saa716x_adap->demux.stop_feed = saa716x_dvb_stop_feed; -+ saa716x_adap->demux.write_to_decoder = NULL; -+ switch (saa716x->pdev->subsystem_device) { -+ case TEVII_S472: { -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ u8 mac[6]; -+ u8 b0[] = { 0, 9 }; -+ struct i2c_msg msg[] = { -+ { -+ .addr = 0x50, -+ .flags = 0, -+ .buf = b0, -+ .len = 2 -+ }, { -+ .addr = 0x50, -+ .flags = I2C_M_RD, -+ .buf = mac, -+ .len = 6 -+ } -+ }; -+ -+ i2c_transfer(adapter, msg, 2); -+ dprintk(SAA716x_INFO, 1, "TeVii S472 MAC= %pM\n", mac); -+ memcpy(saa716x_adap->dvb_adapter.proposed_mac, mac, 6); -+ } -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_dmx_init"); -+ if ((result = dvb_dmx_init(&saa716x_adap->demux)) < 0) { -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err0; -+ } -+ -+ saa716x_adap->dmxdev.filternum = 256; -+ saa716x_adap->dmxdev.demux = &saa716x_adap->demux.dmx; -+ saa716x_adap->dmxdev.capabilities = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_dmxdev_init"); -+ if ((result = dvb_dmxdev_init(&saa716x_adap->dmxdev, -+ &saa716x_adap->dvb_adapter)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result); -+ goto err1; -+ } -+ -+ saa716x_adap->fe_hw.source = DMX_FRONTEND_0; -+ -+ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_hw)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err2; -+ } -+ -+ saa716x_adap->fe_mem.source = DMX_MEMORY_FE; -+ -+ if ((result = saa716x_adap->demux.dmx.add_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_mem)) < 0) { -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err3; -+ } -+ -+ if ((result = saa716x_adap->demux.dmx.connect_frontend(&saa716x_adap->demux.dmx, -+ &saa716x_adap->fe_hw)) < 0) { -+ -+ dprintk(SAA716x_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result); -+ goto err4; -+ } -+ -+ dvb_net_init(&saa716x_adap->dvb_adapter, &saa716x_adap->dvb_net, &saa716x_adap->demux.dmx); -+// tasklet_init(&saa716x_adap->tasklet, saa716x_dma_xfer, (unsigned long) saa716x); -+ dprintk(SAA716x_DEBUG, 1, "Frontend Init"); -+ saa716x_adap->saa716x = saa716x; -+ -+ if (config->frontend_attach) { -+ result = config->frontend_attach(saa716x_adap, i); -+ if (result < 0) -+ dprintk(SAA716x_ERROR, 1, "SAA716x frontend attach failed"); -+ -+ if (saa716x_adap->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "A frontend driver was not found for [%04x:%04x] subsystem [%04x:%04x]\n", -+ saa716x->pdev->vendor, -+ saa716x->pdev->device, -+ saa716x->pdev->subsystem_vendor, -+ saa716x->pdev->subsystem_device); -+ } else { -+ result = dvb_register_frontend(&saa716x_adap->dvb_adapter, saa716x_adap->fe); -+ if (result < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x register frontend failed"); -+ goto err6; -+ } -+ } -+ -+ } else { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach = NULL"); -+ } -+ -+ saa716x_fgpi_init(saa716x, config->adap_config[i].ts_port, -+ config->adap_config[i].worker); -+ -+ saa716x_adap++; -+ } -+ -+ -+ return 0; -+ -+ /* Error conditions */ -+err6: -+ dvb_frontend_detach(saa716x_adap->fe); -+err4: -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); -+err3: -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); -+err2: -+ dvb_dmxdev_release(&saa716x_adap->dmxdev); -+err1: -+ dvb_dmx_release(&saa716x_adap->demux); -+err0: -+ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); -+ -+ return result; -+} -+EXPORT_SYMBOL(saa716x_dvb_init); -+ -+void saa716x_dvb_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ int i; -+ -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ -+ saa716x_fgpi_exit(saa716x, saa716x->config->adap_config[i].ts_port); -+ -+ if (saa716x_adap->fe) { -+ dvb_unregister_frontend(saa716x_adap->fe); -+ dvb_frontend_detach(saa716x_adap->fe); -+ } -+ -+// tasklet_kill(&saa716x->tasklet); -+ dvb_net_release(&saa716x_adap->dvb_net); -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_mem); -+ saa716x_adap->demux.dmx.remove_frontend(&saa716x_adap->demux.dmx, &saa716x_adap->fe_hw); -+ dvb_dmxdev_release(&saa716x_adap->dmxdev); -+ dvb_dmx_release(&saa716x_adap->demux); -+ -+ dprintk(SAA716x_DEBUG, 1, "dvb_unregister_adapter"); -+ dvb_unregister_adapter(&saa716x_adap->dvb_adapter); -+ -+ saa716x_adap++; -+ } -+ -+ return; -+} -+EXPORT_SYMBOL(saa716x_dvb_exit); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_adap.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_adap.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_adap.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_adap.h 2013-01-16 10:41:10.907798312 +0100 -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_ADAP_H -+#define __SAA716x_ADAP_H -+ -+struct saa716x_dev; -+ -+extern int saa716x_dvb_init(struct saa716x_dev *saa716x); -+extern void saa716x_dvb_exit(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_ADAP_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_aip.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_aip.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip.c 2013-01-16 10:41:10.907798312 +0100 -@@ -0,0 +1,20 @@ -+#include -+ -+#include "saa716x_mod.h" -+#include "saa716x_aip_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_aip.h" -+#include "saa716x_priv.h" -+ -+int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev) -+{ -+ return SAA716x_EPRD(dev, AI_CTL) == 0 ? 0 : -1; -+} -+EXPORT_SYMBOL_GPL(saa716x_aip_status); -+ -+void saa716x_aip_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(AI0, AI_CTL, 0x00); -+ SAA716x_EPWR(AI1, AI_CTL, 0x00); -+} -+EXPORT_SYMBOL_GPL(saa716x_aip_disable); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_aip.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_aip.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip.h 2013-01-16 10:41:10.907798312 +0100 -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_AIP_H -+#define __SAA716x_AIP_H -+ -+struct saa716x_dev; -+ -+extern int saa716x_aip_status(struct saa716x_dev *saa716x, u32 dev); -+extern void saa716x_aip_disable(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_AIP_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_aip_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_aip_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_aip_reg.h 2013-01-16 10:41:10.908798304 +0100 -@@ -0,0 +1,62 @@ -+#ifndef __SAA716x_AIP_REG_H -+#define __SAA716x_AIP_REG_H -+ -+/* -------------- AI Registers ---------------- */ -+ -+#define AI_STATUS 0x000 -+#define AI_BUF1_ACTIVE (0x00000001 << 4) -+#define AI_OVERRUN (0x00000001 << 3) -+#define AI_HBE (0x00000001 << 2) -+#define AI_BUF2_FULL (0x00000001 << 1) -+#define AI_BUF1_FULL (0x00000001 << 0) -+ -+#define AI_CTL 0x004 -+#define AI_RESET (0x00000001 << 31) -+#define AI_CAP_ENABLE (0x00000001 << 30) -+#define AI_CAP_MODE (0x00000003 << 28) -+#define AI_SIGN_CONVERT (0x00000001 << 27) -+#define AI_EARLYMODE (0x00000001 << 26) -+#define AI_DIAGMODE (0x00000001 << 25) -+#define AI_RAWMODE (0x00000001 << 24) -+#define AI_OVR_INTEN (0x00000001 << 7) -+#define AI_HBE_INTEN (0x00000001 << 6) -+#define AI_BUF2_INTEN (0x00000001 << 5) -+#define AI_BUF1_INTEN (0x00000001 << 4) -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_SERIAL 0x008 -+#define AI_SER_MASTER (0x00000001 << 31) -+#define AI_DATAMODE (0x00000001 << 30) -+#define AI_FRAMEMODE (0x00000003 << 28) -+#define AI_CLOCK_EDGE (0x00000001 << 27) -+#define AI_SSPOS4 (0x00000001 << 19) -+#define AI_NR_CHAN (0x00000003 << 17) -+#define AI_WSDIV (0x000001ff << 8) -+#define AI_SCKDIV (0x000000ff << 0) -+ -+#define AI_FRAMING 0x00c -+#define AI_VALIDPOS (0x000001ff << 22) -+#define AI_LEFTPOS (0x000001ff << 13) -+#define AI_RIGHTPOS (0x000001ff << 4) -+#define AI_SSPOS_3_0 (0x0000000f << 0) -+ -+#define AI_BASE1 0x014 -+#define AI_BASE2 0x018 -+#define AI_BASE (0x03ffffff << 6) -+ -+#define AI_SIZE 0x01c -+#define AI_SAMPLE_SIZE (0x03ffffff << 6) -+ -+#define AI_INT_ACK 0x020 -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_PWR_DOWN 0xff4 -+#define AI_PWR_DWN (0x00000001 << 0) -+ -+#endif /* __SAA716x_AIP_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_boot.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_boot.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_boot.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_boot.c 2013-01-16 10:41:10.908798304 +0100 -@@ -0,0 +1,319 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_greg_reg.h" -+#include "saa716x_cgu_reg.h" -+#include "saa716x_vip_reg.h" -+#include "saa716x_aip_reg.h" -+#include "saa716x_msi_reg.h" -+#include "saa716x_dma_reg.h" -+#include "saa716x_gpio_reg.h" -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_dcs_reg.h" -+ -+#include "saa716x_boot.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static int saa716x_ext_boot(struct saa716x_dev *saa716x) -+{ -+ /* Write GREG boot_ready to 0 -+ * DW_0 = 0x0001_2018 -+ * DW_1 = 0x0000_0000 -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000000); -+ -+ /* Clear VI0 interrupt -+ * DW_2 = 0x0000_0fe8 -+ * DW_3 = 0x0000_03ff -+ */ -+ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x000003ff); -+ -+ /* Clear VI1 interrupt -+ * DW_4 = 0x0000_1fe8 -+ * DW_5 = 0x0000_03ff -+ */ -+ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x000003ff); -+ -+ /* CLear FGPI0 interrupt -+ * DW_6 = 0x0000_2fe8 -+ * DW_7 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI0, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI1 interrupt -+ * DW_8 = 0x0000_3fe8 -+ * DW_9 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI1, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI2 interrupt -+ * DW_10 = 0x0000_4fe8 -+ * DW_11 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI2, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear FGPI3 interrupt -+ * DW_12 = 0x0000_5fe8 -+ * DW_13 = 0x0000_007f -+ */ -+ SAA716x_EPWR(FGPI3, INT_CLR_STATUS, 0x0000007f); -+ -+ /* Clear AI0 interrupt -+ * DW_14 = 0x0000_6020 -+ * DW_15 = 0x0000_000f -+ */ -+ SAA716x_EPWR(AI0, AI_INT_ACK, 0x0000000f); -+ -+ /* Clear AI1 interrupt -+ * DW_16 = 0x0000_7020 -+ * DW_17 = 0x0000_200f -+ */ -+ SAA716x_EPWR(AI1, AI_INT_ACK, 0x0000000f); -+ -+ /* Set GREG boot_ready bit to 1 -+ * DW_18 = 0x0001_2018 -+ * DW_19 = 0x0000_2000 -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); -+#if 0 -+ /* End of Boot script command -+ * DW_20 = 0x0000_0006 -+ * Where to write this value ?? -+ * This seems very odd an address to trigger the -+ * Boot Control State Machine ! -+ */ -+ SAA716x_EPWR(VI0, 0x00000006, 0xffffffff); -+#endif -+ return 0; -+} -+ -+/* Internal Bootscript configuration */ -+static void saa716x_int_boot(struct saa716x_dev *saa716x) -+{ -+ /* #1 Configure PCI COnfig space -+ * GREG_JETSTR_CONFIG_0 -+ */ -+ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, saa716x->pdev->subsystem_vendor); -+ -+ /* GREG_JETSTR_CONFIG_1 -+ * pmcsr_scale:7 = 0x00 -+ * pmcsr_scale:6 = 0x00 -+ * pmcsr_scale:5 = 0x00 -+ * pmcsr_scale:4 = 0x00 -+ * pmcsr_scale:3 = 0x00 -+ * pmcsr_scale:2 = 0x00 -+ * pmcsr_scale:1 = 0x00 -+ * pmcsr_scale:0 = 0x00 -+ * BAR mask = 20 bit -+ * BAR prefetch = no -+ * MSI capable = 32 messages -+ */ -+ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, 0x00001005); -+ -+ /* GREG_JETSTR_CONFIG_2 -+ * pmcsr_data:3 = 0x0 -+ * pmcsr_data:2 = 0x0 -+ * pmcsr_data:1 = 0x0 -+ * pmcsr_data:0 = 0x0 -+ */ -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, 0x00000000); -+ -+ /* GREG_JETSTR_CONFIG_3 -+ * pmcsr_data:7 = 0x0 -+ * pmcsr_data:6 = 0x0 -+ * pmcsr_data:5 = 0x0 -+ * pmcsr_data:4 = 0x0 -+ */ -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, 0x00000000); -+ -+ /* #2 Release GREG resets -+ * ip_rst_an -+ * dpa1_rst_an -+ * jetsream_reset_an -+ */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00000e00); -+ -+ /* #3 GPIO Setup -+ * GPIO 25:24 = Output -+ * GPIO Output "0" after Reset -+ */ -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); -+ -+ /* #4 Custom stuff goes in here */ -+ -+ /* #5 Disable CGU Clocks -+ * except for PHY, Jetstream, DPA1, DCS, Boot, GREG -+ * CGU_PCR_0_3: pss_mmu_clk:0 = 0x0 -+ */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_3, 0x00000006); -+ -+ /* CGU_PCR_0_4: pss_dtl2mtl_mmu_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_4, 0x00000006); -+ -+ /* CGU_PCR_0_5: pss_msi_ck:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_5, 0x00000006); -+ -+ /* CGU_PCR_0_7: pss_gpio_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_7, 0x00000006); -+ -+ /* CGU_PCR_2_1: spi_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_2_1, 0x00000006); -+ -+ /* CGU_PCR_3_2: i2c_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_2, 0x00000006); -+ -+ /* CGU_PCR_4_1: phi_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_4_1, 0x00000006); -+ -+ /* CGU_PCR_5: vip0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_5, 0x00000006); -+ -+ /* CGU_PCR_6: vip1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_6, 0x00000006); -+ -+ /* CGU_PCR_7: fgpi0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_7, 0x00000006); -+ -+ /* CGU_PCR_8: fgpi1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_8, 0x00000006); -+ -+ /* CGU_PCR_9: fgpi2_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_9, 0x00000006); -+ -+ /* CGU_PCR_10: fgpi3_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_10, 0x00000006); -+ -+ /* CGU_PCR_11: ai0_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_11, 0x00000006); -+ -+ /* CGU_PCR_12: ai1_clk:0 = 0x0 */ -+ SAA716x_EPWR(CGU, CGU_PCR_12, 0x00000006); -+ -+ /* #6 Set GREG boot_ready = 0x1 */ -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, 0x00002000); -+ -+ /* #7 Disable GREG CGU Clock */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_6, 0x00000006); -+ -+ /* End of Bootscript command ?? */ -+} -+ -+int saa716x_core_boot(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_config *config = saa716x->config; -+ -+ switch (config->boot_mode) { -+ case SAA716x_EXT_BOOT: -+ dprintk(SAA716x_DEBUG, 1, "Using External Boot from config"); -+ saa716x_ext_boot(saa716x); -+ break; -+ case SAA716x_INT_BOOT: -+ dprintk(SAA716x_DEBUG, 1, "Using Internal Boot from config"); -+ saa716x_int_boot(saa716x); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown configuration %d", config->boot_mode); -+ break; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_core_boot); -+ -+static void saa716x_bus_report(struct pci_dev *pdev, int enable) -+{ -+ u32 reg; -+ -+ pci_read_config_dword(pdev, 0x04, ®); -+ if (enable) -+ reg |= 0x00000100; /* enable SERR */ -+ else -+ reg &= 0xfffffeff; /* disable SERR */ -+ pci_write_config_dword(pdev, 0x04, reg); -+ -+ pci_read_config_dword(pdev, 0x58, ®); -+ reg &= 0xfffffffd; -+ pci_write_config_dword(pdev, 0x58, reg); -+} -+ -+int saa716x_jetpack_init(struct saa716x_dev *saa716x) -+{ -+ /* -+ * configure PHY through config space not to report -+ * non-fatal error messages to avoid problems with -+ * quirky BIOS'es -+ */ -+ saa716x_bus_report(saa716x->pdev, 0); -+ -+ /* -+ * create time out for blocks that have no clock -+ * helps with lower bitrates on FGPI -+ */ -+ SAA716x_EPWR(DCS, DCSC_CTRL, ENABLE_TIMEOUT); -+ -+ /* Reset all blocks */ -+ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); -+ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); -+ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); -+ -+ switch (saa716x->pdev->device) { -+ case SAA7162: -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfcffffff); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ -+ msleep(10); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x03000000); /* Enable decoders */ -+ break; -+ case SAA7161: -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Decoder disable", saa716x->pdev->device); -+ SAA716x_EPWR(GPIO, GPIO_OEN, 0xfeffffff); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x00000000); /* Disable decoders */ -+ msleep(10); -+ SAA716x_EPWR(GPIO, GPIO_WR, 0x01000000); /* Enable decoder */ -+ break; -+ case SAA7160: -+ saa716x->i2c_rate = SAA716x_I2C_RATE_100; -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown device (0x%02x)", saa716x->pdev->device); -+ return -ENODEV; -+ } -+ -+ /* General setup for MMU */ -+ SAA716x_EPWR(MMU, MMU_MODE, 0x14); -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x Jetpack Successfully initialized", saa716x->pdev->device); -+ -+ return 0; -+} -+EXPORT_SYMBOL(saa716x_jetpack_init); -+ -+void saa716x_core_reset(struct saa716x_dev *saa716x) -+{ -+ dprintk(SAA716x_DEBUG, 1, "RESET Modules"); -+ -+ /* VIP */ -+ SAA716x_EPWR(VI0, VI_MODE, SOFT_RESET); -+ SAA716x_EPWR(VI1, VI_MODE, SOFT_RESET); -+ -+ /* FGPI */ -+ SAA716x_EPWR(FGPI0, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI1, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI2, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ SAA716x_EPWR(FGPI3, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ -+ /* AIP */ -+ SAA716x_EPWR(AI0, AI_CTL, AI_RESET); -+ SAA716x_EPWR(AI1, AI_CTL, AI_RESET); -+ -+ /* BAM */ -+ SAA716x_EPWR(BAM, BAM_SW_RST, BAM_SW_RESET); -+ -+ /* MMU */ -+ SAA716x_EPWR(MMU, MMU_SW_RST, MMU_SW_RESET); -+ -+ /* MSI */ -+ SAA716x_EPWR(MSI, MSI_SW_RST, MSI_SW_RESET); -+} -+EXPORT_SYMBOL_GPL(saa716x_core_reset); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_boot.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_boot.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_boot.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_boot.h 2013-01-16 10:41:10.908798304 +0100 -@@ -0,0 +1,18 @@ -+#ifndef __SAA716x_BOOT_H -+#define __SAA716x_BOOT_H -+ -+#define DISABLE_TIMEOUT 0x17 -+#define ENABLE_TIMEOUT 0x16 -+ -+enum saa716x_boot_mode { -+ SAA716x_EXT_BOOT = 1, -+ SAA716x_INT_BOOT, /* GPIO[31:30] = 0x01 */ -+}; -+ -+struct saa716x_dev; -+ -+extern int saa716x_core_boot(struct saa716x_dev *saa716x); -+extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); -+extern void saa716x_core_reset(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_BOOT_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_budget.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_budget.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_budget.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_budget.c 2013-01-16 10:41:10.909798296 +0100 -@@ -0,0 +1,717 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_budget.h" -+#include "saa716x_gpio.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "mb86a16.h" -+#include "stv6110x.h" -+#include "stv090x.h" -+#include "ds3103.h" -+#include "ts2022.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+#define DRIVER_NAME "SAA716x Budget" -+ -+static int saa716x_budget_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ int err = 0; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM read failed"); -+ } -+ -+ /* set default port mapping */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x04080FA9); -+ /* enable FGPI3 and FGPI1 for TS input from Port 2 and 6 */ -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x321); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail4; -+ } -+ -+ return 0; -+ -+fail4: -+ saa716x_dvb_exit(saa716x); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_budget_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ -+ saa716x_dvb_exit(saa716x); -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static irqreturn_t saa716x_budget_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ u32 stat_h, stat_l, mask_h, mask_l; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ -+ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ stat_l, stat_h, mask_l, mask_h); -+ -+ if (!((stat_l & mask_l) || (stat_h & mask_h))) -+ return IRQ_NONE; -+ -+ if (stat_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); -+ -+ if (stat_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); -+ -+ saa716x_msi_event(saa716x, stat_l, stat_h); -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ -+ if (stat_l) { -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) { -+ tasklet_schedule(&saa716x->fgpi[0].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) { -+ tasklet_schedule(&saa716x->fgpi[1].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) { -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) { -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP3071 "Twinhan/Azurewave VP-3071" -+#define SAA716x_DEV_TWINHAN_VP3071 "2x DVB-T" -+ -+static int saa716x_vp3071_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp3071_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP3071, -+ .dev_type = SAA716x_DEV_TWINHAN_VP3071, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_vp3071_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP1028 "Twinhan/Azurewave VP-1028" -+#define SAA716x_DEV_TWINHAN_VP1028 "DVB-S" -+ -+static int vp1028_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct saa716x_dev *saa716x = fe->dvb->priv; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); -+ break; -+ case SEC_VOLTAGE_18: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); -+ break; -+ case SEC_VOLTAGE_OFF: -+ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+struct mb86a16_config vp1028_mb86a16_config = { -+ .demod_address = 0x08, -+ .set_voltage = vp1028_dvbs_set_voltage, -+}; -+ -+static int saa716x_vp1028_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[1]; -+ -+ if (count == 0) { -+ -+ mutex_lock(&saa716x->adap_lock); -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Power ON", count); -+ saa716x_gpio_set_output(saa716x, 10); -+ msleep(1); -+ -+ /* VP-1028 has inverted power supply control */ -+ saa716x_gpio_write(saa716x, 10, 1); /* set to standby */ -+ saa716x_gpio_write(saa716x, 10, 0); /* switch it on */ -+ msleep(100); -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Reset", count); -+ saa716x_gpio_set_output(saa716x, 12); -+ msleep(1); -+ -+ /* reset demodulator (Active LOW) */ -+ saa716x_gpio_write(saa716x, 12, 1); -+ msleep(100); -+ saa716x_gpio_write(saa716x, 12, 0); -+ msleep(100); -+ saa716x_gpio_write(saa716x, 12, 1); -+ msleep(100); -+ -+ mutex_unlock(&saa716x->adap_lock); -+ -+ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); -+ adapter->fe = mb86a16_attach(&vp1028_mb86a16_config, &i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", -+ vp1028_mb86a16_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ } -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp1028_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP1028, -+ .dev_type = SAA716x_DEV_TWINHAN_VP1028, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp1028_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_TWINHAN_VP6002 "Twinhan/Azurewave VP-6002" -+#define SAA716x_DEV_TWINHAN_VP6002 "DVB-S" -+ -+static int saa716x_vp6002_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_vp6002_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP6002, -+ .dev_type = SAA716x_DEV_TWINHAN_VP6002, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp6002_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_KNC1_DUALS2 "KNC One Dual S2" -+#define SAA716x_DEV_KNC1_DUALS2 "1xDVB-S + 1xDVB-S/S2" -+ -+static int saa716x_knc1_duals2_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_knc1_duals2_config = { -+ .model_name = SAA716x_MODEL_KNC1_DUALS2, -+ .dev_type = SAA716x_DEV_KNC1_DUALS2, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_knc1_duals2_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+ -+#define SAA716x_MODEL_SKYSTAR2_EXPRESS_HD "SkyStar 2 eXpress HD" -+#define SAA716x_DEV_SKYSTAR2_EXPRESS_HD "DVB-S/S2" -+ -+static struct stv090x_config skystar2_stv090x_config = { -+ .device = STV0903, -+ .demod_mode = STV090x_SINGLE, -+ .clk_mode = STV090x_CLK_EXT, -+ -+ .xtal = 8000000, -+ .address = 0x68, -+ -+ .ts1_mode = STV090x_TSMODE_DVBCI, -+ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ -+ .repeater_level = STV090x_RPTLEVEL_16, -+ -+ .tuner_init = NULL, -+ .tuner_sleep = NULL, -+ .tuner_set_mode = NULL, -+ .tuner_set_frequency = NULL, -+ .tuner_get_frequency = NULL, -+ .tuner_set_bandwidth = NULL, -+ .tuner_get_bandwidth = NULL, -+ .tuner_set_bbgain = NULL, -+ .tuner_get_bbgain = NULL, -+ .tuner_set_refclk = NULL, -+ .tuner_get_status = NULL, -+}; -+ -+static int skystar2_set_voltage(struct dvb_frontend *fe, -+ enum fe_sec_voltage voltage) -+{ -+ int err; -+ u8 en = 0; -+ u8 sel = 0; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_OFF: -+ en = 0; -+ break; -+ -+ case SEC_VOLTAGE_13: -+ en = 1; -+ sel = 0; -+ break; -+ -+ case SEC_VOLTAGE_18: -+ en = 1; -+ sel = 1; -+ break; -+ -+ default: -+ break; -+ } -+ -+ err = stv090x_set_gpio(fe, 2, 0, en, 0); -+ if (err < 0) -+ goto exit; -+ err = stv090x_set_gpio(fe, 3, 0, sel, 0); -+ if (err < 0) -+ goto exit; -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static int skystar2_voltage_boost(struct dvb_frontend *fe, long arg) -+{ -+ int err; -+ u8 value; -+ -+ if (arg) -+ value = 1; -+ else -+ value = 0; -+ -+ err = stv090x_set_gpio(fe, 4, 0, value, 0); -+ if (err < 0) -+ goto exit; -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static struct stv6110x_config skystar2_stv6110x_config = { -+ .addr = 0x60, -+ .refclk = 16000000, -+ .clk_div = 2, -+}; -+ -+static int skystar2_express_hd_frontend_attach(struct saa716x_adapter *adapter, -+ int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ struct stv6110x_devctl *ctl; -+ -+ if (count < saa716x->config->adapters) { -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", -+ count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, -+ saa716x->pdev->subsystem_device); -+ -+ saa716x_gpio_set_output(saa716x, 26); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, 26, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 26, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 26, 1); -+ msleep(10); -+ -+ adapter->fe = dvb_attach(stv090x_attach, -+ &skystar2_stv090x_config, -+ &i2c->i2c_adapter, -+ STV090x_DEMODULATOR_0); -+ -+ if (adapter->fe) { -+ dprintk(SAA716x_NOTICE, 1, "found STV0903 @0x%02x", -+ skystar2_stv090x_config.address); -+ } else { -+ goto exit; -+ } -+ -+ adapter->fe->ops.set_voltage = skystar2_set_voltage; -+ adapter->fe->ops.enable_high_lnb_voltage = skystar2_voltage_boost; -+ -+ ctl = dvb_attach(stv6110x_attach, -+ adapter->fe, -+ &skystar2_stv6110x_config, -+ &i2c->i2c_adapter); -+ -+ if (ctl) { -+ dprintk(SAA716x_NOTICE, 1, "found STV6110(A) @0x%02x", -+ skystar2_stv6110x_config.addr); -+ -+ skystar2_stv090x_config.tuner_init = ctl->tuner_init; -+ skystar2_stv090x_config.tuner_sleep = ctl->tuner_sleep; -+ skystar2_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; -+ skystar2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; -+ skystar2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; -+ skystar2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; -+ skystar2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; -+ skystar2_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; -+ skystar2_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; -+ skystar2_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; -+ skystar2_stv090x_config.tuner_get_status = ctl->tuner_get_status; -+ -+ /* call the init function once to initialize -+ tuner's clock output divider and demod's -+ master clock */ -+ if (adapter->fe->ops.init) -+ adapter->fe->ops.init(adapter->fe); -+ } else { -+ goto exit; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config skystar2_express_hd_config = { -+ .model_name = SAA716x_MODEL_SKYSTAR2_EXPRESS_HD, -+ .dev_type = SAA716x_DEV_SKYSTAR2_EXPRESS_HD, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = skystar2_express_hd_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 1, /* using FGPI 1 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+static struct ds3103_config s472_ds3103_config = { -+ .demod_address = 0x68, -+ .ci_mode = 1, -+}; -+ -+static int saa716x_s472_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[1]; -+ -+ if (count != 0) -+ return 0; -+ -+ dprintk(SAA716x_ERROR, 1, "Probing for DS3103 (DVB-S/S2)"); -+ adapter->fe = dvb_attach(ds3103_attach, &s472_ds3103_config, -+ &i2c->i2c_adapter); -+ -+ if (adapter->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "found DS3103 DVB-S/S2 frontend @0x%02x", -+ s472_ds3103_config.demod_address); -+ if (NULL == dvb_attach(ts2022_attach, adapter->fe, 0x60, &i2c->i2c_adapter)) -+ dprintk(SAA716x_ERROR, 1, "ts2022 attach failed"); -+ else -+ dprintk(SAA716x_ERROR, 1, "ts2022 attached!"); -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ -+} -+ -+static struct saa716x_config tevii_s472_config = { -+ .model_name = "TeVii S472 DVB-S2", -+ .dev_type = "DVB-S/S2", -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_s472_frontend_attach, -+ .irq_handler = saa716x_budget_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 1, /* using FGPI 1 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+static struct pci_device_id saa716x_budget_pci_table[] = { -+ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_1028, SAA7160, &saa716x_vp1028_config), /* VP-1028 */ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_3071, SAA7160, &saa716x_vp3071_config), /* VP-3071 */ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6002, SAA7160, &saa716x_vp6002_config), /* VP-6002 */ -+ MAKE_ENTRY(KNC_One, KNC_Dual_S2, SAA7160, &saa716x_knc1_duals2_config), -+ MAKE_ENTRY(TECHNISAT, SKYSTAR2_EXPRESS_HD, SAA7160, &skystar2_express_hd_config), -+ MAKE_ENTRY(TEVII, TEVII_S472, SAA7160, &tevii_s472_config), -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_budget_pci_table); -+ -+static struct pci_driver saa716x_budget_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_budget_pci_table, -+ .probe = saa716x_budget_pci_probe, -+ .remove = saa716x_budget_pci_remove, -+}; -+ -+static int saa716x_budget_init(void) -+{ -+ return pci_register_driver(&saa716x_budget_pci_driver); -+} -+ -+static void saa716x_budget_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_budget_pci_driver); -+} -+ -+module_init(saa716x_budget_init); -+module_exit(saa716x_budget_exit); -+ -+MODULE_DESCRIPTION("SAA716x Budget driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_budget.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_budget.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_budget.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_budget.h 2013-01-16 10:41:10.910798289 +0100 -@@ -0,0 +1,17 @@ -+#ifndef __SAA716x_BUDGET_H -+#define __SAA716x_BUDGET_H -+ -+#define TWINHAN_TECHNOLOGIES 0x1822 -+#define TWINHAN_VP_3071 0x0039 -+#define TWINHAN_VP_1028 0x0044 -+#define TWINHAN_VP_6002 0x0047 -+ -+#define KNC_One 0x1894 -+#define KNC_Dual_S2 0x0110 -+ -+#define TECHNISAT 0x1AE4 -+#define SKYSTAR2_EXPRESS_HD 0x0700 -+#define TEVII 0x9022 -+#define TEVII_S472 0xd472 -+ -+#endif /* __SAA716x_BUDGET_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu.c 2013-01-16 10:41:10.910798289 +0100 -@@ -0,0 +1,539 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_cgu_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+u32 cgu_clk[14] = { -+ CGU_FDC_0, -+ CGU_FDC_1, -+ CGU_FDC_2, -+ CGU_FDC_3, -+ CGU_FDC_4, -+ CGU_FDC_5, -+ CGU_FDC_6, -+ CGU_FDC_7, -+ CGU_FDC_8, -+ CGU_FDC_9, -+ CGU_FDC_10, -+ CGU_FDC_11, -+ CGU_FDC_12, -+ CGU_FDC_13 -+}; -+ -+char *clk_desc[14] = { -+ "Clk PSS", -+ "Clk DCS", -+ "Clk SPI", -+ "Clk I2C/Boot", -+ "Clk PHI", -+ "Clk VI0", -+ "Clk VI1", -+ "Clk FGPI0", -+ "Clk FGPI1", -+ "Clk FGPI2", -+ "Clk FGPI3", -+ "Clk AI0", -+ "Clk AI1", -+ "Clk Phy" -+}; -+ -+int saa716x_getbootscript_setup(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 i; -+ s8 N = 0; -+ s16 M = 0; -+ -+ SAA716x_EPWR(CGU, CGU_PCR_0_6, CGU_PCR_RUN); /* GREG */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_3, CGU_PCR_RUN); /* PSS_MMU */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_4, CGU_PCR_RUN); /* PSS_DTL2MTL */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_5, CGU_PCR_RUN); /* MSI */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_2, CGU_PCR_RUN); /* I2C */ -+ SAA716x_EPWR(CGU, CGU_PCR_4_1, CGU_PCR_RUN); /* PHI */ -+ SAA716x_EPWR(CGU, CGU_PCR_0_7, CGU_PCR_RUN); /* GPIO */ -+ SAA716x_EPWR(CGU, CGU_PCR_2_1, CGU_PCR_RUN); /* SPI */ -+ SAA716x_EPWR(CGU, CGU_PCR_1_1, CGU_PCR_RUN); /* DCS */ -+ SAA716x_EPWR(CGU, CGU_PCR_3_1, CGU_PCR_RUN); /* BOOT */ -+ -+ /* get all dividers */ -+ for (i = 0; i < CGU_CLKS; i++) { -+ cgu->clk_boot_div[i] = SAA716x_EPRD(CGU, cgu_clk[i]); -+ cgu->clk_curr_div[i] = cgu->clk_boot_div[i]; -+ -+ N = (cgu->clk_boot_div[i] >> 11) & 0xff; -+ N *= -1; -+ M = ((cgu->clk_boot_div[i] >> 3) & 0xff) + N; -+ -+ if (M) -+ cgu->clk_freq[i] = (u32 ) N * PLL_FREQ / (u32 ) M; -+ else -+ cgu->clk_freq[i] = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "Domain %d: %s <0x%02x> Divider: 0x%x --> N=%d, M=%d, freq=%d", -+ i, clk_desc[i], cgu_clk[i], cgu->clk_boot_div[i], N, M, cgu->clk_freq[i]); -+ } -+ /* store clock settings */ -+ cgu->clk_vi_0[0] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_0[1] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_0[2] = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ cgu->clk_vi_1[0] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ cgu->clk_vi_1[1] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ cgu->clk_vi_1[2] = cgu->clk_freq[CLK_DOMAIN_VI1]; -+ -+ return 0; -+} -+ -+int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 delay = 1; -+ -+ switch (port) { -+ case PORT_VI0_VIDEO: -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(5); -+ break; -+ -+ case PORT_VI0_VBI: -+ cgu->clk_int_port[PORT_VI0_VBI] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(5); -+ break; -+ -+ case PORT_VI1_VIDEO: -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(6); -+ break; -+ -+ case PORT_VI1_VBI: -+ cgu->clk_int_port[PORT_VI1_VBI] = 1; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_CGU_CLKRUN(6); -+ break; -+ -+ case PORT_FGPI0: -+ cgu->clk_int_port[PORT_FGPI0] = 1; -+ SAA716x_CGU_CLKRUN(7); -+ break; -+ -+ case PORT_FGPI1: -+ cgu->clk_int_port[PORT_FGPI1] = 1; -+ SAA716x_CGU_CLKRUN(8); -+ break; -+ -+ case PORT_FGPI2: -+ cgu->clk_int_port[PORT_FGPI2] = 1; -+ SAA716x_CGU_CLKRUN(9); -+ break; -+ -+ case PORT_FGPI3: -+ cgu->clk_int_port[PORT_FGPI3] = 1; -+ SAA716x_CGU_CLKRUN(10); -+ break; -+ -+ case PORT_AI0: -+ cgu->clk_int_port[PORT_AI0] = 1; -+ SAA716x_CGU_CLKRUN(11); -+ break; -+ -+ case PORT_AI1: -+ cgu->clk_int_port[PORT_AI1] = 1; -+ SAA716x_CGU_CLKRUN(12); -+ break; -+ -+ case PORT_ALL: -+ SAA716x_CGU_CLKRUN(5); -+ SAA716x_CGU_CLKRUN(6); -+ SAA716x_CGU_CLKRUN(7); -+ SAA716x_CGU_CLKRUN(8); -+ SAA716x_CGU_CLKRUN(9); -+ SAA716x_CGU_CLKRUN(10); -+ SAA716x_CGU_CLKRUN(11); -+ SAA716x_CGU_CLKRUN(12); -+ -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 1; -+ cgu->clk_int_port[PORT_VI0_VBI] = 1; -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 1; -+ cgu->clk_int_port[PORT_VI1_VBI] = 1; -+ cgu->clk_int_port[PORT_FGPI0] = 1; -+ cgu->clk_int_port[PORT_FGPI1] = 1; -+ cgu->clk_int_port[PORT_FGPI2] = 1; -+ cgu->clk_int_port[PORT_FGPI3] = 1; -+ cgu->clk_int_port[PORT_AI0] = 1; -+ cgu->clk_int_port[PORT_AI1] = 1; -+ break; -+ -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); -+ delay = 0; -+ break; -+ } -+ -+ /* wait for PLL */ -+ if (delay) -+ msleep(1); -+ -+ return 0; -+} -+ -+int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u8 delay = 1; -+ -+ switch (port) { -+ case PORT_VI0_VIDEO: -+ cgu->clk_int_port[PORT_VI0_VIDEO] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI0_VBI: -+ cgu->clk_int_port[PORT_VI0_VBI] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI0_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_5, 0x2); /* VI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_5, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI1_VIDEO: -+ cgu->clk_int_port[PORT_VI1_VIDEO] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VBI]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_VI1_VBI: -+ cgu->clk_int_port[PORT_VI1_VBI] = 0; -+ -+ if (!cgu->clk_int_port[PORT_VI1_VIDEO]) { -+ delay = 0; -+ break; -+ } -+ -+ SAA716x_EPWR(CGU, CGU_FS1_6, 0x3); /* VI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_6, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI0: -+ cgu->clk_int_port[PORT_FGPI0] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_7, 0x4); /* FGPI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_7, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI1: -+ cgu->clk_int_port[PORT_FGPI1] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_8, 0x5); /* FGPI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_8, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI2: -+ cgu->clk_int_port[PORT_FGPI2] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_9, 0x6); /* FGPI 2 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_9, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_FGPI3: -+ cgu->clk_int_port[PORT_FGPI3] = 0; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_10, 0x7); /* FGPI 3 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_10, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_AI0: -+ cgu->clk_int_port[PORT_AI0] = 1; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_11, 0x8); /* AI 0 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_11, 0x0); /* disable divider */ -+ break; -+ -+ case PORT_AI1: -+ cgu->clk_int_port[PORT_AI1] = 1; -+ -+ SAA716x_EPWR(CGU, CGU_FS1_12, 0x9); /* AI 1 clk */ -+ SAA716x_EPWR(CGU, CGU_ESR_12, 0x0); /* disable divider */ -+ break; -+ -+ default: -+ dprintk(SAA716x_ERROR, 1, "Unknown port <%02x>", port); -+ delay = 0; -+ break; -+ -+ } -+ -+ if (delay) -+ msleep(1); -+ -+ return 0; -+} -+ -+int saa716x_get_clk(struct saa716x_dev *saa716x, -+ enum saa716x_clk_domain domain, -+ u32 *frequency) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ switch (domain) { -+ case CLK_DOMAIN_PSS: -+ case CLK_DOMAIN_DCS: -+ case CLK_DOMAIN_SPI: -+ case CLK_DOMAIN_I2C: -+ case CLK_DOMAIN_PHI: -+ case CLK_DOMAIN_VI0: -+ case CLK_DOMAIN_VI1: -+ case CLK_DOMAIN_FGPI0: -+ case CLK_DOMAIN_FGPI1: -+ case CLK_DOMAIN_FGPI2: -+ case CLK_DOMAIN_FGPI3: -+ case CLK_DOMAIN_AI0: -+ case CLK_DOMAIN_AI1: -+ case CLK_DOMAIN_PHY: -+ *frequency = cgu->clk_freq[domain]; -+ break; -+ -+ case CLK_DOMAIN_VI0VBI: -+ *frequency = cgu->clk_freq[CLK_DOMAIN_VI0]; -+ break; -+ -+ case CLK_DOMAIN_VI1VBI: -+ *frequency =cgu->clk_freq[CLK_DOMAIN_VI1]; -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Error Clock domain <%02x>", domain); -+ break; -+ } -+ -+ return 0; -+} -+ -+int saa716x_set_clk(struct saa716x_dev *saa716x, -+ enum saa716x_clk_domain domain, -+ u32 frequency) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ u32 M = 1, N = 1, reset, i; -+ s8 N_tmp, M_tmp, sub, add, lsb; -+ -+ -+ if (cgu->clk_freq_min > frequency) -+ frequency = cgu->clk_freq_min; -+ -+ if (cgu->clk_freq_max < frequency) -+ frequency = cgu->clk_freq_max; -+ -+ switch (domain) { -+ case CLK_DOMAIN_PSS: -+ case CLK_DOMAIN_DCS: -+ case CLK_DOMAIN_SPI: -+ case CLK_DOMAIN_I2C: -+ case CLK_DOMAIN_PHI: -+ case CLK_DOMAIN_FGPI0: -+ case CLK_DOMAIN_FGPI1: -+ case CLK_DOMAIN_FGPI2: -+ case CLK_DOMAIN_FGPI3: -+ case CLK_DOMAIN_AI0: -+ case CLK_DOMAIN_AI1: -+ case CLK_DOMAIN_PHY: -+ -+ if (frequency == cgu->clk_freq[domain]) -+ return 0; /* same frequency */ -+ break; -+ -+ case CLK_DOMAIN_VI0: -+ -+ if (frequency == cgu->clk_vi_0[1]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_0[0]) { -+ cgu->clk_vi_0[1] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_0[2]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_0[1] = frequency; -+ -+ if (frequency != cgu->clk_vi_0[2]) -+ return 0; -+ -+ } -+ break; -+ -+ case CLK_DOMAIN_VI1: -+ if (frequency == cgu->clk_vi_1[1]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_1[0]) { -+ cgu->clk_vi_1[1] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_1[2]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_1[1] = frequency; -+ -+ if (frequency != cgu->clk_vi_1[2]) -+ return 0; -+ -+ } -+ break; -+ -+ case CLK_DOMAIN_VI0VBI: -+ if (frequency == cgu->clk_vi_0[2]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_0[0]) { -+ cgu->clk_vi_0[2] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_0[1]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_0[2] = frequency; /* store */ -+ -+ if (frequency != cgu->clk_vi_0[1]) -+ return 0; -+ -+ } -+ domain = CLK_DOMAIN_VI0; /* change domain */ -+ break; -+ -+ case CLK_DOMAIN_VI1VBI: -+ if (frequency == cgu->clk_vi_1[2]) { -+ return 0; -+ -+ } else if (frequency == cgu->clk_vi_1[0]) { -+ cgu->clk_vi_1[2] = frequency; /* store */ -+ -+ if (frequency == cgu->clk_vi_1[1]) -+ return 0; -+ -+ } else { -+ cgu->clk_vi_1[2] = frequency; /* store */ -+ -+ if (frequency != cgu->clk_vi_1[1]) -+ return 0; -+ -+ } -+ domain = CLK_DOMAIN_VI1; /* change domain */ -+ break; -+ } -+ -+ /* calculate divider */ -+ do { -+ M = (N * PLL_FREQ) / frequency; -+ if (M == 0) -+ N++; -+ -+ } while (M == 0); -+ -+ /* calculate frequency */ -+ cgu->clk_freq[domain] = (N * PLL_FREQ) / M; -+ -+ N_tmp = N & 0xff; -+ M_tmp = M & 0xff; -+ sub = -N_tmp; -+ add = M_tmp - N_tmp; -+ lsb = 4; /* run */ -+ -+ if (((10 * N) / M) < 5) -+ lsb |= 1; /* stretch */ -+ -+ /* store new divider */ -+ cgu->clk_curr_div[domain] = sub & 0xff; -+ cgu->clk_curr_div[domain] <<= 8; -+ cgu->clk_curr_div[domain] = add & 0xff; -+ cgu->clk_curr_div[domain] <<= 3; -+ cgu->clk_curr_div[domain] |= lsb; -+ -+ dprintk(SAA716x_DEBUG, 1, "Domain <0x%02x> Frequency <%d> Set Freq <%d> N=%d M=%d Divider <0x%02x>", -+ domain, -+ frequency, -+ cgu->clk_freq[domain], -+ N, -+ M, -+ cgu->clk_curr_div[domain]); -+ -+ reset = 0; -+ -+ /* Reset */ -+ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain] | 0x2); -+ -+ /* Reset disable */ -+ for (i = 0; i < 1000; i++) { -+ msleep(10); -+ reset = SAA716x_EPRD(CGU, cgu_clk[domain]); -+ -+ if (cgu->clk_curr_div[domain == reset]) -+ break; -+ } -+ -+ if (cgu->clk_curr_div[domain] != reset) -+ SAA716x_EPWR(CGU, cgu_clk[domain], cgu->clk_curr_div[domain]); -+ -+ return 0; -+} -+ -+int saa716x_cgu_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_cgu *cgu = &saa716x->cgu; -+ -+ cgu->clk_freq_min = PLL_FREQ / 255; -+ if (PLL_FREQ > (cgu->clk_freq_min * 255)) -+ cgu->clk_freq_min++; -+ -+ cgu->clk_freq_max = PLL_FREQ; -+ -+ saa716x_getbootscript_setup(saa716x); -+ saa716x_set_clk_internal(saa716x, PORT_ALL); -+ -+ return 0; -+} -+EXPORT_SYMBOL(saa716x_cgu_init); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu.h 2013-01-16 10:41:10.911798282 +0100 -@@ -0,0 +1,61 @@ -+#ifndef __SAA716x_CGU_H -+#define __SAA716x_CGU_H -+ -+#define PLL_FREQ 2500 -+ -+#define SAA716x_CGU_CLKRUN(__reg) do { \ -+ SAA716x_EPWR(CGU, CGU_PCR_##__reg, CGU_PCR_RUN); /* Run */ \ -+ SAA716x_EPWR(CGU, CGU_SCR_##__reg, CGU_SCR_ENF1); /* Switch */ \ -+ SAA716x_EPWR(CGU, CGU_FS1_##__reg, 0x00000000); /* PLL Clk */ \ -+ SAA716x_EPWR(CGU, CGU_ESR_##__reg, CGU_ESR_FD_EN); /* Frac div */ \ -+} while (0) -+ -+enum saa716x_clk_domain { -+ CLK_DOMAIN_PSS = 0, -+ CLK_DOMAIN_DCS = 1, -+ CLK_DOMAIN_SPI = 2, -+ CLK_DOMAIN_I2C = 3, -+ CLK_DOMAIN_PHI = 4, -+ CLK_DOMAIN_VI0 = 5, -+ CLK_DOMAIN_VI1 = 6, -+ CLK_DOMAIN_FGPI0 = 7, -+ CLK_DOMAIN_FGPI1 = 8, -+ CLK_DOMAIN_FGPI2 = 9, -+ CLK_DOMAIN_FGPI3 = 10, -+ CLK_DOMAIN_AI0 = 11, -+ CLK_DOMAIN_AI1 = 12, -+ CLK_DOMAIN_PHY = 13, -+ CLK_DOMAIN_VI0VBI = 14, -+ CLK_DOMAIN_VI1VBI = 15 -+}; -+ -+#define PORT_VI0_VIDEO 0 -+#define PORT_VI0_VBI 2 -+#define PORT_VI1_VIDEO 3 -+#define PORT_VI1_VBI 5 -+#define PORT_FGPI0 6 -+#define PORT_FGPI1 7 -+#define PORT_FGPI2 8 -+#define PORT_FGPI3 9 -+#define PORT_AI0 10 -+#define PORT_AI1 11 -+#define PORT_ALL 12 -+ -+#define CGU_CLKS 14 -+ -+struct saa716x_cgu { -+ u8 clk_int_port[12]; -+ u32 clk_vi_0[3]; -+ u32 clk_vi_1[3]; -+ u32 clk_boot_div[CGU_CLKS]; -+ u32 clk_curr_div[CGU_CLKS]; -+ u32 clk_freq[CGU_CLKS]; -+ u32 clk_freq_min; -+ u32 clk_freq_max; -+}; -+ -+extern int saa716x_cgu_init(struct saa716x_dev *saa716x); -+extern int saa716x_set_clk_internal(struct saa716x_dev *saa716x, u32 port); -+extern int saa716x_set_clk_external(struct saa716x_dev *saa716x, u32 port); -+ -+#endif /* __SAA716x_CGU_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_cgu_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_cgu_reg.h 2013-01-16 10:41:10.911798282 +0100 -@@ -0,0 +1,178 @@ -+#ifndef __SAA716x_CGU_REG_H -+#define __SAA716x_CGU_REG_H -+ -+/* -------------- CGU Registers -------------- */ -+ -+#define CGU_SCR_0 0x000 -+#define CGU_SCR_1 0x004 -+#define CGU_SCR_2 0x008 -+#define CGU_SCR_3 0x00c -+#define CGU_SCR_4 0x010 -+#define CGU_SCR_5 0x014 -+#define CGU_SCR_6 0x018 -+#define CGU_SCR_7 0x01c -+#define CGU_SCR_8 0x020 -+#define CGU_SCR_9 0x024 -+#define CGU_SCR_10 0x028 -+#define CGU_SCR_11 0x02c -+#define CGU_SCR_12 0x030 -+#define CGU_SCR_13 0x034 -+#define CGU_SCR_STOP (0x00000001 << 3) -+#define CGU_SCR_RESET (0x00000001 << 2) -+#define CGU_SCR_ENF2 (0x00000001 << 1) -+#define CGU_SCR_ENF1 (0x00000001 << 0) -+ -+#define CGU_FS1_0 0x038 -+#define CGU_FS1_1 0x03c -+#define CGU_FS1_2 0x040 -+#define CGU_FS1_3 0x044 -+#define CGU_FS1_4 0x048 -+#define CGU_FS1_5 0x04c -+#define CGU_FS1_6 0x050 -+#define CGU_FS1_7 0x054 -+#define CGU_FS1_8 0x058 -+#define CGU_FS1_9 0x05c -+#define CGU_FS1_10 0x060 -+#define CGU_FS1_11 0x064 -+#define CGU_FS1_12 0x068 -+#define CGU_FS1_13 0x06c -+#define CGU_FS1_PLL (0x00000000 << 0) -+ -+ -+#define CGU_FS2_0 0x070 -+#define CGU_FS2_1 0x074 -+#define CGU_FS2_2 0x078 -+#define CGU_FS2_3 0x07c -+#define CGU_FS2_4 0x080 -+#define CGU_FS2_5 0x084 -+#define CGU_FS2_6 0x088 -+#define CGU_FS2_7 0x08c -+#define CGU_FS2_8 0x090 -+#define CGU_FS2_9 0x094 -+#define CGU_FS2_10 0x098 -+#define CGU_FS2_11 0x09c -+#define CGU_FS2_12 0x0a0 -+#define CGU_FS2_13 0x0a4 -+ -+#define CGU_SSR_0 0x0a8 -+#define CGU_SSR_1 0x0ac -+#define CGU_SSR_2 0x0b0 -+#define CGU_SSR_3 0x0b4 -+#define CGU_SSR_4 0x0b8 -+#define CGU_SSR_5 0x0bc -+#define CGU_SSR_6 0x0c0 -+#define CGU_SSR_7 0x0c4 -+#define CGU_SSR_8 0x0c8 -+#define CGU_SSR_9 0x0cc -+#define CGU_SSR_10 0x0d0 -+#define CGU_SSR_11 0x0d4 -+#define CGU_SSR_12 0x0d8 -+#define CGU_SSR_13 0x0dc -+ -+#define CGU_PCR_0_0 0x0e0 -+#define CGU_PCR_0_1 0x0e4 -+#define CGU_PCR_0_2 0x0e8 -+#define CGU_PCR_0_3 0x0ec -+#define CGU_PCR_0_4 0x0f0 -+#define CGU_PCR_0_5 0x0f4 -+#define CGU_PCR_0_6 0x0f8 -+#define CGU_PCR_0_7 0x0fc -+#define CGU_PCR_1_0 0x100 -+#define CGU_PCR_1_1 0x104 -+#define CGU_PCR_2_0 0x108 -+#define CGU_PCR_2_1 0x10c -+#define CGU_PCR_3_0 0x110 -+#define CGU_PCR_3_1 0x114 -+#define CGU_PCR_3_2 0x118 -+#define CGU_PCR_4_0 0x11c -+#define CGU_PCR_4_1 0x120 -+#define CGU_PCR_5 0x124 -+#define CGU_PCR_6 0x128 -+#define CGU_PCR_7 0x12c -+#define CGU_PCR_8 0x130 -+#define CGU_PCR_9 0x134 -+#define CGU_PCR_10 0x138 -+#define CGU_PCR_11 0x13c -+#define CGU_PCR_12 0x140 -+#define CGU_PCR_13 0x144 -+#define CGU_PCR_WAKE_EN (0x00000001 << 2) -+#define CGU_PCR_AUTO (0x00000001 << 1) -+#define CGU_PCR_RUN (0x00000001 << 0) -+ -+ -+#define CGU_PSR_0_0 0x148 -+#define CGU_PSR_0_1 0x14c -+#define CGU_PSR_0_2 0x150 -+#define CGU_PSR_0_3 0x154 -+#define CGU_PSR_0_4 0x158 -+#define CGU_PSR_0_5 0x15c -+#define CGU_PSR_0_6 0x160 -+#define CGU_PSR_0_7 0x164 -+#define CGU_PSR_1_0 0x168 -+#define CGU_PSR_1_1 0x16c -+#define CGU_PSR_2_0 0x170 -+#define CGU_PSR_2_1 0x174 -+#define CGU_PSR_3_0 0x178 -+#define CGU_PSR_3_1 0x17c -+#define CGU_PSR_3_2 0x180 -+#define CGU_PSR_4_0 0x184 -+#define CGU_PSR_4_1 0x188 -+#define CGU_PSR_5 0x18c -+#define CGU_PSR_6 0x190 -+#define CGU_PSR_7 0x194 -+#define CGU_PSR_8 0x198 -+#define CGU_PSR_9 0x19c -+#define CGU_PSR_10 0x1a0 -+#define CGU_PSR_11 0x1a4 -+#define CGU_PSR_12 0x1a8 -+#define CGU_PSR_13 0x1ac -+ -+#define CGU_ESR_0_0 0x1b0 -+#define CGU_ESR_0_1 0x1b4 -+#define CGU_ESR_0_2 0x1b8 -+#define CGU_ESR_0_3 0x1bc -+#define CGU_ESR_0_4 0x1c0 -+#define CGU_ESR_0_5 0x1c4 -+#define CGU_ESR_0_6 0x1c8 -+#define CGU_ESR_0_7 0x1cc -+#define CGU_ESR_1_0 0x1d0 -+#define CGU_ESR_1_1 0x1d4 -+#define CGU_ESR_2_0 0x1d8 -+#define CGU_ESR_2_1 0x1dc -+#define CGU_ESR_3_0 0x1e0 -+#define CGU_ESR_3_1 0x1e4 -+#define CGU_ESR_3_2 0x1e8 -+#define CGU_ESR_4_0 0x1ec -+#define CGU_ESR_4_1 0x1f0 -+#define CGU_ESR_5 0x1f4 -+#define CGU_ESR_6 0x1f8 -+#define CGU_ESR_7 0x1fc -+#define CGU_ESR_8 0x200 -+#define CGU_ESR_9 0x204 -+#define CGU_ESR_10 0x208 -+#define CGU_ESR_11 0x20c -+#define CGU_ESR_12 0x210 -+#define CGU_ESR_13 0x214 -+#define CGU_ESR_FD_EN (0x00000001 << 0) -+ -+#define CGU_FDC_0 0x218 -+#define CGU_FDC_1 0x21c -+#define CGU_FDC_2 0x220 -+#define CGU_FDC_3 0x224 -+#define CGU_FDC_4 0x228 -+#define CGU_FDC_5 0x22c -+#define CGU_FDC_6 0x230 -+#define CGU_FDC_7 0x234 -+#define CGU_FDC_8 0x238 -+#define CGU_FDC_9 0x23c -+#define CGU_FDC_10 0x240 -+#define CGU_FDC_11 0x244 -+#define CGU_FDC_12 0x248 -+#define CGU_FDC_13 0x24c -+#define CGU_FDC_STRETCH (0x00000001 << 0) -+#define CGU_FDC_RESET (0x00000001 << 1) -+#define CGU_FDC_RUN1 (0x00000001 << 2) -+#define CGU_FDC_MADD (0x000000ff << 3) -+#define CGU_FDC_MSUB (0x000000ff << 11) -+ -+#endif /* __SAA716x_CGU_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_dcs_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dcs_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_dcs_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dcs_reg.h 2013-01-16 10:41:10.912798275 +0100 -@@ -0,0 +1,56 @@ -+#ifndef __SAA716x_DCS_REG_H -+#define __SAA716x_DCS_REG_H -+ -+/* -------------- DCS Registers -------------- */ -+ -+#define DCSC_CTRL 0x000 -+#define DCSC_SEL_PLLDI (0x03ffffff << 5) -+#define DCSC_TOUT_SEL (0x0000000f << 1) -+#define DCSC_TOUT_OFF (0x00000001 << 0) -+ -+#define DCSC_ADDR 0x00c -+#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) -+ -+#define DCSC_STAT 0x010 -+#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) -+#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) -+#define DCSC_ERR_TOUT_READ (0x00000001 << 8) -+#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) -+#define DCSC_ERR_ACK (0x00000001 << 1) -+ -+#define DCSC_FEATURES 0x040 -+#define DCSC_UNIQUE_ID (0x00000007 << 16) -+#define DCSC_SECURITY (0x00000001 << 14) -+#define DCSC_NUM_BASE_REGS (0x00000003 << 11) -+#define DCSC_NUM_TARGETS (0x0000001f << 5) -+#define DCSC_NUM_INITIATORS (0x0000001f << 0) -+ -+#define DCSC_BASE_REG0 0x100 -+#define DCSC_BASE_N_REG (0x00000fff << 20) -+ -+#define DCSC_INT_CLR_ENABLE 0xfd8 -+#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_ENABLE 0xfdc -+#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_STATUS 0xfe0 -+#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) -+#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_ENABLE 0xfe4 -+#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_CLR_STATUS 0xfe8 -+#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_STATUS 0xfec -+#define DCSC_INT_SET_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ERROR (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_DCS_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_dma.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_dma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma.c 2013-01-16 10:41:10.912798275 +0100 -@@ -0,0 +1,306 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include "saa716x_dma.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+/* Allocates one page of memory, which is stores the data of one -+ * 716x page table. The result gets stored in the passed DMA buffer -+ * structure. -+ */ -+static int saa716x_allocate_ptable(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "SG Page table allocate"); -+ dmabuf->mem_ptab_virt = (void *) __get_free_page(GFP_KERNEL); -+ -+ if (dmabuf->mem_ptab_virt == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Out of pages !"); -+ return -ENOMEM; -+ } -+ -+ dmabuf->mem_ptab_phys = dma_map_single(&pdev->dev, -+ dmabuf->mem_ptab_virt, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+ if (dmabuf->mem_ptab_phys == 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: map memory failed !"); -+ return -ENOMEM; -+ } -+ -+ BUG_ON(!(((unsigned long) dmabuf->mem_ptab_phys % SAA716x_PAGE_SIZE) == 0)); -+ -+ return 0; -+} -+ -+static void saa716x_free_ptable(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG Page table free"); -+ -+ /* free physical PCI memory */ -+ if (dmabuf->mem_ptab_phys != 0) { -+ dma_unmap_single(&pdev->dev, -+ dmabuf->mem_ptab_phys, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+ dmabuf->mem_ptab_phys = 0; -+ } -+ -+ /* free kernel memory */ -+ if (dmabuf->mem_ptab_virt != NULL) { -+ free_page((unsigned long) dmabuf->mem_ptab_virt); -+ dmabuf->mem_ptab_virt = NULL; -+ } -+} -+ -+static void saa716x_dmabuf_sgfree(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG free"); -+ -+ dmabuf->mem_virt = NULL; -+ if (dmabuf->mem_virt_noalign != NULL) { -+ if (dmabuf->dma_type == SAA716x_DMABUF_INT) -+ vfree(dmabuf->mem_virt_noalign); -+ -+ dmabuf->mem_virt_noalign = NULL; -+ } -+ -+ if (dmabuf->sg_list != NULL) { -+ kfree(dmabuf->sg_list); -+ dmabuf->sg_list = NULL; -+ } -+} -+ -+/* -+ * Create a SG, when an allocated buffer is passed to it, -+ * otherwise the needed memory gets allocated by itself -+ */ -+static int saa716x_dmabuf_sgalloc(struct saa716x_dmabuf *dmabuf, void *buf, int size) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct scatterlist *list; -+ struct page *pg; -+ -+ int i, pages; -+ -+ BUG_ON(!(size > 0)); -+ BUG_ON(dmabuf == NULL); -+ dprintk(SAA716x_DEBUG, 1, "SG allocate"); -+ -+ if ((size % SAA716x_PAGE_SIZE) != 0) /* calculate required pages */ -+ pages = size / SAA716x_PAGE_SIZE + 1; -+ else -+ pages = size / SAA716x_PAGE_SIZE; -+ -+ /* Allocate memory for SG list */ -+ dmabuf->sg_list = kzalloc(sizeof (struct scatterlist) * pages, GFP_KERNEL); -+ if (dmabuf->sg_list == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for scatterlist."); -+ return -ENOMEM; -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SG table"); -+ sg_init_table(dmabuf->sg_list, pages); -+ -+ if (buf == NULL) { -+ -+ /* allocate memory, unaligned */ -+ dmabuf->mem_virt_noalign = vmalloc((pages + 1) * SAA716x_PAGE_SIZE); -+ if (dmabuf->mem_virt_noalign == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Failed to allocate memory for buffer"); -+ return -ENOMEM; -+ } -+ -+ /* align memory to page */ -+ dmabuf->mem_virt = (void *) PAGE_ALIGN (((unsigned long) dmabuf->mem_virt_noalign)); -+ -+ BUG_ON(!((((unsigned long) dmabuf->mem_virt) % SAA716x_PAGE_SIZE) == 0)); -+ } else { -+ dmabuf->mem_virt = buf; -+ } -+ -+ dmabuf->list_len = pages; /* scatterlist length */ -+ list = dmabuf->sg_list; -+ -+ dprintk(SAA716x_DEBUG, 1, "Allocating SG pages"); -+ for (i = 0; i < pages; i++) { -+ if (buf == NULL) -+ pg = vmalloc_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); -+ else -+ pg = virt_to_page(dmabuf->mem_virt + i * SAA716x_PAGE_SIZE); -+ -+ BUG_ON(pg == NULL); -+ sg_set_page(&list[i], pg, SAA716x_PAGE_SIZE, 0); -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "Done!"); -+ return 0; -+} -+ -+/* Fill the "page table" page with the pointers to the specified SG buffer */ -+static void saa716x_dmabuf_sgpagefill(struct saa716x_dmabuf *dmabuf, struct scatterlist *sg_list, int pages, int offset) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ struct scatterlist *sg_cur; -+ -+ u32 *page; -+ int i, j, k = 0; -+ dma_addr_t addr = 0; -+ -+ BUG_ON(dmabuf == NULL); -+ BUG_ON(sg_list == NULL); -+ BUG_ON(pages == 0); -+ dprintk(SAA716x_DEBUG, 1, "SG page fill"); -+ -+ /* make page writable for the PC */ -+ dma_sync_single_for_cpu(&pdev->dev, dmabuf->mem_ptab_phys, SAA716x_PAGE_SIZE, DMA_TO_DEVICE); -+ page = dmabuf->mem_ptab_virt; -+ -+ /* create page table */ -+ for (i = 0; i < pages; i++) { -+ sg_cur = &sg_list[i]; -+ BUG_ON(!(((sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE) == 0)); -+ -+ if (i == 0) -+ dmabuf->offset = (sg_cur->length + sg_cur->offset) % SAA716x_PAGE_SIZE; -+ else -+ BUG_ON(sg_cur->offset != 0); -+ -+ for (j = 0; (j * SAA716x_PAGE_SIZE) < sg_dma_len(sg_cur); j++) { -+ -+ if ((offset + sg_cur->offset) >= SAA716x_PAGE_SIZE) { -+ offset -= SAA716x_PAGE_SIZE; -+ continue; -+ } -+ -+ addr = ((u64)sg_dma_address(sg_cur)) + (j * SAA716x_PAGE_SIZE) - sg_cur->offset; -+ -+ BUG_ON(addr == 0); -+ page[k * 2] = (u32 )addr; /* Low */ -+ page[k * 2 + 1] = (u32 )(((u64) addr) >> 32); /* High */ -+ BUG_ON(page[k * 2] % SAA716x_PAGE_SIZE); -+ k++; -+ } -+ } -+ -+ for (; k < (SAA716x_PAGE_SIZE / 8); k++) { -+ page[k * 2] = (u32 ) addr; -+ page[k * 2 + 1] = (u32 ) (((u64 ) addr) >> 32); -+ } -+ -+ /* make "page table" page writable for the PC */ -+ dma_sync_single_for_device(&pdev->dev, -+ dmabuf->mem_ptab_phys, -+ SAA716x_PAGE_SIZE, -+ DMA_TO_DEVICE); -+ -+} -+ -+void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "DMABUF sync DEVICE"); -+ BUG_ON(dmabuf->sg_list == NULL); -+ -+ dma_sync_sg_for_device(&pdev->dev, -+ dmabuf->sg_list, -+ dmabuf->list_len, -+ DMA_FROM_DEVICE); -+ -+} -+ -+void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ dprintk(SAA716x_DEBUG, 1, "DMABUF sync CPU"); -+ BUG_ON(dmabuf->sg_list == NULL); -+ -+ dma_sync_sg_for_cpu(&pdev->dev, -+ dmabuf->sg_list, -+ dmabuf->list_len, -+ DMA_FROM_DEVICE); -+} -+ -+/* Allocates a DMA buffer for the specified external linear buffer. */ -+int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf, int size) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ int ret; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(dmabuf == NULL); -+ BUG_ON(! (size > 0)); -+ -+ dmabuf->dma_type = SAA716x_DMABUF_INT; -+ -+ dmabuf->mem_virt_noalign = NULL; -+ dmabuf->mem_virt = NULL; -+ dmabuf->mem_ptab_phys = 0; -+ dmabuf->mem_ptab_virt = NULL; -+ -+ dmabuf->list_len = 0; -+ dmabuf->saa716x = saa716x; -+ -+ /* Allocate page table */ -+ ret = saa716x_allocate_ptable(dmabuf); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "PT alloc failed, Out of memory"); -+ goto err1; -+ } -+ -+ /* Allocate buffer as SG */ -+ ret = saa716x_dmabuf_sgalloc(dmabuf, NULL, size); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SG alloc failed"); -+ goto err2; -+ } -+ -+ ret = dma_map_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SG map failed"); -+ goto err3; -+ } -+ -+ saa716x_dmabuf_sgpagefill(dmabuf, dmabuf->sg_list, ret, 0); -+ -+ return 0; -+err3: -+ saa716x_dmabuf_sgfree(dmabuf); -+err2: -+ saa716x_free_ptable(dmabuf); -+err1: -+ return ret; -+} -+ -+void saa716x_dmabuf_free(struct saa716x_dev *saa716x, struct saa716x_dmabuf *dmabuf) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(dmabuf == NULL); -+ -+ dma_unmap_sg(&pdev->dev, dmabuf->sg_list, dmabuf->list_len, DMA_FROM_DEVICE); -+ saa716x_dmabuf_sgfree(dmabuf); -+ saa716x_free_ptable(dmabuf); -+} -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_dma.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_dma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma.h 2013-01-16 10:41:10.913798268 +0100 -@@ -0,0 +1,38 @@ -+#ifndef __SAA716x_DMA_H -+#define __SAA716x_DMA_H -+ -+#define SAA716x_PAGE_SIZE 4096 -+ -+enum saa716x_dma_type { -+ SAA716x_DMABUF_EXT_LIN, /* Linear external */ -+ SAA716x_DMABUF_EXT_SG, /* SG external */ -+ SAA716x_DMABUF_INT /* Linear internal */ -+}; -+ -+struct saa716x_dev; -+ -+struct saa716x_dmabuf { -+ enum saa716x_dma_type dma_type; -+ -+ void *mem_virt_noalign; -+ void *mem_virt; /* page aligned */ -+ dma_addr_t mem_ptab_phys; -+ void *mem_ptab_virt; -+ void *sg_list; /* SG list */ -+ -+ struct saa716x_dev *saa716x; -+ -+ int list_len; /* buffer len */ -+ int offset; /* page offset */ -+}; -+ -+extern int saa716x_dmabuf_alloc(struct saa716x_dev *saa716x, -+ struct saa716x_dmabuf *dmabuf, -+ int size); -+extern void saa716x_dmabuf_free(struct saa716x_dev *saa716x, -+ struct saa716x_dmabuf *dmabuf); -+ -+extern void saa716x_dmabufsync_dev(struct saa716x_dmabuf *dmabuf); -+extern void saa716x_dmabufsync_cpu(struct saa716x_dmabuf *dmabuf); -+ -+#endif /* __SAA716x_DMA_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_dma_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_dma_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_dma_reg.h 2013-01-16 10:41:10.913798268 +0100 -@@ -0,0 +1,200 @@ -+#ifndef __SAA716x_DMA_REG_H -+#define __SAA716x_DMA_REG_H -+ -+/* -------------- BAM Registers -------------- */ -+ -+#define BAM_VI0_0_DMA_BUF_MODE 0x000 -+ -+#define BAM_VI0_0_ADDR_OFFST_0 0x004 -+#define BAM_VI0_0_ADDR_OFFST_1 0x008 -+#define BAM_VI0_0_ADDR_OFFST_2 0x00c -+#define BAM_VI0_0_ADDR_OFFST_3 0x010 -+#define BAM_VI0_0_ADDR_OFFST_4 0x014 -+#define BAM_VI0_0_ADDR_OFFST_5 0x018 -+#define BAM_VI0_0_ADDR_OFFST_6 0x01c -+#define BAM_VI0_0_ADDR_OFFST_7 0x020 -+ -+#define BAM_VI0_1_DMA_BUF_MODE 0x024 -+#define BAM_VI0_1_ADDR_OFFST_0 0x028 -+#define BAM_VI0_1_ADDR_OFFST_1 0x02c -+#define BAM_VI0_1_ADDR_OFFST_2 0x030 -+#define BAM_VI0_1_ADDR_OFFST_3 0x034 -+#define BAM_VI0_1_ADDR_OFFST_4 0x038 -+#define BAM_VI0_1_ADDR_OFFST_5 0x03c -+#define BAM_VI0_1_ADDR_OFFST_6 0x040 -+#define BAM_VI0_1_ADDR_OFFST_7 0x044 -+ -+#define BAM_VI0_2_DMA_BUF_MODE 0x048 -+#define BAM_VI0_2_ADDR_OFFST_0 0x04c -+#define BAM_VI0_2_ADDR_OFFST_1 0x050 -+#define BAM_VI0_2_ADDR_OFFST_2 0x054 -+#define BAM_VI0_2_ADDR_OFFST_3 0x058 -+#define BAM_VI0_2_ADDR_OFFST_4 0x05c -+#define BAM_VI0_2_ADDR_OFFST_5 0x060 -+#define BAM_VI0_2_ADDR_OFFST_6 0x064 -+#define BAM_VI0_2_ADDR_OFFST_7 0x068 -+ -+ -+#define BAM_VI1_0_DMA_BUF_MODE 0x06c -+#define BAM_VI1_0_ADDR_OFFST_0 0x070 -+#define BAM_VI1_0_ADDR_OFFST_1 0x074 -+#define BAM_VI1_0_ADDR_OFFST_2 0x078 -+#define BAM_VI1_0_ADDR_OFFST_3 0x07c -+#define BAM_VI1_0_ADDR_OFFST_4 0x080 -+#define BAM_VI1_0_ADDR_OFFST_5 0x084 -+#define BAM_VI1_0_ADDR_OFFST_6 0x088 -+#define BAM_VI1_0_ADDR_OFFST_7 0x08c -+ -+#define BAM_VI1_1_DMA_BUF_MODE 0x090 -+#define BAM_VI1_1_ADDR_OFFST_0 0x094 -+#define BAM_VI1_1_ADDR_OFFST_1 0x098 -+#define BAM_VI1_1_ADDR_OFFST_2 0x09c -+#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 -+#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 -+#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 -+#define BAM_VI1_1_ADDR_OFFST_6 0x0ac -+#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 -+ -+#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 -+#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 -+#define BAM_VI1_2_ADDR_OFFST_1 0x0bc -+#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 -+#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 -+#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 -+#define BAM_VI1_2_ADDR_OFFST_5 0x0cc -+#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 -+#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 -+ -+ -+#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 -+#define BAM_FGPI0_ADDR_OFFST_0 0x0dc -+#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 -+#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 -+#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 -+#define BAM_FGPI0_ADDR_OFFST_4 0x0ec -+#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 -+#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 -+#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 -+ -+#define BAM_FGPI1_DMA_BUF_MODE 0x0fc -+#define BAM_FGPI1_ADDR_OFFST_0 0x100 -+#define BAM_FGPI1_ADDR_OFFST_1 0x104 -+#define BAM_FGPI1_ADDR_OFFST_2 0x108 -+#define BAM_FGPI1_ADDR_OFFST_3 0x10c -+#define BAM_FGPI1_ADDR_OFFST_4 0x110 -+#define BAM_FGPI1_ADDR_OFFST_5 0x114 -+#define BAM_FGPI1_ADDR_OFFST_6 0x118 -+#define BAM_FGPI1_ADDR_OFFST_7 0x11c -+ -+#define BAM_FGPI2_DMA_BUF_MODE 0x120 -+#define BAM_FGPI2_ADDR_OFFST_0 0x124 -+#define BAM_FGPI2_ADDR_OFFST_1 0x128 -+#define BAM_FGPI2_ADDR_OFFST_2 0x12c -+#define BAM_FGPI2_ADDR_OFFST_3 0x130 -+#define BAM_FGPI2_ADDR_OFFST_4 0x134 -+#define BAM_FGPI2_ADDR_OFFST_5 0x138 -+#define BAM_FGPI2_ADDR_OFFST_6 0x13c -+#define BAM_FGPI2_ADDR_OFFST_7 0x140 -+ -+#define BAM_FGPI3_DMA_BUF_MODE 0x144 -+#define BAM_FGPI3_ADDR_OFFST_0 0x148 -+#define BAM_FGPI3_ADDR_OFFST_1 0x14c -+#define BAM_FGPI3_ADDR_OFFST_2 0x150 -+#define BAM_FGPI3_ADDR_OFFST_3 0x154 -+#define BAM_FGPI3_ADDR_OFFST_4 0x158 -+#define BAM_FGPI3_ADDR_OFFST_5 0x15c -+#define BAM_FGPI3_ADDR_OFFST_6 0x160 -+#define BAM_FGPI3_ADDR_OFFST_7 0x164 -+ -+ -+#define BAM_AI0_DMA_BUF_MODE 0x168 -+#define BAM_AI0_ADDR_OFFST_0 0x16c -+#define BAM_AI0_ADDR_OFFST_1 0x170 -+#define BAM_AI0_ADDR_OFFST_2 0x174 -+#define BAM_AI0_ADDR_OFFST_3 0x178 -+#define BAM_AI0_ADDR_OFFST_4 0x17c -+#define BAM_AIO_ADDR_OFFST_5 0x180 -+#define BAM_AI0_ADDR_OFFST_6 0x184 -+#define BAM_AIO_ADDR_OFFST_7 0x188 -+ -+#define BAM_AI1_DMA_BUF_MODE 0x18c -+#define BAM_AI1_ADDR_OFFST_0 0x190 -+#define BAM_AI1_ADDR_OFFST_1 0x194 -+#define BAM_AI1_ADDR_OFFST_2 0x198 -+#define BAM_AI1_ADDR_OFFST_3 0x19c -+#define BAM_AI1_ADDR_OFFST_4 0x1a0 -+#define BAM_AI1_ADDR_OFFST_5 0x1a4 -+#define BAM_AI1_ADDR_OFFST_6 0x1a8 -+#define BAM_AI1_ADDR_OFFST_7 0x1ac -+ -+#define BAM_SW_RST 0xff0 -+#define BAM_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+ -+/* -------------- MMU Registers -------------- */ -+ -+#define MMU_MODE 0x000 -+ -+#define MMU_DMA_CONFIG0 0x004 -+#define MMU_DMA_CONFIG1 0x008 -+#define MMU_DMA_CONFIG2 0x00c -+#define MMU_DMA_CONFIG3 0x010 -+#define MMU_DMA_CONFIG4 0x014 -+#define MMU_DMA_CONFIG5 0x018 -+#define MMU_DMA_CONFIG6 0x01c -+#define MMU_DMA_CONFIG7 0x020 -+#define MMU_DMA_CONFIG8 0x024 -+#define MMU_DMA_CONFIG9 0x028 -+#define MMU_DMA_CONFIG10 0x02c -+#define MMU_DMA_CONFIG11 0x030 -+#define MMU_DMA_CONFIG12 0x034 -+#define MMU_DMA_CONFIG13 0x038 -+#define MMU_DMA_CONFIG14 0x03c -+#define MMU_DMA_CONFIG15 0x040 -+ -+#define MMU_SW_RST 0xff0 -+#define MMU_SW_RESET (0x0001 << 0) -+ -+#define MMU_PTA_BASE0 0x044 /* DMA 0 */ -+#define MMU_PTA_BASE1 0x084 /* DMA 1 */ -+#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ -+#define MMU_PTA_BASE3 0x104 /* DMA 3 */ -+#define MMU_PTA_BASE4 0x144 /* DMA 4 */ -+#define MMU_PTA_BASE5 0x184 /* DMA 5 */ -+#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ -+#define MMU_PTA_BASE7 0x204 /* DMA 7 */ -+#define MMU_PTA_BASE8 0x244 /* DMA 8 */ -+#define MMU_PTA_BASE9 0x284 /* DMA 9 */ -+#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ -+#define MMU_PTA_BASE11 0x304 /* DMA 11 */ -+#define MMU_PTA_BASE12 0x344 /* DMA 12 */ -+#define MMU_PTA_BASE13 0x384 /* DMA 13 */ -+#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ -+#define MMU_PTA_BASE15 0x404 /* DMA 15 */ -+ -+#define MMU_PTA_BASE 0x044 /* DMA 0 */ -+#define MMU_PTA_OFFSET 0x40 -+ -+#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) -+ -+#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 -+#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 -+#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 -+#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c -+#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 -+#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 -+#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 -+#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c -+#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 -+#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 -+#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 -+#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c -+#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 -+#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 -+#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 -+#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c -+ -+#endif /* __SAA716x_DMA_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_cmd.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_cmd.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_cmd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_cmd.c 2013-01-16 10:41:10.914798261 +0100 -@@ -0,0 +1,412 @@ -+#include -+ -+#include -+#include -+ -+#include "saa716x_phi_reg.h" -+ -+#include "saa716x_phi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+#include "saa716x_ff.h" -+#include "saa716x_ff_cmd.h" -+ -+ -+int sti7109_cmd_init(struct sti7109_dev *sti7109) -+{ -+ mutex_init(&sti7109->cmd_lock); -+ mutex_init(&sti7109->osd_cmd_lock); -+ mutex_init(&sti7109->data_lock); -+ -+ init_waitqueue_head(&sti7109->boot_finish_wq); -+ sti7109->boot_finished = 0; -+ -+ init_waitqueue_head(&sti7109->cmd_ready_wq); -+ sti7109->cmd_ready = 0; -+ -+ init_waitqueue_head(&sti7109->result_avail_wq); -+ sti7109->result_avail = 0; -+ -+ init_waitqueue_head(&sti7109->osd_cmd_ready_wq); -+ sti7109->osd_cmd_ready = 0; -+ init_waitqueue_head(&sti7109->osd_result_avail_wq); -+ sti7109->osd_result_avail = 0; -+ -+ sti7109->data_handle = 0; -+ sti7109->data_buffer = (u8 *) (sti7109->iobuf + TSOUT_LEN + TSBUF_LEN); -+ init_waitqueue_head(&sti7109->data_ready_wq); -+ sti7109->data_ready = 0; -+ init_waitqueue_head(&sti7109->block_done_wq); -+ sti7109->block_done = 0; -+ return 0; -+} -+ -+static int sti7109_do_raw_cmd(struct sti7109_dev * sti7109) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->cmd_ready_wq, -+ sti7109->cmd_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->cmd_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "cmd ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for command ready"); -+ return -EIO; -+ } -+ -+ sti7109->cmd_ready = 0; -+ sti7109->result_avail = 0; -+ saa716x_phi_write(saa716x, ADDR_CMD_DATA, sti7109->cmd_data, -+ sti7109->cmd_len); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_CMD_MASK); -+ -+ if (sti7109->result_max_len > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout( -+ sti7109->result_avail_wq, -+ sti7109->result_avail == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->result_avail == 0) { -+ sti7109->result_len = 0; -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "result ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for command result"); -+ return -EIO; -+ } -+ -+ if (sti7109->result_len > sti7109->result_max_len) { -+ sti7109->result_len = sti7109->result_max_len; -+ dprintk(SAA716x_NOTICE, 1, -+ "not enough space in result buffer"); -+ } -+ } -+ -+ return 0; -+} -+ -+int sti7109_raw_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (cmd->cmd_len > SIZE_CMD_DATA) { -+ dprintk(SAA716x_ERROR, 1, "command too long"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->cmd_data, (void __user *)cmd->cmd_data, -+ cmd->cmd_len)) -+ goto out; -+ -+ sti7109->cmd_len = cmd->cmd_len; -+ sti7109->result_max_len = cmd->result_len; -+ -+ err = sti7109_do_raw_cmd(sti7109); -+ if (err) -+ goto out; -+ -+ cmd->result_len = sti7109->result_len; -+ if (sti7109->result_len > 0) { -+ if (copy_to_user((void __user *)cmd->result_data, -+ sti7109->result_data, -+ sti7109->result_len)) -+ err = -EFAULT; -+ } -+ -+out: -+ mutex_unlock(&sti7109->cmd_lock); -+ return err; -+} -+ -+static int sti7109_do_raw_osd_cmd(struct sti7109_dev * sti7109) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->osd_cmd_ready_wq, -+ sti7109->osd_cmd_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->osd_cmd_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "osd cmd ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for osd command ready"); -+ return -EIO; -+ } -+ -+ sti7109->osd_cmd_ready = 0; -+ sti7109->osd_result_avail = 0; -+ saa716x_phi_write(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_cmd_data, -+ sti7109->osd_cmd_len); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_OSD_CMD_MASK); -+ -+ if (sti7109->osd_result_max_len > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout( -+ sti7109->osd_result_avail_wq, -+ sti7109->osd_result_avail == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->osd_result_avail == 0) { -+ sti7109->osd_result_len = 0; -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, -+ "osd result ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for osd command result"); -+ return -EIO; -+ } -+ -+ if (sti7109->osd_result_len > sti7109->osd_result_max_len) { -+ sti7109->osd_result_len = sti7109->osd_result_max_len; -+ dprintk(SAA716x_NOTICE, 1, -+ "not enough space in result buffer"); -+ } -+ } -+ -+ return 0; -+} -+ -+int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, osd_raw_cmd_t * cmd) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (cmd->cmd_len > SIZE_OSD_CMD_DATA) { -+ dprintk(SAA716x_ERROR, 1, "command too long"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->osd_cmd_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->osd_cmd_data, (void __user *)cmd->cmd_data, -+ cmd->cmd_len)) -+ goto out; -+ -+ sti7109->osd_cmd_len = cmd->cmd_len; -+ sti7109->osd_result_max_len = cmd->result_len; -+ -+ err = sti7109_do_raw_osd_cmd(sti7109); -+ if (err) -+ goto out; -+ -+ cmd->result_len = sti7109->osd_result_len; -+ if (sti7109->osd_result_len > 0) { -+ if (copy_to_user((void __user *)cmd->result_data, -+ sti7109->osd_result_data, -+ sti7109->osd_result_len)) -+ err = -EFAULT; -+ } -+ -+out: -+ mutex_unlock(&sti7109->osd_cmd_lock); -+ return err; -+} -+ -+static int sti7109_do_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ unsigned long timeout; -+ u16 blockSize; -+ u16 lastBlockSize; -+ u16 numBlocks; -+ u16 blockIndex; -+ u8 blockHeader[SIZE_BLOCK_HEADER]; -+ u8 * blockPtr; -+ int activeBlock; -+ -+ timeout = 1 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->data_ready_wq, -+ sti7109->data_ready == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->data_ready == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ dprintk(SAA716x_ERROR, 1, "data ERESTARTSYS"); -+ return -ERESTARTSYS; -+ } -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for data ready"); -+ return -EIO; -+ } -+ -+ sti7109->data_ready = 0; -+ -+ /* -+ * 8 bytes is the size of the block header. Block header structure is: -+ * 16 bit - block index -+ * 16 bit - number of blocks -+ * 16 bit - current block data size -+ * 16 bit - block handle. This is used to reference the data in the -+ * command that uses it. -+ */ -+ blockSize = (SIZE_BLOCK_DATA / 2) - SIZE_BLOCK_HEADER; -+ numBlocks = data->data_length / blockSize; -+ lastBlockSize = data->data_length % blockSize; -+ if (lastBlockSize > 0) -+ numBlocks++; -+ -+ blockHeader[2] = (u8) (numBlocks >> 8); -+ blockHeader[3] = (u8) numBlocks; -+ blockHeader[6] = (u8) (sti7109->data_handle >> 8); -+ blockHeader[7] = (u8) sti7109->data_handle; -+ blockPtr = sti7109->data_buffer; -+ activeBlock = 0; -+ for (blockIndex = 0; blockIndex < numBlocks; blockIndex++) { -+ u32 addr; -+ -+ if (lastBlockSize && (blockIndex == (numBlocks - 1))) -+ blockSize = lastBlockSize; -+ -+ blockHeader[0] = (uint8_t) (blockIndex >> 8); -+ blockHeader[1] = (uint8_t) blockIndex; -+ blockHeader[4] = (uint8_t) (blockSize >> 8); -+ blockHeader[5] = (uint8_t) blockSize; -+ -+ addr = ADDR_BLOCK_DATA + activeBlock * (SIZE_BLOCK_DATA / 2); -+ saa716x_phi_write(saa716x, addr, blockHeader, -+ SIZE_BLOCK_HEADER); -+ saa716x_phi_write(saa716x, addr + SIZE_BLOCK_HEADER, blockPtr, -+ blockSize); -+ activeBlock = (activeBlock + 1) & 1; -+ if (blockIndex > 0) { -+ timeout = 1 * HZ; -+ timeout = wait_event_timeout(sti7109->block_done_wq, -+ sti7109->block_done == 1, -+ timeout); -+ -+ if (sti7109->block_done == 0) { -+ dprintk(SAA716x_ERROR, 1, -+ "timed out waiting for block done"); -+ return -EIO; -+ } -+ } -+ sti7109->block_done = 0; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PHI_ISET, ISR_BLOCK_MASK); -+ blockPtr += blockSize; -+ } -+ timeout = 1 * HZ; -+ timeout = wait_event_timeout(sti7109->block_done_wq, -+ sti7109->block_done == 1, -+ timeout); -+ -+ if (sti7109->block_done == 0) { -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for block done"); -+ return -EIO; -+ } -+ sti7109->block_done = 0; -+ -+ data->data_handle = sti7109->data_handle; -+ sti7109->data_handle++; -+ return 0; -+} -+ -+int sti7109_raw_data(struct sti7109_dev * sti7109, osd_raw_data_t * data) -+{ -+ struct saa716x_dev * saa716x = sti7109->dev; -+ int err; -+ -+ if (data->data_length > MAX_DATA_LEN) { -+ dprintk(SAA716x_ERROR, 1, "data too big"); -+ return -EFAULT; -+ } -+ -+ mutex_lock(&sti7109->data_lock); -+ -+ err = -EFAULT; -+ if (copy_from_user(sti7109->data_buffer, -+ (void __user *)data->data_buffer, -+ data->data_length)) -+ goto out; -+ -+ err = sti7109_do_raw_data(sti7109, data); -+ if (err) -+ goto out; -+ -+out: -+ mutex_unlock(&sti7109->data_lock); -+ return err; -+} -+ -+int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, u32 *fw_version) -+{ -+ int ret_val = -EINVAL; -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ sti7109->cmd_data[0] = 0x00; -+ sti7109->cmd_data[1] = 0x04; -+ sti7109->cmd_data[2] = 0x00; -+ sti7109->cmd_data[3] = 0x00; -+ sti7109->cmd_data[4] = 0x00; -+ sti7109->cmd_data[5] = 0x00; -+ sti7109->cmd_len = 6; -+ sti7109->result_max_len = MAX_RESULT_LEN; -+ -+ ret_val = sti7109_do_raw_cmd(sti7109); -+ if (ret_val == 0) { -+ *fw_version = (sti7109->result_data[6] << 16) -+ | (sti7109->result_data[7] << 8) -+ | sti7109->result_data[8]; -+ } -+ -+ mutex_unlock(&sti7109->cmd_lock); -+ -+ return ret_val; -+} -+ -+int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, video_size_t *vs) -+{ -+ int ret_val = -EINVAL; -+ -+ mutex_lock(&sti7109->cmd_lock); -+ -+ sti7109->cmd_data[0] = 0x00; -+ sti7109->cmd_data[1] = 0x05; /* command length */ -+ sti7109->cmd_data[2] = 0x00; -+ sti7109->cmd_data[3] = 0x01; /* A/V decoder command group */ -+ sti7109->cmd_data[4] = 0x00; -+ sti7109->cmd_data[5] = 0x10; /* get video format info command */ -+ sti7109->cmd_data[6] = 0x00; /* decoder index 0 */ -+ sti7109->cmd_len = 7; -+ sti7109->result_max_len = MAX_RESULT_LEN; -+ -+ ret_val = sti7109_do_raw_cmd(sti7109); -+ if (ret_val == 0) { -+ vs->w = (sti7109->result_data[7] << 8) -+ | sti7109->result_data[8]; -+ vs->h = (sti7109->result_data[9] << 8) -+ | sti7109->result_data[10]; -+ vs->aspect_ratio = sti7109->result_data[11] >> 4; -+ } -+ -+ mutex_unlock(&sti7109->cmd_lock); -+ -+ return ret_val; -+} -+ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_cmd.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_cmd.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_cmd.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_cmd.h 2013-01-16 10:41:10.914798261 +0100 -@@ -0,0 +1,16 @@ -+#ifndef __SAA716x_FF_CMD_H -+#define __SAA716x_FF_CMD_H -+ -+extern int sti7109_cmd_init(struct sti7109_dev *sti7109); -+extern int sti7109_raw_cmd(struct sti7109_dev * sti7109, -+ osd_raw_cmd_t * cmd); -+extern int sti7109_raw_osd_cmd(struct sti7109_dev * sti7109, -+ osd_raw_cmd_t * cmd); -+extern int sti7109_raw_data(struct sti7109_dev * sti7109, -+ osd_raw_data_t * data); -+extern int sti7109_cmd_get_fw_version(struct sti7109_dev *sti7109, -+ u32 *fw_version); -+extern int sti7109_cmd_get_video_format(struct sti7109_dev *sti7109, -+ video_size_t *vs); -+ -+#endif /* __SAA716x_FF_CMD_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff.h 2013-01-16 10:41:10.915798254 +0100 -@@ -0,0 +1,158 @@ -+#ifndef __SAA716x_FF_H -+#define __SAA716x_FF_H -+ -+#include "dvb_filter.h" -+#include "dvb_ringbuffer.h" -+ -+#define TECHNOTREND 0x13c2 -+#define S2_6400_DUAL_S2_PREMIUM_DEVEL 0x3009 -+#define S2_6400_DUAL_S2_PREMIUM_PROD 0x300A -+ -+#define TT_PREMIUM_GPIO_POWER_ENABLE 27 -+#define TT_PREMIUM_GPIO_RESET_BACKEND 26 -+#define TT_PREMIUM_GPIO_FPGA_CS1 17 -+#define TT_PREMIUM_GPIO_FPGA_CS0 16 -+#define TT_PREMIUM_GPIO_FPGA_PROGRAMN 15 -+#define TT_PREMIUM_GPIO_FPGA_DONE 14 -+#define TT_PREMIUM_GPIO_FPGA_INITN 13 -+ -+/* fpga interrupt register addresses */ -+#define FPGA_ADDR_PHI_ICTRL 0x8000 /* PHI General control of the PC => STB interrupt controller */ -+#define FPGA_ADDR_PHI_ISR 0x8010 /* PHI Interrupt Status Register */ -+#define FPGA_ADDR_PHI_ISET 0x8020 /* PHI Interrupt Set Register */ -+#define FPGA_ADDR_PHI_ICLR 0x8030 /* PHI Interrupt Clear Register */ -+#define FPGA_ADDR_EMI_ICTRL 0x8100 /* EMI General control of the STB => PC interrupt controller */ -+#define FPGA_ADDR_EMI_ISR 0x8110 /* EMI Interrupt Status Register */ -+#define FPGA_ADDR_EMI_ISET 0x8120 /* EMI Interrupt Set Register */ -+#define FPGA_ADDR_EMI_ICLR 0x8130 /* EMI Interrupt Clear Register */ -+ -+/* fpga TS router register addresses */ -+#define FPGA_ADDR_TSR_CTRL 0x8200 /* TS router control register */ -+#define FPGA_ADDR_TSR_MUX1 0x8210 /* TS multiplexer 1 selection register */ -+#define FPGA_ADDR_TSR_MUX2 0x8220 /* TS multiplexer 2 selection register */ -+#define FPGA_ADDR_TSR_MUX3 0x8230 /* TS multiplexer 3 selection register */ -+#define FPGA_ADDR_TSR_MUXCI1 0x8240 /* TS multiplexer CI 1 selection register */ -+#define FPGA_ADDR_TSR_MUXCI2 0x8250 /* TS multiplexer CI 2 selection register */ -+ -+#define FPGA_ADDR_TSR_BRFE1 0x8280 /* bit rate for TS coming from frontend 1 */ -+#define FPGA_ADDR_TSR_BRFE2 0x8284 /* bit rate for TS coming from frontend 2 */ -+#define FPGA_ADDR_TSR_BRFF1 0x828C /* bit rate for TS coming from FIFO 1 */ -+#define FPGA_ADDR_TSR_BRO1 0x8294 /* bit rate for TS going to output 1 */ -+#define FPGA_ADDR_TSR_BRO2 0x8298 /* bit rate for TS going to output 2 */ -+#define FPGA_ADDR_TSR_BRO3 0x829C /* bit rate for TS going to output 3 */ -+ -+/* fpga TS FIFO register addresses */ -+#define FPGA_ADDR_FIFO_CTRL 0x8300 /* FIFO control register */ -+#define FPGA_ADDR_FIFO_STAT 0x8310 /* FIFO status register */ -+ -+#define FPGA_ADDR_VERSION 0x80F0 /* FPGA bitstream version register */ -+ -+#define FPGA_ADDR_PIO_CTRL 0x8500 /* FPGA GPIO control register */ -+ -+#define ISR_CMD_MASK 0x0001 /* interrupt source for normal cmds (osd, fre, av, ...) */ -+#define ISR_READY_MASK 0x0002 /* interrupt source for command acknowledge */ -+#define ISR_BLOCK_MASK 0x0004 /* interrupt source for single block transfers and acknowledge */ -+#define ISR_DATA_MASK 0x0008 /* interrupt source for data transfer acknowledge */ -+#define ISR_BOOT_FINISH_MASK 0x0010 /* interrupt source for boot finish indication */ -+#define ISR_AUDIO_PTS_MASK 0x0020 /* interrupt source for audio PTS */ -+#define ISR_VIDEO_PTS_MASK 0x0040 /* interrupt source for video PTS */ -+#define ISR_CURRENT_STC_MASK 0x0080 /* interrupt source for current system clock */ -+#define ISR_REMOTE_EVENT_MASK 0x0100 /* interrupt source for remote events */ -+#define ISR_DVO_FORMAT_MASK 0x0200 /* interrupt source for DVO format change */ -+#define ISR_OSD_CMD_MASK 0x0400 /* interrupt source for OSD cmds */ -+#define ISR_OSD_READY_MASK 0x0800 /* interrupt source for OSD command acknowledge */ -+#define ISR_FE_CMD_MASK 0x1000 /* interrupt source for frontend cmds */ -+#define ISR_FE_READY_MASK 0x2000 /* interrupt source for frontend command acknowledge */ -+#define ISR_LOG_MESSAGE_MASK 0x4000 /* interrupt source for log messages */ -+#define ISR_FIFO1_EMPTY_MASK 0x8000 /* interrupt source for FIFO1 empty */ -+ -+#define ADDR_CMD_DATA 0x0000 /* address for cmd data in fpga dpram */ -+#define ADDR_OSD_CMD_DATA 0x01A0 /* address for OSD cmd data */ -+#define ADDR_FE_CMD_DATA 0x05C0 /* address for frontend cmd data */ -+#define ADDR_BLOCK_DATA 0x0600 /* address for block data */ -+#define ADDR_AUDIO_PTS 0x3E00 /* address for audio PTS (64 Bits) */ -+#define ADDR_VIDEO_PTS 0x3E08 /* address for video PTS (64 Bits) */ -+#define ADDR_CURRENT_STC 0x3E10 /* address for system clock (64 Bits) */ -+#define ADDR_DVO_FORMAT 0x3E18 /* address for DVO format 32 Bits) */ -+#define ADDR_REMOTE_EVENT 0x3F00 /* address for remote events (32 Bits) */ -+#define ADDR_LOG_MESSAGE 0x3F80 /* address for log messages */ -+ -+#define SIZE_CMD_DATA 0x01A0 /* maximum size for command data (416 Bytes) */ -+#define SIZE_OSD_CMD_DATA 0x0420 /* maximum size for OSD command data (1056 Bytes) */ -+#define SIZE_FE_CMD_DATA 0x0040 /* maximum size for frontend command data (64 Bytes) */ -+#define SIZE_BLOCK_DATA 0x3800 /* maximum size for block data (14 kB) */ -+#define SIZE_LOG_MESSAGE_DATA 0x0080 /* maximum size for log message data (128 Bytes) */ -+ -+#define SIZE_BLOCK_HEADER 8 /* block header size */ -+ -+#define MAX_RESULT_LEN 256 -+#define MAX_DATA_LEN (1024 * 1024) -+ -+#define TSOUT_LEN (1024 * TS_SIZE) -+#define TSBUF_LEN (8 * 1024) -+ -+/* place to store all the necessary device information */ -+struct sti7109_dev { -+ struct saa716x_dev *dev; -+ struct dvb_device *osd_dev; -+ struct dvb_device *video_dev; -+ struct dvb_device *audio_dev; -+ -+ void *iobuf; /* memory for all buffers */ -+ struct dvb_ringbuffer tsout; /* buffer for TS output */ -+ u8 *tsbuf; /* temp ts buffer */ -+ -+ struct tasklet_struct fifo_tasklet; -+ -+ wait_queue_head_t boot_finish_wq; -+ int boot_finished; -+ -+ wait_queue_head_t cmd_ready_wq; -+ int cmd_ready; -+ u8 cmd_data[SIZE_CMD_DATA]; -+ u32 cmd_len; -+ -+ wait_queue_head_t result_avail_wq; -+ int result_avail; -+ u8 result_data[MAX_RESULT_LEN]; -+ u32 result_len; -+ u32 result_max_len; -+ -+ wait_queue_head_t osd_cmd_ready_wq; -+ int osd_cmd_ready; -+ u8 osd_cmd_data[SIZE_OSD_CMD_DATA]; -+ u32 osd_cmd_len; -+ -+ wait_queue_head_t osd_result_avail_wq; -+ int osd_result_avail; -+ u8 osd_result_data[MAX_RESULT_LEN]; -+ u32 osd_result_len; -+ u32 osd_result_max_len; -+ -+ u16 data_handle; -+ u8 *data_buffer; /* raw data transfer buffer */ -+ wait_queue_head_t data_ready_wq; -+ int data_ready; -+ wait_queue_head_t block_done_wq; -+ int block_done; -+ -+ struct mutex cmd_lock; -+ struct mutex osd_cmd_lock; -+ struct mutex data_lock; -+ -+ u64 audio_pts; -+ u64 video_pts; -+ u64 current_stc; -+ -+ u32 int_count_enable; -+ u32 total_int_count; -+ u32 fgpi_int_count[2]; -+ u32 i2c_int_count[2]; -+ u32 ext_int_total_count; -+ u32 ext_int_source_count[16]; -+ u32 last_int_ticks; -+ -+ u16 fpga_version; -+}; -+ -+#endif /* __SAA716x_FF_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_ir.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_ir.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_ir.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_ir.c 2013-01-16 10:41:10.915798254 +0100 -@@ -0,0 +1,265 @@ -+/* -+ * Driver for the remote control of the TT6400 DVB-S2 card -+ * -+ * Copyright (C) 2010 Oliver Endriss -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html -+ * -+ */ -+ -+#include -+#include -+ -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+#include "saa716x_ff.h" -+ -+ -+/* infrared remote control */ -+struct infrared { -+ u16 key_map[128]; -+ struct input_dev *input_dev; -+ char input_phys[32]; -+ struct timer_list keyup_timer; -+ struct tasklet_struct tasklet; -+ u32 command; -+ u32 device_mask; -+ u8 protocol; -+ u16 last_key; -+ u16 last_toggle; -+ bool delay_timer_finished; -+}; -+ -+#define IR_RC5 0 -+#define UP_TIMEOUT (HZ*7/25) -+ -+ -+/* key-up timer */ -+static void ir_emit_keyup(unsigned long parm) -+{ -+ struct infrared *ir = (struct infrared *) parm; -+ -+ if (!ir || !test_bit(ir->last_key, ir->input_dev->key)) -+ return; -+ -+ input_report_key(ir->input_dev, ir->last_key, 0); -+ input_sync(ir->input_dev); -+} -+ -+ -+/* tasklet */ -+static void ir_emit_key(unsigned long parm) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) parm; -+ struct infrared *ir = saa716x->ir_priv; -+ u32 ircom = ir->command; -+ u8 data; -+ u8 addr; -+ u16 toggle; -+ u16 keycode; -+ -+ /* extract device address and data */ -+ if (ircom & 0x80000000) { /* CEC remote command */ -+ addr = 0; -+ data = ircom & 0x7F; -+ toggle = 0; -+ } else { -+ switch (ir->protocol) { -+ case IR_RC5: /* extended RC5: 5 bits device address, 7 bits data */ -+ addr = (ircom >> 6) & 0x1f; -+ /* data bits 1..6 */ -+ data = ircom & 0x3f; -+ /* data bit 7 (inverted) */ -+ if (!(ircom & 0x1000)) -+ data |= 0x40; -+ toggle = ircom & 0x0800; -+ break; -+ -+ default: -+ printk(KERN_ERR "%s: invalid protocol %x\n", -+ __func__, ir->protocol); -+ return; -+ } -+ } -+ -+ input_event(ir->input_dev, EV_MSC, MSC_RAW, (addr << 16) | data); -+ input_event(ir->input_dev, EV_MSC, MSC_SCAN, data); -+ -+ keycode = ir->key_map[data]; -+ -+ dprintk(SAA716x_DEBUG, 0, -+ "%s: code %08x -> addr %i data 0x%02x -> keycode %i\n", -+ __func__, ircom, addr, data, keycode); -+ -+ /* check device address */ -+ if (!(ir->device_mask & (1 << addr))) -+ return; -+ -+ if (!keycode) { -+ printk(KERN_WARNING "%s: code %08x -> addr %i data 0x%02x -> unknown key!\n", -+ __func__, ircom, addr, data); -+ return; -+ } -+ -+ if (timer_pending(&ir->keyup_timer)) { -+ del_timer(&ir->keyup_timer); -+ if (ir->last_key != keycode || toggle != ir->last_toggle) { -+ ir->delay_timer_finished = false; -+ input_event(ir->input_dev, EV_KEY, ir->last_key, 0); -+ input_event(ir->input_dev, EV_KEY, keycode, 1); -+ input_sync(ir->input_dev); -+ } else if (ir->delay_timer_finished) { -+ input_event(ir->input_dev, EV_KEY, keycode, 2); -+ input_sync(ir->input_dev); -+ } -+ } else { -+ ir->delay_timer_finished = false; -+ input_event(ir->input_dev, EV_KEY, keycode, 1); -+ input_sync(ir->input_dev); -+ } -+ -+ ir->last_key = keycode; -+ ir->last_toggle = toggle; -+ -+ ir->keyup_timer.expires = jiffies + UP_TIMEOUT; -+ add_timer(&ir->keyup_timer); -+ -+} -+ -+ -+/* register with input layer */ -+static void ir_register_keys(struct infrared *ir) -+{ -+ int i; -+ -+ set_bit(EV_KEY, ir->input_dev->evbit); -+ set_bit(EV_REP, ir->input_dev->evbit); -+ set_bit(EV_MSC, ir->input_dev->evbit); -+ -+ set_bit(MSC_RAW, ir->input_dev->mscbit); -+ set_bit(MSC_SCAN, ir->input_dev->mscbit); -+ -+ memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); -+ -+ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) { -+ if (ir->key_map[i] > KEY_MAX) -+ ir->key_map[i] = 0; -+ else if (ir->key_map[i] > KEY_RESERVED) -+ set_bit(ir->key_map[i], ir->input_dev->keybit); -+ } -+ -+ ir->input_dev->keycode = ir->key_map; -+ ir->input_dev->keycodesize = sizeof(ir->key_map[0]); -+ ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map); -+} -+ -+ -+/* called by the input driver after rep[REP_DELAY] ms */ -+static void ir_repeat_key(unsigned long parm) -+{ -+ struct infrared *ir = (struct infrared *) parm; -+ -+ ir->delay_timer_finished = true; -+} -+ -+ -+/* interrupt handler */ -+void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd) -+{ -+ struct infrared *ir = saa716x->ir_priv; -+ -+ if (!ir) -+ return; -+ -+ ir->command = ir_cmd; -+ tasklet_schedule(&ir->tasklet); -+} -+ -+ -+int saa716x_ir_init(struct saa716x_dev *saa716x) -+{ -+ struct input_dev *input_dev; -+ struct infrared *ir; -+ int rc; -+ int i; -+ -+ if (!saa716x) -+ return -ENOMEM; -+ -+ ir = kzalloc(sizeof(struct infrared), GFP_KERNEL); -+ if (!ir) -+ return -ENOMEM; -+ -+ init_timer(&ir->keyup_timer); -+ ir->keyup_timer.function = ir_emit_keyup; -+ ir->keyup_timer.data = (unsigned long) ir; -+ -+ input_dev = input_allocate_device(); -+ if (!input_dev) -+ goto err; -+ -+ ir->input_dev = input_dev; -+ input_dev->name = "TT6400 DVB IR receiver"; -+ snprintf(ir->input_phys, sizeof(ir->input_phys), -+ "pci-%s/ir0", pci_name(saa716x->pdev)); -+ input_dev->phys = ir->input_phys; -+ input_dev->id.bustype = BUS_PCI; -+ input_dev->id.version = 1; -+ input_dev->id.vendor = saa716x->pdev->subsystem_vendor; -+ input_dev->id.product = saa716x->pdev->subsystem_device; -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) -+ input_dev->dev.parent = &saa716x->pdev->dev; -+#else -+ input_dev->cdev.dev = &saa716x->pdev->dev; -+#endif -+ rc = input_register_device(input_dev); -+ if (rc) -+ goto err; -+ -+ /* TODO: fix setup/keymap */ -+ ir->protocol = IR_RC5; -+ ir->device_mask = 0xffffffff; -+ for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) -+ ir->key_map[i] = i+1; -+ ir_register_keys(ir); -+ -+ /* override repeat timer */ -+ input_dev->timer.function = ir_repeat_key; -+ input_dev->timer.data = (unsigned long) ir; -+ -+ tasklet_init(&ir->tasklet, ir_emit_key, (unsigned long) saa716x); -+ saa716x->ir_priv = ir; -+ -+ return 0; -+ -+err: -+ if (ir->input_dev) -+ input_free_device(ir->input_dev); -+ kfree(ir); -+ return -ENOMEM; -+} -+ -+ -+void saa716x_ir_exit(struct saa716x_dev *saa716x) -+{ -+ struct infrared *ir = saa716x->ir_priv; -+ -+ saa716x->ir_priv = NULL; -+ tasklet_kill(&ir->tasklet); -+ del_timer_sync(&ir->keyup_timer); -+ input_unregister_device(ir->input_dev); -+ kfree(ir); -+} -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_main.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_main.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_ff_main.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_ff_main.c 2013-01-16 10:41:10.917798240 +0100 -@@ -0,0 +1,1535 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_dma_reg.h" -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_phi_reg.h" -+#include "saa716x_spi_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_vip.h" -+#include "saa716x_aip.h" -+#include "saa716x_msi.h" -+#include "saa716x_adap.h" -+#include "saa716x_gpio.h" -+#include "saa716x_phi.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "saa716x_ff.h" -+#include "saa716x_ff_cmd.h" -+ -+#include "stv6110x.h" -+#include "stv090x.h" -+#include "isl6423.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+unsigned int int_count_enable; -+module_param(int_count_enable, int, 0644); -+MODULE_PARM_DESC(int_count_enable, "enable counting of interrupts"); -+ -+#define DRIVER_NAME "SAA716x FF" -+ -+static int saa716x_ff_fpga_init(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ int fpgaInit; -+ int fpgaDone; -+ int rounds; -+ int ret; -+ const struct firmware *fw; -+ -+ /* request the FPGA firmware, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-fpga-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load FPGA firmware," -+ " file not found: dvb-ttpremium-fpga-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ -+ /* set FPGA PROGRAMN high */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); -+ msleep(10); -+ -+ /* set FPGA PROGRAMN low to set it into configuration mode */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 0); -+ msleep(10); -+ -+ /* set FPGA PROGRAMN high to start configuration process */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN, 1); -+ -+ rounds = 0; -+ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ while (fpgaInit == 0 && rounds < 5000) { -+ //msleep(1); -+ fpgaInit = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ rounds++; -+ } -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA INITN=%d, rounds=%d", -+ fpgaInit, rounds); -+ -+ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, 0x08); -+ SAA716x_EPWR(SPI, SPI_CONTROL_REG, SPI_MODE_SELECT); -+ -+ msleep(10); -+ -+ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream"); -+ saa716x_spi_write(saa716x, fw->data, fw->size); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA write bitstream done"); -+ fpgaDone = saa716x_gpio_read(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ dprintk(SAA716x_INFO, 1, "SAA716x FF FPGA DONE=%d", fpgaDone); -+ -+ msleep(10); -+ -+ release_firmware(fw); -+ -+ if (!fpgaDone) { -+ printk(KERN_ERR "SAA716x FF FPGA is not responding, did you " -+ "connect the power supply?\n"); -+ return -EINVAL; -+ } -+ -+ sti7109->fpga_version = SAA716x_EPRD(PHI_1, FPGA_ADDR_VERSION); -+ printk(KERN_INFO "SAA716x FF FPGA version %X.%02X\n", -+ sti7109->fpga_version >> 8, sti7109->fpga_version & 0xFF); -+ -+ return 0; -+} -+ -+static int saa716x_ff_st7109_init(struct saa716x_dev *saa716x) -+{ -+ int i; -+ int length; -+ u32 requestedBlock; -+ u32 writtenBlock; -+ u32 numBlocks; -+ u32 blockSize; -+ u32 lastBlockSize; -+ u64 startTime; -+ u64 currentTime; -+ u64 waitTime; -+ int ret; -+ const struct firmware *fw; -+ u32 loaderVersion; -+ -+ /* request the st7109 loader, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-loader-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 loader," -+ " file not found: dvb-ttpremium-loader-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ loaderVersion = (fw->data[0x1385] << 8) | fw->data[0x1384]; -+ printk(KERN_INFO "SAA716x FF loader version %X.%02X\n", -+ loaderVersion >> 8, loaderVersion & 0xFF); -+ -+ saa716x_phi_write(saa716x, 0, fw->data, fw->size); -+ msleep(10); -+ -+ release_firmware(fw); -+ -+ /* take ST out of reset */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 1); -+ -+ startTime = jiffies; -+ waitTime = 0; -+ do { -+ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); -+ if (requestedBlock == 1) -+ break; -+ -+ currentTime = jiffies; -+ waitTime = currentTime - startTime; -+ } while (waitTime < (1 * HZ)); -+ -+ if (waitTime >= 1 * HZ) { -+ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); -+ return -1; -+ } -+ dprintk(SAA716x_INFO, 1, "STi7109 ready after %llu ticks", waitTime); -+ -+ /* request the st7109 firmware, this will block until someone uploads it */ -+ ret = request_firmware(&fw, "dvb-ttpremium-st7109-01.fw", &saa716x->pdev->dev); -+ if (ret) { -+ if (ret == -ENOENT) { -+ printk(KERN_ERR "dvb-ttpremium: could not load ST7109 firmware," -+ " file not found: dvb-ttpremium-st7109-01.fw\n"); -+ printk(KERN_ERR "dvb-ttpremium: usually this should be in " -+ "/usr/lib/hotplug/firmware or /lib/firmware\n"); -+ } else -+ printk(KERN_ERR "dvb-ttpremium: cannot request firmware" -+ " (error %i)\n", ret); -+ return -EINVAL; -+ } -+ -+ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware"); -+ writtenBlock = 0; -+ blockSize = 0x3c00; -+ length = fw->size; -+ numBlocks = length / blockSize; -+ lastBlockSize = length % blockSize; -+ for (i = 0; i < length; i += blockSize) { -+ writtenBlock++; -+ /* write one block (last may differ from blockSize) */ -+ if (lastBlockSize && writtenBlock == (numBlocks + 1)) -+ saa716x_phi_write(saa716x, 0, &fw->data[i], lastBlockSize); -+ else -+ saa716x_phi_write(saa716x, 0, &fw->data[i], blockSize); -+ -+ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); -+ startTime = jiffies; -+ waitTime = 0; -+ do { -+ requestedBlock = SAA716x_EPRD(PHI_1, 0x3ffc); -+ if (requestedBlock == (writtenBlock + 1)) -+ break; -+ -+ currentTime = jiffies; -+ waitTime = currentTime - startTime; -+ } while (waitTime < (1 * HZ)); -+ -+ if (waitTime >= 1 * HZ) { -+ dprintk(SAA716x_ERROR, 1, "STi7109 seems to be DEAD!"); -+ release_firmware(fw); -+ return -1; -+ } -+ } -+ -+ /* disable frontend support through ST firmware */ -+ SAA716x_EPWR(PHI_1, 0x3ff4, 1); -+ -+ /* indicate end of transfer */ -+ writtenBlock++; -+ writtenBlock |= 0x80000000; -+ SAA716x_EPWR(PHI_1, 0x3ff8, writtenBlock); -+ -+ dprintk(SAA716x_INFO, 1, "SAA716x FF download ST7109 firmware done"); -+ -+ release_firmware(fw); -+ -+ return 0; -+} -+ -+static int saa716x_usercopy(struct dvb_device *dvbdev, -+ unsigned int cmd, unsigned long arg, -+ int (*func)(struct dvb_device *dvbdev, -+ unsigned int cmd, void *arg)) -+{ -+ char sbuf[128]; -+ void *mbuf = NULL; -+ void *parg = NULL; -+ int err = -EINVAL; -+ -+ /* Copy arguments into temp kernel buffer */ -+ switch (_IOC_DIR(cmd)) { -+ case _IOC_NONE: -+ /* -+ * For this command, the pointer is actually an integer -+ * argument. -+ */ -+ parg = (void *) arg; -+ break; -+ case _IOC_READ: /* some v4l ioctls are marked wrong ... */ -+ case _IOC_WRITE: -+ case (_IOC_WRITE | _IOC_READ): -+ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { -+ parg = sbuf; -+ } else { -+ /* too big to allocate from stack */ -+ mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); -+ if (NULL == mbuf) -+ return -ENOMEM; -+ parg = mbuf; -+ } -+ -+ err = -EFAULT; -+ if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) -+ goto out; -+ break; -+ } -+ -+ /* call driver */ -+ if ((err = func(dvbdev, cmd, parg)) == -ENOIOCTLCMD) -+ err = -EINVAL; -+ -+ if (err < 0) -+ goto out; -+ -+ /* Copy results into user buffer */ -+ switch (_IOC_DIR(cmd)) -+ { -+ case _IOC_READ: -+ case (_IOC_WRITE | _IOC_READ): -+ if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ break; -+ } -+ -+out: -+ kfree(mbuf); -+ return err; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_osd_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_osd_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ int err = -EINVAL; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ if (cmd == OSD_RAW_CMD) { -+ osd_raw_cmd_t raw_cmd; -+ u8 hdr[4]; -+ -+ err = -EFAULT; -+ if (copy_from_user(&raw_cmd, (void __user *)arg, -+ _IOC_SIZE(cmd))) -+ goto out; -+ -+ if (copy_from_user(hdr, (void __user *)raw_cmd.cmd_data, 4)) -+ goto out; -+ -+ if (hdr[3] == 4) -+ err = sti7109_raw_osd_cmd(sti7109, &raw_cmd); -+ else -+ err = sti7109_raw_cmd(sti7109, &raw_cmd); -+ -+ if (err) -+ goto out; -+ -+ if (copy_to_user((void __user *)arg, &raw_cmd, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ } -+ else if (cmd == OSD_RAW_DATA) { -+ osd_raw_data_t raw_data; -+ -+ err = -EFAULT; -+ if (copy_from_user(&raw_data, (void __user *)arg, -+ _IOC_SIZE(cmd))) -+ goto out; -+ -+ err = sti7109_raw_data(sti7109, &raw_data); -+ if (err) -+ goto out; -+ -+ if (copy_to_user((void __user *)arg, &raw_data, _IOC_SIZE(cmd))) -+ err = -EFAULT; -+ } -+ -+out: -+ return err; -+} -+ -+static struct file_operations dvb_osd_fops = { -+ .owner = THIS_MODULE, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_osd_ioctl, -+#else -+ .unlocked_ioctl = dvb_osd_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+}; -+ -+static struct dvb_device dvbdev_osd = { -+ .priv = NULL, -+ .users = 2, -+ .writers = 2, -+ .fops = &dvb_osd_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_osd_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_unregister_device(sti7109->osd_dev); -+ return 0; -+} -+ -+static int saa716x_ff_osd_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->osd_dev, -+ &dvbdev_osd, -+ sti7109, -+ DVB_DEVICE_OSD); -+ -+ return 0; -+} -+ -+static int do_dvb_audio_ioctl(struct dvb_device *dvbdev, -+ unsigned int cmd, void *parg) -+{ -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ //struct saa716x_dev *saa716x = sti7109->dev; -+ int ret = 0; -+ -+ switch (cmd) { -+ case AUDIO_GET_PTS: -+ { -+ *(u64 *)parg = sti7109->audio_pts; -+ break; -+ } -+ default: -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return ret; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_audio_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_audio_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_audio_ioctl); -+} -+ -+static struct file_operations dvb_audio_fops = { -+ .owner = THIS_MODULE, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_audio_ioctl, -+#else -+ .unlocked_ioctl = dvb_audio_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+}; -+ -+static struct dvb_device dvbdev_audio = { -+ .priv = NULL, -+ .users = 1, -+ .writers = 1, -+ .fops = &dvb_audio_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_audio_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_unregister_device(sti7109->audio_dev); -+ return 0; -+} -+ -+static int saa716x_ff_audio_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->audio_dev, -+ &dvbdev_audio, -+ sti7109, -+ DVB_DEVICE_AUDIO); -+ -+ return 0; -+} -+ -+static void fifo_worker(unsigned long data) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) data; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ u32 fifoCtrl; -+ u32 fifoStat; -+ u16 fifoSize; -+ u16 fifoUsage; -+ u16 fifoFree; -+ int len; -+ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoStat = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_STAT); -+ fifoSize = (u16) (fifoStat >> 16); -+ fifoUsage = (u16) fifoStat; -+ fifoFree = fifoSize - fifoUsage; -+ spin_lock(&sti7109->tsout.lock); -+ len = dvb_ringbuffer_avail(&sti7109->tsout); -+ if (len > fifoFree) -+ len = fifoFree; -+ if (len >= TS_SIZE) -+ { -+ while (len >= TS_SIZE) -+ { -+ dvb_ringbuffer_read(&sti7109->tsout, sti7109->tsbuf, (size_t) TS_SIZE); -+ saa716x_phi_write_fifo(saa716x, sti7109->tsbuf, TS_SIZE); -+ len -= TS_SIZE; -+ } -+ wake_up(&sti7109->tsout.queue); -+ fifoCtrl |= 0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ } -+ spin_unlock(&sti7109->tsout.lock); -+} -+ -+#define FREE_COND_TS (dvb_ringbuffer_free(&sti7109->tsout) >= TS_SIZE) -+ -+static ssize_t dvb_video_write(struct file *file, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ struct saa716x_dev *saa716x = sti7109->dev; -+ unsigned long todo = count; -+ -+ if ((file->f_flags & O_ACCMODE) == O_RDONLY) -+ return -EPERM; -+/* -+ if (av7110->videostate.stream_source != VIDEO_SOURCE_MEMORY) -+ return -EPERM; -+*/ -+ if ((file->f_flags & O_NONBLOCK) && !FREE_COND_TS) -+ return -EWOULDBLOCK; -+ -+ while (todo >= TS_SIZE) { -+ if (!FREE_COND_TS) { -+ if (file->f_flags & O_NONBLOCK) -+ break; -+ if (wait_event_interruptible(sti7109->tsout.queue, FREE_COND_TS)) -+ break; -+ } -+ dvb_ringbuffer_write(&sti7109->tsout, buf, TS_SIZE); -+ todo -= TS_SIZE; -+ buf += TS_SIZE; -+ } -+ -+ if (count > todo) { -+ u32 fifoCtrl; -+ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoCtrl |= 0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ } -+ -+ return count - todo; -+} -+ -+static unsigned int dvb_video_poll(struct file *file, poll_table *wait) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ unsigned int mask = 0; -+ -+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) -+ poll_wait(file, &sti7109->tsout.queue, wait); -+ -+ if ((file->f_flags & O_ACCMODE) != O_RDONLY) { -+ if (1/*sti7109->playing*/) { -+ if (FREE_COND_TS) -+ mask |= (POLLOUT | POLLWRNORM); -+ } else /* if not playing: may play if asked for */ -+ mask |= (POLLOUT | POLLWRNORM); -+ } -+ -+ return mask; -+} -+ -+static int do_dvb_video_ioctl(struct dvb_device *dvbdev, -+ unsigned int cmd, void *parg) -+{ -+ struct sti7109_dev *sti7109 = dvbdev->priv; -+ struct saa716x_dev *saa716x = sti7109->dev; -+ int ret = 0; -+ -+ switch (cmd) { -+ case VIDEO_SELECT_SOURCE: -+ { -+ video_stream_source_t stream_source; -+ -+ stream_source = (video_stream_source_t) parg; -+ if (stream_source == VIDEO_SOURCE_DEMUX) { -+ /* stop and reset FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); -+ } -+ else { -+ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); -+ /* reset FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 1); -+ /* start FIFO 1 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, 2); -+ } -+ break; -+ } -+ case VIDEO_CLEAR_BUFFER: -+ { -+ dvb_ringbuffer_flush_spinlock_wakeup(&sti7109->tsout); -+ break; -+ } -+ case VIDEO_GET_PTS: -+ { -+ *(u64 *)parg = sti7109->video_pts; -+ break; -+ } -+ case VIDEO_GET_SIZE: -+ { -+ ret = sti7109_cmd_get_video_format(sti7109, (video_size_t *) parg); -+ break; -+ } -+ default: -+ ret = -ENOIOCTLCMD; -+ break; -+ } -+ return ret; -+} -+ -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+static int dvb_video_ioctl(struct inode *inode, struct file *file, -+#else -+static long dvb_video_ioctl(struct file *file, -+#endif -+ unsigned int cmd, unsigned long arg) -+{ -+ struct dvb_device *dvbdev = file->private_data; -+ -+ if (!dvbdev) -+ return -ENODEV; -+ -+ return saa716x_usercopy (dvbdev, cmd, arg, do_dvb_video_ioctl); -+} -+ -+static struct file_operations dvb_video_fops = { -+ .owner = THIS_MODULE, -+ .write = dvb_video_write, -+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) && !defined(EXPERIMENTAL_TREE) -+ .ioctl = dvb_video_ioctl, -+#else -+ .unlocked_ioctl = dvb_video_ioctl, -+#endif -+ .open = dvb_generic_open, -+ .release = dvb_generic_release, -+ .poll = dvb_video_poll, -+}; -+ -+static struct dvb_device dvbdev_video = { -+ .priv = NULL, -+ .users = 1, -+ .writers = 1, -+ .fops = &dvb_video_fops, -+ .kernel_ioctl = NULL, -+}; -+ -+static int saa716x_ff_video_exit(struct saa716x_dev *saa716x) -+{ -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ tasklet_kill(&sti7109->fifo_tasklet); -+ dvb_unregister_device(sti7109->video_dev); -+ return 0; -+} -+ -+static int saa716x_ff_video_init(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_adapter *saa716x_adap = saa716x->saa716x_adap; -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ dvb_ringbuffer_init(&sti7109->tsout, sti7109->iobuf, TSOUT_LEN); -+ sti7109->tsbuf = (u8 *) (sti7109->iobuf + TSOUT_LEN); -+ -+ dvb_register_device(&saa716x_adap->dvb_adapter, -+ &sti7109->video_dev, -+ &dvbdev_video, -+ sti7109, -+ DVB_DEVICE_VIDEO); -+ -+ tasklet_init(&sti7109->fifo_tasklet, fifo_worker, -+ (unsigned long)saa716x); -+ -+ return 0; -+} -+ -+static int saa716x_ff_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ struct sti7109_dev *sti7109; -+ int err = 0; -+ u32 value; -+ unsigned long timeout; -+ u32 fw_version; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_budget_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ err = saa716x_phi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PHI Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ /* prepare the sti7109 device struct */ -+ sti7109 = kzalloc(sizeof(struct sti7109_dev), GFP_KERNEL); -+ if (!sti7109) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x: out of memory"); -+ goto fail3; -+ } -+ -+ sti7109->dev = saa716x; -+ -+ sti7109->iobuf = vmalloc(TSOUT_LEN + TSBUF_LEN + MAX_DATA_LEN); -+ if (!sti7109->iobuf) -+ goto fail4; -+ -+ sti7109_cmd_init(sti7109); -+ -+ sti7109->int_count_enable = int_count_enable; -+ sti7109->total_int_count = 0; -+ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); -+ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); -+ sti7109->ext_int_total_count = 0; -+ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); -+ sti7109->last_int_ticks = jiffies; -+ -+ saa716x->priv = sti7109; -+ -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS0); -+ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS0, 1); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_CS1); -+ saa716x_gpio_set_mode(saa716x, TT_PREMIUM_GPIO_FPGA_CS1, 1); -+ saa716x_gpio_set_output(saa716x, TT_PREMIUM_GPIO_FPGA_PROGRAMN); -+ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_DONE); -+ saa716x_gpio_set_input(saa716x, TT_PREMIUM_GPIO_FPGA_INITN); -+ -+ /* hold ST in reset */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_RESET_BACKEND, 0); -+ -+ /* enable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 1); -+ msleep(100); -+ -+ err = saa716x_ff_fpga_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF FPGA Initialization failed"); -+ goto fail5; -+ } -+ -+ /* configure TS muxer */ -+ if (sti7109->fpga_version < 0x110) { -+ /* select FIFO 1 for TS mux 3 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 4); -+ } else { -+ /* select FIFO 1 for TS mux 3 */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_TSR_MUX3, 1); -+ } -+ -+ /* enable interrupts from ST7109 -> PC */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICTRL, 0x3); -+ -+ value = SAA716x_EPRD(MSI, MSI_CONFIG33); -+ value &= 0xFCFFFFFF; -+ value |= MSI_INT_POL_EDGE_FALL; -+ SAA716x_EPWR(MSI, MSI_CONFIG33, value); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_EXTINT_0); -+ -+ /* enable tuner reset */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 0); -+ msleep(50); -+ /* disable tuner reset */ -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_PIO_CTRL, 1); -+ -+ err = saa716x_ff_st7109_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF STi7109 initialization failed"); -+ goto fail5; -+ } -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ /* enable FGPI2 and FGPI3 for TS inputs */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x0689F04); -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x280); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail6; -+ } -+ -+ /* wait a maximum of 10 seconds for the STi7109 to boot */ -+ timeout = 10 * HZ; -+ timeout = wait_event_interruptible_timeout(sti7109->boot_finish_wq, -+ sti7109->boot_finished == 1, -+ timeout); -+ -+ if (timeout == -ERESTARTSYS || sti7109->boot_finished == 0) { -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ goto fail6; -+ } -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for boot finish"); -+ err = -1; -+ goto fail6; -+ } -+ dprintk(SAA716x_INFO, 1, "STi7109 finished booting"); -+ -+ err = saa716x_ff_video_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF VIDEO initialization failed"); -+ goto fail7; -+ } -+ -+ err = saa716x_ff_audio_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF AUDIO initialization failed"); -+ goto fail8; -+ } -+ -+ err = saa716x_ff_osd_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x FF OSD initialization failed"); -+ goto fail9; -+ } -+ -+ err = sti7109_cmd_get_fw_version(sti7109, &fw_version); -+ if (!err) { -+ printk(KERN_INFO "SAA716x FF firmware version %X.%X.%X\n", -+ (fw_version >> 16) & 0xFF, (fw_version >> 8) & 0xFF, -+ fw_version & 0xFF); -+ } -+ -+ err = saa716x_ir_init(saa716x); -+ if (err) -+ goto fail9; -+ -+ return 0; -+ -+fail9: -+ saa716x_ff_osd_exit(saa716x); -+fail8: -+ saa716x_ff_audio_exit(saa716x); -+fail7: -+ saa716x_ff_video_exit(saa716x); -+fail6: -+ saa716x_dvb_exit(saa716x); -+fail5: -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); -+ -+ /* disable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); -+ -+ vfree(sti7109->iobuf); -+fail4: -+ kfree(sti7109); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_ff_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ struct sti7109_dev *sti7109 = saa716x->priv; -+ -+ saa716x_ir_exit(saa716x); -+ -+ saa716x_ff_osd_exit(saa716x); -+ -+ saa716x_ff_audio_exit(saa716x); -+ -+ saa716x_ff_video_exit(saa716x); -+ -+ saa716x_dvb_exit(saa716x); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, MSI_INT_EXTINT_0); -+ -+ /* disable board power */ -+ saa716x_gpio_write(saa716x, TT_PREMIUM_GPIO_POWER_ENABLE, 0); -+ -+ vfree(sti7109->iobuf); -+ -+ saa716x->priv = NULL; -+ kfree(sti7109); -+ -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+static irqreturn_t saa716x_ff_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ struct sti7109_dev *sti7109; -+ u32 msiStatusL; -+ u32 msiStatusH; -+ u32 phiISR; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ sti7109 = saa716x->priv; -+ if (unlikely(sti7109 == NULL)) { -+ printk("%s: sti7109=NULL", __func__); -+ return IRQ_NONE; -+ } -+ if (sti7109->int_count_enable) -+ sti7109->total_int_count++; -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_L), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ msiStatusL = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, msiStatusL); -+ msiStatusH = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, msiStatusH); -+ -+ if (msiStatusL) { -+ if (msiStatusL & MSI_INT_TAGACK_FGPI_2) { -+ if (sti7109->int_count_enable) -+ sti7109->fgpi_int_count[0]++; -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (msiStatusL & MSI_INT_TAGACK_FGPI_3) { -+ if (sti7109->int_count_enable) -+ sti7109->fgpi_int_count[1]++; -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ if (msiStatusH) { -+ //dprintk(SAA716x_INFO, 1, "msiStatusH: %08X", msiStatusH); -+ } -+ -+ if (msiStatusH & MSI_INT_I2CINT_0) { -+ if (sti7109->int_count_enable) -+ sti7109->i2c_int_count[0]++; -+ saa716x->i2c[0].i2c_op = 0; -+ wake_up(&saa716x->i2c[0].i2c_wq); -+ } -+ if (msiStatusH & MSI_INT_I2CINT_1) { -+ if (sti7109->int_count_enable) -+ sti7109->i2c_int_count[1]++; -+ saa716x->i2c[1].i2c_op = 0; -+ wake_up(&saa716x->i2c[1].i2c_wq); -+ } -+ -+ if (msiStatusH & MSI_INT_EXTINT_0) { -+ -+ phiISR = SAA716x_EPRD(PHI_1, FPGA_ADDR_EMI_ISR); -+ //dprintk(SAA716x_INFO, 1, "interrupt status register: %08X", phiISR); -+ -+ if (sti7109->int_count_enable) { -+ int i; -+ sti7109->ext_int_total_count++; -+ for (i = 0; i < 16; i++) -+ if (phiISR & (1 << i)) -+ sti7109->ext_int_source_count[i]++; -+ } -+ -+ if (phiISR & ISR_CMD_MASK) { -+ -+ u32 value; -+ u32 length; -+ /*dprintk(SAA716x_INFO, 1, "CMD interrupt source");*/ -+ -+ value = SAA716x_EPRD(PHI_1, ADDR_CMD_DATA); -+ value = __cpu_to_be32(value); -+ length = (value >> 16) + 2; -+ -+ /*dprintk(SAA716x_INFO, 1, "CMD length: %d", length);*/ -+ -+ if (length > MAX_RESULT_LEN) { -+ dprintk(SAA716x_ERROR, 1, "CMD length %d > %d", length, MAX_RESULT_LEN); -+ length = MAX_RESULT_LEN; -+ } -+ -+ saa716x_phi_read(saa716x, ADDR_CMD_DATA, sti7109->result_data, length); -+ sti7109->result_len = length; -+ sti7109->result_avail = 1; -+ wake_up(&sti7109->result_avail_wq); -+ -+ phiISR &= ~ISR_CMD_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CMD_MASK); -+ } -+ -+ if (phiISR & ISR_READY_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "READY interrupt source");*/ -+ sti7109->cmd_ready = 1; -+ wake_up(&sti7109->cmd_ready_wq); -+ phiISR &= ~ISR_READY_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_READY_MASK); -+ } -+ -+ if (phiISR & ISR_OSD_CMD_MASK) { -+ -+ u32 value; -+ u32 length; -+ /*dprintk(SAA716x_INFO, 1, "OSD CMD interrupt source");*/ -+ -+ value = SAA716x_EPRD(PHI_1, ADDR_OSD_CMD_DATA); -+ value = __cpu_to_be32(value); -+ length = (value >> 16) + 2; -+ -+ /*dprintk(SAA716x_INFO, 1, "OSD CMD length: %d", length);*/ -+ -+ if (length > MAX_RESULT_LEN) { -+ dprintk(SAA716x_ERROR, 1, "OSD CMD length %d > %d", length, MAX_RESULT_LEN); -+ length = MAX_RESULT_LEN; -+ } -+ -+ saa716x_phi_read(saa716x, ADDR_OSD_CMD_DATA, sti7109->osd_result_data, length); -+ sti7109->osd_result_len = length; -+ sti7109->osd_result_avail = 1; -+ wake_up(&sti7109->osd_result_avail_wq); -+ -+ phiISR &= ~ISR_OSD_CMD_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_CMD_MASK); -+ } -+ -+ if (phiISR & ISR_OSD_READY_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "OSD_READY interrupt source");*/ -+ sti7109->osd_cmd_ready = 1; -+ wake_up(&sti7109->osd_cmd_ready_wq); -+ phiISR &= ~ISR_OSD_READY_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_OSD_READY_MASK); -+ } -+ -+ if (phiISR & ISR_BLOCK_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "BLOCK interrupt source");*/ -+ sti7109->block_done = 1; -+ wake_up(&sti7109->block_done_wq); -+ phiISR &= ~ISR_BLOCK_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BLOCK_MASK); -+ } -+ -+ if (phiISR & ISR_DATA_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "DATA interrupt source");*/ -+ sti7109->data_ready = 1; -+ wake_up(&sti7109->data_ready_wq); -+ phiISR &= ~ISR_DATA_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DATA_MASK); -+ } -+ -+ if (phiISR & ISR_BOOT_FINISH_MASK) { -+ /*dprintk(SAA716x_INFO, 1, "BOOT FINISH interrupt source");*/ -+ sti7109->boot_finished = 1; -+ wake_up(&sti7109->boot_finish_wq); -+ phiISR &= ~ISR_BOOT_FINISH_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_BOOT_FINISH_MASK); -+ } -+ -+ if (phiISR & ISR_AUDIO_PTS_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_AUDIO_PTS, data, 8); -+ sti7109->audio_pts = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_AUDIO_PTS_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_AUDIO_PTS_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "AUDIO PTS: %llX", sti7109->audio_pts);*/ -+ } -+ -+ if (phiISR & ISR_VIDEO_PTS_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_VIDEO_PTS, data, 8); -+ sti7109->video_pts = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_VIDEO_PTS_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_VIDEO_PTS_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "VIDEO PTS: %llX", sti7109->video_pts);*/ -+ } -+ -+ if (phiISR & ISR_CURRENT_STC_MASK) { -+ u8 data[8]; -+ -+ saa716x_phi_read(saa716x, ADDR_CURRENT_STC, data, 8); -+ sti7109->current_stc = (((u64) data[3] & 0x01) << 32) -+ | ((u64) data[4] << 24) -+ | ((u64) data[5] << 16) -+ | ((u64) data[6] << 8) -+ | ((u64) data[7]); -+ -+ phiISR &= ~ISR_CURRENT_STC_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_CURRENT_STC_MASK); -+ -+ /*dprintk(SAA716x_INFO, 1, "CURRENT STC: %llu", sti7109->current_stc);*/ -+ } -+ -+ if (phiISR & ISR_REMOTE_EVENT_MASK) { -+ u8 data[4]; -+ u32 remote_event; -+ -+ saa716x_phi_read(saa716x, ADDR_REMOTE_EVENT, data, 4); -+ remote_event = (data[3] << 24) -+ | (data[2] << 16) -+ | (data[1] << 8) -+ | (data[0]); -+ memset(data, 0, sizeof(data)); -+ saa716x_phi_write(saa716x, ADDR_REMOTE_EVENT, data, 4); -+ -+ phiISR &= ~ISR_REMOTE_EVENT_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_REMOTE_EVENT_MASK); -+ -+ if (remote_event == 0) { -+ dprintk(SAA716x_ERROR, 1, "REMOTE EVENT: %X ignored", remote_event); -+ } else { -+ dprintk(SAA716x_INFO, 1, "REMOTE EVENT: %X", remote_event); -+ saa716x_ir_handler(saa716x, remote_event); -+ } -+ } -+ -+ if (phiISR & ISR_DVO_FORMAT_MASK) { -+ u8 data[4]; -+ u32 format; -+ -+ saa716x_phi_read(saa716x, ADDR_DVO_FORMAT, data, 4); -+ format = (data[0] << 24) -+ | (data[1] << 16) -+ | (data[2] << 8) -+ | (data[3]); -+ -+ phiISR &= ~ISR_DVO_FORMAT_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_DVO_FORMAT_MASK); -+ -+ dprintk(SAA716x_INFO, 1, "DVO FORMAT CHANGE: %u", format); -+ } -+ -+ if (phiISR & ISR_LOG_MESSAGE_MASK) { -+ char message[SIZE_LOG_MESSAGE_DATA]; -+ -+ saa716x_phi_read(saa716x, ADDR_LOG_MESSAGE, message, -+ SIZE_LOG_MESSAGE_DATA); -+ -+ phiISR &= ~ISR_LOG_MESSAGE_MASK; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, ISR_LOG_MESSAGE_MASK); -+ -+ dprintk(SAA716x_INFO, 1, "LOG MESSAGE: %.*s", -+ SIZE_LOG_MESSAGE_DATA, message); -+ } -+ -+ if (phiISR & ISR_FIFO1_EMPTY_MASK) { -+ u32 fifoCtrl; -+ -+ /*dprintk(SAA716x_INFO, 1, "FIFO EMPTY interrupt source");*/ -+ fifoCtrl = SAA716x_EPRD(PHI_1, FPGA_ADDR_FIFO_CTRL); -+ fifoCtrl &= ~0x4; -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_FIFO_CTRL, fifoCtrl); -+ tasklet_schedule(&sti7109->fifo_tasklet); -+ phiISR &= ~ISR_FIFO1_EMPTY_MASK; -+ } -+ -+ if (phiISR) { -+ dprintk(SAA716x_INFO, 1, "unknown interrupt source"); -+ SAA716x_EPWR(PHI_1, FPGA_ADDR_EMI_ICLR, phiISR); -+ } -+ } -+ -+ if (sti7109->int_count_enable) { -+ if (jiffies - sti7109->last_int_ticks >= HZ) { -+ dprintk(SAA716x_INFO, 1, "int count: t: %d, f:%d %d, i:%d %d," -+ "e: %d (%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)", -+ sti7109->total_int_count, -+ sti7109->fgpi_int_count[0], -+ sti7109->fgpi_int_count[1], -+ sti7109->i2c_int_count[0], -+ sti7109->i2c_int_count[1], -+ sti7109->ext_int_total_count, -+ sti7109->ext_int_source_count[0], -+ sti7109->ext_int_source_count[1], -+ sti7109->ext_int_source_count[2], -+ sti7109->ext_int_source_count[3], -+ sti7109->ext_int_source_count[4], -+ sti7109->ext_int_source_count[5], -+ sti7109->ext_int_source_count[6], -+ sti7109->ext_int_source_count[7], -+ sti7109->ext_int_source_count[8], -+ sti7109->ext_int_source_count[9], -+ sti7109->ext_int_source_count[10], -+ sti7109->ext_int_source_count[11], -+ sti7109->ext_int_source_count[12], -+ sti7109->ext_int_source_count[13], -+ sti7109->ext_int_source_count[14], -+ sti7109->ext_int_source_count[15]); -+ sti7109->total_int_count = 0; -+ memset(sti7109->fgpi_int_count, 0, sizeof(sti7109->fgpi_int_count)); -+ memset(sti7109->i2c_int_count, 0, sizeof(sti7109->i2c_int_count)); -+ sti7109->ext_int_total_count = 0; -+ memset(sti7109->ext_int_source_count, 0, sizeof(sti7109->ext_int_source_count)); -+ sti7109->last_int_ticks = jiffies; -+ } -+ } -+ return IRQ_HANDLED; -+} -+ -+#define SAA716x_MODEL_S2_6400_DUAL "Technotrend S2 6400 Dual S2 Premium" -+#define SAA716x_DEV_S2_6400_DUAL "2x DVB-S/S2 + Hardware decode" -+ -+static struct stv090x_config tt6400_stv090x_config = { -+ .device = STV0900, -+ .demod_mode = STV090x_DUAL, -+ .clk_mode = STV090x_CLK_EXT, -+ -+ .xtal = 13500000, -+ .address = 0x68, -+ -+ .ts1_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ .ts2_mode = STV090x_TSMODE_SERIAL_CONTINUOUS, -+ .ts1_clk = 135000000, -+ .ts2_clk = 135000000, -+ -+ .repeater_level = STV090x_RPTLEVEL_16, -+ -+ .tuner_init = NULL, -+ .tuner_set_mode = NULL, -+ .tuner_set_frequency = NULL, -+ .tuner_get_frequency = NULL, -+ .tuner_set_bandwidth = NULL, -+ .tuner_get_bandwidth = NULL, -+ .tuner_set_bbgain = NULL, -+ .tuner_get_bbgain = NULL, -+ .tuner_set_refclk = NULL, -+ .tuner_get_status = NULL, -+}; -+ -+static struct stv6110x_config tt6400_stv6110x_config = { -+ .addr = 0x60, -+ .refclk = 27000000, -+ .clk_div = 2, -+}; -+ -+static struct isl6423_config tt6400_isl6423_config[2] = { -+ { -+ .current_max = SEC_CURRENT_515m, -+ .curlim = SEC_CURRENT_LIM_ON, -+ .mod_extern = 1, -+ .addr = 0x09, -+ }, -+ { -+ .current_max = SEC_CURRENT_515m, -+ .curlim = SEC_CURRENT_LIM_ON, -+ .mod_extern = 1, -+ .addr = 0x08, -+ } -+}; -+ -+ -+static int saa716x_s26400_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *i2c_adapter = &i2c[SAA716x_I2C_BUS_A].i2c_adapter; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ if (count == 0 || count == 1) { -+ adapter->fe = dvb_attach(stv090x_attach, -+ &tt6400_stv090x_config, -+ i2c_adapter, -+ STV090x_DEMODULATOR_0 + count); -+ -+ if (adapter->fe) { -+ struct stv6110x_devctl *ctl; -+ ctl = dvb_attach(stv6110x_attach, -+ adapter->fe, -+ &tt6400_stv6110x_config, -+ i2c_adapter); -+ -+ tt6400_stv090x_config.tuner_init = ctl->tuner_init; -+ tt6400_stv090x_config.tuner_sleep = ctl->tuner_sleep; -+ tt6400_stv090x_config.tuner_set_mode = ctl->tuner_set_mode; -+ tt6400_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency; -+ tt6400_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency; -+ tt6400_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth; -+ tt6400_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth; -+ tt6400_stv090x_config.tuner_set_bbgain = ctl->tuner_set_bbgain; -+ tt6400_stv090x_config.tuner_get_bbgain = ctl->tuner_get_bbgain; -+ tt6400_stv090x_config.tuner_set_refclk = ctl->tuner_set_refclk; -+ tt6400_stv090x_config.tuner_get_status = ctl->tuner_get_status; -+ -+ if (count == 1) { -+ /* call the init function once to initialize -+ tuner's clock output divider and demod's -+ master clock */ -+ /* The second tuner drives the STV0900 so -+ call it only for adapter 1 */ -+ if (adapter->fe->ops.init) -+ adapter->fe->ops.init(adapter->fe); -+ } -+ -+ dvb_attach(isl6423_attach, -+ adapter->fe, -+ i2c_adapter, -+ &tt6400_isl6423_config[count]); -+ -+ } -+ } -+ return 0; -+} -+ -+static struct saa716x_config saa716x_s26400_config = { -+ .model_name = SAA716x_MODEL_S2_6400_DUAL, -+ .dev_type = SAA716x_DEV_S2_6400_DUAL, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_s26400_frontend_attach, -+ .irq_handler = saa716x_ff_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .i2c_mode = SAA716x_I2C_MODE_IRQ_BUFFERED, -+ -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 2, -+ .worker = demux_worker -+ },{ -+ /* Adapter 1 */ -+ .ts_port = 3, -+ .worker = demux_worker -+ } -+ } -+}; -+ -+ -+static struct pci_device_id saa716x_ff_pci_table[] = { -+ -+ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_DEVEL, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual development version */ -+ MAKE_ENTRY(TECHNOTREND, S2_6400_DUAL_S2_PREMIUM_PROD, SAA7160, &saa716x_s26400_config), /* S2 6400 Dual production version */ -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_ff_pci_table); -+ -+static struct pci_driver saa716x_ff_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_ff_pci_table, -+ .probe = saa716x_ff_pci_probe, -+ .remove = saa716x_ff_pci_remove, -+}; -+ -+static int saa716x_ff_init(void) -+{ -+ return pci_register_driver(&saa716x_ff_pci_driver); -+} -+ -+static void saa716x_ff_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_ff_pci_driver); -+} -+ -+module_init(saa716x_ff_init); -+module_exit(saa716x_ff_exit); -+ -+MODULE_DESCRIPTION("SAA716x FF driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi.c 2013-01-16 10:41:10.917798240 +0100 -@@ -0,0 +1,389 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_fgpi_reg.h" -+#include "saa716x_dma_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_dma.h" -+#include "saa716x_fgpi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static const u32 mmu_pta_base[] = { -+ MMU_PTA_BASE0, -+ MMU_PTA_BASE1, -+ MMU_PTA_BASE2, -+ MMU_PTA_BASE3, -+ MMU_PTA_BASE4, -+ MMU_PTA_BASE5, -+ MMU_PTA_BASE6, -+ MMU_PTA_BASE7, -+ MMU_PTA_BASE8, -+ MMU_PTA_BASE9, -+ MMU_PTA_BASE10, -+ MMU_PTA_BASE11, -+ MMU_PTA_BASE12, -+ MMU_PTA_BASE13, -+ MMU_PTA_BASE14, -+ MMU_PTA_BASE15, -+}; -+ -+static const u32 mmu_dma_cfg[] = { -+ MMU_DMA_CONFIG0, -+ MMU_DMA_CONFIG1, -+ MMU_DMA_CONFIG2, -+ MMU_DMA_CONFIG3, -+ MMU_DMA_CONFIG4, -+ MMU_DMA_CONFIG5, -+ MMU_DMA_CONFIG6, -+ MMU_DMA_CONFIG7, -+ MMU_DMA_CONFIG8, -+ MMU_DMA_CONFIG9, -+ MMU_DMA_CONFIG10, -+ MMU_DMA_CONFIG11, -+ MMU_DMA_CONFIG12, -+ MMU_DMA_CONFIG13, -+ MMU_DMA_CONFIG14, -+ MMU_DMA_CONFIG15, -+}; -+ -+static const u32 fgpi_ch[] = { -+ FGPI0, -+ FGPI1, -+ FGPI2, -+ FGPI3 -+}; -+ -+static const u32 bamdma_bufmode[] = { -+ BAM_FGPI0_DMA_BUF_MODE, -+ BAM_FGPI1_DMA_BUF_MODE, -+ BAM_FGPI2_DMA_BUF_MODE, -+ BAM_FGPI3_DMA_BUF_MODE -+}; -+ -+static const u32 msi_int_tagack[] = { -+ MSI_INT_TAGACK_FGPI_0, -+ MSI_INT_TAGACK_FGPI_1, -+ MSI_INT_TAGACK_FGPI_2, -+ MSI_INT_TAGACK_FGPI_3 -+}; -+ -+static const u32 msi_int_ovrflw[] = { -+ MSI_INT_OVRFLW_FGPI_0, -+ MSI_INT_OVRFLW_FGPI_1, -+ MSI_INT_OVRFLW_FGPI_2, -+ MSI_INT_OVRFLW_FGPI_3 -+}; -+ -+static const u32 msi_int_avint[] = { -+ MSI_INT_AVINT_FGPI_0, -+ MSI_INT_AVINT_FGPI_1, -+ MSI_INT_AVINT_FGPI_2, -+ MSI_INT_AVINT_FGPI_3 -+}; -+ -+void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 fgpi_port; -+ -+ fgpi_port = fgpi_ch[channel]; -+ -+ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0); /* disable FGPI IRQ */ -+ SAA716x_EPWR(fgpi_port, INT_CLR_STATUS, 0x7f); /* clear status */ -+} -+EXPORT_SYMBOL_GPL(saa716x_fgpiint_disable); -+ -+int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, u32 fgpi_index) -+{ -+ u32 fgpi_base; -+ u32 buf_mode_reg; -+ u32 buf_mode; -+ -+ switch (fgpi_index) { -+ case 0: /* FGPI_0 */ -+ fgpi_base = FGPI0; -+ buf_mode_reg = BAM_FGPI0_DMA_BUF_MODE; -+ break; -+ -+ case 1: /* FGPI_1 */ -+ fgpi_base = FGPI1; -+ buf_mode_reg = BAM_FGPI1_DMA_BUF_MODE; -+ break; -+ -+ case 2: /* FGPI_2 */ -+ fgpi_base = FGPI2; -+ buf_mode_reg = BAM_FGPI2_DMA_BUF_MODE; -+ break; -+ -+ case 3: /* FGPI_3 */ -+ fgpi_base = FGPI3; -+ buf_mode_reg = BAM_FGPI3_DMA_BUF_MODE; -+ break; -+ -+ default: -+ printk(KERN_ERR "%s: unexpected fgpi %u\n", -+ __func__, fgpi_index); -+ return -1; -+ } -+ -+ buf_mode = SAA716x_EPRD(BAM, buf_mode_reg); -+ if (saa716x->revision < 2) { -+ /* workaround for revision 1: restore buffer numbers on BAM */ -+ SAA716x_EPWR(fgpi_base, INT_CLR_STATUS, 0x7F); -+ SAA716x_EPWR(BAM, buf_mode_reg, buf_mode | 7); -+ } -+ return (buf_mode >> 3) & 0x7; -+} -+EXPORT_SYMBOL_GPL(saa716x_fgpi_get_write_index); -+ -+static u32 saa716x_init_ptables(struct saa716x_dmabuf *dmabuf, int channel) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 config, i; -+ -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ BUG_ON((dmabuf[i].mem_ptab_phys == 0)); -+ -+ config = mmu_dma_cfg[channel]; /* DMACONFIGx */ -+ -+ SAA716x_EPWR(MMU, config, (FGPI_BUFFERS - 1)); -+ SAA716x_EPWR(MMU, MMU_PTA0_LSB(channel), PTA_LSB(dmabuf[0].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA0_MSB(channel), PTA_MSB(dmabuf[0].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA1_LSB(channel), PTA_LSB(dmabuf[1].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA1_MSB(channel), PTA_MSB(dmabuf[1].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA2_LSB(channel), PTA_LSB(dmabuf[2].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA2_MSB(channel), PTA_MSB(dmabuf[2].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA3_LSB(channel), PTA_LSB(dmabuf[3].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA3_MSB(channel), PTA_MSB(dmabuf[3].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA4_LSB(channel), PTA_LSB(dmabuf[4].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA4_MSB(channel), PTA_MSB(dmabuf[4].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA5_LSB(channel), PTA_LSB(dmabuf[5].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA5_MSB(channel), PTA_MSB(dmabuf[5].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA6_LSB(channel), PTA_LSB(dmabuf[6].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA6_MSB(channel), PTA_MSB(dmabuf[6].mem_ptab_phys)); /* High */ -+ SAA716x_EPWR(MMU, MMU_PTA7_LSB(channel), PTA_LSB(dmabuf[7].mem_ptab_phys)); /* Low */ -+ SAA716x_EPWR(MMU, MMU_PTA7_MSB(channel), PTA_MSB(dmabuf[7].mem_ptab_phys)); /* High */ -+ -+ return 0; -+} -+ -+int saa716x_fgpi_setparams(struct saa716x_dmabuf *dmabuf, -+ struct fgpi_stream_params *stream_params, -+ int port) -+{ -+ struct saa716x_dev *saa716x = dmabuf->saa716x; -+ -+ u32 fgpi_port, buf_mode, val, mid; -+ u32 D1_XY_END, offst_1, offst_2; -+ int i = 0; -+ -+ fgpi_port = fgpi_ch[port]; -+ buf_mode = bamdma_bufmode[port]; -+ -+ /* Reset FGPI block */ -+ SAA716x_EPWR(fgpi_port, FGPI_SOFT_RESET, FGPI_SOFTWARE_RESET); -+ -+ /* Reset DMA channel */ -+ SAA716x_EPWR(BAM, buf_mode, 0x00000040); -+ saa716x_init_ptables(dmabuf, saa716x->fgpi[port].dma_channel); -+ -+ -+ /* monitor BAM reset */ -+ val = SAA716x_EPRD(BAM, buf_mode); -+ while (val && (i < 100)) { -+ msleep(30); -+ val = SAA716x_EPRD(BAM, buf_mode); -+ i++; -+ } -+ -+ if (val) { -+ dprintk(SAA716x_ERROR, 1, "Error: BAM FGPI Reset failed!"); -+ return -EIO; -+ } -+ -+ /* set buffer count */ -+ SAA716x_EPWR(BAM, buf_mode, FGPI_BUFFERS - 1); -+ -+ /* initialize all available address offsets */ -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_0(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_1(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_2(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_3(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_4(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_5(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_6(port), 0x0); -+ SAA716x_EPWR(BAM, BAM_FGPI_ADDR_OFFST_7(port), 0x0); -+ -+ /* get module ID */ -+ mid = SAA716x_EPRD(fgpi_port, FGPI_MODULE_ID); -+ if (mid != 0x14b0100) -+ dprintk(SAA716x_ERROR, 1, "FGPI Id<%04x> is not supported", mid); -+ -+ /* Initialize FGPI block */ -+ SAA716x_EPWR(fgpi_port, FGPI_REC_SIZE, stream_params->samples * (stream_params->bits / 8)); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, stream_params->pitch); -+ -+ offst_1 = 0; -+ offst_2 = 0; -+ switch (stream_params->stream_type) { -+ case FGPI_TRANSPORT_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ break; -+ -+ case FGPI_PROGRAM_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ break; -+ -+ case FGPI_VIDEO_STREAM: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000088); -+ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_START, 0x00000002); -+ -+ if ((stream_params->stream_flags & FGPI_INTERLACED) && -+ (stream_params->stream_flags & FGPI_ODD_FIELD) && -+ (stream_params->stream_flags & FGPI_EVEN_FIELD)) { -+ -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines / 2); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 4); /* interlaced stride of 2 lines */ -+ -+ D1_XY_END = (stream_params->samples << 16); -+ D1_XY_END |= (stream_params->lines / 2) + 2; -+ -+ if (stream_params->stream_flags & FGPI_PAL) -+ offst_1 = 768 * 2; -+ else -+ offst_2 = 768 * 2; -+ -+ } else { -+ SAA716x_EPWR(fgpi_port, FGPI_SIZE, stream_params->lines); -+ SAA716x_EPWR(fgpi_port, FGPI_STRIDE, 768 * 2); /* stride of 1 line */ -+ -+ D1_XY_END = stream_params->samples << 16; -+ D1_XY_END |= stream_params->lines + 2; -+ } -+ -+ SAA716x_EPWR(fgpi_port, FGPI_D1_XY_END, D1_XY_END); -+ break; -+ -+ default: -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, 0x00000080); -+ break; -+ } -+ -+ SAA716x_EPWR(fgpi_port, FGPI_BASE_1, ((saa716x->fgpi[port].dma_channel) << 21) + offst_1); -+ SAA716x_EPWR(fgpi_port, FGPI_BASE_2, ((saa716x->fgpi[port].dma_channel) << 21) + offst_2); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, -+ struct fgpi_stream_params *stream_params) -+{ -+ u32 fgpi_port; -+ u32 config; -+ u32 val; -+ u32 i; -+ -+ fgpi_port = fgpi_ch[port]; -+ -+ SAA716x_EPWR(fgpi_port, FGPI_INTERFACE, 0); -+ msleep(10); -+ -+ if (saa716x_fgpi_setparams(saa716x->fgpi[port].dma_buf, stream_params, port) != 0) { -+ return -EIO; -+ } -+ -+ config = mmu_dma_cfg[saa716x->fgpi[port].dma_channel]; /* DMACONFIGx */ -+ -+ val = SAA716x_EPRD(MMU, config); -+ SAA716x_EPWR(MMU, config, val & ~0x40); -+ SAA716x_EPWR(MMU, config, val | 0x40); -+ -+ SAA716x_EPWR(fgpi_port, INT_ENABLE, 0x7F); -+ -+ val = SAA716x_EPRD(MMU, config); -+ i = 0; -+ while (i < 500) { -+ if (val & 0x80) -+ break; -+ msleep(10); -+ val = SAA716x_EPRD(MMU, config); -+ i++; -+ } -+ -+ if (!(val & 0x80)) { -+ dprintk(SAA716x_ERROR, 1, "Error: PTE pre-fetch failed!"); -+ return -EIO; -+ } -+ -+ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); -+ val |= 0x3000; -+ -+ saa716x_set_clk_external(saa716x, saa716x->fgpi[port].dma_channel); -+ -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, msi_int_tagack[port]); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port) -+{ -+ u32 fgpi_port; -+ u32 val; -+ -+ fgpi_port = fgpi_ch[port]; -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, msi_int_tagack[port]); -+ -+ val = SAA716x_EPRD(fgpi_port, FGPI_CONTROL); -+ val &= ~0x3000; -+ SAA716x_EPWR(fgpi_port, FGPI_CONTROL, val); -+ -+ saa716x_set_clk_internal(saa716x, saa716x->fgpi[port].dma_channel); -+ -+ return 0; -+} -+ -+int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, -+ void (*worker)(unsigned long)) -+{ -+ int i; -+ int ret; -+ -+ saa716x->fgpi[port].dma_channel = port + 6; -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ { -+ /* TODO: what is a good size for TS DMA buffer? */ -+ ret = saa716x_dmabuf_alloc(saa716x, &saa716x->fgpi[port].dma_buf[i], 16 * SAA716x_PAGE_SIZE); -+ if (ret < 0) { -+ return ret; -+ } -+ } -+ saa716x->fgpi[port].saa716x = saa716x; -+ tasklet_init(&saa716x->fgpi[port].tasklet, worker, -+ (unsigned long)&saa716x->fgpi[port]); -+ saa716x->fgpi[port].read_index = 0; -+ -+ return 0; -+} -+ -+int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port) -+{ -+ int i; -+ -+ tasklet_kill(&saa716x->fgpi[port].tasklet); -+ for (i = 0; i < FGPI_BUFFERS; i++) -+ { -+ saa716x_dmabuf_free(saa716x, &saa716x->fgpi[port].dma_buf[i]); -+ } -+ -+ return 0; -+} -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi.h 2013-01-16 10:41:10.917798240 +0100 -@@ -0,0 +1,112 @@ -+#ifndef __SAA716x_FGPI_H -+#define __SAA716x_FGPI_H -+ -+#include -+ -+#define FGPI_BUFFERS 8 -+#define PTA_LSB(__mem) ((u32 ) (__mem)) -+#define PTA_MSB(__mem) ((u32 ) ((u64)(__mem) >> 32)) -+ -+#define BAM_DMA_BUF_MODE_BASE 0x0d8 -+#define BAM_DMA_BUF_MODE_OFFSET 0x24 -+ -+#define BAM_DMA_BUF_MODE(__ch) (BAM_DMA_BUF_MODE_BASE + (BAM_DMA_BUF_MODE_OFFSET * __ch)) -+ -+#define BAM_FGPI_ADDR_OFFST_BASE 0x0dc -+#define BAM_FGPI_ADDR_OFFST_OFFSET 0x24 -+ -+#define BAM_FGPI_ADDR_OFFSET(__ch) (BAM_FGPI_ADDR_OFFST_BASE + (BAM_FGPI_ADDR_OFFST_OFFSET * __ch)) -+ -+#define BAM_FGPI_ADDR_OFFST_0(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x00 -+#define BAM_FGPI_ADDR_OFFST_1(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x04 -+#define BAM_FGPI_ADDR_OFFST_2(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x08 -+#define BAM_FGPI_ADDR_OFFST_3(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x0c -+#define BAM_FGPI_ADDR_OFFST_4(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x10 -+#define BAM_FGPI_ADDR_OFFST_5(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x14 -+#define BAM_FGPI_ADDR_OFFST_6(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x18 -+#define BAM_FGPI_ADDR_OFFST_7(__ch) BAM_FGPI_ADDR_OFFSET(__ch) + 0x1c -+ -+struct saa716x_dmabuf; -+ -+/* -+ * Port supported streams -+ * -+ * FGPI_AUDIO_STREAM -+ * FGPI_VIDEO_STREAM -+ * FGPI_VBI_STREAM -+ * FGPI_TRANSPORT_STREAM -+ * FGPI_PROGRAM_STREAM -+ */ -+enum fgpi_stream_type { -+ FGPI_AUDIO_STREAM = 0x01, -+ FGPI_VIDEO_STREAM = 0x02, -+ FGPI_VBI_STREAM = 0x04, -+ FGPI_TRANSPORT_STREAM = 0x08, -+ FGPI_PROGRAM_STREAM = 0x10 -+}; -+ -+/* -+ * Stream port flags -+ * -+ * FGPI_ODD_FIELD -+ * FGPI_EVEN_FIELD -+ * FGPI_HD_0 -+ * FGPI_HD_1 -+ * FGPI_PAL -+ * FGPI_NTSC -+ */ -+enum fgpi_stream_flags { -+ FGPI_ODD_FIELD = 0x0001, -+ FGPI_EVEN_FIELD = 0x0002, -+ FGPI_INTERLACED = 0x0004, -+ FGPI_HD0 = 0x0010, -+ FGPI_HD1 = 0x0020, -+ FGPI_PAL = 0x0040, -+ FGPI_NTSC = 0x0080, -+ FGPI_NO_SCALER = 0x0100, -+}; -+ -+/* -+ * Stream port parameters -+ * bits: Bits per sample -+ * samples: samples perline -+ * lines: number of lines -+ * pitch: stream pitch in bytes -+ * offset: offset to first valid line -+ */ -+struct fgpi_stream_params { -+ u32 bits; -+ u32 samples; -+ u32 lines; -+ -+ s32 pitch; -+ -+ u32 offset; -+ u32 page_tables; -+ -+ enum fgpi_stream_flags stream_flags; -+ enum fgpi_stream_type stream_type; -+}; -+ -+struct saa716x_dmabuf; -+ -+struct saa716x_fgpi_stream_port { -+ u8 dma_channel; -+ struct saa716x_dmabuf dma_buf[FGPI_BUFFERS]; -+ struct saa716x_dev *saa716x; -+ struct tasklet_struct tasklet; -+ u8 read_index; -+}; -+ -+extern void saa716x_fgpiint_disable(struct saa716x_dmabuf *dmabuf, int channel); -+extern int saa716x_fgpi_get_write_index(struct saa716x_dev *saa716x, -+ u32 fgpi_index); -+extern int saa716x_fgpi_start(struct saa716x_dev *saa716x, int port, -+ struct fgpi_stream_params *stream_params); -+extern int saa716x_fgpi_stop(struct saa716x_dev *saa716x, int port); -+ -+extern int saa716x_fgpi_init(struct saa716x_dev *saa716x, int port, -+ void (*worker)(unsigned long)); -+extern int saa716x_fgpi_exit(struct saa716x_dev *saa716x, int port); -+ -+#endif /* __SAA716x_FGPI_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_fgpi_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_fgpi_reg.h 2013-01-16 10:41:10.918798233 +0100 -@@ -0,0 +1,74 @@ -+#ifndef __SAA716x_FGPI_REG_H -+#define __SAA716x_FGPI_REG_H -+ -+/* -------------- FGPI Registers -------------- */ -+ -+#define FGPI_CONTROL 0x000 -+#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) -+#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) -+#define FGPI_MODE (0x00000001 << 11) -+#define FGPI_SAMPLE_SIZE (0x00000003 << 8) -+#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) -+#define FGPI_REC_START_MSG_START (0x00000003 << 2) -+#define FGPI_TSTAMP_SELECT (0x00000001 << 1) -+#define FGPI_VAR_LENGTH (0x00000001 << 0) -+ -+#define FGPI_BASE_1 0x004 -+#define FGPI_BASE_2 0x008 -+#define FGPI_SIZE 0x00c -+#define FGPI_REC_SIZE 0x010 -+#define FGPI_STRIDE 0x014 -+#define FGPI_NUM_RECORD_1 0x018 -+#define FGPI_NUM_RECORD_2 0x01c -+#define FGPI_THRESHOLD_1 0x020 -+#define FGPI_THRESHOLD_2 0x024 -+#define FGPI_D1_XY_START 0x028 -+#define FGPI_D1_XY_END 0x02c -+ -+#define INT_STATUS 0xfe0 -+#define FGPI_BUF1_ACTIVE (0x00000001 << 7) -+#define FGPI_OVERFLOW (0x00000001 << 6) -+#define FGPI_MBE (0x00000001 << 5) -+#define FGPI_UNDERRUN (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED (0x00000001 << 2) -+#define FGPI_BUF2_FULL (0x00000001 << 1) -+#define FGPI_BUF1_FULL (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define FGPI_OVERFLOW_ENA (0x00000001 << 6) -+#define FGPI_MBE_ENA (0x00000001 << 5) -+#define FGPI_UNDERRUN_ENA (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) -+#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) -+#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define FGPI_OVERFLOW_ACK (0x00000001 << 6) -+#define FGPI_MBE_ACK (0x00000001 << 5) -+#define FGPI_UNDERRUN_ACK (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) -+#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) -+#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define FGPI_OVERFLOW_SET (0x00000001 << 6) -+#define FGPI_MBE_SET (0x00000001 << 5) -+#define FGPI_UNDERRUN_SET (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) -+#define FGPI_BUF2_DONE_SET (0x00000001 << 1) -+#define FGPI_BUF1_DONE_SET (0x00000001 << 0) -+ -+#define FGPI_SOFT_RESET 0xff0 -+#define FGPI_SOFTWARE_RESET (0x00000001 << 0) -+ -+#define FGPI_INTERFACE 0xff4 -+#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) -+ -+#define FGPI_MOD_ID_EXT 0xff8 -+#define FGPI_MODULE_ID 0xffc -+ -+#endif /* __SAA716x_FGPI_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio.c 2013-01-16 10:41:10.918798233 +0100 -@@ -0,0 +1,140 @@ -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+ -+#include "saa716x_gpio.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+void saa716x_gpio_init(struct saa716x_dev *saa716x) -+{ -+ spin_lock_init(&saa716x->gpio_lock); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_init); -+ -+int saa716x_get_gpio_mode(struct saa716x_dev *saa716x, u32 *config) -+{ -+ *config = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ -+ return 0; -+} -+ -+int saa716x_set_gpio_mode(struct saa716x_dev *saa716x, u32 mask, u32 config) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ reg = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ reg &= ~mask; -+ reg |= (config & mask); -+ SAA716x_EPWR(GPIO, GPIO_WR_MODE, reg); -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+ -+ return 0; -+} -+ -+u32 saa716x_gpio_rd(struct saa716x_dev *saa716x) -+{ -+ return SAA716x_EPRD(GPIO, GPIO_RD); -+} -+ -+void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data) -+{ -+ SAA716x_EPWR(GPIO, GPIO_WR, data); -+} -+ -+void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ -+ reg = SAA716x_EPRD(GPIO, GPIO_OEN); -+ reg &= mask; -+ reg |= bits; -+ SAA716x_EPWR(GPIO, GPIO_OEN, reg); -+ -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+ -+void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits) -+{ -+ unsigned long flags; -+ u32 reg; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ -+ reg = SAA716x_EPRD(GPIO, GPIO_WR); -+ reg &= ~bits; -+ /* TODO ! add maskable config bits in here */ -+ /* reg |= (config->mask & bits) */ -+ reg |= bits; -+ SAA716x_EPWR(GPIO, GPIO_WR, reg); -+ -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+ -+void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_OEN); -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_OEN, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_output); -+ -+void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_OEN); -+ value |= 1 << gpio; -+ SAA716x_EPWR(GPIO, GPIO_OEN, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_input); -+ -+void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_WR_MODE); -+ if (mode) -+ value |= 1 << gpio; -+ else -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_WR_MODE, value); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_set_mode); -+ -+void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set) -+{ -+ uint32_t value; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+ value = SAA716x_EPRD(GPIO, GPIO_WR); -+ if (set) -+ value |= 1 << gpio; -+ else -+ value &= ~(1 << gpio); -+ SAA716x_EPWR(GPIO, GPIO_WR, value); -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_write); -+ -+int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio) -+{ -+ uint32_t value; -+ -+ value = SAA716x_EPRD(GPIO, GPIO_RD); -+ if (value & (1 << gpio)) -+ return 1; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_gpio_read); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio.h 2013-01-16 10:41:10.918798233 +0100 -@@ -0,0 +1,26 @@ -+#ifndef __SAA716x_GPIO_H -+#define __SAA716x_GPIO_H -+ -+#define BOOT_MODE GPIO_31 | GPIO_30 -+#define AV_UNIT_B GPIO_25 -+#define AV_UNIT_A GPIO_24 -+#define AV_INTR_B GPIO_01 -+#define AV_INTR_A GPIO_00 -+ -+struct saa716x_dev; -+ -+extern void saa716x_gpio_init(struct saa716x_dev *saa716x); -+ -+extern u32 saa716x_gpio_rd(struct saa716x_dev *saa716x); -+extern void saa716x_gpio_wr(struct saa716x_dev *saa716x, u32 data); -+extern void saa716x_gpio_ctl(struct saa716x_dev *saa716x, u32 mask, u32 bits); -+ -+extern void saa716x_gpio_bits(struct saa716x_dev *saa716x, u32 bits); -+ -+extern void saa716x_gpio_set_output(struct saa716x_dev *saa716x, int gpio); -+extern void saa716x_gpio_set_input(struct saa716x_dev *saa716x, int gpio); -+extern void saa716x_gpio_set_mode(struct saa716x_dev *saa716x, int gpio, int mode); -+extern void saa716x_gpio_write(struct saa716x_dev *saa716x, int gpio, int set); -+extern int saa716x_gpio_read(struct saa716x_dev *saa716x, int gpio); -+ -+#endif /* __SAA716x_GPIO_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_gpio_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_gpio_reg.h 2013-01-16 10:41:10.919798225 +0100 -@@ -0,0 +1,47 @@ -+#ifndef __SAA716x_GPIO_REG_H -+#define __SAA716x_GPIO_REG_H -+ -+/* -------------- GPIO Registers -------------- */ -+ -+#define GPIO_RD 0x000 -+#define GPIO_WR 0x004 -+#define GPIO_WR_MODE 0x008 -+#define GPIO_OEN 0x00c -+ -+#define GPIO_SW_RST 0xff0 -+#define GPIO_SW_RESET (0x00000001 << 0) -+ -+#define GPIO_31 (1 << 31) -+#define GPIO_30 (1 << 30) -+#define GPIO_29 (1 << 29) -+#define GPIO_28 (1 << 28) -+#define GPIO_27 (1 << 27) -+#define GPIO_26 (1 << 26) -+#define GPIO_25 (1 << 25) -+#define GPIO_24 (1 << 24) -+#define GPIO_23 (1 << 23) -+#define GPIO_22 (1 << 22) -+#define GPIO_21 (1 << 21) -+#define GPIO_20 (1 << 20) -+#define GPIO_19 (1 << 19) -+#define GPIO_18 (1 << 18) -+#define GPIO_17 (1 << 17) -+#define GPIO_16 (1 << 16) -+#define GPIO_15 (1 << 15) -+#define GPIO_14 (1 << 14) -+#define GPIO_13 (1 << 13) -+#define GPIO_12 (1 << 12) -+#define GPIO_11 (1 << 11) -+#define GPIO_10 (1 << 10) -+#define GPIO_09 (1 << 9) -+#define GPIO_08 (1 << 8) -+#define GPIO_07 (1 << 7) -+#define GPIO_06 (1 << 6) -+#define GPIO_05 (1 << 5) -+#define GPIO_04 (1 << 4) -+#define GPIO_03 (1 << 3) -+#define GPIO_02 (1 << 2) -+#define GPIO_01 (1 << 1) -+#define GPIO_00 (1 << 0) -+ -+#endif /* __SAA716x_GPIO_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_greg.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_greg.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg.c 2013-01-16 10:41:10.919798225 +0100 -@@ -0,0 +1,42 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_greg_reg.h" -+#include "saa716x_greg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+static u32 g_save[12]; -+ -+void saa716x_greg_save(struct saa716x_dev *saa716x) -+{ -+ g_save[0] = SAA716x_EPRD(GREG, GREG_SUBSYS_CONFIG); -+ g_save[1] = SAA716x_EPRD(GREG, GREG_MSI_BAR_PMCSR); -+ g_save[2] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_1); -+ g_save[3] = SAA716x_EPRD(GREG, GREG_PMCSR_DATA_2); -+ g_save[4] = SAA716x_EPRD(GREG, GREG_VI_CTRL); -+ g_save[5] = SAA716x_EPRD(GREG, GREG_FGPI_CTRL); -+ g_save[6] = SAA716x_EPRD(GREG, GREG_RSTU_CTRL); -+ g_save[7] = SAA716x_EPRD(GREG, GREG_I2C_CTRL); -+ g_save[8] = SAA716x_EPRD(GREG, GREG_OVFLW_CTRL); -+ g_save[9] = SAA716x_EPRD(GREG, GREG_TAG_ACK_FLEN); -+ -+ g_save[10] = SAA716x_EPRD(GREG, GREG_VIDEO_IN_CTRL); -+} -+ -+void saa716x_greg_restore(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(GREG, GREG_SUBSYS_CONFIG, g_save[0]); -+ SAA716x_EPWR(GREG, GREG_MSI_BAR_PMCSR, g_save[1]); -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_1, g_save[2]); -+ SAA716x_EPWR(GREG, GREG_PMCSR_DATA_2, g_save[3]); -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, g_save[4]); -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, g_save[5]); -+ SAA716x_EPWR(GREG, GREG_RSTU_CTRL, g_save[6]); -+ SAA716x_EPWR(GREG, GREG_I2C_CTRL, g_save[7]); -+ SAA716x_EPWR(GREG, GREG_OVFLW_CTRL, g_save[8]); -+ SAA716x_EPWR(GREG, GREG_TAG_ACK_FLEN, g_save[9]); -+ -+ SAA716x_EPWR(GREG, GREG_VIDEO_IN_CTRL, g_save[10]); -+} -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_greg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_greg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg.h 2013-01-16 10:41:10.919798225 +0100 -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_GREG_H -+#define __SAA716x_GREG_H -+ -+struct saa716x_dev; -+ -+extern void saa716x_greg_save(struct saa716x_dev *saa716x); -+extern void saa716x_greg_restore(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_GREG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_greg_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_greg_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_greg_reg.h 2013-01-16 10:41:10.919798225 +0100 -@@ -0,0 +1,91 @@ -+#ifndef __SAA716x_GREG_REG_H -+#define __SAA716x_GREG_REG_H -+ -+/* -------------- GREG Registers -------------- */ -+ -+#define GREG_SUBSYS_CONFIG 0x000 -+#define GREG_SUBSYS_ID (0x0000ffff << 16) -+#define GREG_SUBSYS_VID (0x0000ffff << 0) -+ -+#define GREG_MSI_BAR_PMCSR 0x004 -+#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) -+#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) -+#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) -+#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) -+#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) -+#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) -+#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) -+#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) -+ -+#define GREG_BAR_WIDTH_17 (0x0000001e << 8) -+#define GREG_BAR_WIDTH_18 (0x0000001c << 8) -+#define GREG_BAR_WIDTH_19 (0x00000018 << 8) -+#define GREG_BAR_WIDTH_20 (0x00000010 << 8) -+ -+#define GREG_BAR_PREFETCH (0x00000001 << 3) -+#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! -+#define GREG_MSI_MM_CAP2 (0x00000001 << 0) -+#define GREG_MSI_MM_CAP4 (0x00000002 << 0) -+#define GREG_MSI_MM_CAP8 (0x00000003 << 0) -+#define GREG_MSI_MM_CAP16 (0x00000004 << 0) -+#define GREG_MSI_MM_CAP32 (0x00000005 << 0) -+ -+#define GREG_PMCSR_DATA_1 0x008 -+#define GREG_PMCSR_DATA_2 0x00c -+#define GREG_VI_CTRL 0x010 -+#define GREG_FGPI_CTRL 0x014 -+ -+#define GREG_RSTU_CTRL 0x018 -+#define GREG_BOOT_READY (0x00000001 << 13) -+#define GREG_RESET_REQ (0x00000001 << 12) -+#define GREG_IP_RST_RELEASE (0x00000001 << 11) -+#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) -+#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) -+#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) -+#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) -+#define GREG_CGU_RST_RELEASE (0x00000001 << 6) -+#define GREG_IP_RST_ASSERT (0x00000001 << 5) -+#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) -+#define GREG_RST_ASSERT (0x00000001 << 3) -+#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) -+#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) -+#define GREG_CGU_RST_ASSERT (0x00000001 << 0) -+ -+#define GREG_I2C_CTRL 0x01c -+#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) -+ -+#define GREG_OVFLW_CTRL 0x020 -+#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) -+ -+#define GREG_TAG_ACK_FLEN 0x024 -+#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) -+#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) -+#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) -+#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) -+ -+#define GREG_VIDEO_IN_CTRL 0x028 -+ -+#define GREG_SPARE_1 0x02c -+#define GREG_SPARE_2 0x030 -+#define GREG_SPARE_3 0x034 -+#define GREG_SPARE_4 0x038 -+#define GREG_SPARE_5 0x03c -+#define GREG_SPARE_6 0x040 -+#define GREG_SPARE_7 0x044 -+#define GREG_SPARE_8 0x048 -+#define GREG_SPARE_9 0x04c -+#define GREG_SPARE_10 0x050 -+#define GREG_SPARE_11 0x054 -+#define GREG_SPARE_12 0x058 -+#define GREG_SPARE_13 0x05c -+#define GREG_SPARE_14 0x060 -+#define GREG_SPARE_15 0x064 -+ -+#define GREG_FAIL_DISABLE 0x068 -+#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) -+ -+#define GREG_SW_RST 0xff0 -+#define GREG_SW_RESET (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_GREG_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_hybrid.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_hybrid.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_hybrid.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_hybrid.c 2013-01-16 10:41:10.920798217 +0100 -@@ -0,0 +1,726 @@ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_gpio_reg.h" -+#include "saa716x_greg_reg.h" -+#include "saa716x_msi_reg.h" -+ -+#include "saa716x_adap.h" -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_hybrid.h" -+#include "saa716x_gpio.h" -+#include "saa716x_rom.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#include "zl10353.h" -+#include "mb86a16.h" -+#include "tda1004x.h" -+#include "tda827x.h" -+ -+unsigned int verbose; -+module_param(verbose, int, 0644); -+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)"); -+ -+unsigned int int_type; -+module_param(int_type, int, 0644); -+MODULE_PARM_DESC(int_type, "force Interrupt Handler type: 0=INT-A, 1=MSI, 2=MSI-X. default INT-A mode"); -+ -+#define DRIVER_NAME "SAA716x Hybrid" -+ -+static int saa716x_hybrid_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -+{ -+ struct saa716x_dev *saa716x; -+ int err = 0; -+ -+ saa716x = kzalloc(sizeof (struct saa716x_dev), GFP_KERNEL); -+ if (saa716x == NULL) { -+ printk(KERN_ERR "saa716x_hybrid_pci_probe ERROR: out of memory\n"); -+ err = -ENOMEM; -+ goto fail0; -+ } -+ -+ saa716x->verbose = verbose; -+ saa716x->int_type = int_type; -+ saa716x->pdev = pdev; -+ saa716x->config = (struct saa716x_config *) pci_id->driver_data; -+ -+ err = saa716x_pci_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x PCI Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_cgu_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x CGU Init failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_core_boot(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Core Boot failed"); -+ goto fail2; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA716x Core Boot Success"); -+ -+ err = saa716x_msi_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x MSI Init failed"); -+ goto fail2; -+ } -+ -+ err = saa716x_jetpack_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x Jetpack core Initialization failed"); -+ goto fail1; -+ } -+ -+ err = saa716x_i2c_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x I2C Initialization failed"); -+ goto fail3; -+ } -+ -+ saa716x_gpio_init(saa716x); -+ -+ err = saa716x_dump_eeprom(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ err = saa716x_eeprom_data(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x EEPROM dump failed"); -+ } -+ -+ /* enable decoders on 7162 */ -+ if (pdev->device == SAA7162) { -+ saa716x_gpio_set_output(saa716x, 24); -+ saa716x_gpio_set_output(saa716x, 25); -+ -+ saa716x_gpio_write(saa716x, 24, 0); -+ saa716x_gpio_write(saa716x, 25, 0); -+ -+ msleep(10); -+ -+ saa716x_gpio_write(saa716x, 24, 1); -+ saa716x_gpio_write(saa716x, 25, 1); -+ } -+ -+ /* set default port mapping */ -+ SAA716x_EPWR(GREG, GREG_VI_CTRL, 0x2C688F44); -+ /* enable FGPI3 and FGPI0 for TS input from Port 3 and 6 */ -+ SAA716x_EPWR(GREG, GREG_FGPI_CTRL, 0x894); -+ -+ err = saa716x_dvb_init(saa716x); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x DVB initialization failed"); -+ goto fail4; -+ } -+ -+ return 0; -+ -+fail4: -+ saa716x_dvb_exit(saa716x); -+fail3: -+ saa716x_i2c_exit(saa716x); -+fail2: -+ saa716x_pci_exit(saa716x); -+fail1: -+ kfree(saa716x); -+fail0: -+ return err; -+} -+ -+static void saa716x_hybrid_pci_remove(struct pci_dev *pdev) -+{ -+ struct saa716x_dev *saa716x = pci_get_drvdata(pdev); -+ -+ saa716x_dvb_exit(saa716x); -+ saa716x_i2c_exit(saa716x); -+ saa716x_pci_exit(saa716x); -+ kfree(saa716x); -+} -+ -+static irqreturn_t saa716x_hybrid_pci_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ u32 stat_h, stat_l, mask_h, mask_l; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ -+ stat_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ stat_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ mask_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ mask_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ stat_l, stat_h, mask_l, mask_h); -+ -+ if (!((stat_l & mask_l) || (stat_h & mask_h))) -+ return IRQ_NONE; -+ -+ if (stat_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, stat_l); -+ -+ if (stat_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, stat_h); -+ -+ saa716x_msi_event(saa716x, stat_l, stat_h); -+#if 0 -+ dprintk(SAA716x_DEBUG, 1, "VI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(VI0, INT_STATUS), -+ SAA716x_EPRD(VI1, INT_STATUS), -+ SAA716x_EPRD(VI0, INT_ENABLE), -+ SAA716x_EPRD(VI1, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 0=<%02x> 1=<%02x>, CTL 1=<%02x> 2=<%02x>", -+ SAA716x_EPRD(FGPI0, INT_STATUS), -+ SAA716x_EPRD(FGPI1, INT_STATUS), -+ SAA716x_EPRD(FGPI0, INT_ENABLE), -+ SAA716x_EPRD(FGPI0, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "FGPI STAT 2=<%02x> 3=<%02x>, CTL 2=<%02x> 3=<%02x>", -+ SAA716x_EPRD(FGPI2, INT_STATUS), -+ SAA716x_EPRD(FGPI3, INT_STATUS), -+ SAA716x_EPRD(FGPI2, INT_ENABLE), -+ SAA716x_EPRD(FGPI3, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "AI STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(AI0, AI_STATUS), -+ SAA716x_EPRD(AI1, AI_STATUS), -+ SAA716x_EPRD(AI0, AI_CTL), -+ SAA716x_EPRD(AI1, AI_CTL)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_ENABLE), -+ SAA716x_EPRD(I2C_B, INT_ENABLE)); -+ -+ dprintk(SAA716x_DEBUG, 1, "DCS STAT=<%02x>, CTL=<%02x>", -+ SAA716x_EPRD(DCS, DCSC_INT_STATUS), -+ SAA716x_EPRD(DCS, DCSC_INT_ENABLE)); -+#endif -+ -+ if (stat_l) { -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) { -+ tasklet_schedule(&saa716x->fgpi[0].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) { -+ tasklet_schedule(&saa716x->fgpi[1].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) { -+ tasklet_schedule(&saa716x->fgpi[2].tasklet); -+ } -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) { -+ tasklet_schedule(&saa716x->fgpi[3].tasklet); -+ } -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static void demux_worker(unsigned long data) -+{ -+ struct saa716x_fgpi_stream_port *fgpi_entry = (struct saa716x_fgpi_stream_port *)data; -+ struct saa716x_dev *saa716x = fgpi_entry->saa716x; -+ struct dvb_demux *demux; -+ u32 fgpi_index; -+ u32 i; -+ u32 write_index; -+ -+ fgpi_index = fgpi_entry->dma_channel - 6; -+ demux = NULL; -+ for (i = 0; i < saa716x->config->adapters; i++) { -+ if (saa716x->config->adap_config[i].ts_port == fgpi_index) { -+ demux = &saa716x->saa716x_adap[i].demux; -+ break; -+ } -+ } -+ if (demux == NULL) { -+ printk(KERN_ERR "%s: unexpected channel %u\n", -+ __func__, fgpi_entry->dma_channel); -+ return; -+ } -+ -+ write_index = saa716x_fgpi_get_write_index(saa716x, fgpi_index); -+ if (write_index < 0) -+ return; -+ -+ dprintk(SAA716x_DEBUG, 1, "dma buffer = %d", write_index); -+ -+ if (write_index == fgpi_entry->read_index) { -+ printk(KERN_DEBUG "%s: called but nothing to do\n", __func__); -+ return; -+ } -+ -+ do { -+ u8 *data = (u8 *)fgpi_entry->dma_buf[fgpi_entry->read_index].mem_virt; -+ -+ pci_dma_sync_sg_for_cpu(saa716x->pdev, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].sg_list, -+ fgpi_entry->dma_buf[fgpi_entry->read_index].list_len, -+ PCI_DMA_FROMDEVICE); -+ -+ dvb_dmx_swfilter(demux, data, 348 * 188); -+ -+ fgpi_entry->read_index = (fgpi_entry->read_index + 1) & 7; -+ } while (write_index != fgpi_entry->read_index); -+} -+ -+/* -+ * Twinhan/Azurewave VP-6090 -+ * DVB-S Frontend: 2x MB86A16 -+ * DVB-T Frontend: 2x TDA10046 + TDA8275 -+ */ -+#define SAA716x_MODEL_TWINHAN_VP6090 "Twinhan/Azurewave VP-6090" -+#define SAA716x_DEV_TWINHAN_VP6090 "2xDVB-S + 2xDVB-T + 2xAnalog" -+ -+static int tda1004x_vp6090_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_vp6090_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_4M, -+ .agc_config = TDA10046_AGC_DEFAULT, -+ .if_freq = TDA10046_FREQ_3617, -+ .request_firmware = tda1004x_vp6090_request_firmware, -+}; -+ -+static int vp6090_dvbs_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct saa716x_dev *saa716x = fe->dvb->priv; -+ -+ switch (voltage) { -+ case SEC_VOLTAGE_13: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[13V]"); -+ break; -+ case SEC_VOLTAGE_18: -+ dprintk(SAA716x_ERROR, 1, "Polarization=[18V]"); -+ break; -+ case SEC_VOLTAGE_OFF: -+ dprintk(SAA716x_ERROR, 1, "Frontend (dummy) POWERDOWN"); -+ break; -+ default: -+ dprintk(SAA716x_ERROR, 1, "Invalid = (%d)", (u32 ) voltage); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+struct mb86a16_config vp6090_mb86a16_config = { -+ .demod_address = 0x08, -+ .set_voltage = vp6090_dvbs_set_voltage, -+}; -+ -+static int saa716x_vp6090_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c = &saa716x->i2c[count]; -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); -+ -+ saa716x_gpio_set_output(saa716x, 11); -+ saa716x_gpio_set_output(saa716x, 10); -+ saa716x_gpio_write(saa716x, 11, 1); -+ saa716x_gpio_write(saa716x, 10, 1); -+ msleep(100); -+#if 0 -+ dprintk(SAA716x_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)"); -+ adapter->fe = mb86a16_attach(&vp6090_mb86a16_config, &i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found MB86A16 DVB-S/DSS frontend @0x%02x", -+ vp6090_mb86a16_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+#endif -+ adapter->fe = tda10046_attach(&tda1004x_vp6090_config, &i2c->i2c_adapter); -+ if (adapter->fe == NULL) { -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+ } else { -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+ -+ return 0; -+} -+ -+static struct saa716x_config saa716x_vp6090_config = { -+ .model_name = SAA716x_MODEL_TWINHAN_VP6090, -+ .dev_type = SAA716x_DEV_TWINHAN_VP6090, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_vp6090_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+/* -+ * NXP Reference design (Atlantis) -+ * 2x DVB-T Frontend: 2x TDA10046 -+ * Analog Decoder: 2x Internal -+ */ -+#define SAA716x_MODEL_NXP_ATLANTIS "Atlantis reference board" -+#define SAA716x_DEV_NXP_ATLANTIS "2x DVB-T + 2x Analog" -+ -+static int tda1004x_atlantis_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_atlantis_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_16M, -+ .agc_config = TDA10046_AGC_TDA827X, -+ .if_freq = TDA10046_FREQ_045, -+ .request_firmware = tda1004x_atlantis_request_firmware, -+ .tuner_address = 0x60, -+}; -+ -+static struct tda827x_config tda827x_atlantis_config = { -+ .init = NULL, -+ .sleep = NULL, -+ .config = 0, -+ .switch_addr = 0, -+ .agcf = NULL, -+}; -+ -+static int saa716x_atlantis_frontend_attach(struct saa716x_adapter *adapter, -+ int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *i2c; -+ u8 i2c_buf[3] = { 0x05, 0x23, 0x01 }; /* activate the silent I2C bus */ -+ struct i2c_msg msg = { -+ .addr = 0x42 >> 1, -+ .flags = 0, -+ .buf = i2c_buf, -+ .len = sizeof(i2c_buf) -+ }; -+ -+ if (count < saa716x->config->adapters) { -+ u32 reset_gpio; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", -+ count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, -+ saa716x->pdev->subsystem_device); -+ -+ if (count == 0) { -+ reset_gpio = 14; -+ i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; -+ } else { -+ reset_gpio = 15; -+ i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ } -+ -+ /* activate the silent I2C bus */ -+ i2c_transfer(&i2c->i2c_adapter, &msg, 1); -+ -+ saa716x_gpio_set_output(saa716x, reset_gpio); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, reset_gpio, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, reset_gpio, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, reset_gpio, 1); -+ msleep(10); -+ -+ adapter->fe = tda10046_attach(&tda1004x_atlantis_config, -+ &i2c->i2c_adapter); -+ if (adapter->fe == NULL) -+ goto exit; -+ -+ dprintk(SAA716x_ERROR, 1, -+ "found TDA10046 DVB-T frontend @0x%02x", -+ tda1004x_atlantis_config.demod_address); -+ -+ if (dvb_attach(tda827x_attach, adapter->fe, -+ tda1004x_atlantis_config.tuner_address, -+ &i2c->i2c_adapter, &tda827x_atlantis_config)) { -+ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", -+ tda1004x_atlantis_config.tuner_address); -+ } else { -+ goto exit; -+ } -+ -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ return 0; -+ } -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_atlantis_config = { -+ .model_name = SAA716x_MODEL_NXP_ATLANTIS, -+ .dev_type = SAA716x_DEV_NXP_ATLANTIS, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 2, -+ .frontend_attach = saa716x_atlantis_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 3, /* using FGPI 3 */ -+ .worker = demux_worker -+ }, -+ { -+ /* Adapter 1 */ -+ .ts_port = 0, /* using FGPI 0 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+/* -+ * NXP Reference design (NEMO) -+ * DVB-T Frontend: 1x TDA10046 + TDA8275 -+ * Analog Decoder: External SAA7136 -+ */ -+#define SAA716x_MODEL_NXP_NEMO "NEMO reference board" -+#define SAA716x_DEV_NXP_NEMO "DVB-T + Analog" -+ -+static int tda1004x_nemo_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, -+ char *name) -+{ -+ struct saa716x_adapter *adapter = fe->dvb->priv; -+ -+ return request_firmware(fw, name, &adapter->saa716x->pdev->dev); -+} -+ -+static struct tda1004x_config tda1004x_nemo_config = { -+ .demod_address = 0x8, -+ .invert = 0, -+ .invert_oclk = 0, -+ .xtal_freq = TDA10046_XTAL_16M, -+ .agc_config = TDA10046_AGC_TDA827X, -+ .if_freq = TDA10046_FREQ_045, -+ .request_firmware = tda1004x_nemo_request_firmware, -+ .tuner_address = 0x60, -+}; -+ -+static struct tda827x_config tda827x_nemo_config = { -+ .init = NULL, -+ .sleep = NULL, -+ .config = 0, -+ .switch_addr = 0, -+ .agcf = NULL, -+}; -+ -+static int saa716x_nemo_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ struct saa716x_i2c *demod_i2c = &saa716x->i2c[SAA716x_I2C_BUS_B]; -+ struct saa716x_i2c *tuner_i2c = &saa716x->i2c[SAA716x_I2C_BUS_A]; -+ -+ -+ if (count == 0) { -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) Power ON", count); -+ -+ /* GPIO 26 controls a +15dB gain */ -+ saa716x_gpio_set_output(saa716x, 26); -+ saa716x_gpio_write(saa716x, 26, 0); -+ -+ saa716x_gpio_set_output(saa716x, 14); -+ -+ /* Reset the demodulator */ -+ saa716x_gpio_write(saa716x, 14, 1); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 14, 0); -+ msleep(10); -+ saa716x_gpio_write(saa716x, 14, 1); -+ msleep(10); -+ -+ adapter->fe = tda10046_attach(&tda1004x_nemo_config, -+ &demod_i2c->i2c_adapter); -+ if (adapter->fe) { -+ dprintk(SAA716x_ERROR, 1, "found TDA10046 DVB-T frontend @0x%02x", -+ tda1004x_nemo_config.demod_address); -+ -+ } else { -+ goto exit; -+ } -+ if (dvb_attach(tda827x_attach, adapter->fe, -+ tda1004x_nemo_config.tuner_address, -+ &tuner_i2c->i2c_adapter, &tda827x_nemo_config)) { -+ dprintk(SAA716x_ERROR, 1, "found TDA8275 tuner @0x%02x", -+ tda1004x_nemo_config.tuner_address); -+ } else { -+ goto exit; -+ } -+ dprintk(SAA716x_ERROR, 1, "Done!"); -+ } -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Frontend attach failed"); -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_nemo_config = { -+ .model_name = SAA716x_MODEL_NXP_NEMO, -+ .dev_type = SAA716x_DEV_NXP_NEMO, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_nemo_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+ -+ .adap_config = { -+ { -+ /* Adapter 0 */ -+ .ts_port = 3, /* using FGPI 3 */ -+ .worker = demux_worker -+ } -+ } -+}; -+ -+ -+#define SAA716x_MODEL_AVERMEDIA_HC82 "Avermedia HC82 Express-54" -+#define SAA716x_DEV_AVERMEDIA_HC82 "DVB-T + Analog" -+ -+#if 0 -+static struct zl10353_config saa716x_averhc82_zl10353_config = { -+ .demod_address = 0x1f, -+ .adc_clock = 450560, -+ .if2 = 361667, -+ .no_tuner = 1, -+ .parallel_ts = 1, -+}; -+#endif -+ -+static int saa716x_averhc82_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+// adapter->fe = zl10353_attach(&saa716x_averhc82_zl10353_config, &i2c->i2c_adapter); -+ -+ -+ return 0; -+} -+ -+static struct saa716x_config saa716x_averhc82_config = { -+ .model_name = SAA716x_MODEL_AVERMEDIA_HC82, -+ .dev_type = SAA716x_DEV_AVERMEDIA_HC82, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_averhc82_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+#define SAA716x_MODEL_AVERMEDIA_H788 "Avermedia H788" -+#define SAA716x_DEV_AVERMEDIA_H788 "DVB-T + Analaog" -+ -+static int saa716x_averh88_frontend_attach(struct saa716x_adapter *adapter, int count) -+{ -+ struct saa716x_dev *saa716x = adapter->saa716x; -+ -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) SAA716x frontend Init", count); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%d) Device ID=%02x", count, saa716x->pdev->subsystem_device); -+ -+ return -ENODEV; -+} -+ -+static struct saa716x_config saa716x_averh788_config = { -+ .model_name = SAA716x_MODEL_AVERMEDIA_H788, -+ .dev_type = SAA716x_DEV_AVERMEDIA_H788, -+ .boot_mode = SAA716x_EXT_BOOT, -+ .adapters = 1, -+ .frontend_attach = saa716x_averh88_frontend_attach, -+ .irq_handler = saa716x_hybrid_pci_irq, -+ .i2c_rate = SAA716x_I2C_RATE_100, -+}; -+ -+static struct pci_device_id saa716x_hybrid_pci_table[] = { -+ -+ MAKE_ENTRY(TWINHAN_TECHNOLOGIES, TWINHAN_VP_6090, SAA7162, &saa716x_vp6090_config), -+ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_HC82, SAA7160, &saa716x_averhc82_config), -+ MAKE_ENTRY(AVERMEDIA, AVERMEDIA_H788, SAA7160, &saa716x_averh788_config), -+ MAKE_ENTRY(KWORLD, KWORLD_DVB_T_PE310, SAA7162, &saa716x_atlantis_config), -+ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7162, &saa716x_atlantis_config), -+ MAKE_ENTRY(NXP_REFERENCE_BOARD, PCI_ANY_ID, SAA7160, &saa716x_nemo_config), -+ { } -+}; -+MODULE_DEVICE_TABLE(pci, saa716x_hybrid_pci_table); -+ -+static struct pci_driver saa716x_hybrid_pci_driver = { -+ .name = DRIVER_NAME, -+ .id_table = saa716x_hybrid_pci_table, -+ .probe = saa716x_hybrid_pci_probe, -+ .remove = saa716x_hybrid_pci_remove, -+}; -+ -+static int saa716x_hybrid_init(void) -+{ -+ return pci_register_driver(&saa716x_hybrid_pci_driver); -+} -+ -+static void saa716x_hybrid_exit(void) -+{ -+ return pci_unregister_driver(&saa716x_hybrid_pci_driver); -+} -+ -+module_init(saa716x_hybrid_init); -+module_exit(saa716x_hybrid_exit); -+ -+MODULE_DESCRIPTION("SAA716x Hybrid driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_hybrid.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_hybrid.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_hybrid.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_hybrid.h 2013-01-16 10:41:10.920798217 +0100 -@@ -0,0 +1,13 @@ -+#ifndef __SAA716x_HYBRID_H -+#define __SAA716x_HYBRID_H -+ -+#define TWINHAN_TECHNOLOGIES 0x1822 -+#define AVERMEDIA 0x1461 -+#define KWORLD 0x17DE -+ -+#define TWINHAN_VP_6090 0x0027 -+#define AVERMEDIA_HC82 0x2355 -+#define AVERMEDIA_H788 0x1455 -+#define KWORLD_DVB_T_PE310 0x7521 -+ -+#endif /* __SAA716x_HYBRID_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c.c 2013-01-16 10:41:10.921798210 +0100 -@@ -0,0 +1,738 @@ -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_i2c_reg.h" -+#include "saa716x_msi_reg.h" -+#include "saa716x_cgu_reg.h" -+ -+#include "saa716x_i2c.h" -+#include "saa716x_msi.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#define SAA716x_I2C_TXFAIL (I2C_ERROR_IBE | \ -+ I2C_ACK_INTER_MTNA | \ -+ I2C_FAILURE_INTER_MAF) -+ -+#define SAA716x_I2C_TXBUSY (I2C_TRANSMIT | \ -+ I2C_TRANSMIT_PROG) -+ -+#define SAA716x_I2C_RXBUSY (I2C_RECEIVE | \ -+ I2C_RECEIVE_CLEAR) -+ -+static const char* state[] = { -+ "Idle", -+ "DoneStop", -+ "Busy", -+ "TOscl", -+ "TOarb", -+ "DoneWrite", -+ "DoneRead", -+ "DoneWriteTO", -+ "DoneReadTO", -+ "NoDevice", -+ "NoACK", -+ "BUSErr", -+ "ArbLost", -+ "SEQErr", -+ "STErr" -+}; -+ -+int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus) -+{ -+ u32 stat, mask; -+ u32 *I2C_DEV; -+ -+ BUG_ON(saa716x == NULL); -+ I2C_DEV = saa716x->I2C_DEV; -+ -+ stat = SAA716x_EPRD(I2C_DEV[bus], INT_STATUS); -+ mask = SAA716x_EPRD(I2C_DEV[bus], INT_ENABLE); -+ saa716x->i2c[bus].i2c_stat = stat; -+ dprintk(SAA716x_DEBUG, 0, "Bus(%d) I2C event: Status=<%s> --> Stat=<%02x> Mask=<%02x>", -+ bus, state[stat], stat, mask); -+ -+ if (!(stat & mask)) -+ return -1; -+ -+ SAA716x_EPWR(I2C_DEV[bus], INT_CLR_STATUS, stat); -+ -+ if (stat & I2C_INTERRUPT_STFNF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPT_MTFNF) { -+ dprintk(SAA716x_DEBUG, 0, " "); -+ } -+ -+ if (stat & I2C_INTERRUPT_RFDA) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPTE_RFF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_INTERRUPT_STDR) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_MASTER_INTERRUPT_MTDR) { -+ dprintk(SAA716x_DEBUG, 0, " "); -+ } -+ -+ if (stat & I2C_ERROR_IBE) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_MODE_CHANGE_INTER_MSMC) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_RECEIVE_INTER_SRSD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_SLAVE_TRANSMIT_INTER_STSD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_ACK_INTER_MTNA) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_FAILURE_INTER_MAF) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ if (stat & I2C_INTERRUPT_MTD) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ return 0; -+} -+ -+static irqreturn_t saa716x_i2c_irq(int irq, void *dev_id) -+{ -+ struct saa716x_dev *saa716x = (struct saa716x_dev *) dev_id; -+ -+ if (unlikely(saa716x == NULL)) { -+ printk("%s: saa716x=NULL", __func__); -+ return IRQ_NONE; -+ } -+ dprintk(SAA716x_DEBUG, 1, "MSI STAT L=<%02x> H=<%02x>, CTL L=<%02x> H=<%02x>", -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_L), -+ SAA716x_EPRD(MSI, MSI_INT_STATUS_H), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_L), -+ SAA716x_EPRD(MSI, MSI_INT_ENA_H)); -+ -+ dprintk(SAA716x_DEBUG, 1, "I2C STAT 0=<%02x> 1=<%02x>, CTL 0=<%02x> 1=<%02x>", -+ SAA716x_EPRD(I2C_A, INT_STATUS), -+ SAA716x_EPRD(I2C_B, INT_STATUS), -+ SAA716x_EPRD(I2C_A, INT_CLR_STATUS), -+ SAA716x_EPRD(I2C_B, INT_CLR_STATUS)); -+ -+ return IRQ_HANDLED; -+} -+ -+static void saa716x_term_xfer(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); /* Start: SCL/SDA High */ -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x00); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0x80); -+ msleep(10); -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc0); -+ -+ return; -+} -+ -+static void saa716x_i2c_hwdeinit(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+} -+ -+static int saa716x_i2c_hwinit(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ struct i2c_adapter *adapter = &i2c->i2c_adapter; -+ -+ int i, err = 0; -+ u32 reg; -+ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & 0xd)) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed, Exiting !", -+ I2C_DEV, adapter->name); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* Flush queue */ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xcc); -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ -+ /* Reset I2C Core and generate a delay */ -+ SAA716x_EPWR(I2C_DEV, I2C_CONTROL, 0xc1); -+ -+ for (i = 0; i < 100; i++) { -+ reg = SAA716x_EPRD(I2C_DEV, I2C_CONTROL); -+ if (reg == 0xc0) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET", -+ I2C_DEV, adapter->name); -+ break; -+ } -+ msleep(1); -+ -+ if (i == 99) -+ err = -EIO; -+ } -+ -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%02x) %s RESET failed", -+ I2C_DEV, adapter->name); -+ -+ saa716x_term_xfer(i2c, I2C_DEV); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* I2C Rate Setup */ -+ switch (i2c->i2c_rate) { -+ case SAA716x_I2C_RATE_400: -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 400k", adapter->name); -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x1a); /* 0.5 * 27MHz/400kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x21); /* 0.5 * 27MHz/400kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x19); -+ break; -+ -+ case SAA716x_I2C_RATE_100: -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing Adapter %s @ 100k", adapter->name); -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_HIGH, 0x68); /* 0.5 * 27MHz/100kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_CLOCK_DIVISOR_LOW, 0x87); /* 0.5 * 27MHz/100kHz */ -+ SAA716x_EPWR(I2C_DEV, I2C_SDA_HOLD, 0x60); -+ break; -+ -+ default: -+ -+ dprintk(SAA716x_ERROR, 1, "Adapter %s Unknown Rate (Rate=0x%02x)", -+ adapter->name, -+ i2c->i2c_rate); -+ -+ break; -+ } -+ -+ /* Disable all interrupts and clear status */ -+ SAA716x_EPWR(I2C_DEV, INT_CLR_ENABLE, 0x1fff); -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ -+ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ /* Enabled interrupts: -+ * Master Transaction Done, -+ * Master Transaction Data Request -+ * (0x81) -+ */ -+ msleep(5); -+ -+ SAA716x_EPWR(I2C_DEV, INT_SET_ENABLE, -+ I2C_SET_ENABLE_MTDR | I2C_SET_ENABLE_MTD); -+ -+ /* Check interrupt enable status */ -+ reg = SAA716x_EPRD(I2C_DEV, INT_ENABLE); -+ if (reg != 0x81) { -+ -+ dprintk(SAA716x_ERROR, 1, -+ "Adapter (%d) %s Interrupt enable failed, Exiting !", -+ i, -+ adapter->name); -+ -+ err = -EIO; -+ goto exit; -+ } -+ } -+ -+ /* Check status */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & 0xd)) { -+ -+ dprintk(SAA716x_ERROR, 1, -+ "Adapter (%02x) %s has bad state, Exiting !", -+ I2C_DEV, -+ adapter->name); -+ -+ err = -EIO; -+ goto exit; -+ } -+#if 0 -+ saa716x_add_irqvector(saa716x, -+ i2c_vec[i].vector, -+ i2c_vec[i].edge, -+ i2c_vec[i].handler, -+ SAA716x_I2C_ADAPTER(i)); -+#endif -+ reg = SAA716x_EPRD(CGU, CGU_SCR_3); -+ dprintk(SAA716x_DEBUG, 1, "Adapter (%02x) Autowake <%d> Active <%d>", -+ I2C_DEV, -+ (reg >> 1) & 0x01, -+ reg & 0x01); -+ -+ return 0; -+exit: -+ return err; -+} -+ -+static int saa716x_i2c_send(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 data) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ int i, err = 0; -+ u32 reg; -+ -+ if (i2c->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ /* Write to FIFO */ -+ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); -+ return 0; -+ } -+ -+ /* Check FIFO status before TX */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ i2c->stat_tx_prior = reg; -+ if (reg & SAA716x_I2C_TXBUSY) { -+ for (i = 0; i < 100; i++) { -+ /* TODO! check for hotplug devices */ -+ msleep(10); -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ -+ if (reg & SAA716x_I2C_TXBUSY) { -+ dprintk(SAA716x_ERROR, 1, "FIFO full or Blocked"); -+ -+ err = saa716x_i2c_hwinit(i2c, I2C_DEV); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Error Reinit"); -+ err = -EIO; -+ goto exit; -+ } -+ } else { -+ break; -+ } -+ } -+ } -+ -+ /* Write to FIFO */ -+ SAA716x_EPWR(I2C_DEV, TX_FIFO, data); -+ -+ /* Check for data write */ -+ for (i = 0; i < 1000; i++) { -+ /* TODO! check for hotplug devices */ -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (reg & I2C_TRANSMIT_CLEAR) { -+ break; -+ } -+ } -+ i2c->stat_tx_done = reg; -+ -+ if (!(reg & I2C_TRANSMIT_CLEAR)) { -+ dprintk(SAA716x_ERROR, 1, "TXFIFO not empty after Timeout, tried %d loops!", i); -+ err = -EIO; -+ goto exit; -+ } -+ -+ return err; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "I2C Send failed (Err=%d)", err); -+ return err; -+} -+ -+static int saa716x_i2c_recv(struct saa716x_i2c *i2c, u32 I2C_DEV, u32 *data) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ int i, err = 0; -+ u32 reg; -+ -+ /* Check FIFO status before RX */ -+ for (i = 0; i < 1000; i++) { -+ reg = SAA716x_EPRD(I2C_DEV, I2C_STATUS); -+ if (!(reg & SAA716x_I2C_RXBUSY)) { -+ break; -+ } -+ } -+ if (reg & SAA716x_I2C_RXBUSY) { -+ dprintk(SAA716x_INFO, 1, "FIFO empty"); -+ err = -EIO; -+ goto exit; -+ } -+ -+ /* Read from FIFO */ -+ *data = SAA716x_EPRD(I2C_DEV, RX_FIFO); -+ -+ return 0; -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error Reading data, err=%d", err); -+ return err; -+} -+ -+static void saa716x_i2c_irq_start(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) -+ return; -+ -+ i2c->i2c_op = 1; -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+} -+ -+static int saa716x_i2c_irq_wait(struct saa716x_i2c *i2c, u32 I2C_DEV) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ unsigned long timeout; -+ int err = 0; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_POLLING) -+ return 0; -+ -+ timeout = HZ/100 + 1; /* 10ms */ -+ timeout = wait_event_interruptible_timeout(i2c->i2c_wq, i2c->i2c_op == 0, timeout); -+ if (timeout == -ERESTARTSYS || i2c->i2c_op) { -+ SAA716x_EPWR(I2C_DEV, INT_CLR_STATUS, 0x1fff); -+ if (timeout == -ERESTARTSYS) { -+ /* a signal arrived */ -+ err = -ERESTARTSYS; -+ } else { -+ dprintk(SAA716x_ERROR, 1, "timed out waiting for end of xfer!"); -+ err = -EIO; -+ } -+ } -+ return err; -+} -+ -+static int saa716x_i2c_write_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, -+ u16 addr, u8 *buf, u16 len, u8 add_stop) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ u32 data; -+ int err; -+ int i; -+ int bytes; -+ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ -+ /* first write START with I2C address */ -+ data = I2C_START_BIT | (addr << 1); -+ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Address write failed"); -+ goto exit; -+ } -+ -+ bytes = i2c->block_size - 1; -+ -+ /* now write the data */ -+ while (len > 0) { -+ if (bytes == i2c->block_size) { -+ /* this is not the first round, so restart irq */ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ } -+ -+ if (bytes > len) -+ bytes = len; -+ -+ for (i = 0; i < bytes; i++) { -+ data = buf[i]; -+ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n", i, data); -+ if (add_stop && i == (len - 1)) -+ data |= I2C_STOP_BIT; -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data send failed"); -+ goto exit; -+ } -+ } -+ -+ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); -+ if (err < 0) { -+ goto exit; -+ } -+ -+ len -= bytes; -+ buf += bytes; -+ bytes = i2c->block_size; -+ } -+ -+ return 0; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error writing data, err=%d", err); -+ return err; -+} -+ -+static int saa716x_i2c_read_msg(struct saa716x_i2c *i2c, u32 I2C_DEV, -+ u16 addr, u8 *buf, u16 len, u8 add_stop) -+{ -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ u32 data; -+ int err; -+ int i; -+ int bytes; -+ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ -+ /* first write START with I2C address */ -+ data = I2C_START_BIT | (addr << 1) | 1; -+ dprintk(SAA716x_DEBUG, 1, "length=%d Addr:0x%02x", len, data); -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Address write failed"); -+ goto exit; -+ } -+ -+ bytes = i2c->block_size - 1; -+ -+ /* now read the data */ -+ while (len > 0) { -+ if (bytes == i2c->block_size) { -+ /* this is not the first round, so restart irq */ -+ saa716x_i2c_irq_start(i2c, I2C_DEV); -+ } -+ -+ if (bytes > len) -+ bytes = len; -+ -+ for (i = 0; i < bytes; i++) { -+ data = 0x00; /* dummy write for reading */ -+ if (add_stop && i == (len - 1)) -+ data |= I2C_STOP_BIT; -+ err = saa716x_i2c_send(i2c, I2C_DEV, data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data send failed"); -+ goto exit; -+ } -+ } -+ -+ err = saa716x_i2c_irq_wait(i2c, I2C_DEV); -+ if (err < 0) { -+ goto exit; -+ } -+ -+ for (i = 0; i < bytes; i++) { -+ err = saa716x_i2c_recv(i2c, I2C_DEV, &data); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Data receive failed"); -+ goto exit; -+ } -+ dprintk(SAA716x_DEBUG, 0, " 0x%02x\n\n", i, data); -+ buf[i] = data; -+ } -+ -+ len -= bytes; -+ buf += bytes; -+ bytes = i2c->block_size; -+ } -+ -+ return 0; -+ -+exit: -+ dprintk(SAA716x_ERROR, 1, "Error reading data, err=%d", err); -+ return err; -+} -+ -+static int saa716x_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) -+{ -+ struct saa716x_i2c *i2c = i2c_get_adapdata(adapter); -+ struct saa716x_dev *saa716x = i2c->saa716x; -+ -+ u32 DEV = SAA716x_I2C_BUS(i2c->i2c_dev); -+ int i, j, err = 0; -+ int t; -+ -+ dprintk(SAA716x_DEBUG, 0, "\n"); -+ dprintk(SAA716x_DEBUG, 1, "Bus(%02x) I2C transfer", DEV); -+ mutex_lock(&i2c->i2c_lock); -+ -+ for (t = 0; t < 3; t++) { -+ for (i = 0; i < num; i++) { -+ if (msgs[i].flags & I2C_M_RD) -+ err = saa716x_i2c_read_msg(i2c, DEV, -+ msgs[i].addr, msgs[i].buf, msgs[i].len, -+ i == (num - 1)); -+ else -+ err = saa716x_i2c_write_msg(i2c, DEV, -+ msgs[i].addr, msgs[i].buf, msgs[i].len, -+ i == (num - 1)); -+ if (err < 0) { -+ err = -EIO; -+ goto retry; -+ } -+ } -+ break; -+retry: -+ dprintk(SAA716x_INFO, 1, "Error in Transfer, try %d", t); -+ for (i = 0; i < num; i++) { -+ dprintk(SAA716x_INFO, 1, "msg %d, addr = 0x%02x, len=%d, flags=0x%x", -+ i, msgs[i].addr, msgs[i].len, msgs[i].flags); -+ if (!(msgs[i].flags & I2C_M_RD)) { -+ for (j = 0; j < msgs[i].len; j++) { -+ dprintk(SAA716x_INFO, 1, " 0x%02x", -+ j, msgs[i].buf[j]); -+ } -+ } -+ } -+ err = saa716x_i2c_hwinit(i2c, DEV); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Error Reinit"); -+ err = -EIO; -+ goto bail_out; -+ } -+ } -+ -+ mutex_unlock(&i2c->i2c_lock); -+ return num; -+ -+bail_out: -+ dprintk(SAA716x_ERROR, 1, "ERROR: Bailing out <%d>", err); -+ mutex_unlock(&i2c->i2c_lock); -+ return err; -+} -+ -+static u32 saa716x_i2c_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_SMBUS_EMUL; -+} -+ -+static const struct i2c_algorithm saa716x_algo = { -+ .master_xfer = saa716x_i2c_xfer, -+ .functionality = saa716x_i2c_func, -+}; -+ -+struct saa716x_i2cvec { -+ u32 vector; -+ enum saa716x_edge edge; -+ irqreturn_t (*handler)(int irq, void *dev_id); -+}; -+ -+static const struct saa716x_i2cvec i2c_vec[] = { -+ { -+ .vector = I2CINT_0, -+ .edge = SAA716x_EDGE_RISING, -+ .handler = saa716x_i2c_irq -+ }, { -+ .vector = I2CINT_1, -+ .edge = SAA716x_EDGE_RISING, -+ .handler = saa716x_i2c_irq -+ } -+}; -+ -+int saa716x_i2c_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = NULL; -+ -+ int i, err = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", -+ saa716x->pdev->device); -+ -+ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { -+ -+ mutex_init(&i2c->i2c_lock); -+ -+ init_waitqueue_head(&i2c->i2c_wq); -+ i2c->i2c_op = 0; -+ -+ i2c->i2c_dev = i; -+ i2c->i2c_rate = saa716x->config->i2c_rate; -+ i2c->i2c_mode = saa716x->config->i2c_mode; -+ adapter = &i2c->i2c_adapter; -+ -+ if (i2c->i2c_mode == SAA716x_I2C_MODE_IRQ_BUFFERED) -+ i2c->block_size = 8; -+ else -+ i2c->block_size = 1; -+ -+ if (adapter != NULL) { -+ -+ i2c_set_adapdata(adapter, i2c); -+ -+ strcpy(adapter->name, SAA716x_I2C_ADAPTER(i)); -+ -+ adapter->owner = THIS_MODULE; -+ adapter->algo = &saa716x_algo; -+ adapter->algo_data = NULL; -+ adapter->timeout = 500; /* FIXME ! */ -+ adapter->retries = 3; /* FIXME ! */ -+ adapter->dev.parent = &pdev->dev; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing adapter (%d) %s", -+ i, -+ adapter->name); -+ -+ err = i2c_add_adapter(adapter); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s init failed", i, adapter->name); -+ goto exit; -+ } -+ -+ i2c->saa716x = saa716x; -+ saa716x_i2c_hwinit(i2c, SAA716x_I2C_BUS(i)); -+ } -+ i2c++; -+ } -+ -+ if (saa716x->config->i2c_mode >= SAA716x_I2C_MODE_IRQ) { -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_0); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, MSI_INT_I2CINT_1); -+ } -+ -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully initialized", -+ saa716x->pdev->device); -+ -+ return 0; -+exit: -+ return err; -+} -+EXPORT_SYMBOL_GPL(saa716x_i2c_init); -+ -+int saa716x_i2c_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = NULL; -+ int i, err = 0; -+ -+ dprintk(SAA716x_DEBUG, 1, "Removing SAA%02x I2C Core", saa716x->pdev->device); -+ -+ for (i = 0; i < SAA716x_I2C_ADAPTERS; i++) { -+ -+ adapter = &i2c->i2c_adapter; -+#if 0 -+ saa716x_remove_irqvector(saa716x, i2c_vec[i].vector); -+#endif -+ saa716x_i2c_hwdeinit(i2c, SAA716x_I2C_BUS(i)); -+ dprintk(SAA716x_DEBUG, 1, "Removing adapter (%d) %s", i, adapter->name); -+ -+ err = i2c_del_adapter(adapter); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "Adapter (%d) %s remove failed", i, adapter->name); -+ goto exit; -+ } -+ i2c++; -+ } -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x I2C Core succesfully removed", saa716x->pdev->device); -+ -+ return 0; -+ -+exit: -+ return err; -+} -+EXPORT_SYMBOL_GPL(saa716x_i2c_exit); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c.h 2013-01-16 10:41:10.921798210 +0100 -@@ -0,0 +1,52 @@ -+#ifndef __SAA716x_I2C_H -+#define __SAA716x_I2C_H -+ -+#define SAA716x_I2C_ADAPTERS 2 -+ -+#define SAA716x_I2C_ADAPTER(__dev) (( \ -+ (__dev == 1) ? \ -+ "SAA716x I2C Core 1" : \ -+ "SAA716x I2C Core 0")) -+ -+#define SAA716x_I2C_BUS(__x) ((__x == 1) ? 0x0000c000 : 0x0000b000) -+ -+#define SAA716x_I2C_BUS_A 0x01 -+#define SAA716x_I2C_BUS_B 0x00 -+ -+struct saa716x_dev; -+ -+enum saa716x_i2c_rate { -+ SAA716x_I2C_RATE_400 = 1, -+ SAA716x_I2C_RATE_100, -+}; -+ -+enum saa716x_i2c_mode { -+ SAA716x_I2C_MODE_POLLING = 0, -+ SAA716x_I2C_MODE_IRQ, -+ SAA716x_I2C_MODE_IRQ_BUFFERED -+}; -+ -+struct saa716x_i2c { -+ struct i2c_adapter i2c_adapter; -+ struct mutex i2c_lock; -+ struct saa716x_dev *saa716x; -+ u8 i2c_dev; -+ -+ enum saa716x_i2c_rate i2c_rate; /* run time */ -+ enum saa716x_i2c_mode i2c_mode; -+ u32 block_size; /* block size for buffered -+ mode, 1 otherwise */ -+ u32 i2c_stat; -+ -+ u32 stat_tx_prior; -+ u32 stat_tx_done; -+ wait_queue_head_t i2c_wq; -+ int i2c_op; -+}; -+ -+extern int saa716x_i2c_init(struct saa716x_dev *saa716x); -+extern int saa716x_i2c_exit(struct saa716x_dev *saa716x); -+extern void saa716x_i2cint_disable(struct saa716x_dev *saa716x); -+extern int saa716x_i2c_irqevent(struct saa716x_dev *saa716x, u8 bus); -+ -+#endif /* __SAA716x_I2C_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_i2c_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_i2c_reg.h 2013-01-16 10:41:10.922798203 +0100 -@@ -0,0 +1,145 @@ -+#ifndef __SAA716x_I2C_REG_H -+#define __SAA716x_I2C_REG_H -+ -+/* -------------- I2C Registers -------------- */ -+ -+#define RX_FIFO 0x000 -+#define I2C_RX_BYTE (0x000000ff << 0) -+ -+#define TX_FIFO 0x000 -+#define I2C_STOP_BIT (0x00000001 << 9) -+#define I2C_START_BIT (0x00000001 << 8) -+#define I2C_TX_BYTE (0x000000ff << 0) -+ -+#define I2C_STATUS 0x008 -+#define I2C_TRANSMIT (0x00000001 << 11) -+#define I2C_RECEIVE (0x00000001 << 10) -+#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) -+#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) -+#define I2C_TRANSMIT_PROG (0x00000001 << 7) -+#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) -+#define I2C_RECEIVE_PROG (0x00000001 << 5) -+#define I2C_RECEIVE_CLEAR (0x00000001 << 4) -+#define I2C_SDA_LINE (0x00000001 << 3) -+#define I2C_SCL_LINE (0x00000001 << 2) -+#define I2C_START_STOP_FLAG (0x00000001 << 1) -+#define I2C_MODE_STATUS (0x00000001 << 0) -+ -+#define I2C_CONTROL 0x00c -+#define I2C_SCL_CONTROL (0x00000001 << 7) -+#define I2C_SDA_CONTROL (0x00000001 << 6) -+#define I2C_RECEIVE_PROTECT (0x00000001 << 5) -+#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) -+#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) -+#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) -+#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) -+#define I2C_RESET (0x00000001 << 0) -+ -+#define I2C_CLOCK_DIVISOR_HIGH 0x010 -+#define I2C_CLOCK_HIGH (0x0000ffff << 0) -+ -+#define I2C_CLOCK_DIVISOR_LOW 0x014 -+#define I2C_CLOCK_LOW (0x0000ffff << 0) -+ -+#define I2C_RX_LEVEL 0x01c -+#define I2C_RECEIVE_RANGE (0x0000007f << 0) -+ -+#define I2C_TX_LEVEL 0x020 -+#define I2C_TRANSMIT_RANGE (0x0000007f << 0) -+ -+#define I2C_SDA_HOLD 0x028 -+#define I2C_HOLD_TIME (0x0000007f << 0) -+ -+#define MODULE_CONF 0xfd4 -+#define INT_CLR_ENABLE 0xfd8 -+#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) -+#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) -+#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) -+#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) -+#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) -+#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_SET_ENABLE 0xfdc -+#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_SET_ENABLE_RFF (0x00000001 << 9) -+#define I2C_SET_ENABLE_STDR (0x00000001 << 8) -+#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_SET_ENABLE_IBE (0x00000001 << 6) -+#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_SET_ENABLE_STSD (0x00000001 << 3) -+#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_SET_ENABLE_MAF (0x00000001 << 1) -+#define I2C_SET_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_STATUS 0xfe0 -+#define I2C_INTERRUPT_STFNF (0x00000001 << 12) -+#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) -+#define I2C_INTERRUPT_RFDA (0x00000001 << 10) -+#define I2C_INTERRUPTE_RFF (0x00000001 << 9) -+#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) -+#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) -+#define I2C_ERROR_IBE (0x00000001 << 6) -+#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) -+#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) -+#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) -+#define I2C_ACK_INTER_MTNA (0x00000001 << 2) -+#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) -+#define I2C_INTERRUPT_MTD (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define I2C_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_ENABLE_RFF (0x00000001 << 9) -+#define I2C_ENABLE_STDR (0x00000001 << 8) -+#define I2C_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_ENABLE_IBE (0x00000001 << 6) -+#define I2C_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_ENABLE_STSD (0x00000001 << 3) -+#define I2C_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_ENABLE_MAF (0x00000001 << 1) -+#define I2C_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) -+#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) -+#define I2C_CLR_STATUS_RFF (0x00000001 << 9) -+#define I2C_CLR_STATUS_STDR (0x00000001 << 8) -+#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) -+#define I2C_CLR_STATUS_IBE (0x00000001 << 6) -+#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) -+#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) -+#define I2C_CLR_STATUS_STSD (0x00000001 << 3) -+#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) -+#define I2C_CLR_STATUS_MAF (0x00000001 << 1) -+#define I2C_CLR_STATIS_MTD (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define I2C_SET_STATUS_STFNF (0x00000001 << 12) -+#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_SET_STATUS_RFDA (0x00000001 << 10) -+#define I2C_SET_STATUS_RFF (0x00000001 << 9) -+#define I2C_SET_STATUS_STDR (0x00000001 << 8) -+#define I2C_SET_STATUS_MTDR (0x00000001 << 7) -+#define I2C_SET_STATUS_IBE (0x00000001 << 6) -+#define I2C_SET_STATUS_MSMC (0x00000001 << 5) -+#define I2C_SET_STATUS_SRSD (0x00000001 << 4) -+#define I2C_SET_STATUS_STSD (0x00000001 << 3) -+#define I2C_SET_STATUS_MTNA (0x00000001 << 2) -+#define I2C_SET_STATUS_MAF (0x00000001 << 1) -+#define I2C_SET_STATIS_MTD (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_I2C_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_mod.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_mod.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_mod.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_mod.h 2013-01-16 10:41:10.922798203 +0100 -@@ -0,0 +1,50 @@ -+#ifndef __SAA716x_MOD_H -+#define __SAA716x_MOD_H -+ -+/* BAR = 17 bits */ -+/* -+ VI0 0x00000000 -+ VI1 0x00001000 -+ FGPI0 0x00002000 -+ FGPI1 0x00003000 -+ FGPI2 0x00004000 -+ FGPI3 0x00005000 -+ AI0 0x00006000 -+ AI1 0x00007000 -+ BAM 0x00008000 -+ MMU 0x00009000 -+ MSI 0x0000a000 -+ I2C_B 0x0000b000 -+ I2C_A 0x0000c000 -+ SPI 0x0000d000 -+ GPIO 0x0000e000 -+ PHI_0 0x0000f000 -+ CGU 0x00013000 -+ DCS 0x00014000 -+ GREG 0x00012000 -+ -+ PHI_1 0x00020000 -+*/ -+ -+#define VI0 0x00000000 -+#define VI1 0x00001000 -+#define FGPI0 0x00002000 -+#define FGPI1 0x00003000 -+#define FGPI2 0x00004000 -+#define FGPI3 0x00005000 -+#define AI0 0x00006000 -+#define AI1 0x00007000 -+#define BAM 0x00008000 -+#define MMU 0x00009000 -+#define MSI 0x0000a000 -+#define I2C_B 0x0000b000 -+#define I2C_A 0x0000c000 -+#define SPI 0x0000d000 -+#define GPIO 0x0000e000 -+#define PHI_0 0x0000f000 -+#define GREG 0x00012000 -+#define CGU 0x00013000 -+#define DCS 0x00014000 -+#define PHI_1 0x00020000 -+ -+#endif /* __SAA716x_MOD_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_msi.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_msi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi.c 2013-01-16 10:41:10.923798196 +0100 -@@ -0,0 +1,479 @@ -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_msi_reg.h" -+#include "saa716x_msi.h" -+#include "saa716x_spi.h" -+ -+#include "saa716x_priv.h" -+ -+#define SAA716x_MSI_VECTORS 50 -+ -+static const char *vector_name[] = { -+ "TAGACK_VI0_0", -+ "TAGACK_VI0_1", -+ "TAGACK_VI0_2", -+ "TAGACK_VI1_0", -+ "TAGACK_VI1_1", -+ "TAGACK_VI1_2", -+ "TAGACK_FGPI_0", -+ "TAGACK_FGPI_1", -+ "TAGACK_FGPI_2", -+ "TAGACK_FGPI_3", -+ "TAGACK_AI_0", -+ "TAGACK_AI_1", -+ "OVRFLW_VI0_0", -+ "OVRFLW_VI0_1", -+ "OVRFLW_VI0_2", -+ "OVRFLW_VI1_0", -+ "OVRFLW_VI1_1", -+ "OVRFLW_VI1_2", -+ "OVRFLW_FGPI_O", -+ "OVRFLW_FGPI_1", -+ "OVRFLW_FGPI_2", -+ "OVRFLW_FGPI_3", -+ "OVRFLW_AI_0", -+ "OVRFLW_AI_1", -+ "AVINT_VI0", -+ "AVINT_VI1", -+ "AVINT_FGPI_0", -+ "AVINT_FGPI_1", -+ "AVINT_FGPI_2", -+ "AVINT_FGPI_3", -+ "AVINT_AI_0", -+ "AVINT_AI_1", -+ "UNMAPD_TC_INT", -+ "EXTINT_0", -+ "EXTINT_1", -+ "EXTINT_2", -+ "EXTINT_3", -+ "EXTINT_4", -+ "EXTINT_5", -+ "EXTINT_6", -+ "EXTINT_7", -+ "EXTINT_8", -+ "EXTINT_9", -+ "EXTINT_10", -+ "EXTINT_11", -+ "EXTINT_12", -+ "EXTINT_13", -+ "EXTINT_14", -+ "EXTINT_15", -+ "I2CINT_0", -+ "I2CINT_1" -+}; -+ -+static u32 MSI_CONFIG_REG[51] = { -+ MSI_CONFIG0, -+ MSI_CONFIG1, -+ MSI_CONFIG2, -+ MSI_CONFIG3, -+ MSI_CONFIG4, -+ MSI_CONFIG5, -+ MSI_CONFIG6, -+ MSI_CONFIG7, -+ MSI_CONFIG8, -+ MSI_CONFIG9, -+ MSI_CONFIG10, -+ MSI_CONFIG11, -+ MSI_CONFIG12, -+ MSI_CONFIG13, -+ MSI_CONFIG14, -+ MSI_CONFIG15, -+ MSI_CONFIG16, -+ MSI_CONFIG17, -+ MSI_CONFIG18, -+ MSI_CONFIG19, -+ MSI_CONFIG20, -+ MSI_CONFIG21, -+ MSI_CONFIG22, -+ MSI_CONFIG23, -+ MSI_CONFIG24, -+ MSI_CONFIG25, -+ MSI_CONFIG26, -+ MSI_CONFIG27, -+ MSI_CONFIG28, -+ MSI_CONFIG29, -+ MSI_CONFIG30, -+ MSI_CONFIG31, -+ MSI_CONFIG32, -+ MSI_CONFIG33, -+ MSI_CONFIG34, -+ MSI_CONFIG35, -+ MSI_CONFIG36, -+ MSI_CONFIG37, -+ MSI_CONFIG38, -+ MSI_CONFIG39, -+ MSI_CONFIG40, -+ MSI_CONFIG41, -+ MSI_CONFIG42, -+ MSI_CONFIG43, -+ MSI_CONFIG44, -+ MSI_CONFIG45, -+ MSI_CONFIG46, -+ MSI_CONFIG47, -+ MSI_CONFIG48, -+ MSI_CONFIG49, -+ MSI_CONFIG50 -+}; -+ -+int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h) -+{ -+ dprintk(SAA716x_DEBUG, 0, "%s: MSI event ", __func__); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[0]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[1]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI0_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[2]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[3]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[4]); -+ -+ if (stat_l & MSI_INT_TAGACK_VI1_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[5]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[6]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[7]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[8]); -+ -+ if (stat_l & MSI_INT_TAGACK_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[9]); -+ -+ if (stat_l & MSI_INT_TAGACK_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[10]); -+ -+ if (stat_l & MSI_INT_TAGACK_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[11]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[12]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[13]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI0_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[14]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[15]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[16]); -+ -+ if (stat_l & MSI_INT_OVRFLW_VI1_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[17]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[18]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[19]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[20]); -+ -+ if (stat_l & MSI_INT_OVRFLW_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[21]); -+ -+ if (stat_l & MSI_INT_OVRFLW_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[22]); -+ -+ if (stat_l & MSI_INT_OVRFLW_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[23]); -+ -+ if (stat_l & MSI_INT_AVINT_VI0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[24]); -+ -+ if (stat_l & MSI_INT_AVINT_VI1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[25]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[26]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[27]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[28]); -+ -+ if (stat_l & MSI_INT_AVINT_FGPI_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[29]); -+ -+ if (stat_l & MSI_INT_AVINT_AI_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[30]); -+ -+ if (stat_l & MSI_INT_AVINT_AI_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[31]); -+ -+ if (stat_h & MSI_INT_UNMAPD_TC_INT) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[32]); -+ -+ if (stat_h & MSI_INT_EXTINT_0) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[33]); -+ -+ if (stat_h & MSI_INT_EXTINT_1) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[34]); -+ -+ if (stat_h & MSI_INT_EXTINT_2) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[35]); -+ -+ if (stat_h & MSI_INT_EXTINT_3) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[36]); -+ -+ if (stat_h & MSI_INT_EXTINT_4) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[37]); -+ -+ if (stat_h & MSI_INT_EXTINT_5) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[38]); -+ -+ if (stat_h & MSI_INT_EXTINT_6) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[39]); -+ -+ if (stat_h & MSI_INT_EXTINT_7) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[40]); -+ -+ if (stat_h & MSI_INT_EXTINT_8) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[41]); -+ -+ if (stat_h & MSI_INT_EXTINT_9) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[42]); -+ -+ if (stat_h & MSI_INT_EXTINT_10) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[43]); -+ -+ if (stat_h & MSI_INT_EXTINT_11) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[44]); -+ -+ if (stat_h & MSI_INT_EXTINT_12) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[45]); -+ -+ if (stat_h & MSI_INT_EXTINT_13) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[46]); -+ -+ if (stat_h & MSI_INT_EXTINT_14) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[47]); -+ -+ if (stat_h & MSI_INT_EXTINT_15) -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[48]); -+ -+ if (stat_h & MSI_INT_I2CINT_0) { -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[49]); -+ saa716x_i2c_irqevent(saa716x, 0); -+ } -+ -+ if (stat_h & MSI_INT_I2CINT_1) { -+ dprintk(SAA716x_DEBUG, 0, "<%s> ", vector_name[50]); -+ saa716x_i2c_irqevent(saa716x, 1); -+ } -+ -+ dprintk(SAA716x_DEBUG, 0, "\n"); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_msi_event); -+ -+int saa716x_msi_init(struct saa716x_dev *saa716x) -+{ -+ u32 ena_l, ena_h, sta_l, sta_h, mid; -+ int i; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing MSI .."); -+ saa716x->handlers = 0; -+ -+ /* get module id & version */ -+ mid = SAA716x_EPRD(MSI, MSI_MODULE_ID); -+ if (mid != 0x30100) -+ dprintk(SAA716x_ERROR, 1, "MSI Id<%04x> is not supported", mid); -+ -+ /* let HW take care of MSI race */ -+ SAA716x_EPWR(MSI, MSI_DELAY_TIMER, 0x0); -+ -+ /* INTA Polarity: Active High */ -+ SAA716x_EPWR(MSI, MSI_INTA_POLARITY, MSI_INTA_POLARITY_HIGH); -+ -+ /* -+ * IRQ Edge Rising: 25:24 = 0x01 -+ * Traffic Class: 18:16 = 0x00 -+ * MSI ID: 4:0 = 0x00 -+ */ -+ for (i = 0; i < SAA716x_MSI_VECTORS; i++) -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[i], MSI_INT_POL_EDGE_RISE); -+ -+ /* get Status */ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ -+ /* disable and clear enabled and asserted IRQ's */ -+ if (sta_l) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, sta_l); -+ -+ if (sta_h) -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_H, sta_h); -+ -+ if (ena_l) -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, ena_l); -+ -+ if (ena_h) -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, ena_h); -+ -+ msleep(5); -+ -+ /* Check IRQ's really disabled */ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ sta_l = SAA716x_EPRD(MSI, MSI_INT_STATUS_L); -+ sta_h = SAA716x_EPRD(MSI, MSI_INT_STATUS_H); -+ -+ if ((ena_l == 0) && (ena_h == 0) && (sta_l == 0) && (sta_h == 0)) { -+ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x> sta_l <%02x> sta_h <%02x>", -+ ena_l, ena_h, sta_l, sta_h); -+ -+ return 0; -+ } else { -+ dprintk(SAA716x_DEBUG, 1, "I/O error"); -+ return -EIO; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_msi_init); -+ -+void saa716x_msiint_disable(struct saa716x_dev *saa716x) -+{ -+ dprintk(SAA716x_DEBUG, 1, "Disabling Interrupts ..."); -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_L, 0x0); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_H, 0x0); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0xffffffff); -+ SAA716x_EPWR(MSI, MSI_INT_STATUS_CLR_L, 0x0000ffff); -+} -+EXPORT_SYMBOL_GPL(saa716x_msiint_disable); -+ -+ -+/* Map the given vector Id to the hardware bitmask. */ -+static void saa716x_map_vector(struct saa716x_dev *saa716x, int vector, u32 *mask_l, u32 *mask_h) -+{ -+ u32 tmp = 1; -+ -+ if (vector < 32) { -+ /* Bits 0 - 31 */ -+ tmp <<= vector; -+ *mask_l = tmp; -+ *mask_h = 0; -+ } else { -+ /* Bits 32 - 48 */ -+ tmp <<= vector - 32; -+ *mask_l = 0; -+ *mask_h = tmp; -+ } -+} -+ -+int saa716x_add_irqvector(struct saa716x_dev *saa716x, -+ int vector, -+ enum saa716x_edge edge, -+ irqreturn_t (*handler)(int irq, void *dev_id), -+ char *desc) -+{ -+ struct saa716x_msix_entry *msix_handler = NULL; -+ -+ u32 config, mask_l, mask_h, ena_l, ena_h; -+ -+ BUG_ON(saa716x == NULL); -+ BUG_ON(vector > SAA716x_MSI_VECTORS); -+ dprintk(SAA716x_DEBUG, 1, "Adding Vector %d <%s>", vector, vector_name[vector]); -+ -+ if ((vector > 32) && (vector < 49)) { -+ config = SAA716x_EPRD(MSI, MSI_CONFIG_REG[vector]); -+ config &= 0xfcffffff; /* clear polarity */ -+ -+ switch (edge) { -+ default: -+ case SAA716x_EDGE_RISING: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x01000000); -+ break; -+ -+ case SAA716x_EDGE_FALLING: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x02000000); -+ break; -+ -+ case SAA716x_EDGE_ANY: -+ SAA716x_EPWR(MSI, MSI_CONFIG_REG[vector], config | 0x03000000); -+ break; -+ } -+ } -+ -+ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); -+ -+ /* add callback */ -+ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; -+ strcpy(msix_handler->desc, desc); -+ msix_handler->vector = vector; -+ msix_handler->handler = handler; -+ saa716x->handlers++; -+ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_L, mask_l); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_SET_H, mask_h); -+ -+ ena_l = SAA716x_EPRD(MSI, MSI_INT_ENA_L); -+ ena_h = SAA716x_EPRD(MSI, MSI_INT_ENA_H); -+ dprintk(SAA716x_DEBUG, 1, "Interrupts ena_l <%02x> ena_h <%02x>", ena_l, ena_h); -+ -+ return 0; -+} -+ -+int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector) -+{ -+ struct saa716x_msix_entry *msix_handler; -+ int i; -+ u32 mask_l, mask_h; -+ -+ msix_handler = &saa716x->saa716x_msix_handler[saa716x->handlers]; -+ BUG_ON(msix_handler == NULL); -+ dprintk(SAA716x_DEBUG, 1, "Removing Vector %d <%s>", vector, vector_name[vector]); -+ -+ /* loop through the registered handlers */ -+ for (i = 0; i < saa716x->handlers; i++) { -+ -+ /* we found our vector */ -+ if (msix_handler->vector == vector) { -+ BUG_ON(msix_handler->handler == NULL); /* no handler yet */ -+ dprintk(SAA716x_DEBUG, 1, "Vector %d <%s> removed", -+ msix_handler->vector, -+ msix_handler->desc); -+ -+ /* check whether it is already released */ -+ if (msix_handler->handler) { -+ msix_handler->vector = 0; -+ msix_handler->handler = NULL; -+ saa716x->handlers--; -+ } -+ } -+ } -+ -+ saa716x_map_vector(saa716x, vector, &mask_l, &mask_h); -+ -+ /* disable vector */ -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_L, mask_l); -+ SAA716x_EPWR(MSI, MSI_INT_ENA_CLR_H, mask_h); -+ -+ return 0; -+} -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_msi.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_msi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi.h 2013-01-16 10:41:10.923798196 +0100 -@@ -0,0 +1,87 @@ -+#ifndef __SAA716x_MSI_H -+#define __SAA716x_MSI_H -+ -+#define TAGACK_VI0_0 0x000 -+#define TAGACK_VI0_1 0x001 -+#define TAGACK_VI0_2 0x002 -+#define TAGACK_VI1_0 0x003 -+#define TAGACK_VI1_1 0x004 -+#define TAGACK_VI1_2 0x005 -+#define TAGACK_FGPI_0 0x006 -+#define TAGACK_FGPI_1 0x007 -+#define TAGACK_FGPI_2 0x008 -+#define TAGACK_FGPI_3 0x009 -+#define TAGACK_AI_0 0x00a -+#define TAGACK_AI_1 0x00b -+#define OVRFLW_VI0_0 0x00c -+#define OVRFLW_VI0_1 0x00d -+#define OVRFLW_VI0_2 0x00e -+#define OVRFLW_VI1_0 0x00f -+#define OVRFLW_VI1_1 0x010 -+#define OVRFLW_VI1_2 0x011 -+#define OVRFLW_FGPI_O 0x012 -+#define OVRFLW_FGPI_1 0x013 -+#define OVRFLW_FGPI_2 0x014 -+#define OVRFLW_FGPI_3 0x015 -+#define OVRFLW_AI_0 0x016 -+#define OVRFLW_AI_1 0x017 -+#define AVINT_VI0 0x018 -+#define AVINT_VI1 0x019 -+#define AVINT_FGPI_0 0x01a -+#define AVINT_FGPI_1 0x01b -+#define AVINT_FGPI_2 0x01c -+#define AVINT_FGPI_3 0x01d -+#define AVINT_AI_0 0x01e -+#define AVINT_AI_1 0x01f -+#define UNMAPD_TC_INT 0x020 -+#define EXTINT_0 0x021 -+#define EXTINT_1 0x022 -+#define EXTINT_2 0x023 -+#define EXTINT_3 0x024 -+#define EXTINT_4 0x025 -+#define EXTINT_5 0x026 -+#define EXTINT_6 0x027 -+#define EXTINT_7 0x028 -+#define EXTINT_8 0x029 -+#define EXTINT_9 0x02a -+#define EXTINT_10 0x02b -+#define EXTINT_11 0x02c -+#define EXTINT_12 0x02d -+#define EXTINT_13 0x02e -+#define EXTINT_14 0x02f -+#define EXTINT_15 0x030 -+#define I2CINT_0 0x031 -+#define I2CINT_1 0x032 -+ -+#define SAA716x_TC0 0x000 -+#define SAA716x_TC1 0x001 -+#define SAA716x_TC2 0x002 -+#define SAA716x_TC3 0x003 -+#define SAA716x_TC4 0x004 -+#define SAA716x_TC5 0x005 -+#define SAA716x_TC6 0x006 -+#define SAA716x_TC7 0x007 -+ -+ -+enum saa716x_edge { -+ SAA716x_EDGE_RISING = 1, -+ SAA716x_EDGE_FALLING = 2, -+ SAA716x_EDGE_ANY = 3 -+}; -+ -+struct saa716x_dev; -+ -+extern int saa716x_msi_event(struct saa716x_dev *saa716x, u32 stat_l, u32 stat_h); -+ -+extern int saa716x_msi_init(struct saa716x_dev *saa716x); -+extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); -+ -+extern int saa716x_add_irqvector(struct saa716x_dev *saa716x, -+ int vector, -+ enum saa716x_edge edge, -+ irqreturn_t (*handler)(int irq, void *dev_id), -+ char *desc); -+ -+extern int saa716x_remove_irqvector(struct saa716x_dev *saa716x, int vector); -+ -+#endif /* __SAA716x_MSI_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_msi_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_msi_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_msi_reg.h 2013-01-16 10:41:10.923798196 +0100 -@@ -0,0 +1,143 @@ -+#ifndef __SAA716x_MSI_REG_H -+#define __SAA716x_MSI_REG_H -+ -+/* -------------- MSI Registers -------------- */ -+ -+#define MSI_DELAY_TIMER 0x000 -+#define MSI_DELAY_1CLK (0x00000001 << 0) -+#define MSI_DELAY_2CLK (0x00000002 << 0) -+ -+#define MSI_INTA_POLARITY 0x004 -+#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) -+ -+#define MSI_CONFIG0 0x008 -+#define MSI_CONFIG1 0x00c -+#define MSI_CONFIG2 0x010 -+#define MSI_CONFIG3 0x014 -+#define MSI_CONFIG4 0x018 -+#define MSI_CONFIG5 0x01c -+#define MSI_CONFIG6 0x020 -+#define MSI_CONFIG7 0x024 -+#define MSI_CONFIG8 0x028 -+#define MSI_CONFIG9 0x02c -+#define MSI_CONFIG10 0x030 -+#define MSI_CONFIG11 0x034 -+#define MSI_CONFIG12 0x038 -+#define MSI_CONFIG13 0x03c -+#define MSI_CONFIG14 0x040 -+#define MSI_CONFIG15 0x044 -+#define MSI_CONFIG16 0x048 -+#define MSI_CONFIG17 0x04c -+#define MSI_CONFIG18 0x050 -+#define MSI_CONFIG19 0x054 -+#define MSI_CONFIG20 0x058 -+#define MSI_CONFIG21 0x05c -+#define MSI_CONFIG22 0x060 -+#define MSI_CONFIG23 0x064 -+#define MSI_CONFIG24 0x068 -+#define MSI_CONFIG25 0x06c -+#define MSI_CONFIG26 0x070 -+#define MSI_CONFIG27 0x074 -+#define MSI_CONFIG28 0x078 -+#define MSI_CONFIG29 0x07c -+#define MSI_CONFIG30 0x080 -+#define MSI_CONFIG31 0x084 -+#define MSI_CONFIG32 0x088 -+#define MSI_CONFIG33 0x08c -+#define MSI_CONFIG34 0x090 -+#define MSI_CONFIG35 0x094 -+#define MSI_CONFIG36 0x098 -+#define MSI_CONFIG37 0x09c -+#define MSI_CONFIG38 0x0a0 -+#define MSI_CONFIG39 0x0a4 -+#define MSI_CONFIG40 0x0a8 -+#define MSI_CONFIG41 0x0ac -+#define MSI_CONFIG42 0x0b0 -+#define MSI_CONFIG43 0x0b4 -+#define MSI_CONFIG44 0x0b8 -+#define MSI_CONFIG45 0x0bc -+#define MSI_CONFIG46 0x0c0 -+#define MSI_CONFIG47 0x0c4 -+#define MSI_CONFIG48 0x0c8 -+#define MSI_CONFIG49 0x0cc -+#define MSI_CONFIG50 0x0d0 -+ -+#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) -+#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) -+#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) -+#define MSI_TC (0x00000007 << 16) -+#define MSI_ID (0x0000000f << 0) -+ -+#define MSI_INT_STATUS_L 0xfc0 -+#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) -+#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) -+#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) -+#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) -+#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) -+#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) -+#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) -+#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) -+#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) -+#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) -+#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) -+#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) -+#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) -+#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) -+#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) -+#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) -+#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) -+#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) -+#define MSI_INT_OVRFLW_FGPI_0 (0x00000001 << 18) -+#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) -+#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) -+#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) -+#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) -+#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) -+#define MSI_INT_AVINT_VI0 (0x00000001 << 24) -+#define MSI_INT_AVINT_VI1 (0x00000001 << 25) -+#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) -+#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) -+#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) -+#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) -+#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) -+#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) -+ -+#define MSI_INT_STATUS_H 0xfc4 -+#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) -+#define MSI_INT_EXTINT_0 (0x00000001 << 1) -+#define MSI_INT_EXTINT_1 (0x00000001 << 2) -+#define MSI_INT_EXTINT_2 (0x00000001 << 3) -+#define MSI_INT_EXTINT_3 (0x00000001 << 4) -+#define MSI_INT_EXTINT_4 (0x00000001 << 5) -+#define MSI_INT_EXTINT_5 (0x00000001 << 6) -+#define MSI_INT_EXTINT_6 (0x00000001 << 7) -+#define MSI_INT_EXTINT_7 (0x00000001 << 8) -+#define MSI_INT_EXTINT_8 (0x00000001 << 9) -+#define MSI_INT_EXTINT_9 (0x00000001 << 10) -+#define MSI_INT_EXTINT_10 (0x00000001 << 11) -+#define MSI_INT_EXTINT_11 (0x00000001 << 12) -+#define MSI_INT_EXTINT_12 (0x00000001 << 13) -+#define MSI_INT_EXTINT_13 (0x00000001 << 14) -+#define MSI_INT_EXTINT_14 (0x00000001 << 15) -+#define MSI_INT_EXTINT_15 (0x00000001 << 16) -+#define MSI_INT_I2CINT_0 (0x00000001 << 17) -+#define MSI_INT_I2CINT_1 (0x00000001 << 18) -+ -+#define MSI_INT_STATUS_CLR_L 0xfc8 -+#define MSI_INT_STATUS_CLR_H 0xfcc -+#define MSI_INT_STATUS_SET_L 0xfd0 -+#define MSI_INT_STATUS_SET_H 0xfd4 -+#define MSI_INT_ENA_L 0xfd8 -+#define MSI_INT_ENA_H 0xfdc -+#define MSI_INT_ENA_CLR_L 0xfe0 -+#define MSI_INT_ENA_CLR_H 0xfe4 -+#define MSI_INT_ENA_SET_L 0xfe8 -+#define MSI_INT_ENA_SET_H 0xfec -+ -+#define MSI_SW_RST 0xff0 -+#define MSI_SW_RESET (0x0001 << 0) -+ -+#define MSI_MODULE_ID 0xffc -+ -+ -+#endif /* __SAA716x_MSI_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_pci.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_pci.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_pci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_pci.c 2013-01-16 10:41:10.924798189 +0100 -@@ -0,0 +1,275 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include "saa716x_spi.h" -+#include "saa716x_msi.h" -+#include "saa716x_priv.h" -+ -+#define DRIVER_NAME "SAA716x Core" -+ -+static irqreturn_t saa716x_msi_handler(int irq, void *dev_id) -+{ -+ return IRQ_HANDLED; -+} -+ -+static int saa716x_enable_msi(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int err; -+ -+ err = pci_enable_msi(pdev); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "MSI enable failed <%d>", err); -+ return err; -+ } -+ -+ return err; -+} -+ -+static int saa716x_enable_msix(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int i, ret = 0; -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) -+ saa716x->msix_entries[i].entry = i; -+ -+ ret = pci_enable_msix(pdev, saa716x->msix_entries, SAA716x_MSI_MAX_VECTORS); -+ if (ret < 0) -+ dprintk(SAA716x_ERROR, 1, "MSI-X request failed <%d>", ret); -+ if (ret > 0) -+ dprintk(SAA716x_ERROR, 1, "Request exceeds available IRQ's <%d>", ret); -+ -+ return ret; -+} -+ -+static int saa716x_request_irq(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct saa716x_config *config = saa716x->config; -+ int i, ret = 0; -+ -+ if (saa716x->int_type == MODE_MSI) { -+ dprintk(SAA716x_DEBUG, 1, "Using MSI mode"); -+ ret = saa716x_enable_msi(saa716x); -+ } else if (saa716x->int_type == MODE_MSI_X) { -+ dprintk(SAA716x_DEBUG, 1, "Using MSI-X mode"); -+ ret = saa716x_enable_msix(saa716x); -+ } -+ -+ if (ret) { -+ dprintk(SAA716x_ERROR, 1, "INT-A Mode"); -+ saa716x->int_type = MODE_INTA; -+ } -+ -+ if (saa716x->int_type == MODE_MSI) { -+ ret = request_irq(pdev->irq, -+ config->irq_handler, -+ 0, -+ DRIVER_NAME, -+ saa716x); -+ -+ if (ret) { -+ pci_disable_msi(pdev); -+ dprintk(SAA716x_ERROR, 1, "MSI registration failed"); -+ ret = -EIO; -+ } -+ } -+ -+ if (saa716x->int_type == MODE_MSI_X) { -+ for (i = 0; SAA716x_MSI_MAX_VECTORS; i++) { -+ ret = request_irq(saa716x->msix_entries[i].vector, -+ saa716x->saa716x_msix_handler[i].handler, -+ IRQF_SHARED, -+ saa716x->saa716x_msix_handler[i].desc, -+ saa716x); -+ -+ dprintk(SAA716x_ERROR, 1, "%s @ 0x%p", saa716x->saa716x_msix_handler[i].desc, saa716x->saa716x_msix_handler[i].handler); -+ if (ret) { -+ dprintk(SAA716x_ERROR, 1, "%s MSI-X-%d registration failed <%d>", saa716x->saa716x_msix_handler[i].desc, i, ret); -+ return -1; -+ } -+ } -+ } -+ -+ if (saa716x->int_type == MODE_INTA) { -+ ret = request_irq(pdev->irq, -+ config->irq_handler, -+ IRQF_SHARED, -+ DRIVER_NAME, -+ saa716x); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed <%d>", ret); -+ ret = -ENODEV; -+ } -+ } -+ -+ return ret; -+} -+ -+static void saa716x_free_irq(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int i, vector; -+ -+ if (saa716x->int_type == MODE_MSI_X) { -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) { -+ vector = saa716x->msix_entries[i].vector; -+ free_irq(vector, saa716x); -+ } -+ -+ pci_disable_msix(pdev); -+ -+ } else { -+ free_irq(pdev->irq, saa716x); -+ if (saa716x->int_type == MODE_MSI) -+ pci_disable_msi(pdev); -+ } -+} -+ -+int saa716x_pci_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ int err = 0, ret = -ENODEV, i, use_dac, pm_cap; -+ u32 msi_cap; -+ u8 revision; -+ -+ dprintk(SAA716x_ERROR, 1, "found a %s PCIe card", saa716x->config->model_name); -+ -+ err = pci_enable_device(pdev); -+ if (err != 0) { -+ ret = -ENODEV; -+ dprintk(SAA716x_ERROR, 1, "ERROR: PCI enable failed (%i)", err); -+ goto fail0; -+ } -+ -+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { -+ use_dac = 1; -+ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); -+ if (err) { -+ dprintk(SAA716x_ERROR, 1, "Unable to obtain 64bit DMA"); -+ goto fail1; -+ } -+ } else if ((err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) != 0) { -+ dprintk(SAA716x_ERROR, 1, "Unable to obtain 32bit DMA"); -+ goto fail1; -+ } -+ -+ pci_set_master(pdev); -+ -+ pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); -+ if (pm_cap == 0) { -+ dprintk(SAA716x_ERROR, 1, "Cannot find Power Management Capability"); -+ err = -EIO; -+ goto fail1; -+ } -+ -+ if (!request_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0), -+ DRIVER_NAME)) { -+ -+ dprintk(SAA716x_ERROR, 1, "BAR0 Request failed"); -+ ret = -ENODEV; -+ goto fail1; -+ } -+ saa716x->mmio = ioremap(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ -+ if (!saa716x->mmio) { -+ dprintk(SAA716x_ERROR, 1, "Mem 0 remap failed"); -+ ret = -ENODEV; -+ goto fail2; -+ } -+ -+ for (i = 0; i < SAA716x_MSI_MAX_VECTORS; i++) -+ saa716x->msix_entries[i].entry = i; -+ -+ err = saa716x_request_irq(saa716x); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "SAA716x IRQ registration failed, err=%d", err); -+ ret = -ENODEV; -+ goto fail3; -+ } -+ -+ pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); -+ pci_read_config_dword(pdev, 0x40, &msi_cap); -+ -+ saa716x->revision = revision; -+ -+ dprintk(SAA716x_ERROR, 0, " SAA%02x Rev %d [%04x:%04x], ", -+ saa716x->pdev->device, -+ revision, -+ saa716x->pdev->subsystem_vendor, -+ saa716x->pdev->subsystem_device); -+ -+ dprintk(SAA716x_ERROR, 0, -+ "irq: %d,\n mmio: 0x%p\n", -+ saa716x->pdev->irq, -+ saa716x->mmio); -+ -+ dprintk(SAA716x_ERROR, 0, " SAA%02x %sBit, MSI %s, MSI-X=%d msgs", -+ saa716x->pdev->device, -+ (((msi_cap >> 23) & 0x01) == 1 ? "64":"32"), -+ (((msi_cap >> 16) & 0x01) == 1 ? "Enabled" : "Disabled"), -+ (1 << ((msi_cap >> 17) & 0x07))); -+ -+ dprintk(SAA716x_ERROR, 0, "\n"); -+ -+ pci_set_drvdata(pdev, saa716x); -+ -+ return 0; -+ -+fail3: -+ dprintk(SAA716x_ERROR, 1, "Err: IO Unmap"); -+ if (saa716x->mmio) -+ iounmap(saa716x->mmio); -+fail2: -+ dprintk(SAA716x_ERROR, 1, "Err: Release regions"); -+ release_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ -+fail1: -+ dprintk(SAA716x_ERROR, 1, "Err: Disabling device"); -+ pci_disable_device(pdev); -+ -+fail0: -+ pci_set_drvdata(pdev, NULL); -+ return ret; -+} -+EXPORT_SYMBOL_GPL(saa716x_pci_init); -+ -+void saa716x_pci_exit(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ -+ saa716x_free_irq(saa716x); -+ -+ dprintk(SAA716x_NOTICE, 1, "SAA%02x mem0: 0x%p", -+ saa716x->pdev->device, -+ saa716x->mmio); -+ -+ if (saa716x->mmio) { -+ iounmap(saa716x->mmio); -+ release_mem_region(pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ } -+ -+ pci_disable_device(pdev); -+ pci_set_drvdata(pdev, NULL); -+} -+EXPORT_SYMBOL_GPL(saa716x_pci_exit); -+ -+MODULE_DESCRIPTION("SAA716x bridge driver"); -+MODULE_AUTHOR("Manu Abraham"); -+MODULE_LICENSE("GPL"); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_phi.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_phi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi.c 2013-01-16 10:41:10.924798189 +0100 -@@ -0,0 +1,152 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_phi_reg.h" -+ -+#include "saa716x_spi.h" -+#include "saa716x_phi.h" -+#include "saa716x_priv.h" -+ -+u32 PHI_0_REGS[] = { -+ PHI_0_MODE, -+ PHI_0_0_CONFIG, -+ PHI_0_1_CONFIG, -+ PHI_0_2_CONFIG, -+ PHI_0_3_CONFIG -+}; -+ -+u32 PHI_1_REGS[] = { -+ PHI_1_MODE, -+ PHI_1_0_CONFIG, -+ PHI_1_1_CONFIG, -+ PHI_1_2_CONFIG, -+ PHI_1_3_CONFIG, -+ PHI_1_4_CONFIG, -+ PHI_1_5_CONFIG, -+ PHI_1_6_CONFIG, -+ PHI_1_7_CONFIG -+}; -+ -+#define PHI_BASE(__port) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_BASE : \ -+ PHI_0_BASE \ -+)) -+ -+#define PHI_APERTURE(_port) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_APERTURE: \ -+ PHI_0_APERTURE \ -+)) -+ -+#define PHI_REG(__port, __reg) (( \ -+ (__port == PHI_1) ? \ -+ PHI_1_REGS[__reg] : \ -+ PHI_0_REGS[__reg] \ -+)) -+ -+#define PHI_SLAVE(__port, __slave) (( \ -+ PHI_BASE(__port) + (__slave * (PHI_APERTURE(__port))) \ -+)) -+ -+/* // Read SAA716x registers -+ * SAA716x_EPRD(PHI_0, PHI_REG(__port, __reg)) -+ * SAA716x_EPWR(PHI_1, PHI_REG(__port, __reg), __data) -+ * -+ * // Read slave registers -+ * SAA716x_EPRD(PHI_0, PHI_SLAVE(__port, __slave, __offset)) -+ * SAA716x_EPWR(PHI_1, PHI_SLAVE(__port, __slave, _offset), __data) -+ */ -+ -+int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave) -+{ -+ int i; -+ -+ /* Reset */ -+ SAA716x_EPWR(PHI_0, PHI_SW_RST, 0x1); -+ -+ for (i = 0; i < 20; i++) { -+ msleep(1); -+ if (!(SAA716x_EPRD(PHI_0, PHI_SW_RST))) -+ break; -+ } -+ -+ return 0; -+} -+ -+int saa716x_phi_init(struct saa716x_dev *saa716x) -+{ -+ uint32_t value; -+ -+ /* init PHI 0 to FIFO mode */ -+ value = 0; -+ value |= PHI_FIFO_MODE; -+ SAA716x_EPWR(PHI_0, PHI_0_MODE, value); -+ -+ value = 0; -+ value |= 0x02; /* chip select 1 */ -+ value |= 0x00 << 8; /* ready mask */ -+ value |= 0x03 << 12; /* strobe time */ -+ value |= 0x06 << 20; /* cycle time */ -+ SAA716x_EPWR(PHI_0, PHI_0_0_CONFIG, value); -+ -+ /* init PHI 1 to SRAM mode, auto increment on */ -+ value = 0; -+ value |= PHI_AUTO_INCREMENT; -+ SAA716x_EPWR(PHI_0, PHI_1_MODE, value); -+ -+ value = 0; -+ value |= 0x01; /* chip select 0 */ -+ value |= 0x00 << 8; /* ready mask */ -+ value |= 0x03 << 12; /* strobe time */ -+ value |= 0x05 << 20; /* cycle time */ -+ SAA716x_EPWR(PHI_0, PHI_1_0_CONFIG, value); -+ -+ value = 0; -+ value |= PHI_ALE_POL; /* ALE is active high */ -+ SAA716x_EPWR(PHI_0, PHI_POLARITY, value); -+ -+ SAA716x_EPWR(PHI_0, PHI_TIMEOUT, 0x2a); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_init); -+ -+int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ SAA716x_EPWR(PHI_1, address, *((u32 *) &data[i])); -+ address += 4; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_write); -+ -+int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ *((u32 *) &data[i]) = SAA716x_EPRD(PHI_1, address); -+ address += 4; -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_read); -+ -+int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length) -+{ -+ int i; -+ -+ for (i = 0; i < length; i += 4) { -+ SAA716x_EPWR(PHI_0, PHI_0_0_RW_0, *((u32 *) &data[i])); -+ } -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_phi_write_fifo); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_phi.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_phi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi.h 2013-01-16 10:41:10.924798189 +0100 -@@ -0,0 +1,39 @@ -+#ifndef __SAA716x_PHI_H -+#define __SAA716x_PHI_H -+ -+/* PHI SLAVE */ -+#define PHI_SLAVE_0 0 -+#define PHI_SLAVE_1 1 -+#define PHI_SLAVE_2 2 -+#define PHI_SLAVE_3 3 -+#define PHI_SLAVE_4 4 -+#define PHI_SLAVE_5 5 -+#define PHI_SLAVE_6 6 -+#define PHI_SLAVE_7 7 -+ -+/* PHI_REG */ -+#define PHI_MODE 0 -+#define PHI_CONFIG_0 1 -+#define PHI_CONFIG_1 2 -+#define PHI_CONFIG_2 3 -+#define PHI_CONFIG_3 4 -+#define PHI_CONFIG_4 5 -+#define PHI_CONFIG_5 6 -+#define PHI_CONFIG_6 7 -+#define PHI_CONFIG_7 8 -+ -+#define PHI_0_BASE 0x1000 -+#define PHI_0_APERTURE 0x0800 -+ -+#define PHI_1_BASE 0x0000 -+#define PHI_1_APERTURE 0xfffc -+ -+struct saa716x_dev; -+ -+extern int saa716x_init_phi(struct saa716x_dev *saa716x, u32 port, u8 slave); -+extern int saa716x_phi_init(struct saa716x_dev *saa716x); -+extern int saa716x_phi_write(struct saa716x_dev *saa716x, u32 address, const u8 *data, int length); -+extern int saa716x_phi_read(struct saa716x_dev *saa716x, u32 address, u8 *data, int length); -+extern int saa716x_phi_write_fifo(struct saa716x_dev *saa716x, const u8 * data, int length); -+ -+#endif /* __SAA716x_PHI_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_phi_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_phi_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_phi_reg.h 2013-01-16 10:41:10.925798182 +0100 -@@ -0,0 +1,100 @@ -+#ifndef __SAA716x_PHI_REG_H -+#define __SAA716x_PHI_REG_H -+ -+/* -------------- PHI_0 Registers -------------- */ -+ -+#define PHI_0_MODE 0x0000 -+#define PHI_0_0_CONFIG 0x0008 -+#define PHI_0_1_CONFIG 0x000c -+#define PHI_0_2_CONFIG 0x0010 -+#define PHI_0_3_CONFIG 0x0014 -+ -+#define PHI_POLARITY 0x0038 -+#define PHI_TIMEOUT 0x003c -+#define PHI_SW_RST 0x0ff0 -+ -+#define PHI_0_0_RW_0 0x1000 -+#define PHI_0_0_RW_511 0x17fc -+ -+#define PHI_0_1_RW_0 0x1800 -+#define PHI_0_1_RW_511 0x1ffc -+ -+#define PHI_0_2_RW_0 0x2000 -+#define PHI_0_2_RW_511 0x27fc -+ -+#define PHI_0_3_RW_0 0x2800 -+#define PHI_0_3_RW_511 0x2ffc -+ -+#define PHI_CSN_DEASSERT (0x00000001 << 2) -+#define PHI_AUTO_INCREMENT (0x00000001 << 1) -+#define PHI_FIFO_MODE (0x00000001 << 0) -+ -+#define PHI_DELAY_RD_WR (0x0000001f << 27) -+#define PHI_EXTEND_RDY3 (0x00000003 << 25) -+#define PHI_EXTEND_RDY2 (0x00000003 << 23) -+#define PHI_EXTEND_RDY1 (0x00000003 << 21) -+#define PHI_EXTEND_RDY0 (0x00000003 << 19) -+#define PHI_RDY3_OD (0x00000001 << 18) -+#define PHI_RDY2_OD (0x00000001 << 17) -+#define PHI_RDY1_OD (0x00000001 << 16) -+#define PHI_RDY0_OD (0x00000001 << 15) -+#define PHI_ALE_POL (0x00000001 << 14) -+#define PHI_WRN_POL (0x00000001 << 13) -+#define PHI_RDN_POL (0x00000001 << 12) -+#define PHI_RDY3_POL (0x00000001 << 11) -+#define PHI_RDY2_POL (0x00000001 << 10) -+#define PHI_RDY1_POL (0x00000001 << 9) -+#define PHI_RDY0_POL (0x00000001 << 8) -+#define PHI_CSN7_POL (0x00000001 << 7) -+#define PHI_CSN6_POL (0x00000001 << 6) -+#define PHI_CSN5_POL (0x00000001 << 5) -+#define PHI_CSN4_POL (0x00000001 << 4) -+#define PHI_CSN3_POL (0x00000001 << 3) -+#define PHI_CSN2_POL (0x00000001 << 2) -+#define PHI_CSN1_POL (0x00000001 << 1) -+#define PHI_CSN0_POL (0x00000001 << 0) -+ -+/* -------------- PHI_1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+#define PHI_1_MODE 0x00004 -+#define PHI_1_0_CONFIG 0x00018 -+#define PHI_1_1_CONFIG 0x0001c -+#define PHI_1_2_CONFIG 0x00020 -+#define PHI_1_3_CONFIG 0x00024 -+#define PHI_1_4_CONFIG 0x00028 -+#define PHI_1_5_CONFIG 0x0002c -+#define PHI_1_6_CONFIG 0x00030 -+#define PHI_1_7_CONFIG 0x00034 -+ -+#define PHI_1_0_RW_0 0x00000 -+#define PHI_1_0_RW_16383 0x0fffc -+ -+#define PHI_1_1_RW_0 0x1000 -+#define PHI_1_1_RW_16383 0x1ffc -+ -+#define PHI_1_2_RW_0 0x2000 -+#define PHI_1_2_RW_16383 0x2ffc -+ -+#define PHI_1_3_RW_0 0x3000 -+#define PHI_1_3_RW_16383 0x3ffc -+ -+#define PHI_1_4_RW_0 0x4000 -+#define PHI_1_4_RW_16383 0x4ffc -+ -+#define PHI_1_5_RW_0 0x5000 -+#define PHI_1_5_RW_16383 0x5ffc -+ -+#define PHI_1_6_RW_0 0x6000 -+#define PHI_1_6_RW_16383 0x6ffc -+ -+#define PHI_1_7_RW_0 0x7000 -+#define PHI_1_7_RW_16383 0x7ffc -+ -+ -+/* BAR = 20 bits */ -+/* -------------- PHI1 Registers -------------- */ -+ -+ -+#endif /* __SAA716x_PHI_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_priv.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_priv.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_priv.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_priv.h 2013-01-16 10:41:10.925798182 +0100 -@@ -0,0 +1,194 @@ -+#ifndef __SAA716x_PRIV_H -+#define __SAA716x_PRIV_H -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include "saa716x_i2c.h" -+#include "saa716x_boot.h" -+#include "saa716x_cgu.h" -+#include "saa716x_dma.h" -+#include "saa716x_fgpi.h" -+ -+#include "dvbdev.h" -+#include "dvb_demux.h" -+#include "dmxdev.h" -+#include "dvb_frontend.h" -+#include "dvb_net.h" -+ -+#define SAA716x_ERROR 0 -+#define SAA716x_NOTICE 1 -+#define SAA716x_INFO 2 -+#define SAA716x_DEBUG 3 -+ -+#define SAA716x_DEV (saa716x)->num -+#define SAA716x_VERBOSE (saa716x)->verbose -+#define SAA716x_MAX_ADAPTERS 4 -+ -+#define dprintk(__x, __y, __fmt, __arg...) do { \ -+ if (__y) { \ -+ if ((SAA716x_VERBOSE > SAA716x_ERROR) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_ERR "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_NOTICE) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_NOTICE "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_INFO) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_INFO "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ else if ((SAA716x_VERBOSE > SAA716x_DEBUG) && (SAA716x_VERBOSE > __x)) \ -+ printk(KERN_DEBUG "%s (%d): " __fmt "\n" , __func__ , SAA716x_DEV , ##__arg); \ -+ } else { \ -+ if (SAA716x_VERBOSE > __x) \ -+ printk(__fmt , ##__arg); \ -+ } \ -+} while(0) -+ -+ -+#define NXP_SEMICONDUCTOR 0x1131 -+#define SAA7160 0x7160 -+#define SAA7161 0x7161 -+#define SAA7162 0x7162 -+ -+#define NXP_REFERENCE_BOARD 0x1131 -+ -+#define MAKE_ENTRY(__subven, __subdev, __chip, __configptr) { \ -+ .vendor = NXP_SEMICONDUCTOR, \ -+ .device = (__chip), \ -+ .subvendor = (__subven), \ -+ .subdevice = (__subdev), \ -+ .driver_data = (unsigned long) (__configptr) \ -+} -+ -+#define SAA716x_EPWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) -+#define SAA716x_EPRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) -+ -+#define SAA716x_RCWR(__offst, __addr, __data) writel((__data), (saa716x->mmio + (__offst + __addr))) -+#define SAA716x_RCRD(__offst, __addr) readl((saa716x->mmio + (__offst + __addr))) -+ -+ -+#define SAA716x_MSI_MAX_VECTORS 16 -+ -+struct saa716x_msix_entry { -+ int vector; -+ u8 desc[32]; -+ irqreturn_t (*handler)(int irq, void *dev_id); -+}; -+ -+struct saa716x_dev; -+struct saa716x_adapter; -+struct saa716x_spi_config; -+ -+struct saa716x_adap_config { -+ u32 ts_port; -+ void (*worker)(unsigned long); -+}; -+ -+struct saa716x_config { -+ char *model_name; -+ char *dev_type; -+ -+ enum saa716x_boot_mode boot_mode; -+ -+ int adapters; -+ int frontends; -+ -+ int (*frontend_attach)(struct saa716x_adapter *adapter, int count); -+ irqreturn_t (*irq_handler)(int irq, void *dev_id); -+ -+ struct saa716x_adap_config adap_config[SAA716x_MAX_ADAPTERS]; -+ enum saa716x_i2c_rate i2c_rate; -+ enum saa716x_i2c_mode i2c_mode; -+}; -+ -+struct saa716x_adapter { -+ struct dvb_adapter dvb_adapter; -+ struct dvb_frontend *fe; -+ struct dvb_demux demux; -+ struct dmxdev dmxdev; -+ struct dmx_frontend fe_hw; -+ struct dmx_frontend fe_mem; -+ struct dvb_net dvb_net; -+ -+ struct saa716x_dev *saa716x; -+ -+ u8 feeds; -+ u8 count; -+}; -+ -+struct saa716x_dev { -+ struct saa716x_config *config; -+ struct pci_dev *pdev; -+ -+ int num; /* device count */ -+ int verbose; -+ -+ u8 revision; -+ -+ /* PCI */ -+ void __iomem *mmio; -+ -+#define MODE_INTA 0 -+#define MODE_MSI 1 -+#define MODE_MSI_X 2 -+ u8 int_type; -+ -+ struct msix_entry msix_entries[SAA716x_MSI_MAX_VECTORS]; -+ struct saa716x_msix_entry saa716x_msix_handler[56]; -+ u8 handlers; /* no. of active handlers */ -+ -+ /* I2C */ -+ struct saa716x_i2c i2c[2]; -+ u32 i2c_rate; /* init time */ -+ u32 I2C_DEV[2]; -+ -+ struct saa716x_spi_state *saa716x_spi; -+ struct saa716x_spi_config spi_config; -+ -+ struct saa716x_adapter saa716x_adap[SAA716x_MAX_ADAPTERS]; -+ struct mutex adap_lock; -+ struct saa716x_cgu cgu; -+ -+ spinlock_t gpio_lock; -+ /* DMA */ -+ -+ struct saa716x_fgpi_stream_port fgpi[4]; -+ -+ u32 id_offst; -+ u32 id_len; -+ void *priv; -+ -+ /* remote control */ -+ void *ir_priv; -+}; -+ -+/* PCI */ -+extern int saa716x_pci_init(struct saa716x_dev *saa716x); -+extern void saa716x_pci_exit(struct saa716x_dev *saa716x); -+ -+/* MSI */ -+extern int saa716x_msi_init(struct saa716x_dev *saa716x); -+extern void saa716x_msi_exit(struct saa716x_dev *saa716x); -+extern void saa716x_msiint_disable(struct saa716x_dev *saa716x); -+ -+/* DMA */ -+extern int saa716x_dma_init(struct saa716x_dev *saa716x); -+extern void saa716x_dma_exit(struct saa716x_dev *saa716x); -+ -+/* AUDIO */ -+extern int saa716x_audio_init(struct saa716x_dev *saa716x); -+extern void saa716x_audio_exit(struct saa716x_dev *saa716x); -+ -+/* Boot */ -+extern int saa716x_core_boot(struct saa716x_dev *saa716x); -+extern int saa716x_jetpack_init(struct saa716x_dev *saa716x); -+ -+/* Remote control */ -+extern int saa716x_ir_init(struct saa716x_dev *saa716x); -+extern void saa716x_ir_exit(struct saa716x_dev *saa716x); -+extern void saa716x_ir_handler(struct saa716x_dev *saa716x, u32 ir_cmd); -+ -+#endif /* __SAA716x_PRIV_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_reg.h 2013-01-16 10:41:10.925798182 +0100 -@@ -0,0 +1,1279 @@ -+#ifndef __SAA716x_REG_H -+#define __SAA716x_REG_H -+ -+/* BAR = 17 bits */ -+/* -+ VI0 0x00000000 -+ VI1 0x00001000 -+ FGPI0 0x00002000 -+ FGPI1 0x00003000 -+ FGPI2 0x00004000 -+ FGPI3 0x00005000 -+ AI0 0x00006000 -+ AI1 0x00007000 -+ BAM 0x00008000 -+ MMU 0x00009000 -+ MSI 0x0000a000 -+ I2C_B 0x0000b000 -+ I2C_A 0x0000c000 -+ SPI 0x0000d000 -+ GPIO 0x0000e000 -+ PHI_0 0x0000f000 -+ CGU 0x00013000 -+ DCS 0x00014000 -+ GREG 0x00012000 -+ -+ PHI_1 0x00020000 -+*/ -+ -+/* -------------- VIP Registers -------------- */ -+ -+#define VI0 0x00000000 -+#define VI1 0x00001000 -+ -+#define VI_MODE 0x000 -+#define VID_CFEN (0x00000003 << 30) -+#define VID_OSM (0x00000001 << 29) -+#define VID_FSEQ (0x00000001 << 28) -+#define AUX_CFEN (0x00000003 << 26) -+#define AUX_OSM (0x00000001 << 25) -+#define AUX_FSEQ (0x00000001 << 24) -+#define AUX_ANC_DATA (0x00000003 << 22) -+#define AUX_ANC_RAW (0x00000001 << 21) -+#define RST_ON_ERR (0x00000001 << 17) -+#define SOFT_RESET (0x00000001 << 16) -+#define IFF_CLAMP (0x00000001 << 14) -+#define IFF_MODE (0x00000003 << 12) -+#define DFF_CLAMP (0x00000001 << 10) -+#define DFF_MODE (0x00000003 << 8) -+#define HSP_CLAMP (0x00000001 << 3) -+#define HSP_RGB (0x00000001 << 2) -+#define HSP_MODE (0x00000003 << 0) -+ -+#define RCRB_CTRL 0x004 -+#define RCRB_CFG_ADDR 0x008 -+#define RCRB_CFG_EXT_ADDR 0x00c -+#define RCRB_IO_ADDR 0x010 -+#define RCRB_MEM_LADDR 0x014 -+#define RCRB_MEM_UADDR 0x018 -+#define RCRB_DATA 0x01c -+#define RCRB_MASK 0x020 -+#define RCRB_MSG_HDR 0x040 -+#define RCRB_MSG_PL0 0x044 -+#define RCRB_MSG_PL1 0x048 -+ -+#define ID_MASK0 0x020 -+#define VI_ID_MASK_0 (0x000000ff << 8) -+#define VI_DATA_ID_0 (0x000000ff << 0) -+ -+#define ID_MASK1 0x024 -+#define VI_ID_MASK_1 (0x000000ff << 8) -+#define VI_DATA_ID_1 (0x000000ff << 0) -+ -+#define VIP_LINE_THRESH 0x040 -+#define VI_LCTHR (0x000007ff << 0) -+ -+#define VIN_FORMAT 0x100 -+#define VI_VSRA (0x00000003 << 30) -+#define VI_SYNCHD (0x00000001 << 25) -+#define VI_DUAL_STREAM (0x00000001 << 24) -+#define VI_NHDAUX (0x00000001 << 20) -+#define VI_NPAR (0x00000001 << 19) -+#define VI_VSEL (0x00000003 << 14) -+#define VI_TWOS (0x00000001 << 13) -+#define VI_TPG (0x00000001 << 12) -+#define VI_FREF (0x00000001 << 10) -+#define VI_FTGL (0x00000001 << 9) -+#define VI_SF (0x00000001 << 3) -+#define VI_FZERO (0x00000001 << 2) -+#define VI_REVS (0x00000001 << 1) -+#define VI_REHS (0x00000001 << 0) -+ -+#define TC76543210 0x800 -+#define TCFEDCBA98 0x804 -+#define PHYCFG 0x900 -+#define CONFIG 0xfd4 -+#define INT_ENABLE_CLR 0xfd8 -+#define INT_ENABLE_SET 0xfdc -+ -+ -+#define INT_STATUS 0xfe0 -+#define VI_STAT_FID_AUX (0x00000001 << 31) -+#define VI_STAT_FID_VID (0x00000001 << 30) -+#define VI_STAT_FID_VPI (0x00000001 << 29) -+#define VI_STAT_LINE_COUNT (0x00000fff << 16) -+#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) -+#define VI_STAT_VID_OVRFLW (0x00000001 << 8) -+#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) -+#define VI_STAT_FID_SEQBRK (0x00000001 << 6) -+#define VI_STAT_LINE_THRESH (0x00000001 << 5) -+#define VI_STAT_AUX_WRAP (0x00000001 << 4) -+#define VI_STAT_AUX_START_IN (0x00000001 << 3) -+#define VI_STAT_AUX_END_OUT (0x00000001 << 2) -+#define VI_STAT_VID_START_IN (0x00000001 << 1) -+#define VI_STAT_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) -+#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) -+#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) -+#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) -+#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) -+#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) -+#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) -+#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) -+#define VI_ENABLE_VID_START_IN (0x00000001 << 1) -+#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define VIP_POWER_DOWN 0xff4 -+#define VI_PWR_DWN (0x00000001 << 31) -+ -+ -+ -+ -+/* -------------- FGPI Registers -------------- */ -+ -+#define FGPI0 0x00002000 -+#define FGPI1 0x00003000 -+#define FGPI2 0x00004000 -+#define FGPI3 0x00005000 -+ -+#define FGPI_CONTROL 0x000 -+#define FGPI_CAPTURE_ENABLE_2 (0x00000001 << 13) -+#define FGPI_CAPTURE_ENABLE_1 (0x00000001 << 12) -+#define FGPI_MODE (0x00000001 << 11) -+#define FGPI_SAMPLE_SIZE (0x00000003 << 8) -+#define FGPI_BUF_SYNC_MSG_STOP (0x00000003 << 5) -+#define FGPI_REC_START_MSG_START (0x00000003 << 2) -+#define FGPI_TSTAMP_SELECT (0x00000001 << 1) -+#define FGPI_VAR_LENGTH (0x00000001 << 0) -+ -+#define FGPI_BASE_1 0x004 -+#define FGPI_BASE_2 0x008 -+#define FGPI_SIZE 0x00c -+#define FGPI_REC_SIZE 0x010 -+#define FGPI_STRIDE 0x014 -+#define FGPI_NUM_RECORD_1 0x018 -+#define FGPI_NUM_RECORD_2 0x01c -+#define FGPI_THRESHOLD_1 0x020 -+#define FGPI_THRESHOLD_2 0x024 -+#define FGPI_D1_XY_START 0x028 -+#define FGPI_D1_XY_END 0x02c -+ -+#define INT_STATUS 0xfe0 -+#define FGPI_BUF1_ACTIVE (0x00000001 << 7) -+#define FGPI_OVERFLOW (0x00000001 << 6) -+#define FGPI_MBE (0x00000001 << 5) -+#define FGPI_UNDERRUN (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED (0x00000001 << 2) -+#define FGPI_BUF2_FULL (0x00000001 << 1) -+#define FGPI_BUF1_FULL (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define FGPI_OVERFLOW_ENA (0x00000001 << 6) -+#define FGPI_MBE_ENA (0x00000001 << 5) -+#define FGPI_UNDERRUN_ENA (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ENA (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ENA (0x00000001 << 2) -+#define FGPI_BUF2_FULL_ENA (0x00000001 << 1) -+#define FGPI_BUF1_FULL_ENA (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define FGPI_OVERFLOW_ACK (0x00000001 << 6) -+#define FGPI_MBE_ACK (0x00000001 << 5) -+#define FGPI_UNDERRUN_ACK (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_ACK (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_ACK (0x00000001 << 2) -+#define FGPI_BUF2_DONE_ACK (0x00000001 << 1) -+#define FGPI_BUF1_DONE_ACK (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define FGPI_OVERFLOW_SET (0x00000001 << 6) -+#define FGPI_MBE_SET (0x00000001 << 5) -+#define FGPI_UNDERRUN_SET (0x00000001 << 4) -+#define FGPI_THRESH2_REACHED_SET (0x00000001 << 3) -+#define FGPI_THRESH1_REACHED_SET (0x00000001 << 2) -+#define FGPI_BUF2_DONE_SET (0x00000001 << 1) -+#define FGPI_BUF1_DONE_SET (0x00000001 << 0) -+ -+#define FGPI_SOFT_RESET 0xff0 -+#define FGPI_SOFTWARE_RESET (0x00000001 << 0) -+ -+#define FGPI_INTERFACE 0xff4 -+#define FGPI_DISABLE_BUS_IF (0x00000001 << 0) -+ -+#define FGPI_MOD_ID_EXT 0xff8 -+#define FGPI_MODULE_ID 0xffc -+ -+ -+/* -------------- AI Registers ---------------- */ -+ -+#define AI0 0x00006000 -+#define AI1 0x00007000 -+ -+#define AI_STATUS 0x000 -+#define AI_BUF1_ACTIVE (0x00000001 << 4) -+#define AI_OVERRUN (0x00000001 << 3) -+#define AI_HBE (0x00000001 << 2) -+#define AI_BUF2_FULL (0x00000001 << 1) -+#define AI_BUF1_FULL (0x00000001 << 0) -+ -+#define AI_CTL 0x004 -+#define AI_RESET (0x00000001 << 31) -+#define AI_CAP_ENABLE (0x00000001 << 30) -+#define AI_CAP_MODE (0x00000003 << 28) -+#define AI_SIGN_CONVERT (0x00000001 << 27) -+#define AI_EARLYMODE (0x00000001 << 26) -+#define AI_DIAGMODE (0x00000001 << 25) -+#define AI_RAWMODE (0x00000001 << 24) -+#define AI_OVR_INTEN (0x00000001 << 7) -+#define AI_HBE_INTEN (0x00000001 << 6) -+#define AI_BUF2_INTEN (0x00000001 << 5) -+#define AI_BUF1_INTEN (0x00000001 << 4) -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_SERIAL 0x008 -+#define AI_SER_MASTER (0x00000001 << 31) -+#define AI_DATAMODE (0x00000001 << 30) -+#define AI_FRAMEMODE (0x00000003 << 28) -+#define AI_CLOCK_EDGE (0x00000001 << 27) -+#define AI_SSPOS4 (0x00000001 << 19) -+#define AI_NR_CHAN (0x00000003 << 17) -+#define AI_WSDIV (0x000001ff << 8) -+#define AI_SCKDIV (0x000000ff << 0) -+ -+#define AI_FRAMING 0x00c -+#define AI_VALIDPOS (0x000001ff << 22) -+#define AI_LEFTPOS (0x000001ff << 13) -+#define AI_RIGHTPOS (0x000001ff << 4) -+#define AI_SSPOS_3_0 (0x0000000f << 0) -+ -+#define AI_BASE1 0x014 -+#define AI_BASE2 0x018 -+#define AI_BASE (0x03ffffff << 6) -+ -+#define AI_SIZE 0x01c -+#define AI_SAMPLE_SIZE (0x03ffffff << 6) -+ -+#define AI_INT_ACK 0x020 -+#define AI_ACK_OVR (0x00000001 << 3) -+#define AI_ACK_HBE (0x00000001 << 2) -+#define AI_ACK2 (0x00000001 << 1) -+#define AI_ACK1 (0x00000001 << 0) -+ -+#define AI_PWR_DOWN 0xff4 -+#define AI_PWR_DWN (0x00000001 << 0) -+ -+/* -------------- BAM Registers -------------- */ -+ -+#define BAM 0x00008000 -+ -+#define BAM_VI0_0_DMA_BUF_MODE 0x000 -+ -+#define BAM_VI0_0_ADDR_OFFST_0 0x004 -+#define BAM_VI0_0_ADDR_OFFST_1 0x008 -+#define BAM_VI0_0_ADDR_OFFST_2 0x00c -+#define BAM_VI0_0_ADDR_OFFST_3 0x010 -+#define BAM_VI0_0_ADDR_OFFST_4 0x014 -+#define BAM_VI0_0_ADDR_OFFST_5 0x018 -+#define BAM_VI0_0_ADDR_OFFST_6 0x01c -+#define BAM_VI0_0_ADDR_OFFST_7 0x020 -+ -+#define BAM_VI0_1_DMA_BUF_MODE 0x024 -+#define BAM_VI0_1_ADDR_OFFST_0 0x028 -+#define BAM_VI0_1_ADDR_OFFST_1 0x02c -+#define BAM_VI0_1_ADDR_OFFST_2 0x030 -+#define BAM_VI0_1_ADDR_OFFST_3 0x034 -+#define BAM_VI0_1_ADDR_OFFST_4 0x038 -+#define BAM_VI0_1_ADDR_OFFST_5 0x03c -+#define BAM_VI0_1_ADDR_OFFST_6 0x040 -+#define BAM_VI0_1_ADDR_OFFST_7 0x044 -+ -+#define BAM_VI0_2_DMA_BUF_MODE 0x048 -+#define BAM_VI0_2_ADDR_OFFST_0 0x04c -+#define BAM_VI0_2_ADDR_OFFST_1 0x050 -+#define BAM_VI0_2_ADDR_OFFST_2 0x054 -+#define BAM_VI0_2_ADDR_OFFST_3 0x058 -+#define BAM_VI0_2_ADDR_OFFST_4 0x05c -+#define BAM_VI0_2_ADDR_OFFST_5 0x060 -+#define BAM_VI0_2_ADDR_OFFST_6 0x064 -+#define BAM_VI0_2_ADDR_OFFST_7 0x068 -+ -+ -+#define BAM_VI1_0_DMA_BUF_MODE 0x06c -+#define BAM_VI1_0_ADDR_OFFST_0 0x070 -+#define BAM_VI1_0_ADDR_OFFST_1 0x074 -+#define BAM_VI1_0_ADDR_OFFST_2 0x078 -+#define BAM_VI1_0_ADDR_OFFST_3 0x07c -+#define BAM_VI1_0_ADDR_OFFST_4 0x080 -+#define BAM_VI1_0_ADDR_OFFST_5 0x084 -+#define BAM_VI1_0_ADDR_OFFST_6 0x088 -+#define BAM_VI1_0_ADDR_OFFST_7 0x08c -+ -+#define BAM_VI1_1_DMA_BUF_MODE 0x090 -+#define BAM_VI1_1_ADDR_OFFST_0 0x094 -+#define BAM_VI1_1_ADDR_OFFST_1 0x098 -+#define BAM_VI1_1_ADDR_OFFST_2 0x09c -+#define BAM_VI1_1_ADDR_OFFST_3 0x0a0 -+#define BAM_VI1_1_ADDR_OFFST_4 0x0a4 -+#define BAM_VI1_1_ADDR_OFFST_5 0x0a8 -+#define BAM_VI1_1_ADDR_OFFST_6 0x0ac -+#define BAM_VI1_1_ADDR_OFFST_7 0x0b0 -+ -+#define BAM_VI1_2_DMA_BUF_MODE 0x0b4 -+#define BAM_VI1_2_ADDR_OFFST_0 0x0b8 -+#define BAM_VI1_2_ADDR_OFFST_1 0x0bc -+#define BAM_VI1_2_ADDR_OFFST_2 0x0c0 -+#define BAM_VI1_2_ADDR_OFFST_3 0x0c4 -+#define BAM_VI1_2_ADDR_OFFST_4 0x0c8 -+#define BAM_VI1_2_ADDR_OFFST_5 0x0cc -+#define BAM_VI1_2_ADDR_OFFST_6 0x0d0 -+#define BAM_VI1_2_ADDR_OFFST_7 0x0d4 -+ -+ -+#define BAM_FGPI0_DMA_BUF_MODE 0x0d8 -+#define BAM_FGPI0_ADDR_OFFST_0 0x0dc -+#define BAM_FGPI0_ADDR_OFFST_1 0x0e0 -+#define BAM_FGPI0_ADDR_OFFST_2 0x0e4 -+#define BAM_FGPI0_ADDR_OFFST_3 0x0e8 -+#define BAM_FGPI0_ADDR_OFFST_4 0x0ec -+#define BAM_FGPI0_ADDR_OFFST_5 0x0f0 -+#define BAM_FGPI0_ADDR_OFFST_6 0x0f4 -+#define BAM_FGPI0_ADDR_OFFST_7 0x0f8 -+ -+#define BAM_FGPI1_DMA_BUF_MODE 0x0fc -+#define BAM_FGPI1_ADDR_OFFST_0 0x100 -+#define BAM_FGPI1_ADDR_OFFST_1 0x104 -+#define BAM_FGPI1_ADDR_OFFST_2 0x108 -+#define BAM_FGPI1_ADDR_OFFST_3 0x10c -+#define BAM_FGPI1_ADDR_OFFST_4 0x110 -+#define BAM_FGPI1_ADDR_OFFST_5 0x114 -+#define BAM_FGPI1_ADDR_OFFST_6 0x118 -+#define BAM_FGPI1_ADDR_OFFST_7 0x11c -+ -+#define BAM_FGPI2_DMA_BUF_MODE 0x120 -+#define BAM_FGPI2_ADDR_OFFST_0 0x124 -+#define BAM_FGPI2_ADDR_OFFST_1 0x128 -+#define BAM_FGPI2_ADDR_OFFST_2 0x12c -+#define BAM_FGPI2_ADDR_OFFST_3 0x130 -+#define BAM_FGPI2_ADDR_OFFST_4 0x134 -+#define BAM_FGPI2_ADDR_OFFST_5 0x138 -+#define BAM_FGPI2_ADDR_OFFST_6 0x13c -+#define BAM_FGPI2_ADDR_OFFST_7 0x140 -+ -+#define BAM_FGPI3_DMA_BUF_MODE 0x144 -+#define BAM_FGPI3_ADDR_OFFST_0 0x148 -+#define BAM_FGPI3_ADDR_OFFST_1 0x14c -+#define BAM_FGPI3_ADDR_OFFST_2 0x150 -+#define BAM_FGPI3_ADDR_OFFST_3 0x154 -+#define BAM_FGPI3_ADDR_OFFST_4 0x158 -+#define BAM_FGPI3_ADDR_OFFST_5 0x15c -+#define BAM_FGPI3_ADDR_OFFST_6 0x160 -+#define BAM_FGPI3_ADDR_OFFST_7 0x164 -+ -+ -+#define BAM_AI0_DMA_BUF_MODE 0x168 -+#define BAM_AI0_ADDR_OFFST_0 0x16c -+#define BAM_AI0_ADDR_OFFST_1 0x170 -+#define BAM_AI0_ADDR_OFFST_2 0x174 -+#define BAM_AI0_ADDR_OFFST_3 0x178 -+#define BAM_AI0_ADDR_OFFST_4 0x17c -+#define BAM_AIO_ADDR_OFFST_5 0x180 -+#define BAM_AI0_ADDR_OFFST_6 0x184 -+#define BAM_AIO_ADDR_OFFST_7 0x188 -+ -+#define BAM_AI1_DMA_BUF_MODE 0x18c -+#define BAM_AI1_ADDR_OFFST_0 0x190 -+#define BAM_AI1_ADDR_OFFST_1 0x194 -+#define BAM_AI1_ADDR_OFFST_2 0x198 -+#define BAM_AI1_ADDR_OFFST_3 0x19c -+#define BAM_AI1_ADDR_OFFST_4 0x1a0 -+#define BAM_AI1_ADDR_OFFST_5 0x1a4 -+#define BAM_AI1_ADDR_OFFST_6 0x1a8 -+#define BAM_AI1_ADDR_OFFST_7 0x1ac -+ -+#define BAM_SW_RST 0xff0 -+#define BAM_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+ -+/* -------------- MMU Registers -------------- */ -+ -+#define MMU 0x00009000 -+ -+#define MMU_MODE 0x000 -+ -+#define MMU_DMA_CONFIG0 0x004 -+#define MMU_DMA_CONFIG1 0x008 -+#define MMU_DMA_CONFIG2 0x00c -+#define MMU_DMA_CONFIG3 0x010 -+#define MMU_DMA_CONFIG4 0x014 -+#define MMU_DMA_CONFIG5 0x018 -+#define MMU_DMA_CONFIG6 0x01c -+#define MMU_DMA_CONFIG7 0x020 -+#define MMU_DMA_CONFIG8 0x024 -+#define MMU_DMA_CONFIG9 0x028 -+#define MMU_DMA_CONFIG10 0x02c -+#define MMU_DMA_CONFIG11 0x030 -+#define MMU_DMA_CONFIG12 0x034 -+#define MMU_DMA_CONFIG13 0x038 -+#define MMU_DMA_CONFIG14 0x03c -+#define MMU_DMA_CONFIG15 0x040 -+ -+#define MMU_SW_RST 0xff0 -+#define MMU_SW_RESET (0x0001 << 0) -+ -+#define MMU_PTA_BASE0 0x044 /* DMA 0 */ -+#define MMU_PTA_BASE1 0x084 /* DMA 1 */ -+#define MMU_PTA_BASE2 0x0c4 /* DMA 2 */ -+#define MMU_PTA_BASE3 0x104 /* DMA 3 */ -+#define MMU_PTA_BASE4 0x144 /* DMA 4 */ -+#define MMU_PTA_BASE5 0x184 /* DMA 5 */ -+#define MMU_PTA_BASE6 0x1c4 /* DMA 6 */ -+#define MMU_PTA_BASE7 0x204 /* DMA 7 */ -+#define MMU_PTA_BASE8 0x244 /* DMA 8 */ -+#define MMU_PTA_BASE9 0x284 /* DMA 9 */ -+#define MMU_PTA_BASE10 0x2c4 /* DMA 10 */ -+#define MMU_PTA_BASE11 0x304 /* DMA 11 */ -+#define MMU_PTA_BASE12 0x344 /* DMA 12 */ -+#define MMU_PTA_BASE13 0x384 /* DMA 13 */ -+#define MMU_PTA_BASE14 0x3c4 /* DMA 14 */ -+#define MMU_PTA_BASE15 0x404 /* DMA 15 */ -+ -+#define MMU_PTA_BASE 0x044 /* DMA 0 */ -+#define MMU_PTA_OFFSET 0x40 -+ -+#define PTA_BASE(__ch) (MMU_PTA_BASE + (MMU_PTA_OFFSET * __ch)) -+ -+#define MMU_PTA0_LSB(__ch) PTA_BASE(__ch) + 0x00 -+#define MMU_PTA0_MSB(__ch) PTA_BASE(__ch) + 0x04 -+#define MMU_PTA1_LSB(__ch) PTA_BASE(__ch) + 0x08 -+#define MMU_PTA1_MSB(__ch) PTA_BASE(__ch) + 0x0c -+#define MMU_PTA2_LSB(__ch) PTA_BASE(__ch) + 0x10 -+#define MMU_PTA2_MSB(__ch) PTA_BASE(__ch) + 0x14 -+#define MMU_PTA3_LSB(__ch) PTA_BASE(__ch) + 0x18 -+#define MMU_PTA3_MSB(__ch) PTA_BASE(__ch) + 0x1c -+#define MMU_PTA4_LSB(__ch) PTA_BASE(__ch) + 0x20 -+#define MMU_PTA4_MSB(__ch) PTA_BASE(__ch) + 0x24 -+#define MMU_PTA5_LSB(__ch) PTA_BASE(__ch) + 0x28 -+#define MMU_PTA5_MSB(__ch) PTA_BASE(__ch) + 0x2c -+#define MMU_PTA6_LSB(__ch) PTA_BASE(__ch) + 0x30 -+#define MMU_PTA6_MSB(__ch) PTA_BASE(__ch) + 0x34 -+#define MMU_PTA7_LSB(__ch) PTA_BASE(__ch) + 0x38 -+#define MMU_PTA7_MSB(__ch) PTA_BASE(__ch) + 0x3c -+ -+ -+/* -------------- MSI Registers -------------- */ -+ -+#define MSI 0x0000a000 -+ -+#define MSI_DELAY_TIMER 0x000 -+#define MSI_DELAY_1CLK (0x00000001 << 0) -+#define MSI_DELAY_2CLK (0x00000002 << 0) -+ -+#define MSI_INTA_POLARITY 0x004 -+#define MSI_INTA_POLARITY_HIGH (0x00000001 << 0) -+ -+#define MSI_CONFIG0 0x008 -+#define MSI_CONFIG1 0x00c -+#define MSI_CONFIG2 0x010 -+#define MSI_CONFIG3 0x014 -+#define MSI_CONFIG4 0x018 -+#define MSI_CONFIG5 0x01c -+#define MSI_CONFIG6 0x020 -+#define MSI_CONFIG7 0x024 -+#define MSI_CONFIG8 0x028 -+#define MSI_CONFIG9 0x02c -+#define MSI_CONFIG10 0x030 -+#define MSI_CONFIG11 0x034 -+#define MSI_CONFIG12 0x038 -+#define MSI_CONFIG13 0x03c -+#define MSI_CONFIG14 0x040 -+#define MSI_CONFIG15 0x044 -+#define MSI_CONFIG16 0x048 -+#define MSI_CONFIG17 0x04c -+#define MSI_CONFIG18 0x050 -+#define MSI_CONFIG19 0x054 -+#define MSI_CONFIG20 0x058 -+#define MSI_CONFIG21 0x05c -+#define MSI_CONFIG22 0x060 -+#define MSI_CONFIG23 0x064 -+#define MSI_CONFIG24 0x068 -+#define MSI_CONFIG25 0x06c -+#define MSI_CONFIG26 0x070 -+#define MSI_CONFIG27 0x074 -+#define MSI_CONFIG28 0x078 -+#define MSI_CONFIG29 0x07c -+#define MSI_CONFIG30 0x080 -+#define MSI_CONFIG31 0x084 -+#define MSI_CONFIG32 0x088 -+#define MSI_CONFIG33 0x08c -+#define MSI_CONFIG34 0x090 -+#define MSI_CONFIG35 0x094 -+#define MSI_CONFIG36 0x098 -+#define MSI_CONFIG37 0x09c -+#define MSI_CONFIG38 0x0a0 -+#define MSI_CONFIG39 0x0a4 -+#define MSI_CONFIG40 0x0a8 -+#define MSI_CONFIG41 0x0ac -+#define MSI_CONFIG42 0x0b0 -+#define MSI_CONFIG43 0x0b4 -+#define MSI_CONFIG44 0x0b8 -+#define MSI_CONFIG45 0x0bc -+#define MSI_CONFIG46 0x0c0 -+#define MSI_CONFIG47 0x0c4 -+#define MSI_CONFIG48 0x0c8 -+#define MSI_CONFIG49 0x0cc -+#define MSI_CONFIG50 0x0d0 -+ -+#define MSI_INT_POL_EDGE_RISE (0x00000001 << 24) -+#define MSI_INT_POL_EDGE_FALL (0x00000002 << 24) -+#define MSI_INT_POL_EDGE_ANY (0x00000003 << 24) -+#define MSI_TC (0x00000007 << 16) -+#define MSI_ID (0x0000000f << 0) -+ -+#define MSI_INT_STATUS_L 0xfc0 -+#define MSI_INT_TAGACK_VI0_0 (0x00000001 << 0) -+#define MSI_INT_TAGACK_VI0_1 (0x00000001 << 1) -+#define MSI_INT_TAGACK_VI0_2 (0x00000001 << 2) -+#define MSI_INT_TAGACK_VI1_0 (0x00000001 << 3) -+#define MSI_INT_TAGACK_VI1_1 (0x00000001 << 4) -+#define MSI_INT_TAGACK_VI1_2 (0x00000001 << 5) -+#define MSI_INT_TAGACK_FGPI_0 (0x00000001 << 6) -+#define MSI_INT_TAGACK_FGPI_1 (0x00000001 << 7) -+#define MSI_INT_TAGACK_FGPI_2 (0x00000001 << 8) -+#define MSI_INT_TAGACK_FGPI_3 (0x00000001 << 9) -+#define MSI_INT_TAGACK_AI_0 (0x00000001 << 10) -+#define MSI_INT_TAGACK_AI_1 (0x00000001 << 11) -+#define MSI_INT_OVRFLW_VI0_0 (0x00000001 << 12) -+#define MSI_INT_OVRFLW_VI0_1 (0x00000001 << 13) -+#define MSI_INT_OVRFLW_VI0_2 (0x00000001 << 14) -+#define MSI_INT_OVRFLW_VI1_0 (0x00000001 << 15) -+#define MSI_INT_OVRFLW_VI1_1 (0x00000001 << 16) -+#define MSI_INT_OVRFLW_VI1_2 (0x00000001 << 17) -+#define MSI_INT_OVRFLW_FGPI_O (0x00000001 << 18) -+#define MSI_INT_OVRFLW_FGPI_1 (0x00000001 << 19) -+#define MSI_INT_OVRFLW_FGPI_2 (0x00000001 << 20) -+#define MSI_INT_OVRFLW_FGPI_3 (0x00000001 << 21) -+#define MSI_INT_OVRFLW_AI_0 (0x00000001 << 22) -+#define MSI_INT_OVRFLW_AI_1 (0x00000001 << 23) -+#define MSI_INT_AVINT_VI0 (0x00000001 << 24) -+#define MSI_INT_AVINT_VI1 (0x00000001 << 25) -+#define MSI_INT_AVINT_FGPI_0 (0x00000001 << 26) -+#define MSI_INT_AVINT_FGPI_1 (0x00000001 << 27) -+#define MSI_INT_AVINT_FGPI_2 (0x00000001 << 28) -+#define MSI_INT_AVINT_FGPI_3 (0x00000001 << 29) -+#define MSI_INT_AVINT_AI_0 (0x00000001 << 30) -+#define MSI_INT_AVINT_AI_1 (0x00000001 << 31) -+ -+#define MSI_INT_STATUS_H 0xfc4 -+#define MSI_INT_UNMAPD_TC_INT (0x00000001 << 0) -+#define MSI_INT_EXTINT_0 (0x00000001 << 1) -+#define MSI_INT_EXTINT_1 (0x00000001 << 2) -+#define MSI_INT_EXTINT_2 (0x00000001 << 3) -+#define MSI_INT_EXTINT_3 (0x00000001 << 4) -+#define MSI_INT_EXTINT_4 (0x00000001 << 5) -+#define MSI_INT_EXTINT_5 (0x00000001 << 6) -+#define MSI_INT_EXTINT_6 (0x00000001 << 7) -+#define MSI_INT_EXTINT_7 (0x00000001 << 8) -+#define MSI_INT_EXTINT_8 (0x00000001 << 9) -+#define MSI_INT_EXTINT_9 (0x00000001 << 10) -+#define MSI_INT_EXTINT_10 (0x00000001 << 11) -+#define MSI_INT_EXTINT_11 (0x00000001 << 12) -+#define MSI_INT_EXTINT_12 (0x00000001 << 13) -+#define MSI_INT_EXTINT_13 (0x00000001 << 14) -+#define MSI_INT_EXTINT_14 (0x00000001 << 15) -+#define MSI_INT_EXTINT_15 (0x00000001 << 16) -+#define MSI_INT_I2CINT_0 (0x00000001 << 17) -+#define MSI_INT_I2CINT_1 (0x00000001 << 18) -+ -+#define MSI_INT_STATUS_CLR_L 0xfc8 -+#define MSI_INT_STATUS_CLR_H 0xfcc -+#define MSI_INT_STATUS_SET_L 0xfd0 -+#define MSI_INT_STATUS_SET_H 0xfd4 -+#define MSI_INT_ENA_L 0xfd8 -+#define MSI_INT_ENA_H 0xfdc -+#define MSI_INT_ENA_CLR_L 0xfe0 -+#define MSI_INT_ENA_CLR_H 0xfe4 -+#define MSI_INT_ENA_SET_L 0xfe8 -+#define MSI_INT_ENA_SET_H 0xfec -+ -+#define MSI_SW_RST 0xff0 -+#define MSI_SW_RESET (0x0001 << 0) -+ -+#define MSI_MODULE_ID 0xffc -+ -+ -+/* -------------- I2C Registers -------------- */ -+ -+#define I2C_B 0x0000b000 -+#define I2C_A 0x0000c000 -+ -+#define RX_FIFO 0x000 -+#define I2C_RX_BYTE (0x000000ff << 0) -+ -+#define TX_FIFO 0x000 -+#define I2C_STOP_BIT (0x00000001 << 9) -+#define I2C_START_BIT (0x00000001 << 8) -+#define I2C_TX_BYTE (0x000000ff << 0) -+ -+#define I2C_STATUS 0x008 -+#define I2C_TRANSMIT (0x00000001 << 11) -+#define I2C_RECEIVE (0x00000001 << 10) -+#define I2C_TRANSMIT_S_PROG (0x00000001 << 9) -+#define I2C_TRANSMIT_S_CLEAR (0x00000001 << 8) -+#define I2C_TRANSMIT_PROG (0x00000001 << 7) -+#define I2C_TRANSMIT_CLEAR (0x00000001 << 6) -+#define I2C_RECEIVE_PROG (0x00000001 << 5) -+#define I2C_RECEIVE_CLEAR (0x00000001 << 4) -+#define I2C_SDA_LINE (0x00000001 << 3) -+#define I2C_SCL_LINE (0x00000001 << 2) -+#define I2C_START_STOP_FLAG (0x00000001 << 1) -+#define I2C_MODE_STATUS (0x00000001 << 0) -+ -+#define I2C_CONTROL 0x00c -+#define I2C_SCL_CONTROL (0x00000001 << 7) -+#define I2C_SDA_CONTROL (0x00000001 << 6) -+#define I2C_RECEIVE_PROTECT (0x00000001 << 5) -+#define I2C_RECEIVE_PRO_READ (0x00000001 << 4) -+#define I2C_TRANS_SELF_CLEAR (0x00000001 << 3) -+#define I2C_TRANS_S_SELF_CLEAR (0x00000001 << 2) -+#define I2C_SLAVE_ADDR_10BIT (0x00000001 << 1) -+#define I2C_RESET (0x00000001 << 0) -+ -+#define I2C_CLOCK_DIVISOR_HIGH 0x010 -+#define I2C_CLOCK_HIGH (0x0000ffff << 0) -+ -+#define I2C_CLOCK_DIVISOR_LOW 0x014 -+#define I2C_CLOCK_LOW (0x0000ffff << 0) -+ -+#define I2C_RX_LEVEL 0x01c -+#define I2C_RECEIVE_RANGE (0x0000007f << 0) -+ -+#define I2C_TX_LEVEL 0x020 -+#define I2C_TRANSMIT_RANGE (0x0000007f << 0) -+ -+#define I2C_SDA_HOLD 0x028 -+#define I2C_HOLD_TIME (0x0000007f << 0) -+ -+#define MODULE_CONF 0xfd4 -+#define INT_CLR_ENABLE 0xfd8 -+#define I2C_CLR_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_CLR_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_CLR_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_CLR_ENABLE_RFF (0x00000001 << 9) -+#define I2C_CLR_ENABLE_STDR (0x00000001 << 8) -+#define I2C_CLR_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_CLR_ENABLE_IBE (0x00000001 << 6) -+#define I2C_CLR_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_CLR_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_CLR_ENABLE_STSD (0x00000001 << 3) -+#define I2C_CLR_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_CLR_ENABLE_MAF (0x00000001 << 1) -+#define I2C_CLR_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_SET_ENABLE 0xfdc -+#define I2C_SET_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_SET_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_SET_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_SET_ENABLE_RFF (0x00000001 << 9) -+#define I2C_SET_ENABLE_STDR (0x00000001 << 8) -+#define I2C_SET_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_SET_ENABLE_IBE (0x00000001 << 6) -+#define I2C_SET_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_SET_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_SET_ENABLE_STSD (0x00000001 << 3) -+#define I2C_SET_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_SET_ENABLE_MAF (0x00000001 << 1) -+#define I2C_SET_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_STATUS 0xfe0 -+#define I2C_INTERRUPT_STFNF (0x00000001 << 12) -+#define I2C_INTERRUPT_MTFNF (0x00000001 << 11) -+#define I2C_INTERRUPT_RFDA (0x00000001 << 10) -+#define I2C_INTERRUPTE_RFF (0x00000001 << 9) -+#define I2C_SLAVE_INTERRUPT_STDR (0x00000001 << 8) -+#define I2C_MASTER_INTERRUPT_MTDR (0x00000001 << 7) -+#define I2C_ERROR_IBE (0x00000001 << 6) -+#define I2C_MODE_CHANGE_INTER_MSMC (0x00000001 << 5) -+#define I2C_SLAVE_RECEIVE_INTER_SRSD (0x00000001 << 4) -+#define I2C_SLAVE_TRANSMIT_INTER_STSD (0x00000001 << 3) -+#define I2C_ACK_INTER_MTNA (0x00000001 << 2) -+#define I2C_FAILURE_INTER_MAF (0x00000001 << 1) -+#define I2C_INTERRUPT_MTD (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define I2C_ENABLE_STFNF (0x00000001 << 12) -+#define I2C_ENABLE_MTFNF (0x00000001 << 11) -+#define I2C_ENABLE_RFDA (0x00000001 << 10) -+#define I2C_ENABLE_RFF (0x00000001 << 9) -+#define I2C_ENABLE_STDR (0x00000001 << 8) -+#define I2C_ENABLE_MTDR (0x00000001 << 7) -+#define I2C_ENABLE_IBE (0x00000001 << 6) -+#define I2C_ENABLE_MSMC (0x00000001 << 5) -+#define I2C_ENABLE_SRSD (0x00000001 << 4) -+#define I2C_ENABLE_STSD (0x00000001 << 3) -+#define I2C_ENABLE_MTNA (0x00000001 << 2) -+#define I2C_ENABLE_MAF (0x00000001 << 1) -+#define I2C_ENABLE_MTD (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define I2C_CLR_STATUS_STFNF (0x00000001 << 12) -+#define I2C_CLR_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_CLR_STATUS_RFDA (0x00000001 << 10) -+#define I2C_CLR_STATUS_RFF (0x00000001 << 9) -+#define I2C_CLR_STATUS_STDR (0x00000001 << 8) -+#define I2C_CLR_STATUS_MTDR (0x00000001 << 7) -+#define I2C_CLR_STATUS_IBE (0x00000001 << 6) -+#define I2C_CLR_STATUS_MSMC (0x00000001 << 5) -+#define I2C_CLR_STATUS_SRSD (0x00000001 << 4) -+#define I2C_CLR_STATUS_STSD (0x00000001 << 3) -+#define I2C_CLR_STATUS_MTNA (0x00000001 << 2) -+#define I2C_CLR_STATUS_MAF (0x00000001 << 1) -+#define I2C_CLR_STATIS_MTD (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define I2C_SET_STATUS_STFNF (0x00000001 << 12) -+#define I2C_SET_STATUS_MTFNF (0x00000001 << 11) -+#define I2C_SET_STATUS_RFDA (0x00000001 << 10) -+#define I2C_SET_STATUS_RFF (0x00000001 << 9) -+#define I2C_SET_STATUS_STDR (0x00000001 << 8) -+#define I2C_SET_STATUS_MTDR (0x00000001 << 7) -+#define I2C_SET_STATUS_IBE (0x00000001 << 6) -+#define I2C_SET_STATUS_MSMC (0x00000001 << 5) -+#define I2C_SET_STATUS_SRSD (0x00000001 << 4) -+#define I2C_SET_STATUS_STSD (0x00000001 << 3) -+#define I2C_SET_STATUS_MTNA (0x00000001 << 2) -+#define I2C_SET_STATUS_MAF (0x00000001 << 1) -+#define I2C_SET_STATIS_MTD (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- SPI Registers -------------- */ -+ -+#define SPI 0x0000d000 -+ -+#define SPI_CONTROL_REG 0x000 -+#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) -+#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) -+#define SPI_MODE_SELECT (0x00000001 << 5) -+#define SPI_CLOCK_POLARITY (0x00000001 << 4) -+#define SPI_CLOCK_PHASE (0x00000001 << 3) -+ -+#define SPI_STATUS 0x004 -+#define SPI_TRANSFER_FLAG (0x00000001 << 7) -+#define SPI_WRITE_COLLISSION (0x00000001 << 6) -+#define SPI_READ_OVERRUN (0x00000001 << 5) -+#define SPI_MODE_FAULT (0x00000001 << 4) -+#define SPI_SLAVE_ABORT (0x00000001 << 3) -+ -+#define SPI_DATA 0x008 -+#define SPI_BIDI_DATA (0x000000ff << 0) -+ -+#define SPI_CLOCK_COUNTER 0x00c -+#define SPI_CLOCK (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- GPIO Registers -------------- */ -+ -+#define GPIO 0x0000e000 -+ -+#define GPIO_RD 0x000 -+#define GPIO_WR 0x004 -+#define GPIO_WR_MODE 0x008 -+#define GPIO_OEN 0x00c -+ -+#define GPIO_SW_RST 0xff0 -+#define GPIO_SW_RESET (0x00000001 << 0) -+ -+#define GPIO_31 (1 << 31) -+#define GPIO_30 (1 << 30) -+#define GPIO_29 (1 << 29) -+#define GPIO_28 (1 << 28) -+#define GPIO_27 (1 << 27) -+#define GPIO_26 (1 << 26) -+#define GPIO_25 (1 << 25) -+#define GPIO_24 (1 << 24) -+#define GPIO_23 (1 << 23) -+#define GPIO_22 (1 << 22) -+#define GPIO_21 (1 << 21) -+#define GPIO_20 (1 << 20) -+#define GPIO_19 (1 << 19) -+#define GPIO_18 (1 << 18) -+#define GPIO_17 (1 << 17) -+#define GPIO_16 (1 << 16) -+#define GPIO_15 (1 << 15) -+#define GPIO_14 (1 << 14) -+#define GPIO_13 (1 << 13) -+#define GPIO_12 (1 << 12) -+#define GPIO_11 (1 << 11) -+#define GPIO_10 (1 << 10) -+#define GPIO_09 (1 << 9) -+#define GPIO_08 (1 << 8) -+#define GPIO_07 (1 << 7) -+#define GPIO_06 (1 << 6) -+#define GPIO_05 (1 << 5) -+#define GPIO_04 (1 << 4) -+#define GPIO_03 (1 << 3) -+#define GPIO_02 (1 << 2) -+#define GPIO_01 (1 << 1) -+#define GPIO_00 (1 << 0) -+ -+/* -------------- PHI_0 Registers -------------- */ -+ -+#define PHI_0 0x0000f000 -+ -+#define PHI_0_MODE 0x0000 -+#define PHI_0_0_CONFIG 0x0008 -+#define PHI_0_1_CONFIG 0x000c -+#define PHI_0_2_CONFIG 0x0010 -+#define PHI_0_3_CONFIG 0x0014 -+ -+#define PHI_POLARITY 0x0038 -+#define PHI_TIMEOUT 0x003c -+#define PHI_SW_RST 0x0ff0 -+ -+#define PHI_0_0_RW_0 0x1000 -+#define PHI_0_0_RW_511 0x17fc -+ -+#define PHI_0_1_RW_0 0x1800 -+#define PHI_0_1_RW_511 0x1ffc -+ -+#define PHI_0_2_RW_0 0x2000 -+#define PHI_0_2_RW_511 0x27fc -+ -+#define PHI_0_3_RW_0 0x2800 -+#define PHI_0_3_RW_511 0x2ffc -+ -+#define PHI_CSN_DEASSERT (0x00000001 << 2) -+#define PHI_AUTO_INCREMENT (0x00000001 << 1) -+#define PHI_FIFO_MODE (0x00000001 << 0) -+ -+#define PHI_DELAY_RD_WR (0x0000001f << 27) -+#define PHI_EXTEND_RDY3 (0x00000003 << 25) -+#define PHI_EXTEND_RDY2 (0x00000003 << 23) -+#define PHI_EXTEND_RDY1 (0x00000003 << 21) -+#define PHI_EXTEND_RDY0 (0x00000003 << 19) -+#define PHI_RDY3_OD (0x00000001 << 18) -+#define PHI_RDY2_OD (0x00000001 << 17) -+#define PHI_RDY1_OD (0x00000001 << 16) -+#define PHI_RDY0_OD (0x00000001 << 15) -+#define PHI_ALE_POL (0x00000001 << 14) -+#define PHI_WRN_POL (0x00000001 << 13) -+#define PHI_RDN_POL (0x00000001 << 12) -+#define PHI_RDY3_POL (0x00000001 << 11) -+#define PHI_RDY2_POL (0x00000001 << 10) -+#define PHI_RDY1_POL (0x00000001 << 9) -+#define PHI_RDY0_POL (0x00000001 << 8) -+#define PHI_CSN7_POL (0x00000001 << 7) -+#define PHI_CSN6_POL (0x00000001 << 6) -+#define PHI_CSN5_POL (0x00000001 << 5) -+#define PHI_CSN4_POL (0x00000001 << 4) -+#define PHI_CSN3_POL (0x00000001 << 3) -+#define PHI_CSN2_POL (0x00000001 << 2) -+#define PHI_CSN1_POL (0x00000001 << 1) -+#define PHI_CSN0_POL (0x00000001 << 0) -+ -+/* -------------- PHI_1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+#define PHI_1_MODE 0x00004 -+#define PHI_1_0_CONFIG 0x00018 -+#define PHI_1_1_CONFIG 0x0001c -+#define PHI_1_2_CONFIG 0x00020 -+#define PHI_1_3_CONFIG 0x00024 -+#define PHI_1_4_CONFIG 0x00028 -+#define PHI_1_5_CONFIG 0x0002c -+#define PHI_1_6_CONFIG 0x00030 -+#define PHI_1_7_CONFIG 0x00034 -+ -+#define PHI_1_0_RW_0 0x00000 -+#define PHI_1_0_RW_16383 0x0fffc -+ -+#define PHI_1_1_RW_0 0x1000 -+#define PHI_1_1_RW_16383 0x1ffc -+ -+#define PHI_1_2_RW_0 0x2000 -+#define PHI_1_2_RW_16383 0x2ffc -+ -+#define PHI_1_3_RW_0 0x3000 -+#define PHI_1_3_RW_16383 0x3ffc -+ -+#define PHI_1_4_RW_0 0x4000 -+#define PHI_1_4_RW_16383 0x4ffc -+ -+#define PHI_1_5_RW_0 0x5000 -+#define PHI_1_5_RW_16383 0x5ffc -+ -+#define PHI_1_6_RW_0 0x6000 -+#define PHI_1_6_RW_16383 0x6ffc -+ -+#define PHI_1_7_RW_0 0x7000 -+#define PHI_1_7_RW_16383 0x7ffc -+ -+/* -------------- CGU Registers -------------- */ -+ -+#define CGU 0x00013000 -+ -+#define CGU_SCR_0 0x000 -+#define CGU_SCR_1 0x004 -+#define CGU_SCR_2 0x008 -+#define CGU_SCR_3 0x00c -+#define CGU_SCR_4 0x010 -+#define CGU_SCR_5 0x014 -+#define CGU_SCR_6 0x018 -+#define CGU_SCR_7 0x01c -+#define CGU_SCR_8 0x020 -+#define CGU_SCR_9 0x024 -+#define CGU_SCR_10 0x028 -+#define CGU_SCR_11 0x02c -+#define CGU_SCR_12 0x030 -+#define CGU_SCR_13 0x034 -+#define CGU_SCR_STOP (0x00000001 << 3) -+#define CGU_SCR_RESET (0x00000001 << 2) -+#define CGU_SCR_ENF2 (0x00000001 << 1) -+#define CGU_SCR_ENF1 (0x00000001 << 0) -+ -+#define CGU_FS1_0 0x038 -+#define CGU_FS1_1 0x03c -+#define CGU_FS1_2 0x040 -+#define CGU_FS1_3 0x044 -+#define CGU_FS1_4 0x048 -+#define CGU_FS1_5 0x04c -+#define CGU_FS1_6 0x050 -+#define CGU_FS1_7 0x054 -+#define CGU_FS1_8 0x058 -+#define CGU_FS1_9 0x05c -+#define CGU_FS1_10 0x060 -+#define CGU_FS1_11 0x064 -+#define CGU_FS1_12 0x068 -+#define CGU_FS1_13 0x06c -+#define CGU_FS1_PLL (0x00000000 << 0) -+ -+ -+#define CGU_FS2_0 0x070 -+#define CGU_FS2_1 0x074 -+#define CGU_FS2_2 0x078 -+#define CGU_FS2_3 0x07c -+#define CGU_FS2_4 0x080 -+#define CGU_FS2_5 0x084 -+#define CGU_FS2_6 0x088 -+#define CGU_FS2_7 0x08c -+#define CGU_FS2_8 0x090 -+#define CGU_FS2_9 0x094 -+#define CGU_FS2_10 0x098 -+#define CGU_FS2_11 0x09c -+#define CGU_FS2_12 0x0a0 -+#define CGU_FS2_13 0x0a4 -+ -+#define CGU_SSR_0 0x0a8 -+#define CGU_SSR_1 0x0ac -+#define CGU_SSR_2 0x0b0 -+#define CGU_SSR_3 0x0b4 -+#define CGU_SSR_4 0x0b8 -+#define CGU_SSR_5 0x0bc -+#define CGU_SSR_6 0x0c0 -+#define CGU_SSR_7 0x0c4 -+#define CGU_SSR_8 0x0c8 -+#define CGU_SSR_9 0x0cc -+#define CGU_SSR_10 0x0d0 -+#define CGU_SSR_11 0x0d4 -+#define CGU_SSR_12 0x0d8 -+#define CGU_SSR_13 0x0dc -+ -+#define CGU_PCR_0_0 0x0e0 -+#define CGU_PCR_0_1 0x0e4 -+#define CGU_PCR_0_2 0x0e8 -+#define CGU_PCR_0_3 0x0ec -+#define CGU_PCR_0_4 0x0f0 -+#define CGU_PCR_0_5 0x0f4 -+#define CGU_PCR_0_6 0x0f8 -+#define CGU_PCR_0_7 0x0fc -+#define CGU_PCR_1_0 0x100 -+#define CGU_PCR_1_1 0x104 -+#define CGU_PCR_2_0 0x108 -+#define CGU_PCR_2_1 0x10c -+#define CGU_PCR_3_0 0x110 -+#define CGU_PCR_3_1 0x114 -+#define CGU_PCR_3_2 0x118 -+#define CGU_PCR_4_0 0x11c -+#define CGU_PCR_4_1 0x120 -+#define CGU_PCR_5 0x124 -+#define CGU_PCR_6 0x128 -+#define CGU_PCR_7 0x12c -+#define CGU_PCR_8 0x130 -+#define CGU_PCR_9 0x134 -+#define CGU_PCR_10 0x138 -+#define CGU_PCR_11 0x13c -+#define CGU_PCR_12 0x140 -+#define CGU_PCR_13 0x144 -+#define CGU_PCR_WAKE_EN (0x00000001 << 2) -+#define CGU_PCR_AUTO (0x00000001 << 1) -+#define CGU_PCR_RUN (0x00000001 << 0) -+ -+ -+#define CGU_PSR_0_0 0x148 -+#define CGU_PSR_0_1 0x14c -+#define CGU_PSR_0_2 0x150 -+#define CGU_PSR_0_3 0x154 -+#define CGU_PSR_0_4 0x158 -+#define CGU_PSR_0_5 0x15c -+#define CGU_PSR_0_6 0x160 -+#define CGU_PSR_0_7 0x164 -+#define CGU_PSR_1_0 0x168 -+#define CGU_PSR_1_1 0x16c -+#define CGU_PSR_2_0 0x170 -+#define CGU_PSR_2_1 0x174 -+#define CGU_PSR_3_0 0x178 -+#define CGU_PSR_3_1 0x17c -+#define CGU_PSR_3_2 0x180 -+#define CGU_PSR_4_0 0x184 -+#define CGU_PSR_4_1 0x188 -+#define CGU_PSR_5 0x18c -+#define CGU_PSR_6 0x190 -+#define CGU_PSR_7 0x194 -+#define CGU_PSR_8 0x198 -+#define CGU_PSR_9 0x19c -+#define CGU_PSR_10 0x1a0 -+#define CGU_PSR_11 0x1a4 -+#define CGU_PSR_12 0x1a8 -+#define CGU_PSR_13 0x1ac -+ -+#define CGU_ESR_0_0 0x1b0 -+#define CGU_ESR_0_1 0x1b4 -+#define CGU_ESR_0_2 0x1b8 -+#define CGU_ESR_0_3 0x1bc -+#define CGU_ESR_0_4 0x1c0 -+#define CGU_ESR_0_5 0x1c4 -+#define CGU_ESR_0_6 0x1c8 -+#define CGU_ESR_0_7 0x1cc -+#define CGU_ESR_1_0 0x1d0 -+#define CGU_ESR_1_1 0x1d4 -+#define CGU_ESR_2_0 0x1d8 -+#define CGU_ESR_2_1 0x1dc -+#define CGU_ESR_3_0 0x1e0 -+#define CGU_ESR_3_1 0x1e4 -+#define CGU_ESR_3_2 0x1e8 -+#define CGU_ESR_4_0 0x1ec -+#define CGU_ESR_4_1 0x1f0 -+#define CGU_ESR_5 0x1f4 -+#define CGU_ESR_6 0x1f8 -+#define CGU_ESR_7 0x1fc -+#define CGU_ESR_8 0x200 -+#define CGU_ESR_9 0x204 -+#define CGU_ESR_10 0x208 -+#define CGU_ESR_11 0x20c -+#define CGU_ESR_12 0x210 -+#define CGU_ESR_13 0x214 -+#define CGU_ESR_FD_EN (0x00000001 << 0) -+ -+#define CGU_FDC_0 0x218 -+#define CGU_FDC_1 0x21c -+#define CGU_FDC_2 0x220 -+#define CGU_FDC_3 0x224 -+#define CGU_FDC_4 0x228 -+#define CGU_FDC_5 0x22c -+#define CGU_FDC_6 0x230 -+#define CGU_FDC_7 0x234 -+#define CGU_FDC_8 0x238 -+#define CGU_FDC_9 0x23c -+#define CGU_FDC_10 0x240 -+#define CGU_FDC_11 0x244 -+#define CGU_FDC_12 0x248 -+#define CGU_FDC_13 0x24c -+#define CGU_FDC_STRETCH (0x00000001 << 0) -+#define CGU_FDC_RESET (0x00000001 << 1) -+#define CGU_FDC_RUN1 (0x00000001 << 2) -+#define CGU_FDC_MADD (0x000000ff << 3) -+#define CGU_FDC_MSUB (0x000000ff << 11) -+ -+/* -------------- DCS Registers -------------- */ -+ -+#define DCS 0x00014000 -+ -+#define DCSC_CTRL 0x000 -+#define DCSC_SEL_PLLDI (0x03ffffff << 5) -+#define DCSC_TOUT_SEL (0x0000000f << 1) -+#define DCSC_TOUT_OFF (0x00000001 << 0) -+ -+#define DCSC_ADDR 0x00c -+#define DCSC_ERR_TOUT_ADDR (0x3fffffff << 2) -+ -+#define DCSC_STAT 0x010 -+#define DCSC_ERR_TOUT_GNT (0x0000001f << 24) -+#define DCSC_ERR_TOUT_SEL (0x0000007f << 10) -+#define DCSC_ERR_TOUT_READ (0x00000001 << 8) -+#define DCSC_ERR_TOUT_MASK (0x0000000f << 4) -+#define DCSC_ERR_ACK (0x00000001 << 1) -+ -+#define DCSC_FEATURES 0x040 -+#define DCSC_UNIQUE_ID (0x00000007 << 16) -+#define DCSC_SECURITY (0x00000001 << 14) -+#define DCSC_NUM_BASE_REGS (0x00000003 << 11) -+#define DCSC_NUM_TARGETS (0x0000001f << 5) -+#define DCSC_NUM_INITIATORS (0x0000001f << 0) -+ -+#define DCSC_BASE_REG0 0x100 -+#define DCSC_BASE_N_REG (0x00000fff << 20) -+ -+#define DCSC_INT_CLR_ENABLE 0xfd8 -+#define DCSC_INT_CLR_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLR_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_ENABLE 0xfdc -+#define DCSC_INT_SET_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_STATUS 0xfe0 -+#define DCSC_INT_STATUS_TOUT (0x00000001 << 1) -+#define DCSC_INT_STATUS_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_ENABLE 0xfe4 -+#define DCSC_INT_ENABLE_TOUT (0x00000001 << 1) -+#define DCSC_INT_ENABLE_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_CLR_STATUS 0xfe8 -+#define DCSC_INT_CLEAR_TOUT (0x00000001 << 1) -+#define DCSC_INT_CLEAR_ERROR (0x00000001 << 0) -+ -+#define DCSC_INT_SET_STATUS 0xfec -+#define DCSC_INT_SET_TOUT (0x00000001 << 1) -+#define DCSC_INT_SET_ERROR (0x00000001 << 0) -+ -+ -+ -+ -+/* -------------- GREG Registers -------------- */ -+ -+#define GREG 0x00012000 -+ -+#define GREG_SUBSYS_CONFIG 0x000 -+#define GREG_SUBSYS_ID (0x0000ffff << 16) -+#define GREG_SUBSYS_VID (0x0000ffff << 0) -+ -+#define GREG_MSI_BAR_PMCSR 0x004 -+#define GREG_PMCSR_SCALE_7 (0x00000003 << 30) -+#define GREG_PMCSR_SCALE_6 (0x00000003 << 28) -+#define GREG_PMCSR_SCALE_5 (0x00000003 << 26) -+#define GREG_PMCSR_SCALE_4 (0x00000003 << 24) -+#define GREG_PMCSR_SCALE_3 (0x00000003 << 22) -+#define GREG_PMCSR_SCALE_2 (0x00000003 << 20) -+#define GREG_PMCSR_SCALE_1 (0x00000003 << 18) -+#define GREG_PMCSR_SCALE_0 (0x00000003 << 16) -+ -+#define GREG_BAR_WIDTH_17 (0x0000001e << 8) -+#define GREG_BAR_WIDTH_18 (0x0000001c << 8) -+#define GREG_BAR_WIDTH_19 (0x00000018 << 8) -+#define GREG_BAR_WIDTH_20 (0x00000010 << 8) -+ -+#define GREG_BAR_PREFETCH (0x00000001 << 3) -+#define GREG_MSI_MM_CAP1 (0x00000000 << 0) // FIXME ! -+#define GREG_MSI_MM_CAP2 (0x00000001 << 0) -+#define GREG_MSI_MM_CAP4 (0x00000002 << 0) -+#define GREG_MSI_MM_CAP8 (0x00000003 << 0) -+#define GREG_MSI_MM_CAP16 (0x00000004 << 0) -+#define GREG_MSI_MM_CAP32 (0x00000005 << 0) -+ -+#define GREG_PMCSR_DATA_1 0x008 -+#define GREG_PMCSR_DATA_2 0x00c -+#define GREG_VI_CTRL 0x010 -+#define GREG_FGPI_CTRL 0x014 -+ -+#define GREG_RSTU_CTRL 0x018 -+#define GREG_BOOT_READY (0x00000001 << 13) -+#define GREG_RESET_REQ (0x00000001 << 12) -+#define GREG_IP_RST_RELEASE (0x00000001 << 11) -+#define GREG_ADAPTER_RST_RELEASE (0x00000001 << 10) -+#define GREG_PCIE_CORE_RST_RELEASE (0x00000001 << 9) -+#define GREG_BOOT_IP_RST_RELEASE (0x00000001 << 8) -+#define GREG_BOOT_RST_RELEASE (0x00000001 << 7) -+#define GREG_CGU_RST_RELEASE (0x00000001 << 6) -+#define GREG_IP_RST_ASSERT (0x00000001 << 5) -+#define GREG_ADAPTER_RST_ASSERT (0x00000001 << 4) -+#define GREG_RST_ASSERT (0x00000001 << 3) -+#define GREG_BOOT_IP_RST_ASSERT (0x00000001 << 2) -+#define GREG_BOOT_RST_ASSERT (0x00000001 << 1) -+#define GREG_CGU_RST_ASSERT (0x00000001 << 0) -+ -+#define GREG_I2C_CTRL 0x01c -+#define GREG_I2C_SLAVE_ADDR (0x0000007f << 0) -+ -+#define GREG_OVFLW_CTRL 0x020 -+#define GREG_OVERFLOW_ENABLE (0x00001fff << 0) -+ -+#define GREG_TAG_ACK_FLEN 0x024 -+#define GREG_TAG_ACK_FLEN_1B (0x00000000 << 0) -+#define GREG_TAG_ACK_FLEN_2B (0x00000001 << 0) -+#define GREG_TAG_ACK_FLEN_4B (0x00000002 << 0) -+#define GREG_TAG_ACK_FLEN_8B (0x00000003 << 0) -+ -+#define GREG_VIDEO_IN_CTRL 0x028 -+ -+#define GREG_SPARE_1 0x02c -+#define GREG_SPARE_2 0x030 -+#define GREG_SPARE_3 0x034 -+#define GREG_SPARE_4 0x038 -+#define GREG_SPARE_5 0x03c -+#define GREG_SPARE_6 0x040 -+#define GREG_SPARE_7 0x044 -+#define GREG_SPARE_8 0x048 -+#define GREG_SPARE_9 0x04c -+#define GREG_SPARE_10 0x050 -+#define GREG_SPARE_11 0x054 -+#define GREG_SPARE_12 0x058 -+#define GREG_SPARE_13 0x05c -+#define GREG_SPARE_14 0x060 -+#define GREG_SPARE_15 0x064 -+ -+#define GREG_FAIL_DISABLE 0x068 -+#define GREG_BOOT_FAIL_DISABLE (0x00000001 << 0) -+ -+#define GREG_SW_RST 0xff0 -+#define GREG_SW_RESET (0x00000001 << 0) -+ -+ -+ -+ -+/* BAR = 20 bits */ -+ -+/* -------------- PHI1 Registers -------------- */ -+ -+#define PHI_1 0x00020000 -+ -+ -+ -+#endif /* __SAA716x_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_rom.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_rom.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_rom.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_rom.c 2013-01-16 10:41:10.926798175 +0100 -@@ -0,0 +1,1071 @@ -+#include -+#include -+ -+#include "saa716x_rom.h" -+#include "saa716x_adap.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+int i; -+ -+static int eeprom_read_bytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ -+ u8 b0[] = { MSB(reg), LSB(reg) }; -+ int ret; -+ -+ struct i2c_msg msg[] = { -+ { .addr = 0x50, .flags = 0, .buf = b0, .len = sizeof (b0) }, -+ { .addr = 0x50, .flags = I2C_M_RD, .buf = val, .len = len } -+ }; -+ -+ ret = i2c_transfer(adapter, msg, 2); -+ if (ret != 2) { -+ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); -+ return -EREMOTEIO; -+ } -+ -+ return ret; -+} -+ -+static int saa716x_read_rombytes(struct saa716x_dev *saa716x, u16 reg, u16 len, u8 *val) -+{ -+ struct saa716x_i2c *i2c = saa716x->i2c; -+ struct i2c_adapter *adapter = &i2c[SAA716x_I2C_BUS_B].i2c_adapter; -+ struct i2c_msg msg[2]; -+ -+ u8 b0[2]; -+ int ret, count; -+ -+ count = len / DUMP_BYTES; -+ if (len % DUMP_BYTES) -+ count++; -+ -+ count *= 2; -+ -+ for (i = 0; i < count; i += 2) { -+ dprintk(SAA716x_DEBUG, 1, "Length=%d, Count=%d, Reg=0x%02x", -+ len, -+ count, -+ reg); -+ -+ b0[0] = MSB(reg); -+ b0[1] = LSB(reg); -+ -+ /* Write */ -+ msg[0].addr = 0x50; -+ msg[0].flags = 0; -+ msg[0].buf = b0; -+ msg[0].len = 2; -+ -+ /* Read */ -+ msg[1].addr = 0x50; -+ msg[1].flags = I2C_M_RD; -+ msg[1].buf = val; -+ -+ if (i == (count - 2)) { -+ /* last message */ -+ if (len % DUMP_BYTES) { -+ msg[1].len = len % DUMP_BYTES; -+ dprintk(SAA716x_DEBUG, 1, "Last Message length=%d", len % DUMP_BYTES); -+ } else { -+ msg[1].len = DUMP_BYTES; -+ } -+ } else { -+ msg[1].len = DUMP_BYTES; -+ } -+ -+ ret = i2c_transfer(adapter, msg, 2); -+ if (ret != 2) { -+ dprintk(SAA716x_ERROR, 1, "read error ", reg, ret); -+ return -EREMOTEIO; -+ } -+ -+ reg += DUMP_BYTES; -+ val += DUMP_BYTES; -+ } -+ -+ return 0; -+} -+ -+static int saa716x_get_offset(struct saa716x_dev *saa716x, u8 *buf, u32 *offset) -+{ -+ int i; -+ -+ *offset = 0; -+ for (i = 0; i < 256; i++) { -+ if (!(strncmp("START", buf + i, 5))) -+ break; -+ } -+ dprintk(SAA716x_INFO, 1, "Offset @ %d", i); -+ *offset = i; -+ -+ return 0; -+} -+ -+static int saa716x_eeprom_header(struct saa716x_dev *saa716x, -+ struct saa716x_romhdr *rom_header, -+ u8 *buf, -+ u32 *offset) -+{ -+ memcpy(rom_header, &buf[*offset], sizeof (struct saa716x_romhdr)); -+ if (rom_header->header_size != sizeof (struct saa716x_romhdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ (int)sizeof (struct saa716x_romhdr), -+ rom_header->header_size); -+ -+ return -1; -+ } -+ *offset += sizeof (struct saa716x_romhdr); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Data=%d bytes\n", -+ saa716x->pdev->device, -+ rom_header->data_size); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Version=%d\n", -+ saa716x->pdev->device, -+ rom_header->version); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Devices=%d\n", -+ saa716x->pdev->device, -+ rom_header->devices); -+ -+ dprintk(SAA716x_NOTICE, 0, "SAA%02x ROM: Compressed=%d\n\n", -+ saa716x->pdev->device, -+ rom_header->compression); -+ -+ return 0; -+} -+ -+int saa716x_dump_eeprom(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_romhdr rom_header; -+ u8 buf[DUMP_BYTES]; -+ int i, err = 0; -+ u32 offset = 0; -+ -+ err = eeprom_read_bytes(saa716x, DUMP_OFFST, DUMP_BYTES, buf); -+ if (err < 0) { -+ dprintk(SAA716x_ERROR, 1, "EEPROM Read error"); -+ return err; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, " Card: %s\n", -+ saa716x->config->model_name); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " ---------------- SAA%02x ROM @ Offset 0x%02x ----------------", -+ saa716x->pdev->device, -+ DUMP_OFFST); -+ -+ for (i = 0; i < DUMP_BYTES; i++) { -+ if ((i % 16) == 0) { -+ dprintk(SAA716x_NOTICE, 0, "\n "); -+ dprintk(SAA716x_NOTICE, 0, "%04x: ", i); -+ } -+ -+ if ((i % 8) == 0) -+ dprintk(SAA716x_NOTICE, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_NOTICE, 0, " "); -+ dprintk(SAA716x_NOTICE, 0, "%02x ", buf[i]); -+ } -+ dprintk(SAA716x_NOTICE, 0, "\n"); -+ dprintk(SAA716x_NOTICE, 0, -+ " ---------------- SAA%02x ROM Dump end ---------------------\n\n", -+ saa716x->pdev->device); -+ -+ err = saa716x_get_offset(saa716x, buf, &offset); -+ if (err != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Descriptor not found <%d>", err); -+ return err; -+ } -+ offset += 5; -+ saa716x->id_offst = offset; -+ /* Get header */ -+ err = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); -+ if (err != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", err); -+ return -1; -+ } -+ saa716x->id_len = rom_header.data_size; -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(saa716x_dump_eeprom); -+ -+static void saa716x_descriptor_dbg(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset, -+ u8 size, -+ u8 ext_size) -+{ -+ int i; -+ -+ dprintk(SAA716x_INFO, 0, " "); -+ for (i = 0; i < 49; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ -+ for (i = 0; i < size + ext_size; i++) { -+ if ((i % 16) == 0) -+ dprintk(SAA716x_INFO, 0, "\n "); -+ if ((i % 8) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ -+ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); -+ } -+ -+ dprintk(SAA716x_INFO, 0, "\n "); -+ for (i = 0; i < 49; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ dprintk(SAA716x_INFO, 0, "\n"); -+ -+} -+ -+static int saa716x_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext Data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_gpio_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_gpio_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_gpio_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_gpio_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_gpio_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Pins=%d\n", -+ saa716x->pdev->device, -+ header.pins); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ -+ return 0; -+} -+ -+static int saa716x_video_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_video_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_video_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_video_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_video_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 0=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port0); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 1=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port1); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: PORT 2=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port2); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI PORT ID=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_port_id); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Video PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Encoder PORT Type=0x%02x\n", -+ saa716x->pdev->device, -+ header.encoder_port_type); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Video Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.video_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: VBI Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.vbi_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Encoder Output=0x%02x\n", -+ saa716x->pdev->device, -+ header.encoder_output); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_audio_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_audio_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_audio_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_audio_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_audio_decoder_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_event_source_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_evsrc_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_evsrc_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_evsrc_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_evsrc_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_crossbar_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_xbar_hdr header; -+ struct saa716x_xbar_pair_info pair_info; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_xbar_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_xbar_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_xbar_hdr)); -+ -+ return -1; -+ } -+ -+ memcpy(&pair_info, &buf[*offset], sizeof (struct saa716x_xbar_pair_info)); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Pairs=%d\n", -+ saa716x->pdev->device, -+ header.pair_inputs); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data + (sizeof (struct saa716x_xbar_pair_info) * header.pair_inputs); -+ return 0; -+} -+ -+static int saa716x_tuner_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_tuner_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_tuner_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_tuner_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_tuner_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_pll_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_pll_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_pll_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_pll_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_pll_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_channel_decoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_channel_decoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_channel_decoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_channel_decoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_channel_decoder_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_encoder_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_encoder_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_encoder_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_encoder_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_encoder_hdr)); -+ -+ return -1; -+ } -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_ir_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_ir_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_ir_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_ir_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_ir_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_eeprom_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_eeprom_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_eeprom_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_eeprom_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof (struct saa716x_eeprom_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_filter_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_filter_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_filter_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_filter_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof(struct saa716x_filter_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_streamdev_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ struct saa716x_streamdev_hdr header; -+ -+ memcpy(&header, &buf[*offset], sizeof (struct saa716x_streamdev_hdr)); -+ saa716x_descriptor_dbg(saa716x, buf, offset, header.size, header.ext_data); -+ if (header.size != sizeof (struct saa716x_streamdev_hdr)) { -+ dprintk(SAA716x_ERROR, 1, -+ "ERROR: Header size mismatch! Read size=%d bytes, Expected=%d", -+ header.size, -+ (int)sizeof(struct saa716x_streamdev_hdr)); -+ -+ return -1; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ header.size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n", -+ saa716x->pdev->device, -+ header.ext_data); -+ -+ *offset += header.size + header.ext_data; -+ return 0; -+} -+ -+static int saa716x_unknown_device_info(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset) -+{ -+ u8 size; -+ u8 ext_size = 0; -+ -+ size = buf[*offset]; -+ if (size > 1) -+ ext_size = buf[*offset + size -1]; -+ -+ saa716x_descriptor_dbg(saa716x, buf, offset, size, ext_size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ size); -+ -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Ext data=%d bytes\n\n", -+ saa716x->pdev->device, -+ ext_size); -+ -+ *offset += size + ext_size; -+ return 0; -+} -+ -+ -+static void saa716x_device_dbg(struct saa716x_dev *saa716x, -+ u8 *buf, -+ u32 *offset, -+ u8 size, -+ u8 ext_size, -+ u8 addr_size) -+{ -+ int i; -+ -+ dprintk(SAA716x_INFO, 0, " "); -+ for (i = 0; i < 53; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ -+ for (i = 0; i < size + ext_size + addr_size; i++) { -+ if ((i % 16) == 0) -+ dprintk(SAA716x_INFO, 0, "\n "); -+ if ((i % 8) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ if ((i % 4) == 0) -+ dprintk(SAA716x_INFO, 0, " "); -+ -+ dprintk(SAA716x_INFO, 0, "%02x ", buf[*offset + i]); -+ } -+ -+ dprintk(SAA716x_INFO, 0, "\n "); -+ for (i = 0; i < 53; i++) -+ dprintk(SAA716x_INFO, 0, "-"); -+ dprintk(SAA716x_INFO, 0, "\n"); -+ -+} -+ -+ -+static int saa716x_device_info(struct saa716x_dev *saa716x, -+ struct saa716x_devinfo *device, -+ u8 *buf, -+ u32 *offset) -+{ -+ u8 address = 0; -+ -+ memcpy(device, &buf[*offset], sizeof(struct saa716x_devinfo)); -+ if (device->struct_size != sizeof(struct saa716x_devinfo)) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Device size mismatch! Read=%d bytes, expected=%d bytes", -+ device->struct_size, -+ (int)sizeof(struct saa716x_devinfo)); -+ -+ return -1; -+ } -+ -+ saa716x_device_dbg(saa716x, -+ buf, -+ offset, -+ device->struct_size, -+ device->extd_data_size, -+ device->addr_size); -+ -+ *offset += device->struct_size; -+ -+ if (device->addr_size) { -+ address = buf[*offset]; -+ address >>= 1; -+ *offset += device->addr_size; -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device @ 0x%02x\n", -+ saa716x->pdev->device, -+ address); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Size=%d bytes\n", -+ saa716x->pdev->device, -+ device->struct_size); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->device_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Master ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->master_devid); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Bus ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->master_busid); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Device type=0x%02x\n", -+ saa716x->pdev->device, -+ device->device_type); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Implementation ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->implem_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Path ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->path_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: GPIO ID=0x%02x\n", -+ saa716x->pdev->device, -+ device->gpio_id); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Address=%d bytes\n", -+ saa716x->pdev->device, -+ device->addr_size); -+ -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: Extended data=%d bytes\n\n", -+ saa716x->pdev->device, -+ device->extd_data_size); -+ -+ if (device->extd_data_size) { -+ u32 mask; -+ -+ mask = 0x00000001; -+ while (mask) { -+ if (device->device_type & mask) { -+ switch (mask) { -+ case DECODER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case GPIO_SOURCE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found GPIO device\n", -+ saa716x->pdev->device); -+ -+ saa716x_gpio_info(saa716x, buf, offset); -+ break; -+ -+ case VIDEO_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Video Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_video_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case AUDIO_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Audio Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_audio_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case EVENT_SOURCE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Event source\n", -+ saa716x->pdev->device); -+ -+ saa716x_event_source_info(saa716x, buf, offset); -+ break; -+ -+ case CROSSBAR: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Crossbar device\n", -+ saa716x->pdev->device); -+ -+ saa716x_crossbar_info(saa716x, buf, offset); -+ break; -+ -+ case TUNER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Tuner device\n", -+ saa716x->pdev->device); -+ -+ saa716x_tuner_info(saa716x, buf, offset); -+ break; -+ -+ case PLL_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found PLL device\n", -+ saa716x->pdev->device); -+ -+ saa716x_pll_info(saa716x, buf, offset); -+ break; -+ -+ case CHANNEL_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Channel Demodulator device\n", -+ saa716x->pdev->device); -+ -+ saa716x_channel_decoder_info(saa716x, buf, offset); -+ break; -+ -+ case RDS_DECODER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found RDS Decoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ case ENCODER_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Encoder device\n", -+ saa716x->pdev->device); -+ -+ saa716x_encoder_info(saa716x, buf, offset); -+ break; -+ -+ case IR_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found IR device\n", -+ saa716x->pdev->device); -+ -+ saa716x_ir_info(saa716x, buf, offset); -+ break; -+ -+ case EEPROM_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found EEPROM device\n", -+ saa716x->pdev->device); -+ -+ saa716x_eeprom_info(saa716x, buf, offset); -+ break; -+ -+ case NOISE_FILTER: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Noise filter device\n", -+ saa716x->pdev->device); -+ -+ saa716x_filter_info(saa716x, buf, offset); -+ break; -+ -+ case LNx_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found LNx device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ case STREAM_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found streaming device\n", -+ saa716x->pdev->device); -+ -+ saa716x_streamdev_info(saa716x, buf, offset); -+ break; -+ -+ case CONFIGSPACE_DEVICE: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found Configspace device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ -+ default: -+ dprintk(SAA716x_NOTICE, 0, -+ " SAA%02x ROM: Found unknown device\n", -+ saa716x->pdev->device); -+ -+ saa716x_unknown_device_info(saa716x, buf, offset); -+ break; -+ } -+ } -+ mask <<= 1; -+ } -+ } -+ -+ dprintk(SAA716x_NOTICE, 0, "\n"); -+ -+ return 0; -+} -+ -+int saa716x_eeprom_data(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_romhdr rom_header; -+ struct saa716x_devinfo *device; -+ -+ u8 buf[1024]; -+ int i, ret = 0; -+ u32 offset = 0; -+ -+ /* dump */ -+ ret = saa716x_read_rombytes(saa716x, saa716x->id_offst, saa716x->id_len + 8, buf); -+ if (ret < 0) { -+ dprintk(SAA716x_ERROR, 1, "EEPROM Read error <%d>", ret); -+ goto err0; -+ } -+ -+ /* Get header */ -+ ret = saa716x_eeprom_header(saa716x, &rom_header, buf, &offset); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Header Read failed <%d>", ret); -+ goto err0; -+ } -+ -+ /* allocate for device info */ -+ device = kzalloc(sizeof (struct saa716x_devinfo) * rom_header.devices, GFP_KERNEL); -+ if (device == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: out of memory"); -+ goto err0; -+ } -+ -+ for (i = 0; i < rom_header.devices; i++) { -+ dprintk(SAA716x_NOTICE, 0, " SAA%02x ROM: ===== Device %d =====\n", -+ saa716x->pdev->device, -+ i); -+ -+ ret = saa716x_device_info(saa716x, &device[i], buf, &offset); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Device info read failed <%d>", ret); -+ goto err1; -+ } -+ } -+ -+ kfree(device); -+ -+ return 0; -+ -+err1: -+ kfree(device); -+ -+err0: -+ return ret; -+} -+EXPORT_SYMBOL_GPL(saa716x_eeprom_data); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_rom.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_rom.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_rom.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_rom.h 2013-01-16 10:41:10.926798175 +0100 -@@ -0,0 +1,253 @@ -+#ifndef __SAA716x_ROM_H -+#define __SAA716x_ROM_H -+ -+ -+#define MSB(__x) ((__x >> 8) & 0xff) -+#define LSB(__x) (__x & 0xff) -+ -+#define DUMP_BYTES 0xf0 -+#define DUMP_OFFST 0x000 -+ -+struct saa716x_dev; -+ -+struct saa716x_romhdr { -+ u16 header_size; -+ u8 compression; -+ u8 version; -+ u16 data_size; -+ u8 devices; -+ u8 checksum; -+} __attribute__((packed)); -+ -+struct saa716x_devinfo { -+ u8 struct_size; -+ u8 device_id; -+ u8 master_devid; -+ u8 master_busid; -+ u32 device_type; -+ u16 implem_id; -+ u8 path_id; -+ u8 gpio_id; -+ u16 addr_size; -+ u16 extd_data_size; -+} __attribute__((packed)); -+ -+enum saa716x_device_types { -+ DECODER_DEVICE = 0x00000001, -+ GPIO_SOURCE = 0x00000002, -+ VIDEO_DECODER = 0x00000004, -+ AUDIO_DECODER = 0x00000008, -+ EVENT_SOURCE = 0x00000010, -+ CROSSBAR = 0x00000020, -+ TUNER_DEVICE = 0x00000040, -+ PLL_DEVICE = 0x00000080, -+ CHANNEL_DECODER = 0x00000100, -+ RDS_DECODER = 0x00000200, -+ ENCODER_DEVICE = 0x00000400, -+ IR_DEVICE = 0x00000800, -+ EEPROM_DEVICE = 0x00001000, -+ NOISE_FILTER = 0x00002000, -+ LNx_DEVICE = 0x00004000, -+ STREAM_DEVICE = 0x00010000, -+ CONFIGSPACE_DEVICE = 0x80000000 -+}; -+ -+struct saa716x_decoder_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_decoder_info { -+ struct saa716x_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_gpio_hdr { -+ u8 size; -+ u8 pins; -+ u8 rsvd; -+ u8 ext_data; -+}; -+ -+struct saa716x_gpio_info { -+ struct saa716x_gpio_hdr gpio_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_video_decoder_hdr { -+ u8 size; -+ u8 video_port0; -+ u8 video_port1; -+ u8 video_port2; -+ u8 vbi_port_id; -+ u8 video_port_type; -+ u8 vbi_port_type; -+ u8 encoder_port_type; -+ u8 video_output; -+ u8 vbi_output; -+ u8 encoder_output; -+ u8 ext_data; -+}; -+ -+struct saa716x_video_decoder_info { -+ struct saa716x_video_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_audio_decoder_hdr { -+ u8 size; -+ u8 port; -+ u8 output; -+ u8 ext_data; -+}; -+ -+struct saa716x_audio_decoder_info { -+ struct saa716x_audio_decoder_hdr decoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_evsrc_hdr { -+ u8 size; -+ u8 master_devid; -+ u16 condition_id; -+ u8 rsvd; -+ u8 ext_data; -+}; -+ -+struct saa716x_evsrc_info { -+ struct saa716x_evsrc_hdr evsrc_hdr; -+ u8 *ext_data; -+}; -+ -+enum saa716x_input_pair_type { -+ TUNER_SIF = 0x00, -+ TUNER_LINE = 0x01, -+ TUNER_SPDIF = 0x02, -+ TUNER_NONE = 0x03, -+ CVBS_LINE = 0x04, -+ CVBS_SPDIF = 0x05, -+ CVBS_NONE = 0x06, -+ YC_LINE = 0x07, -+ YC_SPDIF = 0x08, -+ YC_NONE = 0x09, -+ YPbPr_LINE = 0x0a, -+ YPbPr_SPDIF = 0x0b, -+ YPbPr_NONE = 0x0c, -+ NO_LINE = 0x0d, -+ NO_SPDIF = 0x0e, -+ RGB_LINE = 0x0f, -+ RGB_SPDIF = 0x10, -+ RGB_NONE = 0x11 -+}; -+ -+struct saa716x_xbar_pair_info { -+ u8 pair_input_type; -+ u8 video_input_id; -+ u8 audio_input_id; -+}; -+ -+struct saa716x_xbar_hdr { -+ u8 size; -+ u8 pair_inputs; -+ u8 pair_route_default; -+ u8 ext_data; -+}; -+ -+struct saa716x_xbar_info { -+ struct saa716x_xbar_hdr xbar_hdr; -+ struct saa716x_xbar_pair_info *pair_info; -+ u8 *ext_data; -+}; -+ -+struct saa716x_tuner_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_tuner_info { -+ struct saa716x_tuner_hdr tuner_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_pll_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_pll_info { -+ struct saa716x_pll_hdr pll_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_channel_decoder_hdr { -+ u8 size; -+ u8 port; -+ u8 ext_data; -+}; -+ -+struct saa716x_channel_decoder_info { -+ struct saa716x_channel_decoder_hdr channel_dec_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_encoder_hdr { -+ u8 size; -+ u8 stream_port0; -+ u8 stream_port1; -+ u8 ext_data; -+}; -+ -+struct saa716x_encoder_info { -+ struct saa716x_encoder_hdr encoder_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_ir_hdr { -+ u8 size; -+ u8 ir_caps; -+ u8 ext_data; -+}; -+ -+struct saa716x_ir_info { -+ struct saa716x_ir_hdr ir_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_eeprom_hdr { -+ u8 size; -+ u8 rel_device; -+ u8 ext_data; -+}; -+ -+struct saa716x_eeprom_info { -+ struct saa716x_eeprom_hdr eeprom_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_filter_hdr { -+ u8 size; -+ u8 video_decoder; -+ u8 audio_decoder; -+ u8 event_source; -+ u8 ext_data; -+}; -+ -+struct saa716x_filter_info { -+ struct saa716x_filter_hdr filter_hdr; -+ u8 *ext_data; -+}; -+ -+struct saa716x_streamdev_hdr { -+ u8 size; -+ u8 ext_data; -+}; -+ -+struct saa716x_streamdev_info { -+ struct saa716x_streamdev_hdr streamdev_hdr; -+ u8 *ext_data; -+}; -+ -+extern int saa716x_dump_eeprom(struct saa716x_dev *saa716x); -+extern int saa716x_eeprom_data(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_ROM_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_spi.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_spi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi.c 2013-01-16 10:41:10.926798175 +0100 -@@ -0,0 +1,313 @@ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_spi_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+#if 0 // not needed atm -+int saa716x_spi_irqevent(struct saa716x_dev *saa716x) -+{ -+ u32 stat, mask; -+ -+ BUG_ON(saa716x == NULL); -+ -+ stat = SAA716x_EPRD(SPI, SPI_STATUS); -+ mask = SAA716x_EPRD(SPI, SPI_CONTROL_REG) & SPI_SERIAL_INTER_ENABLE; -+ if ((!stat && !mask)) -+ return -1; -+ -+ dprintk(SAA716x_DEBUG, 0, "SPI event: Stat=<%02x>", stat); -+ -+ if (stat & SPI_TRANSFER_FLAG) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_WRITE_COLLISSION) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_READ_OVERRUN) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_MODE_FAULT) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ if (stat & SPI_SLAVE_ABORT) -+ dprintk(SAA716x_DEBUG, 0, " "); -+ -+ return 0; -+} -+#endif -+ -+void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length) -+{ -+ int i; -+ u32 value; -+ int rounds; -+ -+ for (i = 0; i < length; i++) { -+ SAA716x_EPWR(SPI, SPI_DATA, data[i]); -+ rounds = 0; -+ value = SAA716x_EPRD(SPI, SPI_STATUS); -+ -+ while ((value & SPI_TRANSFER_FLAG) == 0 && rounds < 5000) { -+ value = SAA716x_EPRD(SPI, SPI_STATUS); -+ rounds++; -+ } -+ } -+} -+EXPORT_SYMBOL_GPL(saa716x_spi_write); -+ -+#if 0 // not needed atm -+static int saa716x_spi_status(struct saa716x_dev *saa716x, u32 *status) -+{ -+ u32 stat; -+ -+ stat = SAA716x_EPRD(SPI, SPI_STATUS); -+ -+ if (stat & SPI_TRANSFER_FLAG) -+ dprintk(SAA716x_DEBUG, 1, "Transfer complete <%02x>", stat); -+ -+ if (stat & SPI_WRITE_COLLISSION) -+ dprintk(SAA716x_DEBUG, 1, "Write collission <%02x>", stat); -+ -+ if (stat & SPI_READ_OVERRUN) -+ dprintk(SAA716x_DEBUG, 1, "Read Overrun <%02x>", stat); -+ -+ if (stat & SPI_MODE_FAULT) -+ dprintk(SAA716x_DEBUG, 1, "MODE fault <%02x>", stat); -+ -+ if (stat & SPI_SLAVE_ABORT) -+ dprintk(SAA716x_DEBUG, 1, "SLAVE abort <%02x>", stat); -+ -+ *status = stat; -+ -+ return 0; -+} -+ -+#define SPI_CYCLE_TIMEOUT 100 -+ -+static int saa716x_spi_xfer(struct saa716x_dev *saa716x, u32 *data) -+{ -+ u32 i, status = 0; -+ -+ /* write data and wait for completion */ -+ SAA716x_EPWR(SPI, SPI_DATA, data[i]); -+ for (i = 0; i < SPI_CYCLE_TIMEOUT; i++) { -+ msleep(10); -+ saa716x_spi_status(saa716x, &status); -+#if 0 -+ if (status & SPI_TRANSFER_FLAG) { -+ data = SAA716x_EPRD(SPI, SPI_DATA); -+ return 0; -+ } -+#endif -+ if (status & (SPI_WRITE_COLLISSION | -+ SPI_READ_OVERRUN | -+ SPI_MODE_FAULT | -+ SPI_SLAVE_ABORT)) -+ -+ return -EIO; -+ } -+ -+ return -EIO; -+} -+ -+#if 0 -+static int saa716x_spi_wr(struct saa716x_dev *saa716x, const u8 *data, int length) -+{ -+ struct saa716x_spi_config *config = saa716x->spi_config; -+ u32 gpio_mask; -+ int ret = 0; -+ -+ // protect against multiple access -+ spin_lock(&saa716x->gpio_lock); -+ -+ // configure the module -+ saa716x_spi_config(saa716x); -+ -+ // check input -+ -+ // change polarity of GPIO if active high -+ if (config->active_hi) { -+ select = 1; -+ release = 0; -+ } -+ -+ // configure GPIO, first set output register to low selected level -+ saa716x_gpio_write(saa716x, gpio, select); -+ -+ // set mode register to register controlled (0) -+ gpio_mask = (1 << gpio); -+ saa716x_set_gpio_mode(saa716x, gpio_mask, 0); -+ -+ // configure bit as output (0) -+ saa716x_gpio_ctl(saa716x, gpio_mask, 0); -+ -+ // wait at least 500ns before sending a byte -+ msleep(1); -+ -+ // send command -+ for (i = 0; i < dwCommandSize; i++) { -+ ucData = 0; -+// dwStatus = TransferData(pucCommand[i], &ucData); -+ ret = saa716x_spi_xfer(saa716x); -+ //tmDBGPRINTEx(4,("Info: Command 0x%x ", pucCommand[i] )); -+ -+ /* If command length > 1, disable CS at the end of each command. -+ * But after the last command byte CS must be left active! -+ */ -+ if ((dwCommandSize > 1) && (i < dwCommandSize - 1)) { -+ -+ saa716x_gpio_write(saa716x, gpio, release); -+ msleep(1); /* 500 nS minimum */ -+ saa716x_gpio_write(saa716x, gpio, select); -+ } -+ -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Command transfer failed"); -+ msleep(1); /* 500 nS minimum */ -+ saa716x_gpio_write(saa716x, gpio, release); /* release GPIO */ -+ spin_unlock(&saa716x->spi_lock); -+ return ret; -+ } -+ -+ if (config->LSB_first) -+ dwTransferByte++; -+ else -+ dwTransferByte--; -+ } -+ -+// assume that the byte order is the same as the bit order -+ -+// send read address -+ -+// send data -+ -+// wait at least 500ns before releasing slave -+ -+// release GPIO pin -+ -+ // release spinlock -+ spin_unlock(&saa716x->gpio_lock); -+} -+#endif -+ -+#define MODEBITS (SPI_CPOL | SPI_CPHA) -+ -+static int saa716x_spi_setup(struct spi_device *spi) -+{ -+ struct spi_master *master = spi->master; -+ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); -+ struct saa716x_dev *saa716x = saa716x_spi->saa716x; -+ struct saa716x_spi_config *config = &saa716x->spi_config; -+ -+ u8 control = 0; -+ -+ if (spi->mode & ~MODEBITS) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Unsupported MODE bits <%x>", -+ spi->mode & ~MODEBITS); -+ -+ return -EINVAL; -+ } -+ -+ SAA716x_EPWR(SPI, SPI_CLOCK_COUNTER, config->clk_count); -+ -+ control |= SPI_MODE_SELECT; /* SPI Master */ -+ -+ if (config->LSB_first) -+ control |= SPI_LSB_FIRST_ENABLE; -+ -+ if (config->clk_pol) -+ control |= SPI_CLOCK_POLARITY; -+ -+ if (config->clk_pha) -+ control |= SPI_CLOCK_PHASE; -+ -+ SAA716x_EPWR(SPI, SPI_CONTROL_REG, control); -+ -+ return 0; -+} -+ -+static void saa716x_spi_cleanup(struct spi_device *spi) -+{ -+ -+} -+ -+static int saa716x_spi_transfer(struct spi_device *spi, struct spi_message *msg) -+{ -+ struct spi_master *master = spi->master; -+ struct saa716x_spi_state *saa716x_spi = spi_master_get_devdata(master); -+ struct saa716x_dev *saa716x = saa716x_spi->saa716x; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&saa716x->gpio_lock, flags); -+#if 0 -+ if (saa716x_spi->run == QUEUE_STOPPED) { -+ spin_unlock_irqrestore(&saa716x_spi->lock, flags); -+ return -ESHUTDOWN; -+ } -+ -+ msg->actual_length = 0; -+ msg->status = -EINPROGRESS; -+ msg->state = START_STATE; -+ -+ list_add_tail(&msg->queue, &saa716x_spi->queue); -+ -+ if (saa716x_spi->run == QUEUE_RUNNING && !saa716x_spi->busy) -+ queue_work(saa716x_spi->workqueue, &saa716x_spi->pump_messages); -+#endif -+ spin_unlock_irqrestore(&saa716x->gpio_lock, flags); -+ -+ return 0; -+} -+ -+int saa716x_spi_init(struct saa716x_dev *saa716x) -+{ -+ struct pci_dev *pdev = saa716x->pdev; -+ struct spi_master *master; -+ struct saa716x_spi_state *saa716x_spi; -+ int ret; -+ -+ dprintk(SAA716x_DEBUG, 1, "Initializing SAA%02x I2C Core", -+ saa716x->pdev->device); -+ -+ master = spi_alloc_master(&pdev->dev, sizeof (struct saa716x_spi_state)); -+ if (master == NULL) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: Cannot allocate SPI Master!"); -+ return -ENOMEM; -+ } -+ -+ saa716x_spi = spi_master_get_devdata(master); -+ saa716x_spi->master = master; -+ saa716x_spi->saa716x = saa716x; -+ saa716x->saa716x_spi = saa716x_spi; -+ -+ master->bus_num = pdev->bus->number; -+ master->num_chipselect = 1; /* TODO! use config */ -+ master->cleanup = saa716x_spi_cleanup; -+ master->setup = saa716x_spi_setup; -+ master->transfer = saa716x_spi_transfer; -+ -+ ret = spi_register_master(master); -+ if (ret != 0) { -+ dprintk(SAA716x_ERROR, 1, "ERROR: registering SPI Master!"); -+ goto err; -+ } -+err: -+ spi_master_put(master); -+ return ret; -+} -+EXPORT_SYMBOL(saa716x_spi_init); -+ -+void saa716x_spi_exit(struct saa716x_dev *saa716x) -+{ -+ struct saa716x_spi_state *saa716x_spi = saa716x->saa716x_spi; -+ -+ spi_unregister_master(saa716x_spi->master); -+ dprintk(SAA716x_DEBUG, 1, "SAA%02x SPI succesfully removed", saa716x->pdev->device); -+} -+EXPORT_SYMBOL(saa716x_spi_exit); -+#endif -+ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_spi.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_spi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi.h 2013-01-16 10:41:10.926798175 +0100 -@@ -0,0 +1,23 @@ -+#ifndef __SAA716x_SPI_H -+#define __SAA716x_SPI_H -+ -+struct saa716x_dev; -+ -+struct saa716x_spi_config { -+ u8 clk_count; -+ u8 clk_pol:1; -+ u8 clk_pha:1; -+ u8 LSB_first:1; -+}; -+ -+struct saa716x_spi_state { -+ struct spi_master *master; -+ struct saa716x_dev *saa716x; -+}; -+ -+extern void saa716x_spi_write(struct saa716x_dev *saa716x, const u8 *data, int length); -+ -+extern int saa716x_spi_init(struct saa716x_dev *saa716x); -+extern void saa716x_spi_exit(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_SPI_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_spi_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_spi_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_spi_reg.h 2013-01-16 10:41:10.926798175 +0100 -@@ -0,0 +1,27 @@ -+#ifndef __SAA716x_SPI_REG_H -+#define __SAA716x_SPI_REG_H -+ -+/* -------------- SPI Registers -------------- */ -+ -+#define SPI_CONTROL_REG 0x000 -+#define SPI_SERIAL_INTER_ENABLE (0x00000001 << 7) -+#define SPI_LSB_FIRST_ENABLE (0x00000001 << 6) -+#define SPI_MODE_SELECT (0x00000001 << 5) -+#define SPI_CLOCK_POLARITY (0x00000001 << 4) -+#define SPI_CLOCK_PHASE (0x00000001 << 3) -+ -+#define SPI_STATUS 0x004 -+#define SPI_TRANSFER_FLAG (0x00000001 << 7) -+#define SPI_WRITE_COLLISSION (0x00000001 << 6) -+#define SPI_READ_OVERRUN (0x00000001 << 5) -+#define SPI_MODE_FAULT (0x00000001 << 4) -+#define SPI_SLAVE_ABORT (0x00000001 << 3) -+ -+#define SPI_DATA 0x008 -+#define SPI_BIDI_DATA (0x000000ff << 0) -+ -+#define SPI_CLOCK_COUNTER 0x00c -+#define SPI_CLOCK (0x00000001 << 0) -+ -+ -+#endif /* __SAA716x_SPI_REG_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_vip.c linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip.c ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_vip.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip.c 2013-01-16 10:41:10.926798175 +0100 -@@ -0,0 +1,23 @@ -+#include -+ -+#include "saa716x_mod.h" -+ -+#include "saa716x_vip_reg.h" -+#include "saa716x_spi.h" -+#include "saa716x_priv.h" -+ -+void saa716x_vipint_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(VI0, INT_ENABLE, 0); /* disable VI 0 IRQ */ -+ SAA716x_EPWR(VI1, INT_ENABLE, 0); /* disable VI 1 IRQ */ -+ SAA716x_EPWR(VI0, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ -+ SAA716x_EPWR(VI1, INT_CLR_STATUS, 0x3ff); /* clear IRQ */ -+} -+EXPORT_SYMBOL_GPL(saa716x_vipint_disable); -+ -+void saa716x_vip_disable(struct saa716x_dev *saa716x) -+{ -+ SAA716x_EPWR(VI0, VIP_POWER_DOWN, VI_PWR_DWN); -+ SAA716x_EPWR(VI1, VIP_POWER_DOWN, VI_PWR_DWN); -+} -+EXPORT_SYMBOL_GPL(saa716x_vip_disable); -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_vip.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_vip.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip.h 2013-01-16 10:41:10.927798168 +0100 -@@ -0,0 +1,9 @@ -+#ifndef __SAA716x_VIP_H -+#define __SAA716x_VIP_H -+ -+struct saa716x_dev; -+ -+extern void saa716x_vipint_disable(struct saa716x_dev *saa716x); -+extern void saa716x_vip_disable(struct saa716x_dev *saa716x); -+ -+#endif /* __SAA716x_VIP_H */ -diff -Naur linux-3.7.2/drivers/media/common/saa716x/saa716x_vip_reg.h linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip_reg.h ---- linux-3.7.2/drivers/media/common/saa716x/saa716x_vip_reg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/common/saa716x/saa716x_vip_reg.h 2013-01-16 10:41:10.927798168 +0100 -@@ -0,0 +1,127 @@ -+#ifndef __SAA716x_VIP_REG_H -+#define __SAA716x_VIP_REG_H -+ -+/* -------------- VIP Registers -------------- */ -+ -+#define VI_MODE 0x000 -+#define VID_CFEN (0x00000003 << 30) -+#define VID_OSM (0x00000001 << 29) -+#define VID_FSEQ (0x00000001 << 28) -+#define AUX_CFEN (0x00000003 << 26) -+#define AUX_OSM (0x00000001 << 25) -+#define AUX_FSEQ (0x00000001 << 24) -+#define AUX_ANC_DATA (0x00000003 << 22) -+#define AUX_ANC_RAW (0x00000001 << 21) -+#define RST_ON_ERR (0x00000001 << 17) -+#define SOFT_RESET (0x00000001 << 16) -+#define IFF_CLAMP (0x00000001 << 14) -+#define IFF_MODE (0x00000003 << 12) -+#define DFF_CLAMP (0x00000001 << 10) -+#define DFF_MODE (0x00000003 << 8) -+#define HSP_CLAMP (0x00000001 << 3) -+#define HSP_RGB (0x00000001 << 2) -+#define HSP_MODE (0x00000003 << 0) -+ -+#define RCRB_CTRL 0x004 -+#define RCRB_CFG_ADDR 0x008 -+#define RCRB_CFG_EXT_ADDR 0x00c -+#define RCRB_IO_ADDR 0x010 -+#define RCRB_MEM_LADDR 0x014 -+#define RCRB_MEM_UADDR 0x018 -+#define RCRB_DATA 0x01c -+#define RCRB_MASK 0x020 -+#define RCRB_MSG_HDR 0x040 -+#define RCRB_MSG_PL0 0x044 -+#define RCRB_MSG_PL1 0x048 -+ -+#define ID_MASK0 0x020 -+#define VI_ID_MASK_0 (0x000000ff << 8) -+#define VI_DATA_ID_0 (0x000000ff << 0) -+ -+#define ID_MASK1 0x024 -+#define VI_ID_MASK_1 (0x000000ff << 8) -+#define VI_DATA_ID_1 (0x000000ff << 0) -+ -+#define VIP_LINE_THRESH 0x040 -+#define VI_LCTHR (0x000007ff << 0) -+ -+#define VIN_FORMAT 0x100 -+#define VI_VSRA (0x00000003 << 30) -+#define VI_SYNCHD (0x00000001 << 25) -+#define VI_DUAL_STREAM (0x00000001 << 24) -+#define VI_NHDAUX (0x00000001 << 20) -+#define VI_NPAR (0x00000001 << 19) -+#define VI_VSEL (0x00000003 << 14) -+#define VI_TWOS (0x00000001 << 13) -+#define VI_TPG (0x00000001 << 12) -+#define VI_FREF (0x00000001 << 10) -+#define VI_FTGL (0x00000001 << 9) -+#define VI_SF (0x00000001 << 3) -+#define VI_FZERO (0x00000001 << 2) -+#define VI_REVS (0x00000001 << 1) -+#define VI_REHS (0x00000001 << 0) -+ -+#define TC76543210 0x800 -+#define TCFEDCBA98 0x804 -+#define PHYCFG 0x900 -+#define CONFIG 0xfd4 -+#define INT_ENABLE_CLR 0xfd8 -+#define INT_ENABLE_SET 0xfdc -+ -+ -+#define INT_STATUS 0xfe0 -+#define VI_STAT_FID_AUX (0x00000001 << 31) -+#define VI_STAT_FID_VID (0x00000001 << 30) -+#define VI_STAT_FID_VPI (0x00000001 << 29) -+#define VI_STAT_LINE_COUNT (0x00000fff << 16) -+#define VI_STAT_AUX_OVRFLW (0x00000001 << 9) -+#define VI_STAT_VID_OVRFLW (0x00000001 << 8) -+#define VI_STAT_WIN_SEQBRK (0x00000001 << 7) -+#define VI_STAT_FID_SEQBRK (0x00000001 << 6) -+#define VI_STAT_LINE_THRESH (0x00000001 << 5) -+#define VI_STAT_AUX_WRAP (0x00000001 << 4) -+#define VI_STAT_AUX_START_IN (0x00000001 << 3) -+#define VI_STAT_AUX_END_OUT (0x00000001 << 2) -+#define VI_STAT_VID_START_IN (0x00000001 << 1) -+#define VI_STAT_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_ENABLE 0xfe4 -+#define VI_ENABLE_AUX_OVRFLW (0x00000001 << 9) -+#define VI_ENABLE_VID_OVRFLW (0x00000001 << 8) -+#define VI_ENABLE_WIN_SEQBRK (0x00000001 << 7) -+#define VI_ENABLE_FID_SEQBRK (0x00000001 << 6) -+#define VI_ENABLE_LINE_THRESH (0x00000001 << 5) -+#define VI_ENABLE_AUX_WRAP (0x00000001 << 4) -+#define VI_ENABLE_AUX_START_IN (0x00000001 << 3) -+#define VI_ENABLE_AUX_END_OUT (0x00000001 << 2) -+#define VI_ENABLE_VID_START_IN (0x00000001 << 1) -+#define VI_ENABLE_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_CLR_STATUS 0xfe8 -+#define VI_CLR_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_CLR_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_CLR_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_CLR_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_CLR_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_CLR_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_CLR_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_CLR_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_CLR_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_CLR_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define INT_SET_STATUS 0xfec -+#define VI_SET_STATUS_AUX_OVRFLW (0x00000001 << 9) -+#define VI_SET_STATUS_VID_OVRFLW (0x00000001 << 8) -+#define VI_SET_STATUS_WIN_SEQBRK (0x00000001 << 7) -+#define VI_SET_STATUS_FID_SEQBRK (0x00000001 << 6) -+#define VI_SET_STATUS_LINE_THRESH (0x00000001 << 5) -+#define VI_SET_STATUS_AUX_WRAP (0x00000001 << 4) -+#define VI_SET_STATUS_AUX_START_IN (0x00000001 << 3) -+#define VI_SET_STATUS_AUX_END_OUT (0x00000001 << 2) -+#define VI_SET_STATUS_VID_START_IN (0x00000001 << 1) -+#define VI_SET_STATUS_VID_END_OUT (0x00000001 << 0) -+ -+#define VIP_POWER_DOWN 0xff4 -+#define VI_PWR_DWN (0x00000001 << 31) -+ -+#endif /* __SAA716x_VIP_REG_H */ -diff -Naur linux-3.7.2/drivers/media/dvb-frontends/ds3103.h linux-3.7.2.patch/drivers/media/dvb-frontends/ds3103.h ---- linux-3.7.2/drivers/media/dvb-frontends/ds3103.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/dvb-frontends/ds3103.h 2013-01-16 10:41:10.927798168 +0100 -@@ -0,0 +1,47 @@ -+/* -+ Montage Technology DS3103 - DVBS/S2 Demodulator driver -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#ifndef DS3103_H -+#define DS3103_H -+ -+#include -+ -+struct ds3103_config { -+ /* the demodulator's i2c address */ -+ u8 demod_address; -+ u8 ci_mode; -+ /* Set device param to start dma */ -+ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); -+ /* Hook for Lock LED */ -+ void (*set_lock_led)(struct dvb_frontend *fe, int offon); -+}; -+ -+#if defined(CONFIG_DVB_DS3103) || \ -+ (defined(CONFIG_DVB_DS3103_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, -+ struct i2c_adapter *i2c); -+#else -+static inline -+struct dvb_frontend *ds3103_attach(const struct ds3103_config *config, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_DS3103 */ -+#endif /* DS3103_H */ -diff -Naur linux-3.7.2/drivers/media/dvb-frontends/ts2022.h linux-3.7.2.patch/drivers/media/dvb-frontends/ts2022.h ---- linux-3.7.2/drivers/media/dvb-frontends/ts2022.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-3.7.2.patch/drivers/media/dvb-frontends/ts2022.h 2013-01-16 10:41:10.927798168 +0100 -@@ -0,0 +1,51 @@ -+ /* -+ Driver for Montage TS2022 DVBS/S2 Silicon tuner -+ -+ Copyright (C) 2012 Tomazzo Muzumici -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ -+ */ -+ -+#ifndef __DVB_TS2022_H__ -+#define __DVB_TS2022_H__ -+ -+#include -+#include "dvb_frontend.h" -+ -+/** -+ * Attach a ts2022 tuner to the supplied frontend structure. -+ * -+ * @param fe Frontend to attach to. -+ * @param addr i2c address of the tuner. -+ * @param i2c i2c adapter to use. -+ * @return FE pointer on success, NULL on failure. -+ */ -+#if defined(CONFIG_DVB_TS2022) || (defined(CONFIG_DVB_TS2022_MODULE) \ -+ && defined(MODULE)) -+extern struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, int addr, -+ struct i2c_adapter *i2c); -+#else -+static inline struct dvb_frontend *ts2022_attach(struct dvb_frontend *fe, -+ int addr, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+#endif /* CONFIG_DVB_TS2022 */ -+ -+#endif /* __DVB_TS2022_H__ */ -diff -Naur linux-3.7.2/include/uapi/linux/dvb/osd.h linux-3.7.2.patch/include/uapi/linux/dvb/osd.h ---- linux-3.7.2/include/uapi/linux/dvb/osd.h 2013-01-11 18:19:28.000000000 +0100 -+++ linux-3.7.2.patch/include/uapi/linux/dvb/osd.h 2013-01-16 10:41:21.992712972 +0100 -@@ -141,4 +141,20 @@ - #define OSD_SEND_CMD _IOW('o', 160, osd_cmd_t) - #define OSD_GET_CAPABILITY _IOR('o', 161, osd_cap_t) - -+typedef struct osd_raw_cmd_s { -+ const void __user *cmd_data; -+ int cmd_len; -+ void __user *result_data; -+ int result_len; -+} osd_raw_cmd_t; -+ -+typedef struct osd_raw_data_s { -+ const void __user *data_buffer; -+ int data_length; -+ int data_handle; -+} osd_raw_data_t; -+ -+#define OSD_RAW_CMD _IOWR('o', 162, osd_raw_cmd_t) -+#define OSD_RAW_DATA _IOWR('o', 163, osd_raw_data_t) -+ - #endif diff --git a/packages/linux/patches/3.9.8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch.todo b/packages/linux/patches/3.9.8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch.todo deleted file mode 100644 index ac59d4a7a1..0000000000 --- a/packages/linux/patches/3.9.8/linux-990.06-hda-Avoid-outputting-HDMI-audio-before-prepare-.patch.todo +++ /dev/null @@ -1,76 +0,0 @@ -From a6024295fd3290a8c9c5519a03316081ee82378a Mon Sep 17 00:00:00 2001 -From: Anssi Hannula -Date: Sat, 16 Feb 2013 17:42:46 +0200 -Subject: [PATCH] ALSA: hda - Avoid outputting HDMI audio before prepare() and - after close() - -Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) start -transmitting an empty audio stream as soon as PIN_OUT and AC_DIG1_ENABLE -are enabled. - -Since commit 6169b673618bf0b2518ce413b54925782a603f06 ("ALSA: hda - -Always turn on pins for HDMI/DP") this happens at first open() time, and -will continue even after close(). - -Additionally, some codecs (at least Intel PantherPoint HDMI) currently -continue transmitting HDMI audio even after close() in case some actual -audio was output after open() (this happens regardless of PIN_OUT). - -Empty HDMI audio transmission when not intended has the effect that a -possible HDMI audio sink/receiver may prefer the empty HDMI audio stream -over an actual audio stream on its S/PDIF inputs. - -To avoid the issue before first prepare(), set stream format to 0 on -codec initialization. 0 is not a valid format value for HDMI and will -prevent the audio stream from being output. - -Additionally, at close() time, make sure that the stream is cleaned up. -This will ensure that the format is reset to 0 at that time, preventing -audio from being output in that case. - -Thanks to OpenELEC developers and users for their help in investigating -this issue on the affected NVIDIA "ION2" hardware. Testing of the final -version on NVIDIA ION2 was done by OpenELEC user "MrXIII". Testing on -Intel PantherPoint was done by myself. - -Signed-off-by: Anssi Hannula -Cc: stable@vger.kernel.org ---- - sound/pci/hda/patch_hdmi.c | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c -index 807a2aa..bcb83c7 100644 ---- a/sound/pci/hda/patch_hdmi.c -+++ b/sound/pci/hda/patch_hdmi.c -@@ -1253,6 +1253,14 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) - if (err < 0) - return err; - -+ /* -+ * Some HDMI codecs (at least NVIDIA 0x10de000b:0x10de0101:0x100100) -+ * start transmitting an empty audio stream as soon as PIN_OUT and -+ * AC_DIG1_ENABLE are enabled, which happens at open() time. -+ * To avoid that, set format to 0, which is not valid for HDMI. -+ */ -+ snd_hda_codec_write(codec, cvt_nid, 0, AC_VERB_SET_STREAM_FORMAT, 0); -+ - spec->num_cvts++; - - return 0; -@@ -1372,6 +1380,12 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, - struct hdmi_spec_per_pin *per_pin; - - if (hinfo->nid) { -+ /* -+ * Make sure no empty audio is output after this point by -+ * setting stream format to 0, which is not valid for HDMI. -+ */ -+ __snd_hda_codec_cleanup_stream(codec, hinfo->nid, 1); -+ - cvt_idx = cvt_nid_to_cvt_index(spec, hinfo->nid); - if (snd_BUG_ON(cvt_idx < 0)) - return -EINVAL; --- -1.7.10 - diff --git a/packages/linux/patches/3.9.8/linux-995-CX24120-13Z_frontend.patch b/packages/linux/patches/3.9.8/linux-995-CX24120-13Z_frontend.patch deleted file mode 100755 index 32e45a1e88..0000000000 --- a/packages/linux/patches/3.9.8/linux-995-CX24120-13Z_frontend.patch +++ /dev/null @@ -1,1577 +0,0 @@ -http://patchwork.linuxtv.org/patch/10575/ -modified for 3.7.10 - -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:23:44.824143495 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:26:40.756140116 +0400 -@@ -91,6 +91,8 @@ - int feedcount; - int pid_filtering; - int fullts_streaming_state; -+ /* the stream will be activated by an externally (by the fe for example) */ -+ int need_external_stream_control; - - /* bus specific callbacks */ - flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *, -@@ -177,6 +179,8 @@ - struct dvb_demux_feed *dvbdmxfeed, int onoff); - void flexcop_hw_filter_init(struct flexcop_device *fc); - -+extern void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff); -+ - void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff); - - void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]); -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:23:44.828143388 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:26:40.760141513 +0400 -@@ -12,6 +12,7 @@ - #include "cx24113.h" - #include "cx24123.h" - #include "isl6421.h" -+#include "cx24120.h" - #include "mt352.h" - #include "bcm3510.h" - #include "nxt200x.h" -@@ -26,6 +27,15 @@ - #define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \ - (defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE))) - -+#if FE_SUPPORTED(BCM3510) || FE_SUPPORTED(CX24120) -+static int flexcop_fe_request_firmware(struct dvb_frontend *fe, -+ const struct firmware **fw, char* name) -+{ -+ struct flexcop_device *fc = fe->dvb->priv; -+ return request_firmware(fw, name, fc->dev); -+} -+#endif -+ - /* lnb control */ - #if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299) - static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -@@ -445,13 +455,6 @@ - - /* AirStar ATSC 1st generation */ - #if FE_SUPPORTED(BCM3510) --static int flexcop_fe_request_firmware(struct dvb_frontend *fe, -- const struct firmware **fw, char* name) --{ -- struct flexcop_device *fc = fe->dvb->priv; -- return request_firmware(fw, name, fc->dev); --} -- - static struct bcm3510_config air2pc_atsc_first_gen_config = { - .demod_address = 0x0f, - .request_firmware = flexcop_fe_request_firmware, -@@ -619,10 +622,40 @@ - #define cablestar2_attach NULL - #endif - -+/* SkyStar S2 PCI DVB-S/S2 card based on Conexant cx24120/cx24118 */ -+#if FE_SUPPORTED(CX24120) && FE_SUPPORTED(ISL6421) -+static const struct cx24120_config skystar2_rev3_3_cx24120_config = { -+ .i2c_addr = 0x55, -+ .request_firmware = flexcop_fe_request_firmware, -+}; -+ -+static int skystarS2_rev33_attach(struct flexcop_device *fc, struct i2c_adapter *i2c) -+{ -+// struct dvb_frontend_ops *ops; -+ -+ fc->fe = dvb_attach(cx24120_attach, -+ &skystar2_rev3_3_cx24120_config, i2c); -+ if (fc->fe == NULL) return 0; -+ fc->dev_type = FC_SKYS2_REV33; -+ fc->fc_i2c_adap[2].no_base_addr = 1; -+ if ( (dvb_attach(isl6421_attach, fc->fe, -+ &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0) == NULL) ) { -+ err("ISL6421 could NOT be attached!"); -+ return 0; -+ } -+ info("ISL6421 successfully attached."); -+// ops = &fc->fe->ops; -+ return 1; -+} -+#else -+#define skystarS2_rev33_attach NULL -+#endif -+ - static struct { - flexcop_device_type_t type; - int (*attach)(struct flexcop_device *, struct i2c_adapter *); - } flexcop_frontends[] = { -+ { FC_SKYS2_REV33, skystarS2_rev33_attach }, - { FC_SKY_REV27, skystar2_rev27_attach }, - { FC_SKY_REV28, skystar2_rev28_attach }, - { FC_SKY_REV26, skystar2_rev26_attach }, -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:23:44.828143388 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:26:40.760141513 +0400 -@@ -11,6 +11,12 @@ - deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off"); - } - -+void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff) -+{ -+ struct flexcop_device *fc = fe->dvb->priv; -+ flexcop_rcv_data_ctrl(fc, onoff); -+} -+ - void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff) - { - flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff); -@@ -199,6 +205,7 @@ - - /* if it was the first or last feed request change the stream-status */ - if (fc->feedcount == onoff) { -+ if (!fc->need_external_stream_control) - flexcop_rcv_data_ctrl(fc, onoff); - if (fc->stream_control) /* device specific stream control */ - fc->stream_control(fc, onoff); -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:23:44.832143280 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:26:40.760141513 +0400 -@@ -56,6 +56,7 @@ - [FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6", - [FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u", - [FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8", -+ [FC_SKYS2_REV33]= "Sky2PC/SkyStar S2 DVB-S/S2 rev 3.3", - }; - - static const char *flexcop_bus_names[] = { -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h ---- linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:23:44.832143280 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:26:40.760141513 +0400 -@@ -24,6 +24,7 @@ - FC_SKY_REV26, - FC_SKY_REV27, - FC_SKY_REV28, -+ FC_SKYS2_REV33, - } flexcop_device_type_t; - - typedef enum { -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/Kconfig linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig ---- linux-3.4-r1/drivers/media/common/b2c2/Kconfig 2012-04-03 15:23:44.824143495 +0400 -+++ linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig 2012-04-03 15:26:40.760141513 +0400 -@@ -3,6 +3,7 @@ - depends on DVB_CORE && I2C - depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB - default y -+ select DVB_CX24120 if !DVB_FE_CUSTOMISE - select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT - select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT - select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c ---- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c 1970-01-01 03:00:00.000000000 +0300 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c 2012-04-03 16:10:59.000000000 +0400 -@@ -0,0 +1,1053 @@ -+/* -+ Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner driver -+ Version 0.0.4a 03.04.2012 -+ -+ Copyright (C) 2009 Sergey Tyurin -+ Updated 2012 by Jannis Achstetter -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 2 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program; if not, write to the Free Software -+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "dvb_frontend.h" -+#include "cx24120.h" -+#include "cx24120_const.h" -+ -+//========================== -+#define dbginfo(args...) do { if(cx24120_debug) { printk(KERN_DEBUG "CX24120: %s: >>> ", __func__); \ -+ printk(args); } } while (0) -+#define info(args...) do { printk(KERN_INFO "CX24120: %s: -> ", __func__); \ -+ printk(args); } while (0) -+#define err(args...) do { printk(KERN_ERR "CX24120: %s: ### ERROR: ", __func__); \ -+ printk(args); } while (0) -+//========================== -+ -+static int cx24120_debug=0; -+static int reg_debug=0; -+MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24120/CX24118 hardware"); -+module_param(cx24120_debug, int, 0644); -+MODULE_PARM_DESC(cx24120_debug, "Activates frontend debugging (default:0)"); -+ -+// ############################## -+struct cx24120_state { -+ struct i2c_adapter *i2c; -+ const struct cx24120_config *config; -+ struct dvb_frontend frontend; -+ u8 need_set_mpeg_out; -+ u8 attached; -+ u8 dvb_s2_mode; -+ u8 cold_init; -+}; -+// ##################################### -+// #### Command message to firmware #### -+struct cx24120_cmd { // total size = 36 -+ u8 id; // [00] - message id -+ u8 arg[30]; // [04] - message first byte -+ u8 len; // [34] - message lengh or first registers to read -+ u8 reg; // [35] - number of registers to read -+}; -+ -+//=================================================================== -+static int cx24120_readreg(struct cx24120_state *state, u8 reg) -+{ -+ int ret; -+ u8 buf = 0; -+ struct i2c_msg msg[] = { -+ { .addr = state->config->i2c_addr, -+ .flags = 0, -+ .len = 1, -+ .buf = ® }, -+ -+ { .addr = state->config->i2c_addr, -+ .flags = I2C_M_RD, -+ .len = 1, -+ .buf = &buf } -+ }; -+ ret = i2c_transfer(state->i2c, msg, 2); -+ if (ret != 2) { -+ err("Read error: reg=0x%02x, ret=0x%02x)\n", reg, ret); -+ return ret; -+ } -+ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, buf); -+ return buf; -+} // end cx24120_readreg -+//=================================================================== -+static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data) -+{ -+ u8 buf[] = { reg, data }; -+ struct i2c_msg msg = { -+ .addr = state->config->i2c_addr, -+ .flags = 0, -+ .buf = buf, -+ .len = 2 }; -+ int ret; -+ ret = i2c_transfer(state->i2c, &msg, 1); -+ if (ret != 1) { -+ err("Write error: i2c_write error(err == %i, 0x%02x: 0x%02x)\n", ret, reg, data); -+ return ret; -+ } -+ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, data); -+ return 0; -+} // end cx24120_writereg -+//=================================================================== -+static int cx24120_writeregN(struct cx24120_state *state, u8 reg, const u8 *values, u16 len, u8 incr) -+{ -+ u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation (very limited i2c-interface this one) */ -+ struct i2c_msg msg = { -+ .addr = state->config->i2c_addr, -+ .flags = 0, -+ .buf = buf, -+ .len = len }; -+ int ret; -+ -+ do { -+ buf[0] = reg; -+ msg.len = len > 4 ? 4 : len; -+ memcpy(&buf[1], values, msg.len); -+ len -= msg.len; // data length revers counter -+ values += msg.len; // incr data pointer -+ if (incr) reg += msg.len; -+ msg.len++; /* don't forget the addr byte */ -+ ret = i2c_transfer(state->i2c, &msg, 1); -+ if (ret != 1) { -+ err("i2c_write error(err == %i, 0x%02x)\n", ret, reg); -+ return ret; -+ } -+ if (reg_debug) { -+ if( !(reg == 0xFA) && !(reg == 0x20) && !(reg == 0x21)) { // Exclude firmware upload & diseqc messages -+ dbginfo("reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n", // from debug -+ reg, buf[1], buf[2], buf[3], buf[4]); -+ } -+ } -+ } while (len); -+ return 0; -+} // end cx24120_writeregN -+//=================================================================== -+static struct dvb_frontend_ops cx24120_ops; -+//=================================================================== -+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, struct i2c_adapter *i2c) -+{ -+ struct cx24120_state *state = NULL; -+ int demod_rev; -+ -+ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner\n"); -+ info("Driver version: 'SVT - 0.0.4a 03.04.2012'\n"); -+ state = kzalloc(sizeof(struct cx24120_state), -+ GFP_KERNEL); -+ if (state == NULL) { -+ err("### Unable to allocate memory for cx24120_state structure. :(\n"); -+ goto error; -+ } -+ /* setup the state */ -+ state->config = config; -+ state->i2c = i2c; -+ /* check if the demod is present and has proper type */ -+ demod_rev = cx24120_readreg(state, CX24120_REG_REVISION); -+ switch (demod_rev) { -+ case 0x07: -+ info("Demod CX24120 rev. 0x07 detected.\n"); -+ break; -+ case 0x05: -+ info("Demod CX24120 rev. 0x05 detected.\n"); -+ break; -+ default: -+ err("### Unsupported demod revision: 0x%x detected. Exit.\n", demod_rev); -+ goto error; -+ } -+ /* create dvb_frontend */ -+ state->attached = 0x10; // set attached flag -+ state->cold_init=0; -+ memcpy(&state->frontend.ops, &cx24120_ops, sizeof(struct dvb_frontend_ops)); -+ state->frontend.demodulator_priv = state; -+ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner ATTACHED.\n"); -+ return &state->frontend; -+ -+error: -+ kfree(state); -+ return NULL; -+} -+EXPORT_SYMBOL(cx24120_attach); // end cx24120_attach -+//=================================================================== -+static int cx24120_test_rom(struct cx24120_state *state) -+{ -+ int err, ret; -+ err = cx24120_readreg(state, 0xFD); -+ if (err & 4 ) -+ { -+ ret = cx24120_readreg(state, 0xDF) & 0xFE; -+ err = cx24120_writereg(state, 0xDF, ret); -+ } -+ return err; -+} // end cx24120_test_rom -+//=================================================================== -+static int cx24120_read_snr(struct dvb_frontend *fe, u16 *snr) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ -+ *snr = (cx24120_readreg(state, CX24120_REG_QUALITY_H)<<8) | -+ (cx24120_readreg(state, CX24120_REG_QUALITY_L)); -+ dbginfo("read SNR index = %d\n", *snr); -+ -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_read_snr); // end cx24120_read_snr -+//=================================================================== -+static int cx24120_read_ber(struct dvb_frontend *fe, u32 *ber) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ -+ *ber = (cx24120_readreg(state, CX24120_REG_BER_HH) << 24) | // BER high byte of high word -+ (cx24120_readreg(state, CX24120_REG_BER_HL) << 16) | // BER low byte of high word -+ (cx24120_readreg(state, CX24120_REG_BER_LH) << 8) | // BER high byte of low word -+ cx24120_readreg(state, CX24120_REG_BER_LL); // BER low byte of low word -+ dbginfo("read BER index = %d\n", *ber); -+ -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_read_ber); // end cx24120_read_ber -+//=================================================================== -+static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd); -+//=================================================================== -+static int cx24120_msg_mpeg_output_global_config(struct cx24120_state *state, u8 flag) -+{ -+ u8 tristate; -+ struct cx24120_cmd cmd; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = 0x13; // (19) message Enable/Disable mpeg output ??? -+ cmd.arg[0] = 1; -+ cmd.arg[1] = 0; -+ tristate = flag ? 0 : (u8)(-1); -+ cmd.arg[2] = tristate; -+ cmd.arg[3] = 1; -+ cmd.len = 4; -+ -+ if(flag) dbginfo("MPEG output DISABLED\n"); -+ else dbginfo("MPEG output ENABLED\n"); -+ -+ return cx24120_message_send(state, &cmd); -+} // end cx24120_msg_mpeg_output_global_config -+//=================================================================== -+static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd) -+{ -+ u8 xxzz; -+ u32 msg_cmd_mask; -+ int ret, ficus; -+ -+ if(state->dvb_s2_mode & 0x02) { // is MPEG enabled? -+ // if yes: -+ xxzz = cmd->id - 0x11; // look for specific message id -+ if ( xxzz <= 0x13 ) { -+ msg_cmd_mask = 1 << xxzz; -+ //0x0F8021 // if cmd_id 17 or 22 or 33-36, 42, 47, 57-61 etc. disable mpeg output -+ if ( msg_cmd_mask & 0x0F8021 ) { // 000011111000000000100001b -+ cx24120_msg_mpeg_output_global_config(state, 0); -+ msleep(100); -+ state->dvb_s2_mode &= 0xFD; // reset mpeg out enable flag -+ } -+ } -+ } -+ ret = cx24120_writereg(state, 0x00 /* reg id*/, cmd->id /* value */); // message start & target -+ ret = cx24120_writeregN(state, 0x01 /* reg msg*/, &cmd->arg[0], cmd->len /* len*/, 1 /* incr */); // message data -+ ret = cx24120_writereg(state, 0x1F /* reg msg_end */, 0x01 /* value */); // message end -+ -+ ficus = 1000; -+ while ( cx24120_readreg(state, 0x1F)) { // is command done??? -+ msleep(1); -+ if( !(--ficus)) { -+ err("Too long waiting 'done' state from reg(0x1F). :(\n"); -+ return -EREMOTEIO; -+ } -+ } -+ dbginfo("Successfully send message 0x%02x\n", cmd->id); -+ -+ if ( cmd->reg > 30 ) { -+ err("Too much registers to read. cmd->reg = %d", cmd->reg); -+ return -EREMOTEIO; -+ } -+ ficus = 0; -+ if ( cmd->reg ) { // cmd->reg - qty consecutive regs to read -+ while ( ficus < cmd->reg ){ // starts from reg No cmd->len -+ // number of registers to read is cmd->reg -+ // and write results starts from cmd->arg[0]. -+ cmd->arg[ficus] = cx24120_readreg(state, (cmd->len+ficus+1)); -+ ++ficus; -+ } -+ } -+ return 0; -+} // end cx24120_message_send -+//=================================================================== -+static int cx24120_set_frontend(struct dvb_frontend *fe) -+{ -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ u32 srate, freq; -+ fe_code_rate_t fec; -+ fe_spectral_inversion_t inversion; -+ u8 smbr1, smbr2; -+ int ret; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_TUNEREQUEST; // 0x11 set tuner parametrs -+ cmd.len = 15; -+ -+ freq = p->frequency; -+ srate = p->symbol_rate; -+ fec = p->fec_inner; -+ inversion = p->inversion; -+ -+ // check symbol rate -+ if ( srate > 31000000 ) { // if symbol rate > 31 000 -+ smbr1 = (-(srate < 31000001) & 3) + 2; // ebp -+ smbr2 = (-(srate < 31000001) & 6) + 4; // edi -+ } else { -+ smbr1 = 3; -+ smbr2 = 6; -+ } -+ -+ ret = cx24120_writereg(state, 0xE6, smbr1); -+ ret = cx24120_readreg(state, 0xF0); -+ ret &= 0xFFFFFFF0; -+ ret |= smbr2; -+ ret = cx24120_writereg(state, 0xF0, ret); -+ -+ cmd.arg[0] = 0; // CMD_TUNER_REQUEST -+ -+ // Frequency -+ cmd.arg[1] = (freq & 0xFF0000) >> 16; /* intermediate frequency in kHz */ -+ cmd.arg[2] = (freq & 0x00FF00) >> 8; -+ cmd.arg[3] = (freq & 0x0000FF); -+ -+ // Symbol Rate -+ cmd.arg[4] = ((srate/1000) & 0xFF00) >> 8; -+ cmd.arg[5] = ((srate/1000) & 0x00FF); -+ -+ // Inversion -+ if ( inversion ) { -+ if ( inversion == 1 ) cmd.arg[6] = 4; -+ else cmd.arg[6] = 0x0C; -+ } else { -+ cmd.arg[6] = 0; -+ } -+ -+ // FEC -+ switch ( fec ) // fec = p->u.qpsk.fec_inner -+ { -+ case 1: // FEC_1_2 -+ cmd.arg[7] = 0x2E; break; // [11] = 0 by memset -+ case 2: // FEC_2_3 -+ cmd.arg[7] = 0x2F; break; -+ case 3: // FEC_3_4 -+ cmd.arg[7] = 0x30; break; -+ case 5: // FEC_5_6 -+ cmd.arg[7] = 0x31; break; -+ case 7: // FEC_7_8 -+ cmd.arg[7] = 0x32; break; -+ default: // FEC_NONE, FEC_4_5, FEC_6_7, FEC_8_9, -+ // FEC_AUTO, FEC_3_5, FEC_9_10 -+ if ( state->dvb_s2_mode & 1 ) { // if DVB-S2 mode -+ cmd.arg[7] = 0; -+ cmd.arg[11] = 0; -+ } else { -+ cmd.arg[7] = 0x2E; -+ cmd.arg[11] = 0xAC; -+ } -+ break; -+ } -+ cmd.arg[8] = 0x13; -+ cmd.arg[9] = 0x88; -+ cmd.arg[10] = 0; -+ cmd.arg[12] = smbr2; -+ cmd.arg[13] = smbr1; -+ cmd.arg[14] = 0; -+ -+ state->need_set_mpeg_out |= 0x01; // after tune we need restart mpeg out ????? -+ -+ return cx24120_message_send(state, &cmd); -+ -+} -+EXPORT_SYMBOL(cx24120_set_frontend); // end cx24120_set_frontend -+//=================================================================== -+void cx24120_message_fill(struct cx24120_cmd *cmd, -+ u8 msg_id, -+ u8 *msg_addr, -+ u8 msg_len, -+ u8 num_regs) -+{ -+ cmd->id = msg_id; -+ memcpy(&cmd->arg[0], msg_addr, msg_len); -+ cmd->len = msg_len; -+ cmd->reg = num_regs; -+} // end cx24120_message_fill -+//=================================================================== -+static int cx24120_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ int result, sigstr_h, sigstr_l; -+ -+ cx24120_message_fill(&cmd, 0x1A/*msg_id*/, &cx24120_msg_read_sigstr[0], 1/*msg_len*/, 0/*num_regs*/); -+ -+ if( !(cx24120_message_send(state, &cmd)) ) { -+ sigstr_h = (cx24120_readreg(state, CX24120_REG_SIGSTR_H) >> 6) << 8; -+ sigstr_l = cx24120_readreg(state, CX24120_REG_SIGSTR_L ); -+ dbginfo("Signal strength from firmware= 0x%x\n", (sigstr_h | sigstr_l)); -+ *signal_strength = ((sigstr_h | sigstr_l) << 5) & 0x0000FFFF; -+ dbginfo("Signal strength= 0x%x\n", *signal_strength); -+ result = 0; -+ } else { -+ err("error reading signal strength\n"); -+ result = -EREMOTEIO; -+ } -+ return result; -+} -+EXPORT_SYMBOL(cx24120_read_signal_strength); // end cx24120_read_signal_strength -+//=================================================================== -+static int cx24120_msg_mpeg_output_config(struct cx24120_state *state, u8 num, -+ struct cx24120_skystar2_mpeg_config *config_msg) -+{ -+ struct cx24120_cmd cmd; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_MPEG_INIT; // cmd->id=20 - message id -+ cmd.len = 7; -+ cmd.arg[0] = num; // sequental number - can be 0,1,2 -+ cmd.arg[1] = ((config_msg->x1 & 0x01) << 1) | -+ ((config_msg->x1 >> 1) & 0x01); -+ cmd.arg[2] = 0x05; -+ cmd.arg[3] = 0x02; -+ cmd.arg[4] = ((config_msg->x2 >> 1) & 0x01); -+ cmd.arg[5] = (config_msg->x2 & 0xF0) | (config_msg->x3 & 0x0F); -+ cmd.arg[6] = state->attached; /* 0x10 if succesfully attached */ -+ -+ return cx24120_message_send(state, &cmd); -+} // end cx24120_msg_mpeg_output_config -+//=================================================================== -+static int cx24120_diseqc_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_DISEQC_BURST; -+ cmd.arg[0] = 0x00; -+ if (burst) -+ cmd.arg[1] = 0x01; -+ dbginfo("burst sent.\n"); -+ -+ return cx24120_message_send(state, &cmd); -+} -+EXPORT_SYMBOL(cx24120_diseqc_send_burst); // end cx24120_diseqc_send_burst -+//=================================================================== -+static int cx24120_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ -+ dbginfo("cmd(0x23,4) - tone = %d\n", tone); -+ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { -+ err("Invalid tone=%d\n", tone); -+ return -EINVAL; -+ } -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ cmd.id = CMD_SETTONE; // 0x23 -+ cmd.len = 4; -+ if (!tone) -+ cmd.arg[3] = 0x01; -+ return cx24120_message_send(state, &cmd); -+} -+EXPORT_SYMBOL(cx24120_set_tone); // end cx24120_set_tone -+//=================================================================== -+static int cx24120_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ cmd.id = CMD_SETVOLTAGE; // -+ cmd.len = 2; -+ if (!(voltage - 1)) -+ cmd.arg[1] = 0x01; -+ return cx24120_message_send(state, &cmd); -+} -+EXPORT_SYMBOL(cx24120_set_voltage); // end cx24120_set_voltage -+//=================================================================== -+static int cx24120_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *d) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ int back_count; -+ -+ dbginfo("Start sending diseqc sequence===============\n"); -+ -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_DISEQC_MSG1; // 0x20 -+ cmd.len = 11; -+ cmd.arg[0] = 0x00; -+ cmd.arg[1] = 0x00; -+ cmd.arg[2] = 0x03; -+ cmd.arg[3] = 0x16; -+ cmd.arg[4] = 0x28; -+ cmd.arg[5] = 0x01; -+ cmd.arg[6] = 0x01; -+ cmd.arg[7] = 0x14; -+ cmd.arg[8] = 0x19; -+ cmd.arg[9] = 0x14; -+ cmd.arg[10] = 0x1E; -+ if ( cx24120_message_send(state, &cmd) ) { -+ err("send 1st message(0x%x) filed==========\n", cmd.id); -+ return -EREMOTEIO; -+ } -+ cmd.id = CMD_DISEQC_MSG2; // 0x21 -+ cmd.len = d->msg_len + 6; -+ cmd.arg[0] = 0x00; -+ cmd.arg[1] = 0x01; -+ cmd.arg[2] = 0x02; -+ cmd.arg[3] = 0x00; -+ cmd.arg[4] = 0x00; -+ cmd.arg[5] = d->msg_len; -+ -+ memcpy(&cmd.arg[6], &d->msg, d->msg_len); -+ -+ if ( cx24120_message_send(state, &cmd) ) { -+ err("send 2d message(0x%x) filed========\n", cmd.id); -+ return -EREMOTEIO; -+ } -+ back_count = 100; -+ do { -+ if ( !(cx24120_readreg(state, 0x93) & 0x01) ) { -+ dbginfo("diseqc sequence sent success==========.\n"); -+ return 0; -+ } -+ msleep(5); -+ --back_count; -+ } while ( back_count ); -+ err("Too long waiting for diseqc.=============\n"); -+ return -ETIMEDOUT; -+} -+EXPORT_SYMBOL(cx24120_send_diseqc_msg); // end cx24120_send_diseqc_msg -+//=================================================================== -+static int cx24120_read_status(struct dvb_frontend *fe, fe_status_t *status) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ int ret, clock_seq_num, GettedFEC; -+ u8 mode_code, mode_8PSK_flag, attached_flag, clock_id; -+ -+ ret = cx24120_readreg(state, CX24120_REG_STATUS); //0x3A -+ dbginfo("status = 0x%x\n", ret); -+ *status = 0; -+ if ( ret & CX24120_HAS_SIGNAL ) *status = FE_HAS_SIGNAL; -+ if ( ret & CX24120_HAS_CARRIER) *status |= FE_HAS_CARRIER; -+ if ( ret & CX24120_HAS_VITERBI) *status |= (FE_HAS_VITERBI + FE_HAS_SYNC); -+ -+ if ( ret & CX24120_HAS_LOCK ) { // 0x08 -+ *status |= FE_HAS_LOCK; -+ if ( state->need_set_mpeg_out & 1 ) { // just tuned??? -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ cmd.id = CMD_CLOCK_READ; -+ cmd.arg[0] = 0x00; -+ cmd.len = 1; // cmd.reg != 0, so it is first register to read -+ cmd.reg = 6; // number of registers to read (0x01-0x06) -+ if ( !cx24120_message_send(state, &cmd) ) { // in cmd[0]-[5] - result -+ // 0x02-0x07 -+ ret = cx24120_readreg(state, CX24120_REG_FECMODE) & 0x3F; // ntv - 0x8E(142) & 3F = 14 -+ GettedFEC = ret; // 0x0d= 13 -+ dbginfo("Get FEC: %d\n", ret); -+ if ( state->dvb_s2_mode & 0x01 ) { // is DVB-S2? -+ switch (ret-4) { -+ case 0: -+ mode_code = 0x01; goto mode_QPSK; // FEC_1_2 - qpsk only -+ case 1: -+ case 8: -+ mode_code = 0x64; goto mode_8PSK; // FEC_3_5 (10)- 8PSK only -+ case 2: -+ case 9: -+ mode_code = 0x02; goto mode_8PSK; // FEC_2_3 -+ case 3: -+ case 10: -+ mode_code = 0x03; goto mode_8PSK; // FEC_3_4 // 14-4=10 - ntv+ -+ case 4: -+ mode_code = 0x04; goto mode_QPSK; // FEC_4_5 - qpsk only -+ case 5: -+ case 11: -+ mode_code = 0x05; goto mode_8PSK; // FEC_5_6 -+ case 6: -+ case 12: -+ mode_code = 0x08; goto mode_8PSK; // FEC_8_9 -+ case 7: -+ case 13: -+ mode_code = 0x65; goto mode_8PSK; // FEC_9_10 (11)- 8PSK only -+ default: -+ info("Unknown DVB-S2 modefec (not QPSK or 8PSK): %d\n", ret-4); -+ mode_code = 0x01; // set like for mode 0 -+ mode_8PSK: -+ if ( ret > 11 ) { // 14 -+ mode_8PSK_flag = 0x63; // DVB-S2-8PSK flag -+ dbginfo("DVB-S2: 8PSK mode: %d, mode_code= 0x%x\n", ret-4, mode_code); -+ } else { -+ mode_QPSK: -+ mode_8PSK_flag = 0x00; -+ dbginfo("DVB-S2: QPSK mode: %d\n", ret-4); -+ } -+ break; -+ } // end switch -+ } // end if dvb_s2_mode // dvb-s2 -+ else { // state->dvb_s2_mode & 1 = 0 -> #### DVB-S -+ switch ( ret - 2 ) { -+ case 0: -+ mode_code = 2; break; // FEC_2_3 -+ case 1: -+ mode_code = 3; break; // FEC_3_4 -+ case 2: -+ mode_code = 4; break; // FEC_4_5 -+ case 3: -+ mode_code = 5; break; // FEC_5_6 -+ case 4: -+ mode_code = 6; break; // FEC_6_7 -+ case 5: -+ mode_code = 7; break; // FEC_7_8 -+ default: -+ mode_code = 1;break; // FEC_1_2 -+ } -+ mode_8PSK_flag = 0; -+ } // end of switch for dvb-s -+ -+ attached_flag = 0x10; -+ if (state->attached == 0x10) // must be 0x10 if successfully attached in flexcop_fe_tuner -+ attached_flag = 0; -+ ret = 0; -+ if ( state->dvb_s2_mode & 0x01 ) // if dvb-s2 -+ ret = (cx24120_readreg(state, CX24120_REG_FECMODE) >> 7) & 0x01; // QPSK or 8PSK ??? -+ // bit 4 bit 5 bit 0 bit 3 -+ clock_id = (ret << 3) | attached_flag | (state->dvb_s2_mode & 1) | 4; // possible id: 4, 5, 13. 12-impossible, -+ // ntv S2 = 0x8E -> 8 | 1 | 4 = 13 // because 7th bit of ret - is S2 flag -+ // 1/2 S2 = 0x0d -> 0 | 1 | 4 = 5 -+ dbginfo("Check clock table for: clock_id=0x%x, 8PSK_mask=0x%x, mode_code=0x%x\n", -+ clock_id, mode_8PSK_flag, mode_code); -+ -+ clock_seq_num = 0; -+ while ( (clock_ratios_table[clock_seq_num].ratio_id != clock_id) || -+ (clock_ratios_table[clock_seq_num].mode_xPSK != mode_8PSK_flag) || -+ (clock_ratios_table[clock_seq_num].fec_mode != mode_code) ) -+ { -+ /* dbginfo("Check table string(%d): clock_id=%d, 8PSK_flag=%d, mode_code=%d\n", clock_seq_num, -+ * clock_ratios_table[clock_seq_num].ratio_id, -+ * clock_ratios_table[clock_seq_num].mode_xPSK, -+ * clock_ratios_table[clock_seq_num].fec_mode); -+ */ -+ ++clock_seq_num; -+ if ( clock_seq_num == ARRAY_SIZE(clock_ratios_table) ) { -+ info("Check in clock table filed: unsupported modulation tuned - data reception in danger. :(\n"); -+ goto settings_end; -+ } -+ } -+ //############################### -+ dbginfo("Check succesful: GetFEC: %d; post lock: m=%d, n=%d; clock_seq_idx: %d m=%d, n=%d, rate=%d\n", -+ GettedFEC, -+ cmd.arg[2] | (cmd.arg[1] << 8) | (cmd.arg[0] << 16), // registers was readed early -+ cmd.arg[5] | (cmd.arg[4] << 8) | (cmd.arg[3] << 16), // in message with id = 0x16 -+ clock_seq_num, -+ clock_ratios_table[clock_seq_num].m_rat, -+ clock_ratios_table[clock_seq_num].n_rat, -+ clock_ratios_table[clock_seq_num].rate); -+ //############################### -+ cmd.id = CMD_CLOCK_SET; -+ cmd.len = 10; -+ cmd.reg = 0; -+ cmd.arg[0] = 0; -+ cmd.arg[1] = state->attached; // must be 0x10 if successfully attached in flexcop_fe_tuner -+ -+ cmd.arg[2] = (clock_ratios_table[clock_seq_num].m_rat >> 16) & 0xFF; -+ cmd.arg[3] = (clock_ratios_table[clock_seq_num].m_rat >> 8) & 0xFF; -+ cmd.arg[4] = (clock_ratios_table[clock_seq_num].m_rat >> 0) & 0xFF; -+ -+ cmd.arg[5] = (clock_ratios_table[clock_seq_num].n_rat >> 16) & 0xFF; -+ cmd.arg[6] = (clock_ratios_table[clock_seq_num].n_rat >> 8) & 0xFF; -+ cmd.arg[7] = (clock_ratios_table[clock_seq_num].n_rat >> 0) & 0xFF; -+ -+ cmd.arg[8] = (clock_ratios_table[clock_seq_num].rate >> 8) & 0xFF; -+ cmd.arg[9] = (clock_ratios_table[clock_seq_num].rate >> 0) & 0xFF; -+ -+ cx24120_message_send(state, &cmd); -+ -+ settings_end: -+ msleep(200); -+ cx24120_msg_mpeg_output_global_config(state, 1); -+ state->dvb_s2_mode |= 0x02; // set mpeg flag -+ state->need_set_mpeg_out &= 0xFE; // clocks set done -> clear flag -+ } -+ } -+ } -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_read_status); // end cx24120_read_status -+//=================================================================== -+int cx24120_init(struct dvb_frontend *fe) -+{ -+ const struct firmware *fw; -+ struct cx24120_state *state = fe->demodulator_priv; -+ struct cx24120_cmd cmd; -+ u8 ret, ret_EA, reg1, fL, fH; -+ u32 vco, xtal_khz; -+ u64 inv_vco, res, xxyyzz; -+ int reset_result; -+ -+ if( state->cold_init ) return 0; -+ -+ ret = cx24120_writereg(state, 0xEA, 0x00); -+ ret = cx24120_test_rom(state); -+ ret = cx24120_readreg(state, 0xFB) & 0xFE; -+ ret = cx24120_writereg(state, 0xFB, ret); -+ ret = cx24120_readreg(state, 0xFC) & 0xFE; -+ ret = cx24120_writereg(state, 0xFC, ret); -+ ret = cx24120_writereg(state, 0xC3, 0x04); -+ ret = cx24120_writereg(state, 0xC4, 0x04); -+ ret = cx24120_writereg(state, 0xCE, 0x00); -+ ret = cx24120_writereg(state, 0xCF, 0x00); -+ ret_EA = cx24120_readreg(state, 0xEA) & 0xFE; -+ ret = cx24120_writereg(state, 0xEA, ret_EA); -+ ret = cx24120_writereg(state, 0xEB, 0x0C); -+ ret = cx24120_writereg(state, 0xEC, 0x06); -+ ret = cx24120_writereg(state, 0xED, 0x05); -+ ret = cx24120_writereg(state, 0xEE, 0x03); -+ ret = cx24120_writereg(state, 0xEF, 0x05); -+ ret = cx24120_writereg(state, 0xF3, 0x03); -+ ret = cx24120_writereg(state, 0xF4, 0x44); -+ -+ reg1 = 0xF0; -+ do { -+ cx24120_writereg(state, reg1, 0x04); -+ cx24120_writereg(state, reg1 - 10, 0x02); -+ ++reg1; -+ } while ( reg1 != 0xF3 ); -+ -+ ret = cx24120_writereg(state, 0xEA, (ret_EA | 0x01)); -+ reg1 = 0xC5; -+ do { -+ ret = cx24120_writereg(state, reg1, 0x00); -+ ret = cx24120_writereg(state, reg1 + 1, 0x00); -+ reg1 += 2; -+ } while ( reg1 != 0xCB ); -+ -+ ret = cx24120_writereg(state, 0xE4, 0x03); -+ ret = cx24120_writereg(state, 0xEB, 0x0A); -+ -+ dbginfo("Requesting firmware (%s) to download...\n", CX24120_FIRMWARE); -+ ret = state->config->request_firmware(fe, &fw, CX24120_FIRMWARE); -+ if (ret) { -+ err("Could not load firmware (%s): %d\n", CX24120_FIRMWARE, ret); -+ return ret; -+ } -+ dbginfo("Firmware found and it size is %d bytes (%02x %02x .. %02x %02x)\n", -+ (int)fw->size, // firmware_size in bytes u32* -+ fw->data[0], // fw 1st byte -+ fw->data[1], // fw 2d byte -+ fw->data[fw->size - 2], // fw before last byte -+ fw->data[fw->size - 1]); // fw last byte -+ -+ ret = cx24120_test_rom(state); -+ ret = cx24120_readreg(state, 0xFB) & 0xFE; -+ ret = cx24120_writereg(state, 0xFB, ret); -+ ret = cx24120_writereg(state, 0xE0, 0x76); -+ ret = cx24120_writereg(state, 0xF7, 0x81); -+ ret = cx24120_writereg(state, 0xF8, 0x00); -+ ret = cx24120_writereg(state, 0xF9, 0x00); -+ ret = cx24120_writeregN(state, 0xFA, fw->data, (fw->size - 1), 0x00); -+ ret = cx24120_writereg(state, 0xF7, 0xC0); -+ ret = cx24120_writereg(state, 0xE0, 0x00); -+ ret = (fw->size - 2) & 0x00FF; -+ ret = cx24120_writereg(state, 0xF8, ret); // ret now is 0x7a -+ ret = ((fw->size - 2) >> 8) & 0x00FF; -+ ret = cx24120_writereg(state, 0xF9, ret); // ret now is 0xaf -+ ret = cx24120_writereg(state, 0xF7, 0x00); -+ ret = cx24120_writereg(state, 0xDC, 0x00); -+ ret = cx24120_writereg(state, 0xDC, 0x07); -+ msleep(500); -+ -+ ret = cx24120_readreg(state, 0xE1); // now is 0xd5 - last byte of the firmware -+ if ( ret == fw->data[fw->size - 1] ) { -+ dbginfo("Firmware uploaded successfully\n"); -+ reset_result = 0; -+ } else { -+ err("Firmware upload failed. Last byte returned=0x%x\n", ret ); -+ reset_result = -EREMOTEIO; -+ } -+ ret = cx24120_writereg(state, 0xDC, 0x00); -+ release_firmware(fw); -+ if (reset_result) -+ return reset_result; -+ -+ //================== Start tuner -+ cx24120_message_fill(&cmd, CMD_START_TUNER, &cx24120_msg_tuner_init[0], 3, 0); // 0x1B -+ if(cx24120_message_send(state, &cmd)) { -+ err("Error tuner start! :(\n"); -+ return -EREMOTEIO; -+ } -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ -+ cmd.id = CMD_VCO_SET; // 0x10 -+ cmd.len = 12; -+ -+ // ###################### -+ // Calc VCO -+ xtal_khz = 10111; -+ xxyyzz = 0x400000000ULL; // 17179869184 -+ vco = xtal_khz * 10 * 4; // 404440 -+ inv_vco = xxyyzz / vco; // 42478 = 0x00A5EE -+ res = xxyyzz % vco; // 66864 = 0x010530 -+ -+ if( inv_vco > xtal_khz * 10 * 2) ++inv_vco; -+ -+ fH = (inv_vco >> 8) & 0xFF; -+ fL = (inv_vco) & 0xFF; -+ dbginfo("vco= %d, inv_vco= %lld, res= %lld, fL= 0x%x, fH= 0x%x\n", vco, inv_vco, res, fL, fH); -+ // ###################### -+ -+ cmd.arg[0] = 0x06; -+ cmd.arg[1] = 0x2B; -+ cmd.arg[2] = 0xD8; -+ cmd.arg[3] = fH; // 0xA5 -+ cmd.arg[4] = fL; // 0xEE -+ cmd.arg[5] = 0x03; -+ cmd.arg[6] = 0x9D; -+ cmd.arg[7] = 0xFC; -+ cmd.arg[8] = 0x06; -+ cmd.arg[9] = 0x03; -+ cmd.arg[10] = 0x27; -+ cmd.arg[11] = 0x7F; -+ -+ if(cx24120_message_send(state, &cmd)) { -+ err("Error set VCO! :(\n"); -+ return -EREMOTEIO; -+ } -+ memset(&cmd, 0, sizeof(struct cx24120_cmd)); -+ // set bandwidth -+ cmd.id = CMD_BANDWIDTH; // 0x15 -+ cmd.len = 12; -+ cmd.arg[0] = 0x00; -+ cmd.arg[1] = 0x00; -+ cmd.arg[2] = 0x00; -+ cmd.arg[3] = 0x00; -+ cmd.arg[4] = 0x05; -+ cmd.arg[5] = 0x02; -+ cmd.arg[6] = 0x02; -+ cmd.arg[7] = 0x00; -+ cmd.arg[8] = 0x05; -+ cmd.arg[9] = 0x02; -+ cmd.arg[10] = 0x02; -+ cmd.arg[11] = 0x00; -+ -+ if ( cx24120_message_send(state, &cmd) ) { -+ err("Error set bandwidth! :(\n"); -+ return -EREMOTEIO; -+ } -+ ret = cx24120_readreg(state, 0xBA); -+ if ( ret > 3) { -+ dbginfo("Reset-readreg 0xBA: %x\n", ret); -+ err("Error intitilizing tuner! :(\n"); -+ return -EREMOTEIO; -+ } -+ dbginfo("Tuner initialized correctly.\n"); -+ -+ ret = cx24120_writereg(state, 0xEB, 0x0A); -+ if (cx24120_msg_mpeg_output_global_config(state, 0) || -+ cx24120_msg_mpeg_output_config(state, 0, &initial_mpeg_config) || -+ cx24120_msg_mpeg_output_config(state, 1, &initial_mpeg_config) || -+ cx24120_msg_mpeg_output_config(state, 2, &initial_mpeg_config) ) -+ { -+ err("Error initilizing mpeg output. :(\n"); -+ return -EREMOTEIO; -+ } else { -+ cmd.id = 0x3C; // 60 -+ cmd.len = 0x03; -+ cmd.arg[0] = 0x00; -+ cmd.arg[1] = 0x10; -+ cmd.arg[2] = 0x10; -+ if(cx24120_message_send(state, &cmd)) { -+ err("Error sending final init message. :(\n"); -+ return -EREMOTEIO; -+ } -+ } -+ state->cold_init=1; -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_init); // end cx24120_reset -+//=================================================================== -+static int cx24120_tune(struct dvb_frontend *fe, bool re_tune, -+ unsigned int mode_flags, unsigned int *delay, fe_status_t *p_status) -+{ -+ struct dtv_frontend_properties *p = &fe->dtv_property_cache; -+ struct cx24120_state *state = fe->demodulator_priv; -+ int delay_cnt, sd_idx = 0; -+ fe_status_t status; -+ -+ if (re_tune) { -+ -+// dbginfo("Compare symrate with table: symrate= %d, in table= %d\n", -+// p->u.qpsk.symbol_rate, symrates_pairs[sd_idx].symrate); -+ -+ while ( p->symbol_rate > symrates_pairs[sd_idx].symrate ) { -+ ++sd_idx; -+ } -+ dbginfo("Found symrate delay = %d\n", symrates_pairs[sd_idx].delay); -+ state->dvb_s2_mode &= 0xFE; // clear bit -> try not DVB-S2 -+ dbginfo("trying DVB-S =================\n"); -+ cx24120_set_frontend(fe); -+ -+ delay_cnt = symrates_pairs[sd_idx].delay; -+ dbginfo("Wait for LOCK for DVB-S =================\n"); -+ while (delay_cnt >= 0) { -+ cx24120_read_status(fe, &status); -+ if (status & FE_HAS_LOCK) { -+ dbginfo("DVB-S LOCKED================\n"); -+ break; -+ } -+ msleep(100); -+ delay_cnt -=100; -+ } -+ dbginfo("Waiting finished - NO lock for DVB-S =================\n"); -+ -+ cx24120_read_status(fe, &status); -+ if ( !(status & FE_HAS_LOCK) ) { // if no lock on S -+ dbginfo("trying DVB-S2 ++++++++++++++++++++++++++\n"); -+ state->dvb_s2_mode |= 0x01; // may be it locked on S2 ? -+ p->fec_inner = FEC_AUTO; -+ cx24120_set_frontend(fe); -+ delay_cnt = symrates_pairs[sd_idx].delay; -+ dbginfo("Wait for LOCK for DVB-S2 ++++++++++++++++\n"); -+ while (delay_cnt >= 0) { -+ cx24120_read_status(fe, &status); -+ if (status & FE_HAS_LOCK) { -+ dbginfo("DVB-S2 LOCKED++++++++++++++++\n"); -+ break; -+ } -+ msleep(100); -+ delay_cnt -=100; -+ } -+ dbginfo("Waiting finished - NO lock for DVB-S2 ++++++++++++++++\n"); -+ } -+ } -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_tune); // end of cx24120_tune -+//=================================================================== -+static int cx24120_get_algo(struct dvb_frontend *fe) -+{ -+ return DVBFE_ALGO_HW; -+} -+EXPORT_SYMBOL(cx24120_get_algo); -+//=================================================================== -+static int cx24120_sleep(struct dvb_frontend *fe) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_sleep); -+//=================================================================== -+/*static int cx24120_wakeup(struct dvb_frontend *fe) -+ * { -+ * return 0; -+ * } -+ * EXPORT_SYMBOL(cx24120_wakeup); -+ */ -+//=================================================================== -+static int cx24120_get_frontend(struct dvb_frontend *fe) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_get_frontend); -+//=================================================================== -+static void cx24120_release(struct dvb_frontend *fe) -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ dbginfo("Clear state structure\n"); -+ kfree(state); -+} -+EXPORT_SYMBOL(cx24120_release); -+//=================================================================== -+static int cx24120_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) // UNCORRECTED_BLOCKS -+{ -+ struct cx24120_state *state = fe->demodulator_priv; -+ -+ *ucblocks = (cx24120_readreg(state, CX24120_REG_UCB_H) << 8) | -+ cx24120_readreg(state, CX24120_REG_UCB_L); -+ dbginfo("Blocks = %d\n", *ucblocks); -+ return 0; -+} -+EXPORT_SYMBOL(cx24120_read_ucblocks); -+// ######################################################################################## -+static struct dvb_frontend_ops cx24120_ops = { -+ -+ .delsys = { SYS_DVBS2 }, -+ .info = { -+ .name = "Conexant CX24120/CX24118", -+ .frequency_min = 950000, -+ .frequency_max = 2150000, -+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ -+ .frequency_tolerance = 5000, -+ .symbol_rate_min = 1000000, -+ .symbol_rate_max = 45000000, -+ .caps = // 0x500006ff -+ FE_CAN_INVERSION_AUTO | //0x00 000 001 -+ FE_CAN_FEC_1_2 | //0x00 000 002 -+ FE_CAN_FEC_2_3 | //0x00 000 004 -+ FE_CAN_FEC_3_4 | //0x00 000 008 -+ FE_CAN_FEC_4_5 | //0x00 000 010 -+ FE_CAN_FEC_5_6 | //0x00 000 020 -+ FE_CAN_FEC_6_7 | //0x00 000 040 -+ FE_CAN_FEC_7_8 | //0x00 000 080 -+ FE_CAN_FEC_AUTO | //0x00 000 200 -+ FE_CAN_QPSK | //0x00 000 400 -+//??? FE_HAS_EXTENDED_CAPS | //0x00 800 000 /* We need more bitspace for newer APIs, indicate this. */ -+ FE_CAN_2G_MODULATION | //0x10 000 000 /* frontend supports "2nd generation modulation" (DVB-S2) */ -+ FE_CAN_RECOVER //0x40 000 000 /* frontend can recover from a cable unplug automatically */ -+ }, //sum=50 000 6FF -+ .release = cx24120_release, -+ -+ .init = cx24120_init, -+ .sleep = cx24120_sleep, -+ -+ .tune = cx24120_tune, -+ .get_frontend_algo = cx24120_get_algo, -+ .set_frontend = cx24120_set_frontend, -+ -+ .get_frontend = cx24120_get_frontend, -+ .read_status = cx24120_read_status, -+ .read_ber = cx24120_read_ber, -+ .read_signal_strength = cx24120_read_signal_strength, -+ .read_snr = cx24120_read_snr, -+ .read_ucblocks = cx24120_read_ucblocks, -+ -+ .diseqc_send_master_cmd = cx24120_send_diseqc_msg, -+ -+ .diseqc_send_burst = cx24120_diseqc_send_burst, -+ .set_tone = cx24120_set_tone, -+ .set_voltage = cx24120_set_voltage, -+}; -+//=================================================================== -+MODULE_PARM_DESC(cx24120_debug, "prints some verbose debugging information (default:0)"); -+MODULE_AUTHOR("Sergey Tyurin"); -+MODULE_LICENSE("GPL"); -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h ---- linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h 2012-04-03 16:37:20.684139905 +0400 -@@ -0,0 +1,259 @@ -+/* -+ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver -+ * DVBS/S2 Satellite demod/tuner driver static definitins -+ * -+ * Copyright (C) 2009 Sergey Tyurin -+ * Updated 2012 by Jannis Achstetter -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#define CX24120_FIRMWARE "dvb-fe-cx24120-1.20.58.2.fw" -+ -+// ############################## -+// ### cx24120 i2c registers ### -+#define CX24120_REG_CMD_START (0x00) // write cmd_id, and then start write args to next register: -+#define CX24120_REG_CMD_ARGS (0x01) // write command arguments, max 4 at once, then next 4, etc. -+#define CX24120_REG_CMD_END (0x1F) // write 0x01 for end, and read it for command result -+ -+#define CX24120_REG_FECMODE (0x39) // FEC status -+#define CX24120_REG_STATUS (0x3A) // Tuner status - signal, carrier, sync, lock ... -+#define CX24120_REG_QUALITY_H (0x40) // SNR high byte -+#define CX24120_REG_QUALITY_L (0x41) // SNR low byte -+ -+#define CX24120_REG_BER_HH (0x47) // BER high byte of high word -+#define CX24120_REG_BER_HL (0x48) // BER low byte of high word -+#define CX24120_REG_BER_LH (0x49) // BER high byte of low word -+#define CX24120_REG_BER_LL (0x4A) // BER low byte of low word -+ -+#define CX24120_REG_SIGSTR_H (0x3A) // Signal strength high byte & ??? status register ??? -+#define CX24120_REG_SIGSTR_L (0x3B) // Signal strength low byte -+ -+#define CX24120_REG_UCB_H (0x50) // UCB high byte -+#define CX24120_REG_UCB_L (0x51) // UCB low byte -+ -+#define CX24120_REG_REVISION (0xFF) // Chip revision (ro). Must be 0x7 or 0x5 -+ -+// ############################## -+/* Command messages */ -+enum command_message_id { -+ CMD_VCO_SET = 0x10, // cmdlen = 12; -+ CMD_TUNEREQUEST = 0x11, // cmd.len = 15; -+ -+ CMD_MPEG_ONOFF = 0x13, // cmd.len = 4; -+ CMD_MPEG_INIT = 0x14, // cmd.len = 7; -+ CMD_BANDWIDTH = 0x15, // cmd.len = 12; -+ CMD_CLOCK_READ = 0x16, // read clock from registers 0x01-0x06 -+ CMD_CLOCK_SET = 0x17, // cmd.len = 10; -+ -+ CMD_DISEQC_MSG1 = 0x20, // cmd.len = 11; -+ CMD_DISEQC_MSG2 = 0x21, // cmd.len = d->msg_len + 6; -+ CMD_SETVOLTAGE = 0x22, // cmd.len = 2; -+ CMD_SETTONE = 0x23, // cmd.len = 4; -+ CMD_DISEQC_BURST = 0x24, // cmd.len not used !!! -+ -+ CMD_READ_SNR = 0x1A, // Read signal strength -+ CMD_START_TUNER = 0x1B, // ??? -+ -+ CMD_TUNER_INIT = 0x3C, // cmd.len = 0x03; -+}; -+// ############################## -+/* signal status */ -+#define CX24120_HAS_SIGNAL (0x01) -+#define CX24120_HAS_CARRIER (0x02) -+#define CX24120_HAS_VITERBI (0x04) -+#define CX24120_HAS_LOCK (0x08) -+#define CX24120_HAS_UNK1 (0x10) -+#define CX24120_HAS_UNK2 (0x20) -+#define CX24120_STATUS_MASK (0x0f) -+#define CX24120_SIGNAL_MASK (0xc0) -+ -+static u8 cx24120_msg_tuner_init[] = { 0,0,0,0,0,0 }; -+static u8 cx24120_msg_read_sigstr[] = {0,0}; -+ -+static struct cx24120_skystar2_mpeg_config { -+ u8 x1; -+ u8 x2; -+ u8 x3; -+} initial_mpeg_config = { -+ 0xA1, // 10100001 -+ 0x76, // 01110110 -+ 0x07, // 00000111 -+}; -+ -+static struct cx24120_symrate_delay { -+ u32 symrate; -+ u32 delay; -+} symrates_pairs[] = { -+ { 3000000, 15000 }, -+ { 6000000, 10000 }, -+ { 8000000, 5000 }, -+ { 10000000, 2000 }, -+ {0x0FFFFFFFF, 400 }, -+}; -+ -+static struct cx24120_clock_ratios_table { -+ u32 ratio_id; -+ u32 mode_xPSK; -+ u32 fec_mode; -+ u32 m_rat; -+ u32 n_rat; -+ u32 rate; -+} clock_ratios_table[] = { -+{ 21 , 0 , 1 , 770068 , 763515 , 258 }, -+{ 21 , 0 , 100 , 97409 , 80370 , 310 }, -+{ 21 , 0 , 2 , 137293 , 101802 , 345 }, -+{ 21 , 0 , 3 , 4633447 , 3054060 , 388 }, -+{ 21 , 0 , 4 , 2472041 , 1527030 , 414 }, -+{ 21 , 0 , 5 , 85904 , 50901 , 432 }, -+{ 21 , 0 , 8 , 2751229 , 1527030 , 461 }, -+{ 21 , 0 , 101 , 1392872 , 763515 , 467 }, -+{ 21 , 99 , 100 , 1850771 , 1019430 , 464 }, -+{ 21 , 99 , 2 , 137293 , 67962 , 517 }, -+{ 21 , 99 , 3 , 4633447 , 2038860 , 581 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 21 , 99 , 5 , 85904 , 33981 , 647 }, -+{ 21 , 99 , 8 , 2751229 , 1019430 , 690 }, -+{ 21 , 99 , 101 , 1392872 , 509715 , 699 }, -+{ 29 , 0 , 1 , 770068 , 782127 , 252 }, -+{ 29 , 0 , 100 , 1850771 , 1564254 , 302 }, -+{ 29 , 0 , 2 , 686465 , 521418 , 337 }, -+{ 29 , 0 , 3 , 4633447 , 3128508 , 379 }, -+{ 29 , 0 , 4 , 2472041 , 1564254 , 404 }, -+{ 29 , 0 , 5 , 429520 , 260709 , 421 }, -+{ 29 , 0 , 8 , 2751229 , 1564254 , 450 }, -+{ 29 , 0 , 101 , 1392872 , 782127 , 455 }, -+{ 29 , 99 , 100 , 1850771 , 1043118 , 454 }, -+{ 29 , 99 , 2 , 686465 , 347706 , 505 }, -+{ 29 , 99 , 3 , 4633447 , 2086236 , 568 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 29 , 99 , 5 , 429520 , 173853 , 632 }, -+{ 29 , 99 , 8 , 2751229 , 1043118 , 675 }, -+{ 29 , 99 , 101 , 1392872 , 521559 , 683 }, -+{ 17 , 0 , 1 , 766052 , 763515 , 256 }, -+{ 17 , 0 , 100 , 96901 , 80370 , 308 }, -+{ 17 , 0 , 2 , 136577 , 101802 , 343 }, -+{ 17 , 0 , 3 , 4609283 , 3054060 , 386 }, -+{ 17 , 0 , 4 , 2459149 , 1527030 , 412 }, -+{ 17 , 0 , 5 , 85456 , 50901 , 429 }, -+{ 17 , 0 , 8 , 2736881 , 1527030 , 458 }, -+{ 17 , 0 , 101 , 1385608 , 763515 , 464 }, -+{ 17 , 99 , 100 , 1841119 , 1019430 , 462 }, -+{ 17 , 99 , 2 , 136577 , 67962 , 514 }, -+{ 17 , 99 , 3 , 4609283 , 2038860 , 578 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 17 , 99 , 5 , 85456 , 33981 , 643 }, -+{ 17 , 99 , 8 , 2736881 , 1019430 , 687 }, -+{ 17 , 99 , 101 , 1385608 , 509715 , 695 }, -+{ 25 , 0 , 1 , 766052 , 782127 , 250 }, -+{ 25 , 0 , 100 , 1841119 , 1564254 , 301 }, -+{ 25 , 0 , 2 , 682885 , 521418 , 335 }, -+{ 25 , 0 , 3 , 4609283 , 3128508 , 377 }, -+{ 25 , 0 , 4 , 2459149 , 1564254 , 402 }, -+{ 25 , 0 , 5 , 427280 , 260709 , 419 }, -+{ 25 , 0 , 8 , 2736881 , 1564254 , 447 }, -+{ 25 , 0 , 101 , 1385608 , 782127 , 453 }, -+{ 25 , 99 , 100 , 1841119 , 1043118 , 451 }, -+{ 25 , 99 , 2 , 682885 , 347706 , 502 }, -+{ 25 , 99 , 3 , 4609283 , 2086236 , 565 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 25 , 99 , 5 , 427280 , 173853 , 629 }, -+{ 25 , 99 , 8 , 2736881 , 1043118 , 671 }, -+{ 25 , 99 , 101 , 1385608 , 521559 , 680 }, -+{ 5 , 0 , 1 , 273088 , 254505 , 274 }, -+{ 5 , 0 , 100 , 17272 , 13395 , 330 }, -+{ 5 , 0 , 2 , 24344 , 16967 , 367 }, -+{ 5 , 0 , 3 , 410788 , 254505 , 413 }, -+{ 5 , 0 , 4 , 438328 , 254505 , 440 }, -+{ 5 , 0 , 5 , 30464 , 16967 , 459 }, -+{ 5 , 0 , 8 , 487832 , 254505 , 490 }, -+{ 5 , 0 , 101 , 493952 , 254505 , 496 }, -+{ 5 , 99 , 100 , 328168 , 169905 , 494 }, -+{ 5 , 99 , 2 , 24344 , 11327 , 550 }, // work for 0x0d - 11278V - DVB-S2 - 8PSK MPEG-4/HD -+{ 5 , 99 , 3 , 410788 , 169905 , 618 }, // 0x0e S2 8psk // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 5 , 99 , 5 , 30464 , 11327 , 688 }, -+{ 5 , 99 , 8 , 487832 , 169905 , 735 }, -+{ 5 , 99 , 101 , 493952 , 169905 , 744 }, -+{ 13 , 0 , 1 , 273088 , 260709 , 268 }, -+{ 13 , 0 , 100 , 328168 , 260709 , 322 }, -+{ 13 , 0 , 2 , 121720 , 86903 , 358 }, -+{ 13 , 0 , 3 , 410788 , 260709 , 403 }, -+{ 13 , 0 , 4 , 438328 , 260709 , 430 }, -+{ 13 , 0 , 5 , 152320 , 86903 , 448 }, -+{ 13 , 0 , 8 , 487832 , 260709 , 479 }, -+{ 13 , 0 , 101 , 493952 , 260709 , 485 }, -+{ 13 , 99 , 100 , 328168 , 173853 , 483 }, -+{ 13 , 99 , 2 , 121720 , 57951 , 537 }, // work for 0x8d - dvb-s2 8psk -+{ 13 , 99 , 3 , 410788 , 173853 , 604 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 13 , 99 , 5 , 152320 , 57951 , 672 }, -+{ 13 , 99 , 8 , 487832 , 173853 , 718 }, -+{ 13 , 99 , 101 , 493952 , 173853 , 727 }, -+{ 1 , 0 , 1 , 815248 , 763515 , 273 }, -+{ 1 , 0 , 100 , 51562 , 40185 , 328 }, -+{ 1 , 0 , 2 , 72674 , 50901 , 365 }, -+{ 1 , 0 , 3 , 1226323 , 763515 , 411 }, -+{ 1 , 0 , 4 , 1308538 , 763515 , 438 }, -+{ 1 , 0 , 5 , 90944 , 50901 , 457 }, -+{ 1 , 0 , 8 , 1456322 , 763515 , 488 }, -+{ 1 , 0 , 101 , 1474592 , 763515 , 494 }, -+{ 1 , 99 , 100 , 979678 , 509715 , 492 }, -+{ 1 , 99 , 2 , 72674 , 33981 , 547 }, -+{ 1 , 99 , 3 , 1226323 , 509715 , 615 }, // was 4 - ERRORR!? FEC_4_5 not in DVB-S2 -+{ 1 , 99 , 5 , 90944 , 33981 , 685 }, -+{ 1 , 99 , 8 , 1456322 , 509715 , 731 }, -+{ 1 , 99 , 101 , 1474592 , 509715 , 740 }, -+{ 9 , 0 , 1 , 815248 , 782127 , 266 }, -+{ 9 , 0 , 100 , 979678 , 782127 , 320 }, -+{ 9 , 0 , 2 , 363370 , 260709 , 356 }, -+{ 9 , 0 , 3 , 1226323 , 782127 , 401 }, -+{ 9 , 0 , 4 , 1308538 , 782127 , 428 }, -+{ 9 , 0 , 5 , 454720 , 260709 , 446 }, -+{ 9 , 0 , 8 , 1456322 , 782127 , 476 }, -+{ 9 , 0 , 101 , 1474592 , 782127 , 482 }, -+{ 9 , 99 , 100 , 979678 , 521559 , 480 }, -+{ 9 , 99 , 2 , 363370 , 173853 , 535 }, -+{ 9 , 99 , 3 , 1226323 , 521559 , 601 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2 -+{ 9 , 99 , 5 , 454720 , 173853 , 669 }, -+{ 9 , 99 , 8 , 1456322 , 521559 , 714 }, -+{ 9 , 99 , 101 , 1474592 , 521559 , 723 }, -+{ 18 , 0 , 1 , 535 , 588 , 233 }, -+{ 18 , 0 , 2 , 1070 , 882 , 311 }, -+{ 18 , 0 , 6 , 3210 , 2058 , 399 }, -+{ 16 , 0 , 1 , 763 , 816 , 239 }, -+{ 16 , 0 , 2 , 1526 , 1224 , 319 }, -+{ 16 , 0 , 3 , 2289 , 1632 , 359 }, -+{ 16 , 0 , 5 , 3815 , 2448 , 399 }, -+{ 16 , 0 , 7 , 5341 , 3264 , 419 }, -+{ 22 , 0 , 1 , 535 , 588 , 233 }, -+{ 22 , 0 , 2 , 1070 , 882 , 311 }, -+{ 22 , 0 , 6 , 3210 , 2058 , 399 }, -+{ 20 , 0 , 1 , 143429 , 152592 , 241 }, -+{ 20 , 0 , 2 , 286858 , 228888 , 321 }, -+{ 20 , 0 , 3 , 430287 , 305184 , 361 }, -+{ 20 , 0 , 5 , 717145 , 457776 , 401 }, -+{ 20 , 0 , 7 , 1004003 , 610368 , 421 }, -+{ 2 , 0 , 1 , 584 , 588 , 254 }, -+{ 2 , 0 , 2 , 1169 , 882 , 339 }, -+{ 2 , 0 , 6 , 3507 , 2058 , 436 }, -+{ 0 , 0 , 1 , 812 , 816 , 255 }, -+{ 0 , 0 , 2 , 1624 , 1224 , 340 }, -+{ 0 , 0 , 3 , 2436 , 1632 , 382 }, -+{ 0 , 0 , 5 , 4060 , 2448 , 425 }, -+{ 0 , 0 , 7 , 5684 , 3264 , 446 }, -+{ 6 , 0 , 1 , 584 , 588 , 254 }, -+{ 6 , 0 , 2 , 1168 , 882 , 339 }, -+{ 6 , 0 , 6 , 3504 , 2058 , 436 }, -+{ 4 , 0 , 1 , 152592 , 152592 , 256 }, -+{ 4 , 0 , 2 , 305184 , 228888 , 341 }, -+{ 4 , 0 , 3 , 457776 , 305184 , 384 }, -+{ 4 , 0 , 5 , 762960 , 457776 , 427 }, -+{ 4 , 0 , 7 , 1068144 , 610368 , 448 }, -+}; -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h ---- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h 1970-01-01 03:00:00.000000000 +0300 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h 2012-04-03 10:27:59.000000000 +0400 -@@ -0,0 +1,59 @@ -+/* -+ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver -+ * -+ * Copyright (C) 2008 Patrick Boettcher -+ * Copyright (C) 2009 Sergey Tyurin -+ * Updated 2012 by Jannis Achstetter -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef CX24120_H -+#define CX24120_H -+ -+#include -+ -+struct firmware; -+struct dvb_frontend; -+struct i2c_adapter; -+ -+struct cx24120_config -+{ -+ u8 i2c_addr; -+ int (*request_firmware)(struct dvb_frontend *fe, const struct firmware **fw, char *name); -+ void (*stream_control)(struct dvb_frontend *fe, u8 onoff); -+}; -+ -+#if defined(CONFIG_DVB_CX24120) || \ -+ (defined(CONFIG_DVB_CX24120_MODULE) && defined(MODULE)) -+extern struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, -+ struct i2c_adapter *i2c); -+extern int cx24120_reset(struct dvb_frontend *fe); -+#else -+static inline -+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, -+ struct i2c_adapter *i2c) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return NULL; -+} -+static inline int cx24120_reset(struct dvb_frontend *fe) -+{ -+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -+ return -ENODEV; -+} -+#endif -+ -+#endif -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Kconfig linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig ---- linux-3.4-r1/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:23:44.976143444 +0400 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:26:40.760141513 +0400 -@@ -4,6 +4,13 @@ - comment "Multistandard (satellite) frontends" - depends on DVB_CORE - -+config DVB_CX24120 -+ tristate "Conexant CX24120 based" -+ depends on DVB_CORE && I2C -+ default m if DVB_FE_CUSTOMISE -+ help -+ A DVB-S/DVB-S2 tuner module. Say Y when you want to support this frontend. -+ - config DVB_STB0899 - tristate "STB0899 based" - depends on DVB_CORE && I2C -diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Makefile linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile ---- linux-3.4-r1/drivers/media/dvb-frontends/Makefile 2012-04-03 15:23:44.976143444 +0400 -+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile 2012-04-03 15:26:40.760141513 +0400 -@@ -19,6 +19,10 @@ - obj-$(CONFIG_DVB_CX22700) += cx22700.o - obj-$(CONFIG_DVB_S5H1432) += s5h1432.o - obj-$(CONFIG_DVB_CX24110) += cx24110.o -+ -+# inserted by Custler -+obj-$(CONFIG_DVB_CX24120) += cx24120.o -+ - obj-$(CONFIG_DVB_TDA8083) += tda8083.o - obj-$(CONFIG_DVB_L64781) += l64781.o - obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o diff --git a/packages/linux/patches/3.9.8/linux-996-macmini2012-ethernet.patch b/packages/linux/patches/3.9.8/linux-996-macmini2012-ethernet.patch deleted file mode 100644 index 298260ea69..0000000000 --- a/packages/linux/patches/3.9.8/linux-996-macmini2012-ethernet.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- linux-3.9.2/drivers/net/ethernet/broadcom/tg3.c 2013-05-11 18:19:28.000000000 +0400 -+++ linux-3.9.2/drivers/net/ethernet/broadcom/tg3.c 2013-05-25 20:55:00.282972605 +0400 -@@ -333,6 +333,8 @@ - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57766)}, -+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57782)}, -+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57786)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5762)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5725)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5727)}, diff --git a/packages/linux/patches/3.9.8/linux-997-disable-rc6-on-sandybridge-gt1.patch b/packages/linux/patches/3.9.8/linux-997-disable-rc6-on-sandybridge-gt1.patch deleted file mode 100644 index c0a9067fe1..0000000000 --- a/packages/linux/patches/3.9.8/linux-997-disable-rc6-on-sandybridge-gt1.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/drivers/gpu/drm/i915/intel_pm.c 2013-05-30 22:57:09.098080381 +0200 -+++ b/drivers/gpu/drm/i915/intel_pm.c 2013-05-30 23:31:31.644308032 +0200 -@@ -2503,8 +2503,8 @@ - if (i915_enable_rc6 >= 0) - return i915_enable_rc6; - -- /* Disable RC6 on Ironlake */ -- if (INTEL_INFO(dev)->gen == 5) -+ /* Disable RC6 on Ironlake and Sandybridge GT1 */ -+ if (INTEL_INFO(dev)->gen == 5 || IS_SNB_GT1(dev)) - return 0; - - if (IS_HASWELL(dev)) { From 0329e1984987b8cce0dddbf176563a23f016037a Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 17:11:37 +0200 Subject: [PATCH 21/61] libXi: update to libXi-1.7.2 Signed-off-by: Stephan Raue --- packages/x11/lib/libXi/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/x11/lib/libXi/meta b/packages/x11/lib/libXi/meta index 541f519dd2..04d287511b 100644 --- a/packages/x11/lib/libXi/meta +++ b/packages/x11/lib/libXi/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="libXi" -PKG_VERSION="1.7.1" +PKG_VERSION="1.7.2" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="OSS" From 1410bfbcc3fc53742fd1f174bd17b06787b1397f Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Wed, 3 Jul 2013 17:13:44 +0200 Subject: [PATCH 22/61] xz: update to xz-5.0.5 Signed-off-by: Stephan Raue --- packages/toolchain/archivers/xz/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/toolchain/archivers/xz/meta b/packages/toolchain/archivers/xz/meta index 137c1a7375..0c7eaaa859 100644 --- a/packages/toolchain/archivers/xz/meta +++ b/packages/toolchain/archivers/xz/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="xz" -PKG_VERSION="5.0.4" +PKG_VERSION="5.0.5" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From cab38e3042d27c5a2df27cf79922a2625152245e Mon Sep 17 00:00:00 2001 From: vpeter4 Date: Thu, 4 Jul 2013 14:53:36 +0200 Subject: [PATCH 23/61] dvbhdhomerun: update from svn (today's version 20130704) --- packages/linux-drivers/dvbhdhomerun/meta | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/linux-drivers/dvbhdhomerun/meta b/packages/linux-drivers/dvbhdhomerun/meta index af55830e4f..f2f8800b87 100644 --- a/packages/linux-drivers/dvbhdhomerun/meta +++ b/packages/linux-drivers/dvbhdhomerun/meta @@ -19,13 +19,13 @@ ################################################################################ PKG_NAME="dvbhdhomerun" -PKG_VERSION="0.0.15" +PKG_VERSION="20130704" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" PKG_SITE="http://sourceforge.net/projects/dvbhdhomerun/" -# PKG_URL="${DISTRO_SRC}/${PKG_NAME}-${PKG_VERSION}.tar.xz" -PKG_URL="$SOURCEFORGE_SRC/project/dvbhdhomerun/${PKG_NAME}_${PKG_VERSION}.tar.gz" +PKG_URL="${DISTRO_SRC}/${PKG_NAME}-${PKG_VERSION}.tar.xz" +# PKG_URL="$SOURCEFORGE_SRC/project/dvbhdhomerun/${PKG_NAME}_${PKG_VERSION}.tar.gz" PKG_DEPENDS="" PKG_BUILD_DEPENDS="toolchain linux libhdhomerun" PKG_PRIORITY="optional" From 55f35b877fbd9aab042ae0d7e86dab844abb4ebe Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Thu, 4 Jul 2013 16:16:17 +0200 Subject: [PATCH 24/61] projects/RPi/patches/linux: update RPi patches Signed-off-by: Stephan Raue --- ...tch => linux-01-RPi_support-2fa497b.patch} | 1685 ++++++++++++++++- 1 file changed, 1602 insertions(+), 83 deletions(-) rename projects/RPi/patches/linux/{linux-01-RPi_support-1fdd347.patch => linux-01-RPi_support-2fa497b.patch} (98%) diff --git a/projects/RPi/patches/linux/linux-01-RPi_support-1fdd347.patch b/projects/RPi/patches/linux/linux-01-RPi_support-2fa497b.patch similarity index 98% rename from projects/RPi/patches/linux/linux-01-RPi_support-1fdd347.patch rename to projects/RPi/patches/linux/linux-01-RPi_support-2fa497b.patch index 064e5031c7..43e658b2bd 100644 --- a/projects/RPi/patches/linux/linux-01-RPi_support-1fdd347.patch +++ b/projects/RPi/patches/linux/linux-01-RPi_support-2fa497b.patch @@ -1,7 +1,7 @@ From 6080f53cd84a39e1c8245ad0730fb1a3011f0769 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:24:19 +0100 -Subject: [PATCH 01/88] Main bcm2708 linux port +Subject: [PATCH 01/91] Main bcm2708 linux port Signed-off-by: popcornmix --- @@ -8262,7 +8262,7 @@ index b838ffc..f3a39c1 100644 From 17f5dfb674bf0a817f8f3075d4d16ea0da3e2451 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:46:17 +0100 -Subject: [PATCH 02/88] Add dwc_otg driver +Subject: [PATCH 02/91] Add dwc_otg driver Signed-off-by: popcornmix --- @@ -65344,7 +65344,7 @@ index 0000000..abcf284 From 08a588f1e93ac1f3ca0eaa232928b0a3a67a6544 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:54:32 +0100 -Subject: [PATCH 03/88] bcm2708 watchdog driver +Subject: [PATCH 03/91] bcm2708 watchdog driver Signed-off-by: popcornmix --- @@ -65781,7 +65781,7 @@ index 0000000..dd33c35 From 9aa24fa38df74e7bb63e7c5f1e6f0cd7930926f4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 19:55:09 +0100 -Subject: [PATCH 04/88] bcm2708 framebuffer driver +Subject: [PATCH 04/91] bcm2708 framebuffer driver Signed-off-by: popcornmix --- @@ -68819,7 +68819,7 @@ index 3c14e43..7626beb 100644 From 0a4f13f76c049e4819d9f80cf754e0681c299c06 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 2 Jul 2013 23:42:01 +0100 -Subject: [PATCH 05/88] bcm2708 vchiq driver +Subject: [PATCH 05/91] bcm2708 vchiq driver Signed-off-by: popcornmix --- @@ -81270,7 +81270,7 @@ index 0000000..b6bfa21 From a2d8faeec6f4dfa0f81df73ecf86d58f2d25bf8f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:31:47 +0100 -Subject: [PATCH 06/88] cma: Add vc_cma driver to enable use of CMA +Subject: [PATCH 06/91] cma: Add vc_cma driver to enable use of CMA Signed-off-by: popcornmix --- @@ -82569,7 +82569,7 @@ index 0000000..bdc9d79 From 9171ef805ac273e7eabf444b3338ed3a42d7070d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 26 Mar 2012 22:15:50 +0100 -Subject: [PATCH 07/88] bcm2708: alsa sound driver +Subject: [PATCH 07/91] bcm2708: alsa sound driver Signed-off-by: popcornmix --- @@ -84895,7 +84895,7 @@ index 0000000..af3e6eb From debf621c3999ce1d7ff13cbcc8de7beaa85aa14d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 17:26:38 +0000 -Subject: [PATCH 08/88] Allow mac address to be set in smsc95xx +Subject: [PATCH 08/91] Allow mac address to be set in smsc95xx Signed-off-by: popcornmix --- @@ -84992,7 +84992,7 @@ index 3f38ba8..60076fe 100644 From b4a73b853b9734a668aaacdb4b5935bcc883695b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 8 May 2012 23:12:13 +0100 -Subject: [PATCH 09/88] possible fix for sdcard missing status. Thank naren +Subject: [PATCH 09/91] possible fix for sdcard missing status. Thank naren --- drivers/mmc/host/sdhci-bcm2708.c | 9 +++++++++ @@ -85032,7 +85032,7 @@ index e79723d..a405114 100644 From 93779f0e37d786e6360ea7b388ddbc76c3cf4daf Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 17 May 2012 14:44:19 +0100 -Subject: [PATCH 10/88] sdcard patch improvements from naren +Subject: [PATCH 10/91] sdcard patch improvements from naren --- drivers/mmc/host/sdhci-bcm2708.c | 23 +++++++---------------- @@ -85094,7 +85094,7 @@ index a405114..ae8edf7 100644 From c79be143c5db0159c96c8301b1ae4ce50bebeeb1 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 4 Jun 2012 04:27:48 +0200 -Subject: [PATCH 11/88] sdhci-bcm2708: speed up DMA sync +Subject: [PATCH 11/91] sdhci-bcm2708: speed up DMA sync Experiments show that it doesn't really take that long to sync, so we can reduce the poll interval slightly. Might improve performance a bit. @@ -85122,7 +85122,7 @@ index ae8edf7..a6bdc25 100644 From 7e3d10edf2cb0657e032863034b280697eb92d32 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:52:04 +0200 -Subject: [PATCH 12/88] sdhci-bcm2708: remove custom clock handling +Subject: [PATCH 12/91] sdhci-bcm2708: remove custom clock handling The custom clock handling code is redundant and buggy. The MMC/SDHCI subsystem does a better job than it, so remove it for good. @@ -85223,7 +85223,7 @@ index a6bdc25..0ed4d85 100644 From 864e235c6c115a57215cfa40107b180a3d61e3a0 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:53:59 +0200 -Subject: [PATCH 13/88] sdhci-bcm2708: add additional quirks +Subject: [PATCH 13/91] sdhci-bcm2708: add additional quirks Some additional quirks are needed for correct operation. There's no SDHCI capabilities register documented, and it always reads @@ -85256,7 +85256,7 @@ index 0ed4d85..3001836 100644 From f012cd2c3be22b5ac4b6bd2e7fed17b5a47a376c Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:57:13 +0200 -Subject: [PATCH 14/88] sdhci-bcm2708: add allow_highspeed parameter +Subject: [PATCH 14/91] sdhci-bcm2708: add allow_highspeed parameter Add a parameter to disable high-speed mode for the few cards that still might have problems. High-speed mode is enabled by default. @@ -85307,7 +85307,7 @@ index 3001836..c64de21 100644 From de4d917a430e9b1c6ee890eb02e707bdbb5551b7 Mon Sep 17 00:00:00 2001 From: Grigori Goronzy Date: Mon, 11 Jun 2012 18:58:40 +0200 -Subject: [PATCH 15/88] sdhci-bcm2708: assume 50 MHz eMMC clock +Subject: [PATCH 15/91] sdhci-bcm2708: assume 50 MHz eMMC clock 80 MHz clock isnt't suited well to be dividable to get SD clocks of 25 MHz (default mode) or 50 MHz (high speed mode). 50 MHz are perfect to @@ -85336,7 +85336,7 @@ index c64de21..d174938 100644 From ca9519b849238cc00d7fdc045683476152cd680d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 16 Jun 2012 22:31:55 +0100 -Subject: [PATCH 16/88] Allow emmc clock to be specified as command line +Subject: [PATCH 16/91] Allow emmc clock to be specified as command line parameter --- @@ -85386,7 +85386,7 @@ index d174938..0ee983c 100644 From 68681c00fe7e60b3d3205d24531b2a10d8596ea7 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 16 Jun 2012 22:35:38 +0100 -Subject: [PATCH 17/88] sdhci-bcm2708: raise DMA sync timeout +Subject: [PATCH 17/91] sdhci-bcm2708: raise DMA sync timeout Commit d64b84c by accident reduced the maximum overall DMA sync timeout. The maximum overall timeout was reduced from 100ms to 30ms, @@ -85419,7 +85419,7 @@ index 0ee983c..b0cdd7d 100644 From db66a7b0ff1eb7b63ba25003405f7e67d59d497e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 22 Jun 2012 12:57:42 +0100 -Subject: [PATCH 18/88] Use ndelay rather than udelay. Thanks lb +Subject: [PATCH 18/91] Use ndelay rather than udelay. Thanks lb --- drivers/mmc/host/sdhci-bcm2708.c | 8 ++++---- @@ -85469,7 +85469,7 @@ index b0cdd7d..7bba950 100644 From 71392b4e1322e0cd972cb3e7b8efa88b37f3578e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:41:10 +0100 -Subject: [PATCH 19/88] Backport of Chris Boot's i2c and spi drivers. +Subject: [PATCH 19/91] Backport of Chris Boot's i2c and spi drivers. --- arch/arm/configs/bcmrpi_cutdown_defconfig | 10 + @@ -86761,7 +86761,7 @@ index 0000000..9f1580e From 30d5060bcf0883c2b72e362bd76d2d32ea90ba2a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 19 Jul 2012 16:00:28 +0100 -Subject: [PATCH 20/88] Add SPI_SPI_DEV module +Subject: [PATCH 20/91] Add SPI_SPI_DEV module --- arch/arm/configs/bcmrpi_defconfig | 1 + @@ -86786,7 +86786,7 @@ index 6219df3..31f5afaa 100644 From 0139a2bbd4f30ba7b59a44d7f11a38c8ae15c24c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 13 Jul 2012 18:34:18 +0100 -Subject: [PATCH 21/88] Fix for quitting X hang. Interrupted mailbox reads are +Subject: [PATCH 21/91] Fix for quitting X hang. Interrupted mailbox reads are not something we can reliably recover from, so down_interruptable is not a safe call. @@ -86824,7 +86824,7 @@ index 799a0ac..3874051 100644 From a53fbe6aab3b6e996741b0bc12b964c5c39c5da3 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 17 Jul 2012 00:48:27 +0100 -Subject: [PATCH 22/88] Add sync_after_dma module parameter +Subject: [PATCH 22/91] Add sync_after_dma module parameter --- drivers/mmc/host/sdhci-bcm2708.c | 60 +++++++++++++++++++++------------------- @@ -86944,7 +86944,7 @@ index 7bba950..3792b9f 100644 From d55680e3f7f80bb0cfd1cff2b94e2e00874e7ade Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:25:52 +0100 -Subject: [PATCH 23/88] sdhci-bcm2708: use extension FIFO to buffer DMA +Subject: [PATCH 23/91] sdhci-bcm2708: use extension FIFO to buffer DMA transfers The additional FIFO might speed up transfers in some cases. @@ -86999,7 +86999,7 @@ index 3792b9f..326b962 100644 From 55cdffec9f1d501823c9899867f775b97fa38785 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:42:49 +0100 -Subject: [PATCH 24/88] sdhci-bcm2708: use multiblock-type transfers for single +Subject: [PATCH 24/91] sdhci-bcm2708: use multiblock-type transfers for single blocks There are issues with both single block reads (missed completion) @@ -87058,7 +87058,7 @@ index e326ae2..70020e3 100644 From ce3c78e01628a7fd80625223a2377a6c58562b0e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 Aug 2012 19:02:14 +0100 -Subject: [PATCH 25/88] Add module parameter for missing_status quirk. +Subject: [PATCH 25/91] Add module parameter for missing_status quirk. sdhci-bcm2708.missing_status=0 may improve interrupt latency --- @@ -87117,7 +87117,7 @@ index c6d6bb0..8243593 100644 From 6fa717aa060b8d60006aa6bee5f223884d5f8bcf Mon Sep 17 00:00:00 2001 From: ddv2005 Date: Sun, 5 Aug 2012 10:42:12 -0400 -Subject: [PATCH 26/88] Fix spinlock recursion in sdhci-bcm2708.c +Subject: [PATCH 26/91] Fix spinlock recursion in sdhci-bcm2708.c --- drivers/mmc/host/sdhci-bcm2708.c | 14 +++++++------- @@ -87189,7 +87189,7 @@ index 8243593..7a703c2 100644 From eba5eb2eae782a05538df7404ef4dfa00403144e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 21 Aug 2012 18:49:44 +0100 -Subject: [PATCH 27/88] Read memory size for vc_mem through mailbox property +Subject: [PATCH 27/91] Read memory size for vc_mem through mailbox property channel --- @@ -87363,7 +87363,7 @@ index fd9d4be..7a7748e 100644 From 23effc5826fd97a33418646601e5aea1cef1143d Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 8 May 2013 11:46:50 +0100 -Subject: [PATCH 28/88] enabling the realtime clock 1-wire chip DS1307 and +Subject: [PATCH 28/91] enabling the realtime clock 1-wire chip DS1307 and 1-wire on GPIO4 (as a module) --- @@ -87429,7 +87429,7 @@ index 510be0b..d61e747 100644 From 6bfb747cf6be7dd680c15753d78ffcc9117fabb2 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 12 May 2013 12:27:48 +0100 -Subject: [PATCH 29/88] Add low-latency mode to sdcard driver. Disable with +Subject: [PATCH 29/91] Add low-latency mode to sdcard driver. Disable with sdhci-bcm2708.enable_llm=0. Thanks ddv2005. --- @@ -87955,7 +87955,7 @@ index f3a39c1..58bfab0 100644 From 56b675fceebb97e27686cdfaa918591d28e6f1bb Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:46:42 +0100 -Subject: [PATCH 30/88] Add FIQ patch to dwc_otg driver. Enable with +Subject: [PATCH 30/91] Add FIQ patch to dwc_otg driver. Enable with dwc_otg.fiq_fix_enable=1. Should give about 10% more ARM performance. Thanks to Gordon and Costas @@ -89118,7 +89118,7 @@ index a7e9076..bb1c42d 100644 From d2c50dbe9f75e1b89aadfb87eafea7874ec0fe63 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 12 Apr 2013 23:58:47 +0100 -Subject: [PATCH 33/88] Add verious user config requests. +Subject: [PATCH 33/91] Add verious user config requests. CONFIG_DEVTMPFS_MOUNT, CONFIG_NFS_V4_1=y CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y, drbd and IPSEC modules @@ -89531,7 +89531,7 @@ index 31f5afaa..ef43466 100644 From 41886846d6954160e12a8a615670aa75c008f74c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 8 Sep 2012 15:17:53 +0100 -Subject: [PATCH 34/88] Avoid dynamic memory allocation for channel lock in USB +Subject: [PATCH 34/91] Avoid dynamic memory allocation for channel lock in USB driver. Thanks ddv2005. --- @@ -89641,7 +89641,7 @@ index f1658fa..21e8f09 100644 From f7ac5d29e294fd756c952b0a58fba1ede77221e5 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:49:20 +0100 -Subject: [PATCH 35/88] Add cpufreq driver +Subject: [PATCH 35/91] Add cpufreq driver --- arch/arm/Kconfig | 1 + @@ -90171,7 +90171,7 @@ index 0000000..aa6fc66 From 9a13f810caf54c783f29731af4a50da242bca676 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 8 Apr 2013 21:12:48 +0100 -Subject: [PATCH 36/88] Add NAK holdoff scheme. Enabled by default, disable +Subject: [PATCH 36/91] Add NAK holdoff scheme. Enabled by default, disable with dwc_otg.nak_holdoff_enable=0. Thanks gsh --- @@ -90384,7 +90384,7 @@ index ac10323..e6b2a7b 100644 From 8a29d2cd7f9c46ad76010620b3fca8082dd34f1f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 26 Mar 2013 19:24:24 +0000 -Subject: [PATCH 37/88] Added hwmon/thermal driver for reporting core +Subject: [PATCH 37/91] Added hwmon/thermal driver for reporting core temperature. Thanks Dorian --- @@ -90911,7 +90911,7 @@ index 0000000..f1ecdb2 From f10623b14323b7fd230da611043b7098b0353cba Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 12 Apr 2013 23:59:27 +0100 -Subject: [PATCH 38/88] Add config options for thermal sensor, L2TP, +Subject: [PATCH 38/91] Add config options for thermal sensor, L2TP, RT2800USB_UNKNOWN, and various I2C and SPI RTCs. Tidy of thermal driver. --- @@ -91082,7 +91082,7 @@ index f1ecdb2..3f9a733 100644 From d7c871a20faf02c4a9e4fa9434f7109c870de68a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 28 Mar 2013 01:19:54 +0000 -Subject: [PATCH 39/88] 2708fb: Remove some unnecessary dmesg output. +Subject: [PATCH 39/91] 2708fb: Remove some unnecessary dmesg output. --- drivers/video/bcm2708_fb.c | 34 +++++++++++++++++++--------------- @@ -91212,7 +91212,7 @@ index c82dd90..08d9238 100644 From 80027aa78529bb27b8b368eecdc73ddb99b87dca Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 28 Mar 2013 01:20:34 +0000 -Subject: [PATCH 40/88] cpufreq: Remove some unnecessary dmesg output. +Subject: [PATCH 40/91] cpufreq: Remove some unnecessary dmesg output. --- drivers/cpufreq/bcm2835-cpufreq.c | 2 +- @@ -91238,7 +91238,7 @@ index aa6fc66..6ff1edb 100755 From c1d625a495bda54a60b56a5bd0f5449b7ac53d49 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 17 Sep 2012 22:57:29 +0100 -Subject: [PATCH 41/88] Switch to powersave governor. We'll enable ondemand in +Subject: [PATCH 41/91] Switch to powersave governor. We'll enable ondemand in the distribution --- @@ -91269,7 +91269,7 @@ index d11f688..c1afa47 100644 From c33b7bcc3a6de49b94381096f6a0c2e4879682af Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Apr 2013 12:16:36 +0100 -Subject: [PATCH 42/88] Enable multiple ALSA channels +Subject: [PATCH 42/91] Enable multiple ALSA channels --- arch/arm/mach-bcm2708/bcm2708.c | 54 ++++++++++++++++++++++++++++++++++++----- @@ -91347,7 +91347,7 @@ index 2875cd2..27e9553 100644 From 86cd9547f7bc2f8c427e34527be3d8e27a44f298 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Oct 2012 20:08:19 +0100 -Subject: [PATCH 43/88] set i2c speed via module-parameter or menuconfig. +Subject: [PATCH 43/91] set i2c speed via module-parameter or menuconfig. Thanks FrankBoesing --- @@ -91425,7 +91425,7 @@ index 7cae615..3391889 100644 From dc1c709396bd2711af5c4e285a223bb0f026244f Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Oct 2012 21:31:48 +0100 -Subject: [PATCH 44/88] Allow the number of cycles delay between sdcard +Subject: [PATCH 44/91] Allow the number of cycles delay between sdcard peripheral writes to be specified on command line with sdhci-bcm2708.cycle_delay @@ -91470,7 +91470,7 @@ index 7ce2829..ffd7310 100644 From c372f2d12122085d55d03268a0cb4c2d670a7064 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 17 Apr 2013 14:37:25 +0100 -Subject: [PATCH 45/88] Fix vc-mem by using module parameters +Subject: [PATCH 45/91] Fix vc-mem by using module parameters --- arch/arm/mach-bcm2708/bcm2708.c | 12 ++--- @@ -91708,7 +91708,7 @@ index 5ef68b3..057f74f 100644 From 9578fd3da96819661e04f6d856c3fd0cb4d4dcdf Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 5 Oct 2012 22:44:47 +0100 -Subject: [PATCH 46/88] Support dummy vc-mem ioctl used by vcdbg +Subject: [PATCH 46/91] Support dummy vc-mem ioctl used by vcdbg --- arch/arm/mach-bcm2708/include/mach/vc_mem.h | 1 + @@ -91759,7 +91759,7 @@ index 057f74f..aeae4d5 100644 From 321f91d1c01a6dfb91ccc3a05d01f487ddb67c5e Mon Sep 17 00:00:00 2001 From: dero Date: Mon, 19 Nov 2012 12:46:06 +0100 -Subject: [PATCH 47/88] Lazy CRC quirk: Implemented retrying mechanisms for SD +Subject: [PATCH 47/91] Lazy CRC quirk: Implemented retrying mechanisms for SD SSR and SCR, disabled missing_status and spurious CRC ACMD51 quirks by default (should be fixed by the retrying-mechanishm) @@ -91994,7 +91994,7 @@ index ffd7310..3556ed3 100644 From 5fd69f8d1c8b53b52319bb712c9d925b429caa5e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 28 Mar 2013 00:10:32 +0000 -Subject: [PATCH 48/88] bcm2708: Add vc_cma driver to enable use of CMA +Subject: [PATCH 48/91] bcm2708: Add vc_cma driver to enable use of CMA --- arch/arm/mach-bcm2708/bcm2708.c | 18 ++++++++++++++++++ @@ -92058,7 +92058,7 @@ index e010515..9d38d40 100644 From b243d68cd0e3e1ac8fe4d9313e44a6c94886ee5a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 24 Oct 2012 22:00:43 +0100 -Subject: [PATCH 49/88] Fix reboot with new restart method of machine driver +Subject: [PATCH 49/91] Fix reboot with new restart method of machine driver --- arch/arm/mach-bcm2708/bcm2708.c | 18 +++++++++++++++++- @@ -92139,7 +92139,7 @@ index bc9d458..2d0b821 100644 From dafd5e9e557ffa7494f6a5c11ab62b5c2dab6139 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Sun, 4 Nov 2012 15:55:01 +0000 -Subject: [PATCH 50/88] Make sure we wait for the reset to finish +Subject: [PATCH 50/91] Make sure we wait for the reset to finish --- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 2 ++ @@ -92165,7 +92165,7 @@ index 3e762e2..e8c91e7 100644 From cf9d13622e80e613716a03de85045247d7382bfd Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 19 Nov 2012 18:27:05 +0000 -Subject: [PATCH 51/88] Add Simon Hall's dma helper module, useful in future +Subject: [PATCH 51/91] Add Simon Hall's dma helper module, useful in future for X acceleration --- @@ -93506,7 +93506,7 @@ index 0000000..5cb1335 From 6ffd27277fcf553852d92aa961714aef6104d98e Mon Sep 17 00:00:00 2001 From: Aron Szabo Date: Sat, 16 Jun 2012 12:15:55 +0200 -Subject: [PATCH 52/88] lirc: added support for RaspberryPi GPIO +Subject: [PATCH 52/91] lirc: added support for RaspberryPi GPIO --- drivers/staging/media/lirc/Kconfig | 6 + @@ -94244,7 +94244,7 @@ index 0000000..96acab0 From bcf9c84e3c30f79d9beae9bad42f7a18ccd15c3c Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 25 Nov 2012 18:28:09 +0000 -Subject: [PATCH 53/88] Allow mailbox driver to be called from user code though +Subject: [PATCH 53/91] Allow mailbox driver to be called from user code though ioctl --- @@ -94484,7 +94484,7 @@ index 468fdef..09b78b5 100644 From f7048aa2a847de942629ce21d11345a57c2e66e4 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 11 Dec 2012 18:23:03 +0000 -Subject: [PATCH 54/88] Default to dwc_otp.lpm_enable=0 +Subject: [PATCH 54/91] Default to dwc_otp.lpm_enable=0 --- drivers/usb/host/dwc_otg/dwc_otg_driver.c | 2 +- @@ -94510,7 +94510,7 @@ index d353a9a..cea8fcb 100644 From a49eddff6d55578a3caa1d2e5cd11c92df4f278a Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 11 Dec 2012 19:04:27 +0000 -Subject: [PATCH 55/88] Increase default coherent pool so vchiq starts up +Subject: [PATCH 55/91] Increase default coherent pool so vchiq starts up --- arch/arm/mach-bcm2708/bcm2708.c | 4 +--- @@ -94538,7 +94538,7 @@ index 9f456e9..87fd348 100644 From f5adca2359cd6b7bb40d41ddc66e290141e05a58 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 7 Jan 2013 21:34:59 +0000 -Subject: [PATCH 56/88] Add mutex around bcm_mailbox_property function +Subject: [PATCH 56/91] Add mutex around bcm_mailbox_property function --- arch/arm/mach-bcm2708/vcio.c | 5 ++++- @@ -94581,7 +94581,7 @@ index 09b78b5..599eb63 100644 From de86ee42fc5f624a9879bce5b2603c0555741016 Mon Sep 17 00:00:00 2001 From: P33M Date: Wed, 9 Jan 2013 16:12:04 +0000 -Subject: [PATCH 57/88] dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent +Subject: [PATCH 57/91] dwc_otg: fix bug in dwc_otg_hcd.c resulting in silent kernel memory corruption, escalating to OOPS under high USB load. --- @@ -94621,7 +94621,7 @@ index e6b2a7b..b337e1b 100644 From f6156c223969196d360586d6e09d81a1fe85e8de Mon Sep 17 00:00:00 2001 From: popcornmix Date: Mon, 21 Jan 2013 23:03:53 +0000 -Subject: [PATCH 58/88] Return error value from bcm2708_setup_state. Thanks +Subject: [PATCH 58/91] Return error value from bcm2708_setup_state. Thanks notro --- @@ -94647,7 +94647,7 @@ index 9f1580e..8513704 100644 From 3c635bdecfe28dbbaabaf0f7afc9f70066d470ab Mon Sep 17 00:00:00 2001 From: Kamal Mostafa Date: Mon, 22 Oct 2012 15:52:44 -0700 -Subject: [PATCH 59/88] spi/spi-bcm2708: respect per-transfer SPI clock +Subject: [PATCH 59/91] spi/spi-bcm2708: respect per-transfer SPI clock speed_hz value The bcm2708 SPI driver's bcm2708_process_transfer() was ignoring the @@ -94695,7 +94695,7 @@ index 8513704..b74aa32 100644 From 43d6cf5febd600a9ef11ba7b8656519d2c356346 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 3 Jul 2013 00:51:55 +0100 -Subject: [PATCH 60/88] Add hwrng (hardware random number generator) driver +Subject: [PATCH 60/91] Add hwrng (hardware random number generator) driver --- arch/arm/mach-bcm2708/include/mach/platform.h | 1 + @@ -94876,7 +94876,7 @@ index 0000000..1ffa7d7 From ee3463d963f75ec8d1b13d81d7ab583255e1d890 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 7 Feb 2013 17:04:13 +0000 -Subject: [PATCH 61/88] Add missing newlines to log messages +Subject: [PATCH 61/91] Add missing newlines to log messages --- drivers/cpufreq/bcm2835-cpufreq.c | 20 ++++++++++---------- @@ -94978,7 +94978,7 @@ index 6ff1edb..5a19212 100755 From 9f3f17339f5165e1060883db422398a7f165c2be Mon Sep 17 00:00:00 2001 From: Technion Date: Mon, 11 Feb 2013 22:08:53 +1100 -Subject: [PATCH 62/88] Changed wording on logging. Previously, we received +Subject: [PATCH 62/91] Changed wording on logging. Previously, we received errors like this: mmc0: could read SD Status register (SSR) at the 3th attempt A more sensible response is now returned. A typo also fixed in comments. @@ -95016,7 +95016,7 @@ index 1ee6cf3..90228f9 100644 From bbdfaf49aa05257794d7ddc19717e3e1f035285a Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 15 Feb 2013 22:36:47 +0000 -Subject: [PATCH 63/88] dwc_otg: Fix unsafe access of QTD during URB enqueue +Subject: [PATCH 63/91] dwc_otg: Fix unsafe access of QTD during URB enqueue In dwc_otg_hcd_urb_enqueue during qtd creation, it was possible that the transaction could complete almost immediately after the qtd was assigned @@ -95106,7 +95106,7 @@ index b337e1b..b3e6e52 100644 From f385db71cd990d3e6d5e7020127357afabe0b4e4 Mon Sep 17 00:00:00 2001 From: P33M Date: Fri, 15 Feb 2013 22:38:40 +0000 -Subject: [PATCH 64/88] dwc_otg: Fix incorrect URB allocation error handling +Subject: [PATCH 64/91] dwc_otg: Fix incorrect URB allocation error handling If the memory allocation for a dwc_otg_urb failed, the kernel would OOPS because for some reason a member of the *unallocated* struct was set to @@ -95150,7 +95150,7 @@ index e653d84..fcec97f 100644 From 9cb0f13eb3ffc4f82a8756f6b79e3653406f529b Mon Sep 17 00:00:00 2001 From: pjennings Date: Wed, 20 Feb 2013 17:51:43 -0600 -Subject: [PATCH 65/88] Added inverted transmitter support +Subject: [PATCH 65/91] Added inverted transmitter support --- drivers/staging/media/lirc/lirc_rpi.c | 17 +++++++++++------ @@ -95234,7 +95234,7 @@ index 96acab0..5bb0dfe 100644 From c332df8c672e573f6ba42e011fa9d2a6fc5ce527 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sun, 24 Feb 2013 16:30:57 +0000 -Subject: [PATCH 66/88] Add retry on error and tidy of temperature driver +Subject: [PATCH 66/91] Add retry on error and tidy of temperature driver --- drivers/thermal/bcm2835-thermal.c | 78 ++++++++++++++------------------------- @@ -95364,7 +95364,7 @@ index 3f9a733..85fceb5 100644 From 01690a39d2700286bb67bed762b88b4895a40c76 Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 28 Feb 2013 16:52:51 +0000 -Subject: [PATCH 67/88] dwc_otg: fix potential use-after-free case in interrupt +Subject: [PATCH 67/91] dwc_otg: fix potential use-after-free case in interrupt handler If a transaction had previously aborted, certain interrupts are @@ -95399,7 +95399,7 @@ index e8c91e7..0c81a64 100644 From d3ebe68a2b7629d107b31ae0644ebce63ccee58a Mon Sep 17 00:00:00 2001 From: P33M Date: Sun, 3 Mar 2013 14:45:53 +0000 -Subject: [PATCH 68/88] dwc_otg: add handling of SPLIT transaction data toggle +Subject: [PATCH 68/91] dwc_otg: add handling of SPLIT transaction data toggle errors Previously a data toggle error on packets from a USB1.1 device behind @@ -95457,7 +95457,7 @@ index 0c81a64..16e8c6c 100644 From 56cbbf3c61827a1a3e795ba0d2e8ecaa9e3e73da Mon Sep 17 00:00:00 2001 From: popcornmix Date: Wed, 1 May 2013 21:14:28 +0100 -Subject: [PATCH 69/88] Add bitbanging pullups, use them for w1-gpio +Subject: [PATCH 69/91] Add bitbanging pullups, use them for w1-gpio Allows parasite power to work, uses module option pullup=1 --- @@ -95599,7 +95599,7 @@ index e10acc2..667fdd5 100644 From 8af17a0ad8e286c71468d15076f9209791971149 Mon Sep 17 00:00:00 2001 From: notro Date: Sat, 26 Jan 2013 20:38:03 +0100 -Subject: [PATCH 70/88] spi-bcm2708: add 9-bit support using LoSSI mode +Subject: [PATCH 70/91] spi-bcm2708: add 9-bit support using LoSSI mode --- drivers/spi/spi-bcm2708.c | 30 ++++++++++++++++++++++++++++-- @@ -95672,7 +95672,7 @@ index b74aa32..abaa5a6 100644 From ddd6ba1219a97ec27e002ecc6bc8d41bc0b8e591 Mon Sep 17 00:00:00 2001 From: P33M Date: Thu, 21 Mar 2013 19:36:17 +0000 -Subject: [PATCH 71/88] dwc_otg: implement tasklet for returning URBs to +Subject: [PATCH 71/91] dwc_otg: implement tasklet for returning URBs to usbcore hcd layer The dwc_otg driver interrupt handler for transfer completion will spend @@ -95917,7 +95917,7 @@ index 9702f81..7bb133a 100644 From f33f65ca756725be996e508fba215f7d5457341b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 16 Apr 2013 15:36:01 +0100 -Subject: [PATCH 73/88] Add v6wbi_flush_kern_tlb_range to allow zsmalloc to be +Subject: [PATCH 73/91] Add v6wbi_flush_kern_tlb_range to allow zsmalloc to be built as a module --- @@ -95943,7 +95943,7 @@ index 60d3b73..cba4d28 100644 From f79f0fd16fe7e180db35b21566fbb9adf9ff9978 Mon Sep 17 00:00:00 2001 From: P33M Date: Mon, 22 Apr 2013 00:08:36 +0100 -Subject: [PATCH 74/88] dwc_otg: fix NAK holdoff and allow on split +Subject: [PATCH 74/91] dwc_otg: fix NAK holdoff and allow on split transactions only This corrects a bug where if a single active non-periodic endpoint @@ -96016,7 +96016,7 @@ index 91eefecd..eaa8f38 100644 From 4de35edee9be469614d1632a198cfd800ae5b25e Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 26 Apr 2013 10:08:31 -0700 -Subject: [PATCH 75/88] Merge pull request #286 from +Subject: [PATCH 75/91] Merge pull request #286 from martinezjavier/rpi-3.6.y-dev add mmap support and some cleanups to bcm2835 ALSA driver @@ -96500,7 +96500,7 @@ index b966e28..08c763d 100755 From 911b47b068b6e7e15f1abbc918b28b294856870b Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 7 May 2013 22:20:24 +0100 -Subject: [PATCH 76/88] Add quick config. +Subject: [PATCH 76/91] Add quick config. This is designed for quick compiling when developing. No modules are needed and it includes all Pi specific drivers @@ -96719,7 +96719,7 @@ index 0000000..e5efe75 From aacfe85df55f02c51b405a01f4391a2eb790fdff Mon Sep 17 00:00:00 2001 From: popcornmix Date: Fri, 10 May 2013 19:42:38 +0100 -Subject: [PATCH 77/88] mmc: suppress sdcard warnings we are happy about by +Subject: [PATCH 77/91] mmc: suppress sdcard warnings we are happy about by default --- @@ -96788,7 +96788,7 @@ index 3556ed3..c2409b9 100644 From 84d80662cd68320b63ed25cfa4f611b96f2e6f82 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Tue, 14 May 2013 11:42:25 +0100 -Subject: [PATCH 78/88] Allow reboot=q on command line to set a flag that +Subject: [PATCH 78/91] Allow reboot=q on command line to set a flag that bootcode.bin can use to boot from alternate partition --- @@ -96822,7 +96822,7 @@ index 87fd348..1ed4d73 100644 From d88ada9ddccea359ee02e044f86cd9e33aecc02f Mon Sep 17 00:00:00 2001 From: hutorny Date: Mon, 13 May 2013 10:26:14 +0300 -Subject: [PATCH 80/88] Update bcm2708.c to use CONFIG_BCM2708_SPIDEV rather +Subject: [PATCH 80/91] Update bcm2708.c to use CONFIG_BCM2708_SPIDEV rather than CONFIG_SPI --- @@ -96875,7 +96875,7 @@ index 1ed4d73..68c577a 100644 From 8b2532eaea9f27d74973aa563c209e95a6436377 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Sat, 8 Jun 2013 22:14:13 +0100 -Subject: [PATCH 82/88] Only init gpio pins of selected i2c bus +Subject: [PATCH 82/91] Only init gpio pins of selected i2c bus --- drivers/i2c/busses/i2c-bcm2708.c | 8 +++++--- @@ -96922,7 +96922,7 @@ index 3391889..edc90c0 100644 From b87736ed6ed5d4d5cc534f679ab8b832e693d452 Mon Sep 17 00:00:00 2001 From: popcornmix Date: Thu, 13 Jun 2013 16:46:54 +0100 -Subject: [PATCH 83/88] Avoid responding to unexpected I2C interrupts +Subject: [PATCH 83/91] Avoid responding to unexpected I2C interrupts --- drivers/i2c/busses/i2c-bcm2708.c | 6 ++++++ @@ -96959,7 +96959,7 @@ index edc90c0..33f4e7d 100644 From c9e3680fe3d1b66ec5e8947b52cf582001d39690 Mon Sep 17 00:00:00 2001 From: Harm Hanemaaijer Date: Thu, 20 Jun 2013 20:21:39 +0200 -Subject: [PATCH 84/88] Speed up console framebuffer imageblit function +Subject: [PATCH 84/91] Speed up console framebuffer imageblit function Especially on platforms with a slower CPU but a relatively high framebuffer fill bandwidth, like current ARM devices, the existing @@ -97174,7 +97174,7 @@ index baed57d..ce91bf2 100644 From 37fa288e60b2f5cdfde5a392504bf1097699c0d8 Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 13:32:11 +0300 -Subject: [PATCH 85/88] fbdev: add FBIOCOPYAREA ioctl +Subject: [PATCH 85/91] fbdev: add FBIOCOPYAREA ioctl Based on the patch authored by Ali Gholami Rudi at https://lkml.org/lkml/2009/7/13/153 @@ -97273,7 +97273,7 @@ index fb795c3..fa72af0 100644 From 511c5dd60c2023b810e0f419fd37b2bc3f078cdc Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Mon, 17 Jun 2013 16:00:25 +0300 -Subject: [PATCH 86/88] bcm2708_fb: DMA acceleration for fb_copyarea +Subject: [PATCH 86/91] bcm2708_fb: DMA acceleration for fb_copyarea Based on http://www.raspberrypi.org/phpBB3/viewtopic.php?p=62425#p62425 Also used Simon's dmaer_master module as a reference for tweaking DMA @@ -97520,7 +97520,7 @@ index 08d9238..c10c5ee 100644 From 44aa1f6534dbd06e3529d8496a1dd494be5f9b98 Mon Sep 17 00:00:00 2001 From: Mike Bradley Date: Mon, 17 Jun 2013 11:31:42 -0700 -Subject: [PATCH 87/88] dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held +Subject: [PATCH 87/91] dwc_otg: Call usb_hcd_unlink_urb_from_ep with lock held in completion handler usb_hcd_unlink_urb_from_ep must be called with the HCD lock held. Calling it @@ -97610,7 +97610,7 @@ index 7bb133a..fef557d 100644 From 1fdd347791b4e01e811427ab5974b3659b805982 Mon Sep 17 00:00:00 2001 From: Gordon Hollingworth Date: Thu, 4 Apr 2013 11:05:21 +0100 -Subject: [PATCH 88/88] USB fix using a FIQ to implement split transactions +Subject: [PATCH 88/91] USB fix using a FIQ to implement split transactions This commit adds a FIQ implementaion that schedules the split transactions using a FIQ so we don't get @@ -99028,3 +99028,1522 @@ index 27061d3..9720937 100644 -- 1.8.1.6 + +From 03c3eeff807818fc5d7587e556b86f4ea705e93c Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 3 Jul 2013 11:39:46 +0100 +Subject: [PATCH 89/91] dwc_otg: fix device attributes and avoid kernel + warnings on boot + +--- + drivers/usb/host/dwc_otg/dwc_otg_attr.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c +index 95eb7f8..9602fda 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_attr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c +@@ -909,7 +909,7 @@ static ssize_t regdump_show(struct device *_dev, + return sprintf(buf, "Register Dump\n"); + } + +-DEVICE_ATTR(regdump, S_IRUGO | S_IWUSR, regdump_show, 0); ++DEVICE_ATTR(regdump, S_IRUGO, regdump_show, 0); + + /** + * Dump global registers and either host or device registers (depending on the +@@ -925,7 +925,7 @@ static ssize_t spramdump_show(struct device *_dev, + return sprintf(buf, "SPRAM Dump\n"); + } + +-DEVICE_ATTR(spramdump, S_IRUGO | S_IWUSR, spramdump_show, 0); ++DEVICE_ATTR(spramdump, S_IRUGO, spramdump_show, 0); + + /** + * Dump the current hcd state. +@@ -940,7 +940,7 @@ static ssize_t hcddump_show(struct device *_dev, + return sprintf(buf, "HCD Dump\n"); + } + +-DEVICE_ATTR(hcddump, S_IRUGO | S_IWUSR, hcddump_show, 0); ++DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, 0); + + /** + * Dump the average frame remaining at SOF. This can be used to +@@ -958,7 +958,7 @@ static ssize_t hcd_frrem_show(struct device *_dev, + return sprintf(buf, "HCD Dump Frame Remaining\n"); + } + +-DEVICE_ATTR(hcd_frrem, S_IRUGO | S_IWUSR, hcd_frrem_show, 0); ++DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, 0); + + /** + * Displays the time required to read the GNPTXFSIZ register many times (the +@@ -986,7 +986,7 @@ static ssize_t rd_reg_test_show(struct device *_dev, + RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); + } + +-DEVICE_ATTR(rd_reg_test, S_IRUGO | S_IWUSR, rd_reg_test_show, 0); ++DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, 0); + + /** + * Displays the time required to write the GNPTXFSIZ register many times (the +@@ -1014,7 +1014,7 @@ static ssize_t wr_reg_test_show(struct device *_dev, + RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); + } + +-DEVICE_ATTR(wr_reg_test, S_IRUGO | S_IWUSR, wr_reg_test_show, 0); ++DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0); + + #ifdef CONFIG_USB_DWC_OTG_LPM + +-- +1.8.1.6 + + +From 1c11989d30ada6ad6a8de30998d08fdc29d2d406 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 3 Jul 2013 13:39:19 +0100 +Subject: [PATCH 90/91] Revert "USB fix using a FIQ to implement split + transactions" + +This reverts commit 1fdd347791b4e01e811427ab5974b3659b805982. +--- + .../usb/host/dwc_common_port/dwc_common_linux.c | 7 +- + drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c | 37 +- + drivers/usb/host/dwc_otg/dwc_otg_driver.c | 6 +- + drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 125 +---- + drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 20 +- + drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 538 +++------------------ + drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 18 +- + drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c | 31 +- + drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h | 26 +- + drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c | 2 +- + 10 files changed, 114 insertions(+), 696 deletions(-) + +diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c +index 0812d3a..6814e51 100644 +--- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c ++++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c +@@ -580,12 +580,7 @@ void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value) + + void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) + { +- unsigned long flags; +- +- local_irq_save(flags); +- local_fiq_disable(); + writel((readl(reg) & ~clear_mask) | set_mask, reg); +- local_irq_restore(flags); + } + + #if 0 +@@ -1306,7 +1301,7 @@ int DWC_WORKQ_PENDING(dwc_workq_t *wq) + EXPORT_SYMBOL(__DWC_DEBUG); + #endif + +-EXPORT_SYMBOL(__DWC_DMA_ALLOC); ++EXPORT_SYMBOL(__DWC_DMA_ALLOC); + EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); + EXPORT_SYMBOL(__DWC_DMA_FREE); + EXPORT_SYMBOL(__DWC_ALLOC); +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +index b5a007d..b861b55 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +@@ -47,6 +47,8 @@ + #include "dwc_otg_hcd.h" + #include "dwc_otg_mphi_fix.h" + ++extern bool fiq_fix_enable; ++ + #ifdef DEBUG + inline const char *op_state_str(dwc_otg_core_if_t * core_if) + { +@@ -1319,7 +1321,7 @@ static int32_t dwc_otg_handle_lpm_intr(dwc_otg_core_if_t * core_if) + /** + * This function returns the Core Interrupt register. + */ +-static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gintmsk_data_t *reenable_gintmsk) ++static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) + { + gahbcfg_data_t gahbcfg = {.d32 = 0 }; + gintsts_data_t gintsts; +@@ -1336,33 +1338,19 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gin + gintmsk_common.b.lpmtranrcvd = 1; + #endif + gintmsk_common.b.restoredone = 1; +- if(dwc_otg_is_device_mode(core_if)) +- { +- /** @todo: The port interrupt occurs while in device +- * mode. Added code to CIL to clear the interrupt for now! +- */ +- gintmsk_common.b.portintr = 1; +- } ++ /** @todo: The port interrupt occurs while in device ++ * mode. Added code to CIL to clear the interrupt for now! ++ */ ++ gintmsk_common.b.portintr = 1; ++ + gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); + gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); +- { +- unsigned long flags; +- +- // Re-enable the saved interrupts +- local_irq_save(flags); +- local_fiq_disable(); +- gintmsk.d32 |= gintmsk_common.d32; +- gintsts_saved.d32 &= ~gintmsk_common.d32; +- reenable_gintmsk->d32 = gintmsk.d32; +- local_irq_restore(flags); +- } +- + gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); + + #ifdef DEBUG + /* if any common interrupts set */ + if (gintsts.d32 & gintmsk_common.d32) { +- DWC_DEBUGPL(DBG_ANY, "common_intr: gintsts=%08x gintmsk=%08x\n", ++ DWC_DEBUGPL(DBG_ANY, "gintsts=%08x gintmsk=%08x\n", + gintsts.d32, gintmsk.d32); + } + #endif +@@ -1406,7 +1394,6 @@ int32_t dwc_otg_handle_common_intr(void *dev) + { + int retval = 0; + gintsts_data_t gintsts; +- gintmsk_data_t reenable_gintmsk; + gpwrdn_data_t gpwrdn = {.d32 = 0 }; + dwc_otg_device_t *otg_dev = dev; + dwc_otg_core_if_t *core_if = otg_dev->core_if; +@@ -1428,7 +1415,7 @@ int32_t dwc_otg_handle_common_intr(void *dev) + } + + if (core_if->hibernation_suspend <= 0) { +- gintsts.d32 = dwc_otg_read_common_intr(core_if, &reenable_gintmsk); ++ gintsts.d32 = dwc_otg_read_common_intr(core_if); + + if (gintsts.b.modemismatch) { + retval |= dwc_otg_handle_mode_mismatch_intr(core_if); +@@ -1525,12 +1512,8 @@ int32_t dwc_otg_handle_common_intr(void *dev) + gintsts.b.portintr = 1; + DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); + retval |= 1; +- reenable_gintmsk.b.portintr = 1; + + } +- +- DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, reenable_gintmsk.d32); +- + } else { + DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); + +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c +index 6c89a69..cea8fcb 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c +@@ -242,8 +242,7 @@ struct dwc_otg_driver_module_params { + + //Global variable to switch the fiq fix on or off (declared in bcm2708.c) + extern bool fiq_fix_enable; +-// Global variable to enable the split transaction fix +-bool fiq_split_enable = true; ++ + //Global variable to switch the nak holdoff on or off + bool nak_holdoff_enable = true; + +@@ -1091,7 +1090,6 @@ static int __init dwc_otg_driver_init(void) + } + printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled"); + printk(KERN_DEBUG "dwc_otg: NAK holdoff %s\n", nak_holdoff_enable ? "enabled":"disabled"); +- printk(KERN_DEBUG "dwc_otg: FIQ split fix %s\n", fiq_split_enable ? "enabled":"disabled"); + + error = driver_create_file(drv, &driver_attr_version); + #ifdef DEBUG +@@ -1376,8 +1374,6 @@ static void __exit dwc_otg_driver_cleanup(void) + MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix"); + module_param(nak_holdoff_enable, bool, 0444); + MODULE_PARM_DESC(nak_holdoff_enable, "Enable the NAK holdoff"); +-module_param(fiq_split_enable, bool, 0444); +-MODULE_PARM_DESC(fiq_split_enable, "Enable the FIQ fix on split transactions"); + + /** @page "Module Parameters" + * +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +index af9108c..9c2e71a 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -45,7 +45,6 @@ + + #include "dwc_otg_hcd.h" + #include "dwc_otg_regs.h" +-#include "dwc_otg_mphi_fix.h" + + extern bool microframe_schedule, nak_holdoff_enable; + +@@ -582,8 +581,6 @@ int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, + */ + dwc_otg_hc_halt(hcd->core_if, qh->channel, + DWC_OTG_HC_XFER_URB_DEQUEUE); +- +- dwc_otg_hcd_release_port(hcd, qh); + } + } + +@@ -719,8 +716,6 @@ static void completion_tasklet_func(void *ptr) + + usb_hcd_giveback_urb(hcd->priv, urb, urb->status); + +- fiq_print(FIQDBG_PORTHUB, "COMPLETE"); +- + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); + } + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); +@@ -984,10 +979,6 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) + hcd->frame_list = NULL; + hcd->frame_list_dma = 0; + hcd->periodic_qh_count = 0; +- +- DWC_MEMSET(hcd->hub_port, 0, sizeof(hcd->hub_port)); +- DWC_MEMSET(hcd->hub_port_alloc, -1, sizeof(hcd->hub_port_alloc)); +- + out: + return retval; + } +@@ -1133,12 +1124,7 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) + uint32_t hub_addr, port_addr; + hc->do_split = 1; + hc->xact_pos = qtd->isoc_split_pos; +- /* We don't need to do complete splits anymore */ +- if(fiq_split_enable) +- hc->complete_split = qtd->complete_split = 0; +- else +- hc->complete_split = qtd->complete_split; +- ++ hc->complete_split = qtd->complete_split; + hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &port_addr); + hc->hub_addr = (uint8_t) hub_addr; + hc->port_addr = (uint8_t) port_addr; +@@ -1285,62 +1271,6 @@ static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) + hc->qh = qh; + } + +-/* +-** Check the transaction to see if the port / hub has already been assigned for +-** a split transaction +-** +-** Return 0 - Port is already in use +-*/ +-int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) +-{ +- uint32_t hub_addr, port_addr; +- +- if(!fiq_split_enable) +- return 0; +- +- hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr); +- +- if(hcd->hub_port[hub_addr] & (1 << port_addr)) +- { +- fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count); +- +- qh->skip_count++; +- +- if(qh->skip_count > 40000) +- { +- printk_once(KERN_ERR "Error: Having to skip port allocation"); +- local_fiq_disable(); +- BUG(); +- return 0; +- } +- return 1; +- } +- else +- { +- qh->skip_count = 0; +- hcd->hub_port[hub_addr] |= 1 << port_addr; +- fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num); +- hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd); +- return 0; +- } +-} +-void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) +-{ +- uint32_t hub_addr, port_addr; +- +- if(!fiq_split_enable) +- return; +- +- hcd->fops->hub_info(hcd, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->priv, &hub_addr, &port_addr); +- +- hcd->hub_port[hub_addr] &= ~(1 << port_addr); +- hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1; +- +- fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num); +- +-} +- +- + /** + * This function selects transactions from the HCD transfer schedule and + * assigns them to available host channels. It is called from HCD interrupt +@@ -1374,22 +1304,11 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) + + while (qh_ptr != &hcd->periodic_sched_ready && + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { +- +- qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); +- +- if(qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh)) +- { +- qh_ptr = DWC_LIST_NEXT(qh_ptr); +- g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1); +- continue; +- } +- + if (microframe_schedule) { + // Make sure we leave one channel for non periodic transactions. + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + if (hcd->available_host_channels <= 1) { + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); +- if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh); + break; + } + hcd->available_host_channels--; +@@ -1410,6 +1329,8 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, + &qh->qh_list_entry); + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ ++ ret_val = DWC_OTG_TRANSACTION_PERIODIC; + } + + /* +@@ -1448,19 +1369,10 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) + qh->nak_frame = 0xffff; + } + } +- +- if (qh->do_split && dwc_otg_hcd_allocate_port(hcd, qh)) +- { +- g_next_sched_frame = dwc_frame_num_inc(dwc_otg_hcd_get_frame_number(hcd), 1); +- qh_ptr = DWC_LIST_NEXT(qh_ptr); +- continue; +- } +- + if (microframe_schedule) { + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + if (hcd->available_host_channels < 1) { + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); +- if(qh->do_split) dwc_otg_hcd_release_port(hcd, qh); + break; + } + hcd->available_host_channels--; +@@ -1484,17 +1396,16 @@ dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t * hcd) + + g_np_sent++; + ++ if (ret_val == DWC_OTG_TRANSACTION_NONE) { ++ ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; ++ } else { ++ ret_val = DWC_OTG_TRANSACTION_ALL; ++ } ++ + if (!microframe_schedule) + hcd->non_periodic_channels++; + } + +- if(!DWC_LIST_EMPTY(&hcd->periodic_sched_assigned)) +- ret_val |= DWC_OTG_TRANSACTION_PERIODIC; +- +- if(!DWC_LIST_EMPTY(&hcd->non_periodic_sched_active)) +- ret_val |= DWC_OTG_TRANSACTION_NON_PERIODIC; +- +- + #ifdef DEBUG_HOST_CHANNELS + last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels; + #endif /* DEBUG_HOST_CHANNELS */ +@@ -1611,15 +1522,6 @@ static void process_periodic_channels(dwc_otg_hcd_t * hcd) + + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); + +- // Do not send a split start transaction any later than frame .6 +- // Note, we have to schedule a periodic in .5 to make it go in .6 +- if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6) +- { +- qh_ptr = qh_ptr->next; +- g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7; +- continue; +- } +- + /* + * Set a flag if we're queuing high-bandwidth in slave mode. + * The flag prevents any halts to get into the request queue in +@@ -1749,15 +1651,6 @@ static void process_non_periodic_channels(dwc_otg_hcd_t * hcd) + + qh = DWC_LIST_ENTRY(hcd->non_periodic_qh_ptr, dwc_otg_qh_t, + qh_list_entry); +- +- // Do not send a split start transaction any later than frame .5 +- // non periodic transactions will start immediately in this uframe +- if(fiq_split_enable && qh->do_split && ((dwc_otg_hcd_get_frame_number(hcd) + 1) & 7) > 6) +- { +- g_next_sched_frame = dwc_otg_hcd_get_frame_number(hcd) | 7; +- break; +- } +- + status = + queue_transaction(hcd, qh->channel, + tx_status.b.nptxfspcavail); +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +index d3d6e997..0493dbf 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +@@ -168,10 +168,10 @@ static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, + + /** Transaction types. */ + typedef enum dwc_otg_transaction_type { +- DWC_OTG_TRANSACTION_NONE = 0, +- DWC_OTG_TRANSACTION_PERIODIC = 1, +- DWC_OTG_TRANSACTION_NON_PERIODIC = 2, +- DWC_OTG_TRANSACTION_ALL = DWC_OTG_TRANSACTION_PERIODIC + DWC_OTG_TRANSACTION_NON_PERIODIC ++ DWC_OTG_TRANSACTION_NONE, ++ DWC_OTG_TRANSACTION_PERIODIC, ++ DWC_OTG_TRANSACTION_NON_PERIODIC, ++ DWC_OTG_TRANSACTION_ALL + } dwc_otg_transaction_type_e; + + struct dwc_otg_qh; +@@ -370,8 +370,6 @@ static inline void dwc_otg_hcd_fill_pipe(struct dwc_otg_hcd_pipe_info *pipe, + + uint16_t speed; + uint16_t frame_usecs[8]; +- +- uint32_t skip_count; + } dwc_otg_qh_t; + + DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); +@@ -576,10 +574,6 @@ struct dwc_otg_hcd { + /** Frame List */ + uint32_t *frame_list; + +- /** Hub - Port assignment */ +- int hub_port[16]; +- int hub_port_alloc[256]; +- + /** Frame List DMA address */ + dma_addr_t frame_list_dma; + +@@ -610,16 +604,12 @@ extern dwc_otg_transaction_type_e dwc_otg_hcd_select_transactions(dwc_otg_hcd_t + extern void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, + dwc_otg_transaction_type_e tr_type); + +-int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh); +-void dwc_otg_hcd_release_port(dwc_otg_hcd_t * dwc_otg_hcd, dwc_otg_qh_t *qh); +- +- + /** @} */ + + /** @name Interrupt Handler Functions */ + /** @{ */ + extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); +-extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd); ++extern int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd, int32_t); + extern int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * + dwc_otg_hcd); + extern int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +index e8b4d35..16e8c6c 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -38,7 +38,6 @@ + + #include + #include +-#include + + + extern bool microframe_schedule; +@@ -53,295 +52,21 @@ + + void * dummy_send; + mphi_regs_t c_mphi_regs; +-volatile void *dwc_regs_base; + int fiq_done, int_done; +- +-gintsts_data_t gintsts_saved = {.d32 = 0}; +-hcint_data_t hcint_saved[MAX_EPS_CHANNELS]; +-hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS]; +-int split_out_xfersize[MAX_EPS_CHANNELS]; +-haint_data_t haint_saved; +- +-int g_next_sched_frame, g_np_count, g_np_sent; ++int g_next_sched_frame, g_np_count, g_np_sent, g_work_expected; + static int mphi_int_count = 0 ; + ++extern bool fiq_fix_enable, nak_holdoff_enable; ++ + hcchar_data_t nak_hcchar; + hctsiz_data_t nak_hctsiz; + hcsplt_data_t nak_hcsplt; + int nak_count; + +-int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +-int split_start_frame[MAX_EPS_CHANNELS]; +-int queued_port[MAX_EPS_CHANNELS]; +- +-#ifdef FIQ_DEBUG +-char buffer[1000*16]; +-int wptr; +-void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...) +-{ +- FIQDBG_T dbg_lvl_req = FIQDBG_PORTHUB; +- va_list args; +- char text[17]; +- hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) }; +- unsigned long flags; +- +- local_irq_save(flags); +- local_fiq_disable(); +- if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR) +- { +- snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937); +- va_start(args, fmt); +- vsnprintf(text+8, 9, fmt, args); +- va_end(args); +- +- memcpy(buffer + wptr, text, 16); +- wptr = (wptr + 16) % sizeof(buffer); +- } +- local_irq_restore(flags); +-} +-#endif +- +-void fiq_queue_request(int channel, int odd_frame) +-{ +- hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) }; +- hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) }; +- hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10) }; +- +- if(hcsplt.b.spltena == 0) +- { +- fiq_print(FIQDBG_ERR, "SPLTENA "); +- BUG(); +- } +- +- if(hcchar.b.epdir == 1) +- { +- fiq_print(FIQDBG_SCHED, "IN Ch %d", channel); +- } +- else +- { +- hctsiz.b.xfersize = 0; +- fiq_print(FIQDBG_SCHED, "OUT Ch %d", channel); +- } +- FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x10), hctsiz.d32); +- +- hcsplt.b.compsplt = 1; +- FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x4), hcsplt.d32); +- +- // Send the Split complete +- hcchar.b.chen = 1; +- hcchar.b.oddfrm = odd_frame ? 1 : 0; +- +- // Post this for transmit on the next frame for periodic or this frame for non-periodic +- fiq_print(FIQDBG_SCHED, "SND_%s", odd_frame ? "ODD " : "EVEN"); +- +- FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x0), hcchar.d32); +-} +- +-static int last_sof = -1; +- +-/* +-** Function to handle the start of frame interrupt, choose whether we need to do anything and +-** therefore trigger the main interrupt +-** +-** returns int != 0 - interrupt has been handled +-*/ +-int diff; +- +-int fiq_sof_handle(hfnum_data_t hfnum) +-{ +- int handled = 0; +- int i; +- +- // Just check that once we're running we don't miss a SOF +- /*if(last_sof != -1 && (hfnum.b.frnum != ((last_sof + 1) & 0x3fff))) +- { +- fiq_print(FIQDBG_ERR, "LASTSOF "); +- fiq_print(FIQDBG_ERR, "%4d%d ", last_sof / 8, last_sof & 7); +- fiq_print(FIQDBG_ERR, "%4d%d ", hfnum.b.frnum / 8, hfnum.b.frnum & 7); +- BUG(); +- }*/ +- +- // Only start remembering the last sof when the interrupt has been +- // enabled (we don't check the mask to come in here...) +- if(last_sof != -1 || FIQ_READ(dwc_regs_base + 0x18) & (1<<3)) +- last_sof = hfnum.b.frnum; +- +- for(i = 0; i < MAX_EPS_CHANNELS; i++) +- { +- if(complete_sched[i] != -1) +- { +- if(complete_sched[i] <= hfnum.b.frnum || (complete_sched[i] > 0x3f00 && hfnum.b.frnum < 0xf0)) +- { +- fiq_queue_request(i, hfnum.b.frnum & 1); +- complete_sched[i] = -1; +- } +- } +- +- if(complete_sched[i] != -1) +- { +- // This is because we've seen a split complete occur with no start... +- // most likely because missed the complete 0x3fff frames ago! +- +- diff = (hfnum.b.frnum + 0x3fff - complete_sched[i]) & 0x3fff ; +- if(diff > 32 && diff < 0x3f00) +- { +- fiq_print(FIQDBG_ERR, "SPLTMISS"); +- BUG(); +- } +- } +- } +- +- if(g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) +- { +- /* +- * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet +- * g_next_sched_frame is the next frame we have periodic packets for +- * +- * if neither of these are required for this frame then just clear the interrupt +- */ +- handled = 1; +- +- } +- +- return handled; +-} +- +-int port_id(hcsplt_data_t hcsplt) +-{ +- return hcsplt.b.prtaddr + (hcsplt.b.hubaddr << 8); +-} +- +-int fiq_hcintr_handle(int channel, hfnum_data_t hfnum) +-{ +- hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) }; +- hcsplt_data_t hcsplt = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x4) }; +- hcint_data_t hcint = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x8) }; +- hcintmsk_data_t hcintmsk = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0xc) }; +- hctsiz_data_t hctsiz = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x10)}; +- +- hcint_saved[channel].d32 |= hcint.d32; +- hcintmsk_saved[channel].d32 = hcintmsk.d32; +- +- if(hcsplt.b.spltena) +- { +- fiq_print(FIQDBG_PORTHUB, "ph: %4x", port_id(hcsplt)); +- if(hcint.b.chhltd) +- { +- fiq_print(FIQDBG_SCHED, "CH HLT %d", channel); +- fiq_print(FIQDBG_SCHED, "%08x", hcint_saved[channel]); +- } +- if(hcint.b.stall || hcint.b.xacterr || hcint.b.bblerr || hcint.b.frmovrun || hcint.b.datatglerr) +- { +- queued_port[channel] = 0; +- fiq_print(FIQDBG_ERR, "CHAN ERR"); +- } +- if(hcint.b.xfercomp) +- { +- // Clear the port allocation and transmit anything also on this port +- queued_port[channel] = 0; +- fiq_print(FIQDBG_SCHED, "XFERCOMP"); +- } +- if(hcint.b.nak) +- { +- queued_port[channel] = 0; +- fiq_print(FIQDBG_SCHED, "NAK"); +- } +- if(hcint.b.ack && !hcsplt.b.compsplt) +- { +- int i; +- +- // Do not complete isochronous out transactions +- if(hcchar.b.eptype == 1 && hcchar.b.epdir == 0) +- { +- queued_port[channel] = 0; +- fiq_print(FIQDBG_SCHED, "ISOC_OUT"); +- } +- else +- { +- // Make sure we check the port / hub combination that we sent this split on. +- // Do not queue a second request to the same port +- for(i = 0; i < MAX_EPS_CHANNELS; i++) +- { +- if(port_id(hcsplt) == queued_port[i]) +- { +- fiq_print(FIQDBG_ERR, "PORTERR "); +- //BUG(); +- } +- } +- +- split_start_frame[channel] = (hfnum.b.frnum + 1) & ~7; +- +- // Note, the size of an OUT is in the start split phase, not +- // the complete split +- split_out_xfersize[channel] = hctsiz.b.xfersize; +- +- hcint_saved[channel].b.chhltd = 0; +- hcint_saved[channel].b.ack = 0; +- +- queued_port[channel] = port_id(hcsplt); +- +- if(hcchar.b.eptype & 1) +- { +- // Send the periodic complete in the same oddness frame as the ACK went... +- fiq_queue_request(channel, !(hfnum.b.frnum & 1)); +- // complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1); +- } +- else +- { +- // Schedule the split complete to occur later +- complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 2); +- fiq_print(FIQDBG_SCHED, "ACK%04d%d", complete_sched[channel]/8, complete_sched[channel]%8); +- } +- } +- } +- if(hcint.b.nyet) +- { +- fiq_print(FIQDBG_ERR, "NYETERR1"); +- //BUG(); +- // Can transmit a split complete up to uframe .0 of the next frame +- if(hfnum.b.frnum <= dwc_frame_num_inc(split_start_frame[channel], 8)) +- { +- // Send it next frame +- if(hcchar.b.eptype & 1) // type 1 & 3 are interrupt & isoc +- { +- fiq_print(FIQDBG_SCHED, "NYT:SEND"); +- fiq_queue_request(channel, !(hfnum.b.frnum & 1)); +- } +- else +- { +- // Schedule non-periodic access for next frame (the odd-even bit doesn't effect NP) +- complete_sched[channel] = dwc_frame_num_inc(hfnum.b.frnum, 1); +- fiq_print(FIQDBG_SCHED, "NYT%04d%d", complete_sched[channel]/8, complete_sched[channel]%8); +- } +- hcint_saved[channel].b.chhltd = 0; +- hcint_saved[channel].b.nyet = 0; +- } +- else +- { +- queued_port[channel] = 0; +- fiq_print(FIQDBG_ERR, "NYETERR2"); +- //BUG(); +- } +- } +- } +- +- // Clear the interrupt, this will also clear the HAINT bit +- FIQ_WRITE((dwc_regs_base + 0x500 + (channel * 0x20) + 0x8), hcint.d32); +- return hcint_saved[channel].d32 == 0; +-} +- +-gintsts_data_t gintsts; +-gintmsk_data_t gintmsk; +-// triggered: The set of interrupts that were triggered +-// handled: The set of interrupts that have been handled (no IRQ is +-// required) +-// keep: The set of interrupts we want to keep unmasked even though we +-// want to trigger an IRQ to handle it (SOF and HCINTR) +-gintsts_data_t triggered, handled, keep; +-hfnum_data_t hfnum; +- + void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void) + { ++ gintsts_data_t gintsts; ++ hfnum_data_t hfnum; + + /* entry takes care to store registers we will be treading on here */ + asm __volatile__ ( +@@ -349,112 +74,43 @@ void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void) + /* stash FIQ and normal regs */ + "stmdb sp!, {r0-r12, lr};" + /* !! THIS SETS THE FRAME, adjust to > sizeof locals */ +- "sub fp, ip, #512 ;" ++ "sub fp, ip, #256 ;" + ); + +- // Cannot put local variables at the beginning of the function +- // because otherwise 'C' will play with the stack pointer. any locals +- // need to be inside the following block +- do ++ fiq_done++; ++ gintsts.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x14) & FIQ_READ_IO_ADDRESS(USB_BASE + 0x18); ++ hfnum.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x408); ++ ++ if(gintsts.d32) + { +- fiq_done++; +- gintsts.d32 = FIQ_READ(dwc_regs_base + 0x14); +- gintmsk.d32 = FIQ_READ(dwc_regs_base + 0x18); +- hfnum.d32 = FIQ_READ(dwc_regs_base + 0x408); +- triggered.d32 = gintsts.d32 & gintmsk.d32; +- handled.d32 = 0; +- keep.d32 = 0; +- fiq_print(FIQDBG_INT, "FIQ "); +- fiq_print(FIQDBG_INT, "%08x", gintsts.d32); +- fiq_print(FIQDBG_INT, "%08x", gintmsk.d32); +- if(gintsts.d32) ++ if(gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) + { +- // If port enabled +- if((FIQ_READ(dwc_regs_base + 0x440) & 0xf) == 0x5) +- { +- if(gintsts.b.sofintr) +- { +- if(fiq_sof_handle(hfnum)) +- { +- handled.b.sofintr = 1; /* Handled in FIQ */ +- } +- else +- { +- /* Keer interrupt unmasked */ +- keep.b.sofintr = 1; +- } +- { +- // Need to make sure the read and clearing of the SOF interrupt is as close as possible to avoid the possibility of missing +- // a start of frame interrupt +- gintsts_data_t gintsts = { .b.sofintr = 1 }; +- FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32); +- } +- } +- +- if(fiq_split_enable && gintsts.b.hcintr) +- { +- int i; +- haint_data_t haint; +- haintmsk_data_t haintmsk; +- +- haint.d32 = FIQ_READ(dwc_regs_base + 0x414); +- haintmsk.d32 = FIQ_READ(dwc_regs_base + 0x418); +- haint.d32 &= haintmsk.d32; +- haint_saved.d32 |= haint.d32; +- +- fiq_print(FIQDBG_INT, "hcintr"); +- fiq_print(FIQDBG_INT, "%08x", FIQ_READ(dwc_regs_base + 0x414)); +- +- // Go through each channel that has an enabled interrupt +- for(i = 0; i < 16; i++) +- if((haint.d32 >> i) & 1) +- if(fiq_hcintr_handle(i, hfnum)) +- haint_saved.d32 &= ~(1 << i); /* this was handled */ +- +- /* If we've handled all host channel interrupts then don't trigger the interrupt */ +- if(haint_saved.d32 == 0) +- { +- handled.b.hcintr = 1; +- } +- else +- { +- /* Make sure we keep the channel interrupt unmasked when triggering the IRQ */ +- keep.b.hcintr = 1; +- } +- +- { +- gintsts_data_t gintsts = { .b.hcintr = 1 }; ++ /* ++ * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet ++ * g_next_sched_frame is the next frame we have periodic packets for ++ * ++ * if neither of these are required for this frame then just clear the interrupt ++ */ ++ gintsts.d32 = 0; ++ gintsts.b.sofintr = 1; ++ FIQ_WRITE_IO_ADDRESS((USB_BASE + 0x14), gintsts.d32); + +- // Always clear the channel interrupt +- FIQ_WRITE((dwc_regs_base + 0x14), gintsts.d32); +- } +- } +- } +- else +- { +- last_sof = -1; +- } ++ g_work_expected = 0; + } +- +- // Mask out the interrupts triggered - those handled - don't mask out the ones we want to keep +- gintmsk.d32 = keep.d32 | (gintmsk.d32 & ~(triggered.d32 & ~handled.d32)); +- // Save those that were triggered but not handled +- gintsts_saved.d32 |= triggered.d32 & ~handled.d32; +- FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32); +- +- // Clear and save any unhandled interrupts and trigger the interrupt +- if(gintsts_saved.d32) ++ else + { ++ g_work_expected = 1; + /* To enable the MPHI interrupt (INT 32) + */ +- FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send); ++ FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send); + FIQ_WRITE( c_mphi_regs.outddb, (1 << 29)); + + mphi_int_count++; ++ /* Clear the USB global interrupt so we don't just sit in the FIQ */ ++ FIQ_MODIFY_IO_ADDRESS((USB_BASE + 0x8),1,0); ++ + } + } +- while(0); +- + mb(); + + /* exit back to normal mode restoring everything */ +@@ -477,7 +133,6 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; + gintsts_data_t gintsts; +- gintmsk_data_t gintmsk; + hfnum_data_t hfnum; + + #ifdef DEBUG +@@ -485,9 +140,6 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + + #endif + +- gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); +- gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); +- + /* Exit from ISR if core is hibernated */ + if (core_if->hibernation_suspend == 1) { + goto exit_handler_routine; +@@ -495,18 +147,11 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + DWC_SPINLOCK(dwc_otg_hcd->lock); + /* Check if HOST Mode */ + if (dwc_otg_is_host_mode(core_if)) { +- local_fiq_disable(); +- gintmsk.d32 |= gintsts_saved.d32; +- gintsts.d32 |= gintsts_saved.d32; +- gintsts_saved.d32 = 0; +- local_fiq_enable(); ++ gintsts.d32 = dwc_otg_read_core_intr(core_if); + if (!gintsts.d32) { + goto exit_handler_routine; + } +- gintsts.d32 &= gintmsk.d32; +- + #ifdef DEBUG +- // We should be OK doing this because the common interrupts should already have been serviced + /* Don't print debug message in the interrupt handler on SOF */ + #ifndef DEBUG_SOF + if (gintsts.d32 != DWC_SOF_INTR_MASK) +@@ -526,12 +171,11 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) + { + /* Note, we should never get here if the FIQ is doing it's job properly*/ +- retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected); + } + else if (gintsts.b.sofintr) { +- retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected); + } +- + if (gintsts.b.rxstsqlvl) { + retval |= + dwc_otg_hcd_handle_rx_status_q_level_intr +@@ -546,10 +190,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + /** @todo Implement i2cintr handler. */ + } + if (gintsts.b.portintr) { +- +- gintmsk_data_t gintmsk = { .b.portintr = 1}; + retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); +- DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); + } + if (gintsts.b.hcintr) { + retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); +@@ -586,35 +227,26 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) + + if (fiq_fix_enable) + { +- local_fiq_disable(); +- // Make sure that we don't clear the interrupt if we've still got pending work to do +- if(gintsts_saved.d32 == 0) ++ /* Clear the MPHI interrupt */ ++ DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16)); ++ if (mphi_int_count >= 60) + { +- /* Clear the MPHI interrupt */ +- DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16)); +- if (mphi_int_count >= 60) +- { +- DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16))); +- while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17))) +- ; +- DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31)); +- mphi_int_count = 0; +- } +- int_done++; ++ DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16))); ++ while(!(DWC_READ_REG32(c_mphi_regs.ctrl) & (1 << 17))) ++ ; ++ DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31)); ++ mphi_int_count = 0; + } +- +- // Unmask handled interrupts +- FIQ_WRITE(dwc_regs_base + 0x18, gintmsk.d32); +- //DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1); +- +- local_fiq_enable(); +- ++ int_done++; + if((jiffies / HZ) > last_time) + { + /* Once a second output the fiq and irq numbers, useful for debug */ + last_time = jiffies / HZ; + DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done); + } ++ ++ /* Re-Enable FIQ interrupt from USB peripheral */ ++ DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1); + } + + DWC_SPINUNLOCK(dwc_otg_hcd->lock); +@@ -662,12 +294,13 @@ static inline void track_missed_sofs(uint16_t curr_frame_number) + * (micro)frame. Periodic transactions may be queued to the controller for the + * next (micro)frame. + */ +-int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) ++int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd, int32_t work_expected) + { + hfnum_data_t hfnum; + dwc_list_link_t *qh_entry; + dwc_otg_qh_t *qh; + dwc_otg_transaction_type_e tr_type; ++ gintsts_data_t gintsts = {.d32 = 0 }; + int did_something = 0; + int32_t next_sched_frame = -1; + +@@ -693,7 +326,6 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) + qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry); + qh_entry = qh_entry->next; + if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) { +- + /* + * Move QH to the ready list to be executed next + * (micro)frame. +@@ -719,10 +351,15 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) + dwc_otg_hcd_queue_transactions(hcd, tr_type); + did_something = 1; + } ++ if(work_expected && !did_something) ++ DWC_DEBUGPL(DBG_USER, "Nothing to do !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame); ++ if(!work_expected && did_something) ++ DWC_DEBUGPL(DBG_USER, "Unexpected work done !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame); ++ + + /* Clear interrupt */ +- //gintsts.b.sofintr = 1; +- //DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); ++ gintsts.b.sofintr = 1; ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); + + return 1; + } +@@ -1006,15 +643,6 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) + + haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if); + +- // Overwrite with saved interrupts from fiq handler +- if(fiq_split_enable) +- { +- local_fiq_disable(); +- haint.d32 = haint_saved.d32; +- haint_saved.d32 = 0; +- local_fiq_enable(); +- } +- + for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { + if (haint.b2.chint & (1 << i)) { + retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); +@@ -1055,10 +683,7 @@ static uint32_t get_actual_xfer_length(dwc_hc_t * hc, + *short_read = (hctsiz.b.xfersize != 0); + } + } else if (hc->qh->do_split) { +- if(fiq_split_enable) +- length = split_out_xfersize[hc->hc_num]; +- else +- length = qtd->ssplit_out_xfer_count; ++ length = qtd->ssplit_out_xfer_count; + } else { + length = hc->xfer_len; + } +@@ -1102,6 +727,7 @@ static int update_urb_state_xfer_comp(dwc_hc_t * hc, + DWC_OTG_HC_XFER_COMPLETE, + &short_read); + ++ + /* non DWORD-aligned buffer case handling. */ + if (hc->align_buff && xfer_length && hc->ep_is_in) { + dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, +@@ -1304,9 +930,6 @@ static void release_channel(dwc_otg_hcd_t * hcd, + int free_qtd; + dwc_irqflags_t flags; + dwc_spinlock_t *channel_lock = hcd->channel_lock; +-#ifdef FIQ_DEBUG +- int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0; +-#endif + + DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", + __func__, hc->hc_num, halt_status, hc->xfer_len); +@@ -1385,24 +1008,9 @@ static void release_channel(dwc_otg_hcd_t * hcd, + + DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + hcd->available_host_channels++; +- fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels); + DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); + } + +- if(fiq_split_enable && hc->do_split) +- { +- if(!(hcd->hub_port[hc->hub_addr] & (1 << hc->port_addr))) +- { +- fiq_print(FIQDBG_ERR, "PRTNOTAL"); +- //BUG(); +- } +- +- hcd->hub_port[hc->hub_addr] &= ~(1 << hc->port_addr); +- hcd->hub_port_alloc[hc->hub_addr * 16 + hc->port_addr] = -1; +- +- fiq_print(FIQDBG_PORTHUB, "H%dP%d:RR%d", hc->hub_addr, hc->port_addr, endp); +- } +- + /* Try to queue more transfers now that there's a free channel. */ + tr_type = dwc_otg_hcd_select_transactions(hcd); + if (tr_type != DWC_OTG_TRANSACTION_NONE) { +@@ -2025,10 +1633,8 @@ static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd, + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { + int frnum = dwc_otg_hcd_get_frame_number(hcd); + +- // With the FIQ running we only ever see the failed NYET + if (dwc_full_frame_num(frnum) != +- dwc_full_frame_num(hc->qh->sched_frame) || +- fiq_split_enable) { ++ dwc_full_frame_num(hc->qh->sched_frame)) { + /* + * No longer in the same full speed frame. + * Treat this as a transaction error. +@@ -2406,10 +2012,10 @@ static inline int halt_status_ok(dwc_otg_hcd_t * hcd, + static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, + dwc_hc_t * hc, + dwc_otg_hc_regs_t * hc_regs, +- dwc_otg_qtd_t * qtd, +- hcint_data_t hcint, +- hcintmsk_data_t hcintmsk) ++ dwc_otg_qtd_t * qtd) + { ++ hcint_data_t hcint; ++ hcintmsk_data_t hcintmsk; + int out_nak_enh = 0; + + /* For core with OUT NAK enhancement, the flow for high- +@@ -2441,11 +2047,8 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, + } + + /* Read the HCINTn register to determine the cause for the halt. */ +- if(!fiq_split_enable) +- { +- hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); +- hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); +- } ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); + + if (hcint.b.xfercomp) { + /** @todo This is here because of a possible hardware bug. Spec +@@ -2558,15 +2161,13 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd, + static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, + dwc_hc_t * hc, + dwc_otg_hc_regs_t * hc_regs, +- dwc_otg_qtd_t * qtd, +- hcint_data_t hcint, +- hcintmsk_data_t hcintmsk) ++ dwc_otg_qtd_t * qtd) + { + DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Channel Halted--\n", hc->hc_num); + + if (hcd->core_if->dma_enable) { +- handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd, hcint, hcintmsk); ++ handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd); + } else { + #ifdef DEBUG + if (!halt_status_ok(hcd, hc, hc_regs, qtd)) { +@@ -2583,7 +2184,7 @@ static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd, + int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) + { + int retval = 0; +- hcint_data_t hcint, hcint_orig; ++ hcint_data_t hcint; + hcintmsk_data_t hcintmsk; + dwc_hc_t *hc; + dwc_otg_hc_regs_t *hc_regs; +@@ -2596,23 +2197,12 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) + qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); + + hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); +- hcint_orig = hcint; + hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk); + DWC_DEBUGPL(DBG_HCDV, + " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", + hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); + hcint.d32 = hcint.d32 & hcintmsk.d32; + +- if(fiq_split_enable) +- { +- // replace with the saved interrupts from the fiq handler +- local_fiq_disable(); +- hcint_orig.d32 = hcint_saved[num].d32; +- hcint.d32 = hcint_orig.d32 & hcintmsk_saved[num].d32; +- hcint_saved[num].d32 = 0; +- local_fiq_enable(); +- } +- + if (!dwc_otg_hcd->core_if->dma_enable) { + if (hcint.b.chhltd && hcint.d32 != 0x2) { + hcint.b.chhltd = 0; +@@ -2630,7 +2220,7 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) + hcint.b.nyet = 0; + } + if (hcint.b.chhltd) { +- retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd, hcint_orig, hcintmsk_saved[num]); ++ retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd); + } + if (hcint.b.ahberr) { + retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd); +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +index 0d6f5f4..fef557d 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +@@ -392,11 +392,7 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, + static struct fiq_handler fh = { + .name = "usb_fiq", + }; +-struct fiq_stack_s { +- int magic1; +- uint8_t stack[2048]; +- int magic2; +-} fiq_stack; ++static uint8_t fiqStack[1024]; + + extern mphi_regs_t c_mphi_regs; + /** +@@ -438,11 +434,9 @@ int hcd_init(dwc_bus_dev_t *_dev) + memset(®s,0,sizeof(regs)); + regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq; + regs.ARM_r9 = (long)0; +- regs.ARM_sp = (long)fiq_stack.stack + sizeof(fiq_stack.stack) - 4; ++ regs.ARM_sp = (long)fiqStack + sizeof(fiqStack) - 4; + set_fiq_regs(®s); +- fiq_stack.magic1 = 0xdeadbeef; +- fiq_stack.magic2 = 0xaa995566; +- } ++ } + + /* + * Allocate memory for the base HCD plus the DWC OTG HCD. +@@ -465,8 +459,6 @@ int hcd_init(dwc_bus_dev_t *_dev) + + if (fiq_fix_enable) + { +- volatile extern void *dwc_regs_base; +- + //Set the mphi periph to the required registers + c_mphi_regs.base = otg_dev->os_dep.mphi_base; + c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c; +@@ -474,8 +466,6 @@ int hcd_init(dwc_bus_dev_t *_dev) + c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c; + c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50; + +- dwc_regs_base = otg_dev->os_dep.base; +- + //Enable mphi peripheral + writel((1<<31),c_mphi_regs.ctrl); + #ifdef DEBUG +@@ -849,8 +839,6 @@ static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) + usb_hcd_unlink_urb_from_ep(hcd, urb); + #endif + DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); +- +- + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + usb_hcd_giveback_urb(hcd, urb); + #else +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +index 8125307..b3e6e52 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +@@ -41,7 +41,6 @@ + + #include "dwc_otg_hcd.h" + #include "dwc_otg_regs.h" +-#include "dwc_otg_mphi_fix.h" + + extern bool microframe_schedule; + +@@ -192,7 +191,6 @@ void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) + dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, + hub_port); + qh->do_split = 1; +- qh->skip_count = 0; + } + + if (qh->ep_type == UE_INTERRUPT || qh->ep_type == UE_ISOCHRONOUS) { +@@ -739,9 +737,6 @@ void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) + hcd->non_periodic_qh_ptr->next; + } + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); +- +- // If we've removed the last non-periodic entry then there are none left! +- g_np_count = g_np_sent; + } else { + deschedule_periodic(hcd, qh); + hcd->periodic_qh_count--; +@@ -771,21 +766,21 @@ void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, + { + if (dwc_qh_is_non_per(qh)) { + +- dwc_otg_qh_t *qh_tmp; +- dwc_list_link_t *qh_list; +- DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive) ++ dwc_otg_qh_t *qh_tmp; ++ dwc_list_link_t *qh_list; ++ DWC_LIST_FOREACH(qh_list, &hcd->non_periodic_sched_inactive) ++ { ++ qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry); ++ if(qh_tmp == qh) + { +- qh_tmp = DWC_LIST_ENTRY(qh_list, struct dwc_otg_qh, qh_list_entry); +- if(qh_tmp == qh) +- { +- /* +- * FIQ is being disabled because this one nevers gets a np_count increment +- * This is still not absolutely correct, but it should fix itself with +- * just an unnecessary extra interrupt +- */ +- g_np_sent = g_np_count; +- } ++ /* ++ * FIQ is being disabled because this one nevers gets a np_count increment ++ * This is still not absolutely correct, but it should fix itself with ++ * just an unnecessary extra interrupt ++ */ ++ g_np_sent = g_np_count; + } ++ } + + + dwc_otg_hcd_qh_remove(hcd, qh); +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h +index ca17379..22f28e1 100755 +--- a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h ++++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h +@@ -1,7 +1,10 @@ + #ifndef __DWC_OTG_MPHI_FIX_H__ + #define __DWC_OTG_MPHI_FIX_H__ +-#define FIQ_WRITE(_addr_,_data_) (*(volatile uint32_t *) (_addr_) = (_data_)) +-#define FIQ_READ(_addr_) (*(volatile uint32_t *) (_addr_)) ++ ++#define FIQ_WRITE_IO_ADDRESS(_addr_,_data_) *(volatile uint32_t *) IO_ADDRESS(_addr_) = _data_ ++#define FIQ_READ_IO_ADDRESS(_addr_) *(volatile uint32_t *) IO_ADDRESS(_addr_) ++#define FIQ_MODIFY_IO_ADDRESS(_addr_,_clear_,_set_) FIQ_WRITE_IO_ADDRESS(_addr_ , (FIQ_READ_IO_ADDRESS(_addr_)&~_clear_)|_set_) ++#define FIQ_WRITE(_addr_,_data_) *(volatile uint32_t *) _addr_ = _data_ + + typedef struct { + volatile void* base; +@@ -9,13 +12,13 @@ + volatile void* outdda; + volatile void* outddb; + volatile void* intstat; +-} mphi_regs_t; ++} mphi_regs_t; + + void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name); + void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name); + void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name); + +-extern gintsts_data_t gintsts_saved; ++ + + #ifdef DEBUG + #define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__) +@@ -27,22 +30,7 @@ + #define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) + #define DWC_DBG_PRINT_OTG_INT(_arg_) + +-#endif +- +-typedef enum { +- FIQDBG_SCHED = (1 << 0), +- FIQDBG_INT = (1 << 1), +- FIQDBG_ERR = (1 << 2), +- FIQDBG_PORTHUB = (1 << 3), +-} FIQDBG_T; + +-void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...); +-#ifdef FIQ_DEBUG +-#define fiq_print _fiq_print +-#else +-#define fiq_print(x, y, ...) + #endif + +-extern bool fiq_fix_enable, nak_holdoff_enable, fiq_split_enable; +- + #endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +index 9720937..27061d3 100644 +--- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +@@ -4276,7 +4276,7 @@ static int32_t dwc_otg_pcd_handle_out_ep_intr(dwc_otg_pcd_t * pcd) + && (pcd->ep0state == EP0_OUT_DATA_PHASE)) + status.d32 = core_if->dev_if->out_desc_addr->status.d32; + if (pcd->ep0state == EP0_OUT_STATUS_PHASE) +- status.d32 = core_if->dev_if-> ++ status.d32 = status.d32 = core_if->dev_if-> + out_desc_addr->status.d32; + + if (status.b.sr) { +-- +1.8.1.6 + + +From 2fa497bfb56426ce8934f3a0ca3ac85a5c2e6008 Mon Sep 17 00:00:00 2001 +From: popcornmix +Date: Wed, 3 Jul 2013 13:55:00 +0100 +Subject: [PATCH 91/91] hack: fix for incorrect uart fifo size detection + +--- + drivers/tty/serial/amba-pl011.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c +index e2774f9..5254f10 100644 +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -84,7 +84,7 @@ struct vendor_data { + + static unsigned int get_fifosize_arm(unsigned int periphid) + { +- unsigned int rev = (periphid >> 20) & 0xf; ++ unsigned int rev = 0; //(periphid >> 20) & 0xf; + return rev < 3 ? 16 : 32; + } + +-- +1.8.1.6 + From 4e98614cf09d3d2716c8448cff6439304d3aedf9 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Thu, 4 Jul 2013 16:17:34 +0200 Subject: [PATCH 25/61] alsa-lib: build with versioned symbols, see http://openelec.tv/forum/120-news-announcements/64988-openelec-3-0-6-released#78546 Signed-off-by: Stephan Raue --- packages/audio/alsa-lib/build | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/audio/alsa-lib/build b/packages/audio/alsa-lib/build index 108ee7809e..f28bb575af 100755 --- a/packages/audio/alsa-lib/build +++ b/packages/audio/alsa-lib/build @@ -40,7 +40,6 @@ cd $PKG_BUILD --enable-shared \ --disable-python \ --disable-dependency-tracking \ - --with-versioned=no \ sed -i 's/.*PKGLIBDIR.*/#define PKGLIBDIR ""/' include/config.h From 6d54a2c5d74a0764b0fa9827eb3a3aec32e11aad Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Thu, 4 Jul 2013 16:32:42 +0200 Subject: [PATCH 26/61] projects/RPi/linux: build SPI drivers as build-in kernel drivers Signed-off-by: Stephan Raue --- projects/RPi/linux/linux.arm.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/RPi/linux/linux.arm.conf b/projects/RPi/linux/linux.arm.conf index aacb71061a..ea284fd915 100644 --- a/projects/RPi/linux/linux.arm.conf +++ b/projects/RPi/linux/linux.arm.conf @@ -1171,7 +1171,7 @@ CONFIG_SPI_MASTER=y # SPI Master Controller Drivers # # CONFIG_SPI_ALTERA is not set -CONFIG_SPI_BCM2708=m +CONFIG_SPI_BCM2708=y # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_GPIO is not set # CONFIG_SPI_OC_TINY is not set @@ -1185,7 +1185,7 @@ CONFIG_SPI_BCM2708=m # # SPI Protocol Masters # -CONFIG_SPI_SPIDEV=m +CONFIG_SPI_SPIDEV=y # CONFIG_SPI_TLE62X0 is not set # From c8729199f1600eb0bda65fc64bdcaa280ed20e2f Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 18:39:02 +0300 Subject: [PATCH 27/61] transmission: update to transmission-2.80 --- .../service/downloadmanager/transmission/changelog.txt | 3 +++ packages/addons/service/downloadmanager/transmission/meta | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/addons/service/downloadmanager/transmission/changelog.txt b/packages/addons/service/downloadmanager/transmission/changelog.txt index 6725621bbb..7468a705d3 100644 --- a/packages/addons/service/downloadmanager/transmission/changelog.txt +++ b/packages/addons/service/downloadmanager/transmission/changelog.txt @@ -1,3 +1,6 @@ +3.1.2 +- update to transmission-2.80 + 3.1.1 - rebuild for OpenELEC-3.2 diff --git a/packages/addons/service/downloadmanager/transmission/meta b/packages/addons/service/downloadmanager/transmission/meta index ac331728cd..639d68206e 100644 --- a/packages/addons/service/downloadmanager/transmission/meta +++ b/packages/addons/service/downloadmanager/transmission/meta @@ -19,12 +19,12 @@ ################################################################################ PKG_NAME="transmission" -PKG_VERSION="2.77" -PKG_REV="1" +PKG_VERSION="2.80" +PKG_REV="2" PKG_ARCH="any" PKG_LICENSE="OSS" PKG_SITE="http://www.transmissionbt.com/" -PKG_URL="http://download.transmissionbt.com/files/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_URL="http://download.transmissionbt.com/files/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_DEPENDS="zlib $ICONV openssl curl libevent" PKG_BUILD_DEPENDS="toolchain $ICONV zlib openssl curl libevent" PKG_PRIORITY="optional" From 695ec8a956a3b022090570bf30aedb47c1112a28 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 18:39:51 +0300 Subject: [PATCH 28/61] connman: do not touch nat table before enabling tethering --- .../connman-init-nat-after-tethering.patch | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 packages/network/connman/patches/connman-init-nat-after-tethering.patch diff --git a/packages/network/connman/patches/connman-init-nat-after-tethering.patch b/packages/network/connman/patches/connman-init-nat-after-tethering.patch new file mode 100644 index 0000000000..06dd222a55 --- /dev/null +++ b/packages/network/connman/patches/connman-init-nat-after-tethering.patch @@ -0,0 +1,48 @@ +commit 0f41818097e3ada58c21a3a84af86ec3762294ce +Author: Stefan Saraev +Date: Thu Jul 4 18:42:29 2013 +0300 + + do not touch nat table before enabling tethering + + TODO: remove when upstream does a better fix + +diff --git a/src/connman.h b/src/connman.h +index 96f8466..c94d854 100644 +--- a/src/connman.h ++++ b/src/connman.h +@@ -910,6 +910,8 @@ int __connman_nat_enable(const char *name, const char *address, + unsigned char prefixlen); + void __connman_nat_disable(const char *name); + ++static connman_bool_t nat_enabled = FALSE; ++ + struct firewall_context; + + struct firewall_context *__connman_firewall_create(void); +diff --git a/src/firewall.c b/src/firewall.c +index c235d86..1e7dfa9 100644 +--- a/src/firewall.c ++++ b/src/firewall.c +@@ -421,7 +421,8 @@ static void flush_all_tables(void) + + flush_table("filter"); + flush_table("mangle"); +- flush_table("nat"); ++ if (nat_enabled) ++ flush_table("nat"); + } + + int __connman_firewall_init(void) +diff --git a/src/nat.c b/src/nat.c +index 5447eb7..d5ceffd 100644 +--- a/src/nat.c ++++ b/src/nat.c +@@ -78,6 +78,8 @@ static int enable_nat(struct connman_nat *nat) + if (err < 0) + return err; + ++ nat_enabled = TRUE; ++ + return __connman_iptables_commit("nat"); + } + From 6accedbdb541fa1d956d2ef7dae7e447d3d32e28 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 19:35:20 +0300 Subject: [PATCH 29/61] remove package: 'newt' in kernel 3.10 newt is not a perf dependency anymore --- packages/devel/newt/build | 44 ------------------- packages/devel/newt/meta | 36 --------------- packages/devel/newt/patches/newt-libdir.patch | 12 ----- 3 files changed, 92 deletions(-) delete mode 100755 packages/devel/newt/build delete mode 100644 packages/devel/newt/meta delete mode 100644 packages/devel/newt/patches/newt-libdir.patch diff --git a/packages/devel/newt/build b/packages/devel/newt/build deleted file mode 100755 index d815da9ec9..0000000000 --- a/packages/devel/newt/build +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2013 Dag Wieers (dag@wieers.com) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -. config/options $1 - -cd $PKG_BUILD -./configure --host=$TARGET_NAME \ - --build=$HOST_NAME \ - --prefix=/usr \ - --exec-prefix=/usr \ - --sysconfdir=/etc \ - --datadir=/usr/share \ - --without-python \ - --without-tcl - -make libnewt.a - -mkdir -p $SYSROOT_PREFIX/usr/lib - cp libnewt.a $SYSROOT_PREFIX/usr/lib - -mkdir -p $SYSROOT_PREFIX/usr/lib/pkgconfig - cp libnewt.pc $SYSROOT_PREFIX/usr/lib/pkgconfig - -mkdir -p $SYSROOT_PREFIX/usr/include - cp newt.h $SYSROOT_PREFIX/usr/include diff --git a/packages/devel/newt/meta b/packages/devel/newt/meta deleted file mode 100644 index 15c507b596..0000000000 --- a/packages/devel/newt/meta +++ /dev/null @@ -1,36 +0,0 @@ -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2013 Dag Wieers (dag@wieers.com) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -PKG_NAME="newt" -PKG_VERSION="0.52.14" -PKG_REV="1" -PKG_ARCH="any" -PKG_LICENSE="LGPL" -PKG_SITE="https://fedorahosted.org/newt/" -PKG_URL="https://fedorahosted.org/releases/n/e/newt/$PKG_NAME-$PKG_VERSION.tar.gz" -PKG_DEPENDS="" -PKG_BUILD_DEPENDS="toolchain popt slang" -PKG_PRIORITY="optional" -PKG_SECTION="devel" -PKG_SHORTDESC="newt: library for color text mode, widget based user interfaces" -PKG_LONGDESC="Newt is a programming library for color text mode, widget based user interfaces. Newt can be used to add stacked windows, entry widgets, checkboxes, radio buttons, labels, plain text fields, scrollbars, etc., to text mode user interfaces. Newt is based on the S-Lang library." -PKG_IS_ADDON="no" - -PKG_AUTORECONF="yes" diff --git a/packages/devel/newt/patches/newt-libdir.patch b/packages/devel/newt/patches/newt-libdir.patch deleted file mode 100644 index 043b7ca686..0000000000 --- a/packages/devel/newt/patches/newt-libdir.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur newt-0.52.14/Makefile.in newt-0.52.14.patch/Makefile.in ---- newt-0.52.14/Makefile.in 2011-11-11 12:00:15.000000000 +0100 -+++ newt-0.52.14.patch/Makefile.in 2013-05-30 23:40:30.104284277 +0200 -@@ -5,7 +5,7 @@ - CPP = @CPP@ - CFLAGS = @CFLAGS@ - LDFLAGS = @LDFLAGS@ --CPPFLAGS = -D_GNU_SOURCE -I/usr/include/slang @CPPFLAGS@ -+CPPFLAGS = -D_GNU_SOURCE @CPPFLAGS@ - GNU_LD = @GNU_LD@ - - VERSION = @VERSION@ From 84e736f1a15edcfb3960d1f438857bfa4ed9a202 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 19:45:34 +0300 Subject: [PATCH 30/61] connman: update to connman-df37290 --- packages/network/connman/build | 1 - packages/network/connman/meta | 2 +- ...bug_print_so_we_know_when_restarting.patch | 29 ---- ...m_ippool_instead_of_hard_coded_value.patch | 77 --------- ...ink_functions_to_set_default_gateway.patch | 57 ------- ...ove_unused_gateway_setting_functions.patch | 156 ------------------ ...hering_when_connman_is_shutting_down.patch | 36 ---- 7 files changed, 1 insertion(+), 357 deletions(-) delete mode 100644 packages/network/connman/patches/connman-990.01.01-tethering-Add_debug_print_so_we_know_when_restarting.patch delete mode 100644 packages/network/connman/patches/connman-990.01.02-tethering-Use_the_prefix_lenght_from_ippool_instead_of_hard_coded_value.patch delete mode 100644 packages/network/connman/patches/connman-990.01.03-connection-Use_netlink_functions_to_set_default_gateway.patch delete mode 100644 packages/network/connman/patches/connman-990.01.04-inet-Remove_unused_gateway_setting_functions.patch delete mode 100644 packages/network/connman/patches/connman-990.02.01-tethering-Cleanup_tethering_when_connman_is_shutting_down.patch diff --git a/packages/network/connman/build b/packages/network/connman/build index a54a88d0cc..5c550d32d3 100755 --- a/packages/network/connman/build +++ b/packages/network/connman/build @@ -48,7 +48,6 @@ cd $PKG_BUILD --enable-shared \ --disable-gtk-doc \ --disable-debug \ - --enable-threads \ --disable-hh2serial-gps \ --disable-openconnect \ $CONNMAN_OPENVPN \ diff --git a/packages/network/connman/meta b/packages/network/connman/meta index fd6d59cc33..7757ebfe38 100644 --- a/packages/network/connman/meta +++ b/packages/network/connman/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="connman" -PKG_VERSION="3ddffce" +PKG_VERSION="df37290" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" diff --git a/packages/network/connman/patches/connman-990.01.01-tethering-Add_debug_print_so_we_know_when_restarting.patch b/packages/network/connman/patches/connman-990.01.01-tethering-Add_debug_print_so_we_know_when_restarting.patch deleted file mode 100644 index b15cf64e1d..0000000000 --- a/packages/network/connman/patches/connman-990.01.01-tethering-Add_debug_print_so_we_know_when_restarting.patch +++ /dev/null @@ -1,29 +0,0 @@ - -Betreff: -[PATCH 1/5] tethering: Add debug print so we know when restarting -Von: -Jukka Rissanen -Datum: -25.06.2013 14:58 -An: -connman@connman.net - ---- - src/tethering.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/tethering.c b/src/tethering.c -index 223873b..eb05056 100644 ---- a/src/tethering.c -+++ b/src/tethering.c -@@ -176,6 +176,7 @@ static void dhcp_server_stop(GDHCPServer *server) - - static void tethering_restart(struct connman_ippool *pool, void *user_data) - { -+ DBG("pool %p", pool); - __connman_tethering_set_disabled(); - __connman_tethering_set_enabled(); - } --- -1.7.11.7 - diff --git a/packages/network/connman/patches/connman-990.01.02-tethering-Use_the_prefix_lenght_from_ippool_instead_of_hard_coded_value.patch b/packages/network/connman/patches/connman-990.01.02-tethering-Use_the_prefix_lenght_from_ippool_instead_of_hard_coded_value.patch deleted file mode 100644 index 692fe47514..0000000000 --- a/packages/network/connman/patches/connman-990.01.02-tethering-Use_the_prefix_lenght_from_ippool_instead_of_hard_coded_value.patch +++ /dev/null @@ -1,77 +0,0 @@ - -Betreff: -[PATCH 2/5] tethering: Use the prefix lenght from ippool instead of hard coded value -Von: -Jukka Rissanen -Datum: -25.06.2013 14:58 -An: -connman@connman.net - -We were always using prefix length 24 instead of the correct -value from ippool. ---- - src/bridge.c | 8 ++++---- - src/connman.h | 4 ++-- - src/tethering.c | 4 +++- - 3 files changed, 9 insertions(+), 7 deletions(-) - -diff --git a/src/bridge.c b/src/bridge.c -index e46cdda..1610f96 100644 ---- a/src/bridge.c -+++ b/src/bridge.c -@@ -111,8 +111,8 @@ int __connman_bridge_remove(const char *name) - return 0; - } - --int __connman_bridge_enable(const char *name, const char *gateway, -- const char *broadcast) -+int __connman_bridge_enable(const char *name, const char *ip_address, -+ int prefix_len, const char *broadcast) - { - int err, index; - -@@ -121,8 +121,8 @@ int __connman_bridge_enable(const char *name, const char *gateway, - return index; - - err = __connman_inet_modify_address(RTM_NEWADDR, -- NLM_F_REPLACE | NLM_F_ACK, index, AF_INET, -- gateway, NULL, 24, broadcast); -+ NLM_F_REPLACE | NLM_F_ACK, index, AF_INET, -+ ip_address, NULL, prefix_len, broadcast); - if (err < 0) - return err; - -diff --git a/src/connman.h b/src/connman.h -index 11dbc35..96f8466 100644 ---- a/src/connman.h -+++ b/src/connman.h -@@ -899,8 +899,8 @@ void __connman_ippool_deladdr(int index, const char *address, - - int __connman_bridge_create(const char *name); - int __connman_bridge_remove(const char *name); --int __connman_bridge_enable(const char *name, const char *gateway, -- const char *broadcast); -+int __connman_bridge_enable(const char *name, const char *ip_address, -+ int prefix_len, const char *broadcast); - int __connman_bridge_disable(const char *name); - - int __connman_nat_init(void); -diff --git a/src/tethering.c b/src/tethering.c -index eb05056..0b373b9 100644 ---- a/src/tethering.c -+++ b/src/tethering.c -@@ -221,7 +221,9 @@ void __connman_tethering_set_enabled(void) - start_ip = __connman_ippool_get_start_ip(dhcp_ippool); - end_ip = __connman_ippool_get_end_ip(dhcp_ippool); - -- err = __connman_bridge_enable(BRIDGE_NAME, gateway, broadcast); -+ err = __connman_bridge_enable(BRIDGE_NAME, gateway, -+ __connman_ipaddress_netmask_prefix_len(subnet_mask), -+ broadcast); - if (err < 0 && err != -EALREADY) { - __connman_ippool_unref(dhcp_ippool); - __connman_bridge_remove(BRIDGE_NAME); --- -1.7.11.7 - diff --git a/packages/network/connman/patches/connman-990.01.03-connection-Use_netlink_functions_to_set_default_gateway.patch b/packages/network/connman/patches/connman-990.01.03-connection-Use_netlink_functions_to_set_default_gateway.patch deleted file mode 100644 index dbd1ed1834..0000000000 --- a/packages/network/connman/patches/connman-990.01.03-connection-Use_netlink_functions_to_set_default_gateway.patch +++ /dev/null @@ -1,57 +0,0 @@ - -Betreff: -[PATCH 3/5] connection: Use netlink functions to set default gateway -Von: -Jukka Rissanen -Datum: -25.06.2013 14:58 -An: -connman@connman.net - -We were using earlier the ioctl() to set the default gateway. -In some cases that could fail because the desired interface -was not set when calling the ioctl(). -This happened with tethering with following scenario: -* Ethernet cable (uplink connection) is not connected -* Wifi tethering is started with address 192.168.1.1 -* Ethernet cable is connected, uplink address is 192.168.1.0/24 -* There is now a conflict, ippool resolves that in __connman_ippool_newaddr() - and calls tethering_restart() which stops and then starts tethering -* Because of the problems when calling the SIOCADDRT (we do not know - to what interface the default route was added to), the default route - of uplink connection was added to tethering interface (tether) instead - of uplink interface (eth0). This caused the default route to disappear - when tether interface was taken down. -* Solution was to use the netlink interface to set the default gateway - as we can unambiguously set the desired default route to be via the - uplink interface - -Thanks for Stephan Raue for reporting this issue. ---- - src/connection.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/connection.c b/src/connection.c -index c7b1f62..c0fdaf8 100644 ---- a/src/connection.c -+++ b/src/connection.c -@@ -479,12 +479,12 @@ static void set_default_gateway(struct gateway_data *data, - } - - if (do_ipv6 == TRUE && data->ipv6_gateway != NULL) -- status6 = connman_inet_set_ipv6_gateway_address(index, -- data->ipv6_gateway->gateway); -+ status6 = __connman_inet_add_default_to_table(RT_TABLE_MAIN, -+ index, data->ipv6_gateway->gateway); - - if (do_ipv4 == TRUE && data->ipv4_gateway != NULL) -- status4 = connman_inet_set_gateway_address(index, -- data->ipv4_gateway->gateway); -+ status4 = __connman_inet_add_default_to_table(RT_TABLE_MAIN, -+ index, data->ipv4_gateway->gateway); - - if (status4 < 0 || status6 < 0) - return; --- -1.7.11.7 - diff --git a/packages/network/connman/patches/connman-990.01.04-inet-Remove_unused_gateway_setting_functions.patch b/packages/network/connman/patches/connman-990.01.04-inet-Remove_unused_gateway_setting_functions.patch deleted file mode 100644 index 1a04aada5e..0000000000 --- a/packages/network/connman/patches/connman-990.01.04-inet-Remove_unused_gateway_setting_functions.patch +++ /dev/null @@ -1,156 +0,0 @@ - -Betreff: -[PATCH 4/5] inet: Remove unused gateway setting functions -Von: -Jukka Rissanen -Datum: -25.06.2013 14:58 -An: -connman@connman.net - -No need for these functions any more as we are using the netlink -variants to set the default gateway. ---- - include/inet.h | 2 -- - src/inet.c | 98 ---------------------------------------------------------- - 2 files changed, 100 deletions(-) - -diff --git a/include/inet.h b/include/inet.h -index 8f7a35c..10d9dae 100644 ---- a/include/inet.h -+++ b/include/inet.h -@@ -50,7 +50,6 @@ int connman_inet_del_host_route(int index, const char *host); - int connman_inet_add_network_route(int index, const char *host, const char *gateway, - const char *netmask); - int connman_inet_del_network_route(int index, const char *host); --int connman_inet_set_gateway_address(int index, const char *gateway); - int connman_inet_clear_gateway_address(int index, const char *gateway); - int connman_inet_set_gateway_interface(int index); - int connman_inet_clear_gateway_interface(int index); -@@ -66,7 +65,6 @@ int connman_inet_add_ipv6_host_route(int index, const char *host, - int connman_inet_del_ipv6_network_route(int index, const char *host, - unsigned char prefix_len); - int connman_inet_del_ipv6_host_route(int index, const char *host); --int connman_inet_set_ipv6_gateway_address(int index, const char *gateway); - int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway); - int connman_inet_set_ipv6_gateway_interface(int index); - int connman_inet_clear_ipv6_gateway_interface(int index); -diff --git a/src/inet.c b/src/inet.c -index ed98dd5..840f9b1 100644 ---- a/src/inet.c -+++ b/src/inet.c -@@ -727,47 +727,6 @@ int connman_inet_add_ipv6_host_route(int index, const char *host, - return connman_inet_add_ipv6_network_route(index, host, gateway, 128); - } - --int connman_inet_set_ipv6_gateway_address(int index, const char *gateway) --{ -- struct in6_rtmsg rt; -- int sk, err = 0; -- -- DBG("index %d gateway %s", index, gateway); -- -- if (gateway == NULL) -- return -EINVAL; -- -- memset(&rt, 0, sizeof(rt)); -- -- if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) { -- err = -errno; -- goto out; -- } -- -- rt.rtmsg_flags = RTF_UP | RTF_GATEWAY; -- rt.rtmsg_metric = 1; -- rt.rtmsg_dst_len = 0; -- rt.rtmsg_ifindex = index; -- -- sk = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); -- if (sk < 0) { -- err = -errno; -- goto out; -- } -- -- if (ioctl(sk, SIOCADDRT, &rt) < 0 && errno != EEXIST) -- err = -errno; -- -- close(sk); -- --out: -- if (err < 0) -- connman_error("Set default IPv6 gateway error (%s)", -- strerror(-err)); -- -- return err; --} -- - int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway) - { - struct in6_rtmsg rt; -@@ -809,63 +768,6 @@ out: - return err; - } - --int connman_inet_set_gateway_address(int index, const char *gateway) --{ -- struct ifreq ifr; -- struct rtentry rt; -- struct sockaddr_in addr; -- int sk, err = 0; -- -- DBG("index %d gateway %s", index, gateway); -- -- sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); -- if (sk < 0) { -- err = -errno; -- goto out; -- } -- -- memset(&ifr, 0, sizeof(ifr)); -- ifr.ifr_ifindex = index; -- -- if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) { -- err = -errno; -- close(sk); -- goto out; -- } -- -- DBG("ifname %s", ifr.ifr_name); -- -- memset(&rt, 0, sizeof(rt)); -- rt.rt_flags = RTF_UP | RTF_GATEWAY; -- -- memset(&addr, 0, sizeof(addr)); -- addr.sin_family = AF_INET; -- addr.sin_addr.s_addr = INADDR_ANY; -- memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst)); -- -- memset(&addr, 0, sizeof(addr)); -- addr.sin_family = AF_INET; -- addr.sin_addr.s_addr = inet_addr(gateway); -- memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway)); -- -- memset(&addr, 0, sizeof(addr)); -- addr.sin_family = AF_INET; -- addr.sin_addr.s_addr = INADDR_ANY; -- memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask)); -- -- if (ioctl(sk, SIOCADDRT, &rt) < 0 && errno != EEXIST) -- err = -errno; -- -- close(sk); -- --out: -- if (err < 0) -- connman_error("Setting default gateway route failed (%s)", -- strerror(-err)); -- -- return err; --} -- - int connman_inet_set_gateway_interface(int index) - { - struct ifreq ifr; --- -1.7.11.7 - diff --git a/packages/network/connman/patches/connman-990.02.01-tethering-Cleanup_tethering_when_connman_is_shutting_down.patch b/packages/network/connman/patches/connman-990.02.01-tethering-Cleanup_tethering_when_connman_is_shutting_down.patch deleted file mode 100644 index 337ae19655..0000000000 --- a/packages/network/connman/patches/connman-990.02.01-tethering-Cleanup_tethering_when_connman_is_shutting_down.patch +++ /dev/null @@ -1,36 +0,0 @@ - -Betreff: -[PATCH] tethering: Cleanup tethering when connman is shutting down -Von: -Jukka Rissanen -Datum: -26.06.2013 09:40 -An: -connman@connman.net - -We do not want to leave the tether interface and bridge hanging -around after shutdown. ---- - src/tethering.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/tethering.c b/src/tethering.c -index 0b373b9..03ed02a 100644 ---- a/src/tethering.c -+++ b/src/tethering.c -@@ -532,10 +532,10 @@ int __connman_tethering_init(void) - - void __connman_tethering_cleanup(void) - { -- DBG(""); -+ DBG("enabled %d", tethering_enabled); - - __sync_synchronize(); -- if (tethering_enabled == 0) { -+ if (tethering_enabled > 0) { - if (tethering_dhcp_server) - dhcp_server_stop(tethering_dhcp_server); - __connman_bridge_disable(BRIDGE_NAME); --- -1.7.11.7 - From c51b361628ab04b10cd57ff0c8606892c1f066d7 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 22:46:47 +0300 Subject: [PATCH 31/61] connman: rename patches --- ...leanup-routes.patch => connman-01-do-not-cleanup-routes.patch} | 0 ...connman-disable-wispr.patch => connman-02-disable-wispr.patch} | 0 ...-tethering.patch => connman-03-init-nat-after-tethering.patch} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename packages/network/connman/patches/{connman-do-not-cleanup-routes.patch => connman-01-do-not-cleanup-routes.patch} (100%) rename packages/network/connman/patches/{connman-disable-wispr.patch => connman-02-disable-wispr.patch} (100%) rename packages/network/connman/patches/{connman-init-nat-after-tethering.patch => connman-03-init-nat-after-tethering.patch} (100%) diff --git a/packages/network/connman/patches/connman-do-not-cleanup-routes.patch b/packages/network/connman/patches/connman-01-do-not-cleanup-routes.patch similarity index 100% rename from packages/network/connman/patches/connman-do-not-cleanup-routes.patch rename to packages/network/connman/patches/connman-01-do-not-cleanup-routes.patch diff --git a/packages/network/connman/patches/connman-disable-wispr.patch b/packages/network/connman/patches/connman-02-disable-wispr.patch similarity index 100% rename from packages/network/connman/patches/connman-disable-wispr.patch rename to packages/network/connman/patches/connman-02-disable-wispr.patch diff --git a/packages/network/connman/patches/connman-init-nat-after-tethering.patch b/packages/network/connman/patches/connman-03-init-nat-after-tethering.patch similarity index 100% rename from packages/network/connman/patches/connman-init-nat-after-tethering.patch rename to packages/network/connman/patches/connman-03-init-nat-after-tethering.patch From 53c270da572d77f4c93c5f9f7d564bd0459db481 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 22:47:03 +0300 Subject: [PATCH 32/61] connman: add patch to disable ipv6 by default --- .../connman-04-ipv6-disabled-by-default.patch | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 packages/network/connman/patches/connman-04-ipv6-disabled-by-default.patch diff --git a/packages/network/connman/patches/connman-04-ipv6-disabled-by-default.patch b/packages/network/connman/patches/connman-04-ipv6-disabled-by-default.patch new file mode 100644 index 0000000000..db9fafadb4 --- /dev/null +++ b/packages/network/connman/patches/connman-04-ipv6-disabled-by-default.patch @@ -0,0 +1,22 @@ +commit 7b130774c0a0a31879218eedb680ed732a1ee94a +Author: Stefan Saraev +Date: Thu Jul 4 22:43:17 2013 +0300 + + ipv6 disabled by default + +diff --git a/src/ipconfig.c b/src/ipconfig.c +index a97a6f3..2b43935 100644 +--- a/src/ipconfig.c ++++ b/src/ipconfig.c +@@ -1118,10 +1118,7 @@ static struct connman_ipconfig *create_ipv6config(int index) + ipv6config->enabled = FALSE; + ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6; + +- if (is_ipv6_supported == FALSE) +- ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF; +- else +- ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO; ++ ipv6config->method = CONNMAN_IPCONFIG_METHOD_OFF; + + ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); + if (ipdevice != NULL) From b7f4e443a13b5a6cd0e3ad4f0fb83c9ba1769ae0 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 22:54:01 +0300 Subject: [PATCH 33/61] pm-utils: added module cdc_acm to SUSPEND_MODULES closes #2440 --- packages/sysutils/pm-utils/config.d/module | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sysutils/pm-utils/config.d/module b/packages/sysutils/pm-utils/config.d/module index 04c04bc7d3..1321ebc407 100644 --- a/packages/sysutils/pm-utils/config.d/module +++ b/packages/sysutils/pm-utils/config.d/module @@ -1 +1 @@ -SUSPEND_MODULES="xhci-hcd jme asix anysee rtl8192se imon r8712u cx23885" +SUSPEND_MODULES="xhci-hcd jme asix anysee rtl8192se imon r8712u cx23885 cdc_acm" From ea24152296775f34122f1b89e35c18503ac2779d Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 5 Jul 2013 00:55:58 +0200 Subject: [PATCH 34/61] gdb: update to gdb-7.6 Signed-off-by: Stephan Raue --- packages/debug/gdb/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/debug/gdb/meta b/packages/debug/gdb/meta index 15b08989ed..599e26f696 100644 --- a/packages/debug/gdb/meta +++ b/packages/debug/gdb/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="gdb" -PKG_VERSION="7.5.1" +PKG_VERSION="7.6" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From 7aaa04d53a4abb9c0d063d79d44c9049750d2be7 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 19:36:44 +0300 Subject: [PATCH 35/61] linux: perf: build without slang (no tui mode) --- packages/linux/build | 1 + packages/linux/meta | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/linux/build b/packages/linux/build index 6f1b90ce95..a4ce687807 100755 --- a/packages/linux/build +++ b/packages/linux/build @@ -70,6 +70,7 @@ if [ "$PERF_SUPPORT" = "yes" -a "$DEVTOOLS" = "yes" ]; then NO_LIBPYTHON=false \ PYTHON=$SYSROOT_PREFIX/usr/bin/python \ WERROR=0 \ + NO_SLANG=1 \ ) fi diff --git a/packages/linux/meta b/packages/linux/meta index 8dfb627c70..50a8a17bb2 100644 --- a/packages/linux/meta +++ b/packages/linux/meta @@ -55,5 +55,5 @@ PKG_AUTORECONF="no" if [ "$DEVTOOLS" = "yes" ]; then PKG_DEPENDS="$PKG_DEPENDS Python" - PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS slang elfutils Python" + PKG_BUILD_DEPENDS="$PKG_BUILD_DEPENDS elfutils Python" fi From 3d15193ebf3a50530d761056585da5b1185be562 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Thu, 4 Jul 2013 19:37:07 +0300 Subject: [PATCH 36/61] remove package: 'slang' --- packages/devel/slang/build | 42 -------------------------------------- packages/devel/slang/meta | 36 -------------------------------- 2 files changed, 78 deletions(-) delete mode 100755 packages/devel/slang/build delete mode 100644 packages/devel/slang/meta diff --git a/packages/devel/slang/build b/packages/devel/slang/build deleted file mode 100755 index d252857101..0000000000 --- a/packages/devel/slang/build +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2013 Dag Wieers (dag@wieers.com) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -. config/options $1 - -MAKEFLAGS=-j1 - -cd $PKG_BUILD -./configure --host=$TARGET_NAME \ - --build=$HOST_NAME \ - --prefix=/usr \ - --exec-prefix=/usr \ - --sysconfdir=/etc \ - --datadir=/usr/share \ - --without-iconv \ - --without-onig \ - --without-pcre \ - --without-png \ - --without-z \ - --without-x \ - -make -C src static -make DESTDIR="$SYSROOT_PREFIX" -C src install-static diff --git a/packages/devel/slang/meta b/packages/devel/slang/meta deleted file mode 100644 index 9a7460ba15..0000000000 --- a/packages/devel/slang/meta +++ /dev/null @@ -1,36 +0,0 @@ -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2013 Dag Wieers (dag@wieers.com) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -PKG_NAME="slang" -PKG_VERSION="2.2.4" -PKG_REV="1" -PKG_ARCH="any" -PKG_LICENSE="LGPL" -PKG_SITE="http://www.jedsoft.org/slang/" -PKG_URL="ftp://ftp.fu-berlin.de/pub/unix/misc/slang/v2.2/$PKG_NAME-$PKG_VERSION.tar.bz2" -PKG_DEPENDS="" -PKG_BUILD_DEPENDS="toolchain" -PKG_PRIORITY="optional" -PKG_SECTION="devel" -PKG_SHORTDESC="slang: library for the S-Lang extension language" -PKG_LONGDESC="S-Lang is an interpreted language and a programming library. The S-Lang language was designed so that it can be easily embedded into a program to provide the program with a powerful extension language. The S-Lang library, provided in this package, provides the S-Lang extension language. S-Lang's syntax resembles C, which makes it easy to recode S-Lang procedures in C if you need to." -PKG_IS_ADDON="no" - -PKG_AUTORECONF="no" From afa0c91e0c64706c15fe7176a9b16d062c893afb Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 5 Jul 2013 19:00:44 +0200 Subject: [PATCH 37/61] scripts/checkdeps: add dependency 'bc', needed for building the kernel, see https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=70730bca1331fc50c3caacaea00439de1325bd6e Signed-off-by: Stephan Raue --- scripts/checkdeps | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/checkdeps b/scripts/checkdeps index 08dbc02aff..1ffd64e734 100755 --- a/scripts/checkdeps +++ b/scripts/checkdeps @@ -33,8 +33,8 @@ case $1 in deps_pkg="wget" ;; build) - deps="gcc g++ sed patch touch tar bzip2 gzip perl cp gawk makeinfo gperf cvs zip unzip mkfontscale diff xsltproc java" - deps_pkg="gcc g++ sed patch fileutils tar bzip2 gzip perl coreutils gawk texinfo gperf cvs zip unzip xutils diff xsltproc default-jre" + deps="bc gcc g++ sed patch touch tar bzip2 gzip perl cp gawk makeinfo gperf cvs zip unzip mkfontscale diff xsltproc java" + deps_pkg="bc gcc g++ sed patch fileutils tar bzip2 gzip perl coreutils gawk texinfo gperf cvs zip unzip xutils diff xsltproc default-jre" files="/usr/include/stdio.h /usr/include/ncurses.h" files_pkg="libc6-dev libncurses5-dev" ;; From a2340eba1392a62b15c0f825b33282bab4dfd27c Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 5 Jul 2013 23:56:51 +0200 Subject: [PATCH 38/61] xbmc: add PR2890 Signed-off-by: Stephan Raue --- .../12.2.0/xbmc-990.26.01-PR2890.patch | 29 + .../12.2.0/xbmc-990.26.02-PR2890.patch | 1875 +++++++++++++++++ 2 files changed, 1904 insertions(+) create mode 100644 packages/mediacenter/xbmc/patches/12.2.0/xbmc-990.26.01-PR2890.patch create mode 100644 packages/mediacenter/xbmc/patches/12.2.0/xbmc-990.26.02-PR2890.patch diff --git a/packages/mediacenter/xbmc/patches/12.2.0/xbmc-990.26.01-PR2890.patch b/packages/mediacenter/xbmc/patches/12.2.0/xbmc-990.26.01-PR2890.patch new file mode 100644 index 0000000000..ac505a42f8 --- /dev/null +++ b/packages/mediacenter/xbmc/patches/12.2.0/xbmc-990.26.01-PR2890.patch @@ -0,0 +1,29 @@ +From 86a63c5040e307dcb633a5934ab1b3f9114009f5 Mon Sep 17 00:00:00 2001 +From: arnova +Date: Sun, 23 Jun 2013 23:16:55 +0200 +Subject: [PATCH] changed: Make more obvious we're passing a CFileItem + +--- + xbmc/music/infoscanner/MusicInfoScanner.cpp | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp +index 84a155c..f93d613 100644 +--- a/xbmc/music/infoscanner/MusicInfoScanner.cpp ++++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp +@@ -1009,8 +1009,10 @@ void CMusicInfoScanner::FindArtForAlbums(VECALBUMS &albums, const CStdString &pa + } + } + if (albums.size() == 1 && !albumArt.empty()) +- { // assign to folder thumb as well +- CMusicThumbLoader::SetCachedImage(path, "thumb", albumArt); ++ { ++ // assign to folder thumb as well ++ CFileItem albumItem(path, true); ++ CMusicThumbLoader::SetCachedImage(albumItem, "thumb", albumArt); + } + } + +-- +1.8.1.6 + diff --git a/packages/mediacenter/xbmc/patches/12.2.0/xbmc-990.26.02-PR2890.patch b/packages/mediacenter/xbmc/patches/12.2.0/xbmc-990.26.02-PR2890.patch new file mode 100644 index 0000000000..4db4c3470d --- /dev/null +++ b/packages/mediacenter/xbmc/patches/12.2.0/xbmc-990.26.02-PR2890.patch @@ -0,0 +1,1875 @@ +From 9752e490e40e69d53e9dbb10a972dff533192570 Mon Sep 17 00:00:00 2001 +From: arnova +Date: Fri, 14 Jun 2013 12:55:10 +0200 +Subject: [PATCH 1/6] removed: BackGroundInfo Loader multithreading (no longer + needed) + +--- + xbmc/BackgroundInfoLoader.cpp | 62 +++++------------------------ + xbmc/BackgroundInfoLoader.h | 12 ++---- + xbmc/ThumbLoader.cpp | 4 +- + xbmc/ThumbLoader.h | 2 +- + xbmc/addons/GUIWindowAddonBrowser.cpp | 1 - + xbmc/music/MusicInfoLoader.cpp | 2 +- + xbmc/music/MusicThumbLoader.cpp | 2 +- + xbmc/pictures/PictureThumbLoader.cpp | 2 +- + xbmc/pvr/windows/GUIWindowPVRRecordings.cpp | 1 - + xbmc/settings/AdvancedSettings.cpp | 5 --- + xbmc/settings/AdvancedSettings.h | 1 - + xbmc/video/VideoThumbLoader.cpp | 2 +- + 12 files changed, 21 insertions(+), 75 deletions(-) + +diff --git a/xbmc/BackgroundInfoLoader.cpp b/xbmc/BackgroundInfoLoader.cpp +index 3c76188..0c6de8d 100644 +--- a/xbmc/BackgroundInfoLoader.cpp ++++ b/xbmc/BackgroundInfoLoader.cpp +@@ -26,17 +26,12 @@ + + using namespace std; + +-#define ITEMS_PER_THREAD 5 +- +-CBackgroundInfoLoader::CBackgroundInfoLoader(int nThreads) ++CBackgroundInfoLoader::CBackgroundInfoLoader() : m_thread (NULL) + { + m_bStop = true; + m_pObserver=NULL; + m_pProgressCallback=NULL; + m_pVecItems = NULL; +- m_nRequestedThreads = nThreads; +- m_bStartCalled = false; +- m_nActiveThreads = 0; + } + + CBackgroundInfoLoader::~CBackgroundInfoLoader() +@@ -44,29 +39,16 @@ + StopThread(); + } + +-void CBackgroundInfoLoader::SetNumOfWorkers(int nThreads) +-{ +- m_nRequestedThreads = nThreads; +-} +- + void CBackgroundInfoLoader::Run() + { + try + { + if (m_vecItems.size() > 0) + { +- { +- CSingleLock lock(m_lock); +- if (!m_bStartCalled) +- { +- OnLoaderStart(); +- m_bStartCalled = true; +- } +- } ++ OnLoaderStart(); + + while (!m_bStop) + { +- CSingleLock lock(m_lock); + CFileItemPtr pItem; + vector::iterator iter = m_vecItems.begin(); + if (iter != m_vecItems.end()) +@@ -82,7 +64,6 @@ void CBackgroundInfoLoader::Run() + if ((m_pProgressCallback && m_pProgressCallback->Abort()) || m_bStop) + break; + +- lock.Leave(); + try + { + if (LoadItem(pItem.get()) && m_pObserver) +@@ -95,15 +76,10 @@ void CBackgroundInfoLoader::Run() + } + } + +- CSingleLock lock(m_lock); +- if (m_nActiveThreads == 1) +- OnLoaderFinish(); +- m_nActiveThreads--; +- ++ OnLoaderFinish(); + } + catch (...) + { +- m_nActiveThreads--; + CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__); + } + } +@@ -122,26 +98,12 @@ void CBackgroundInfoLoader::Load(CFileItemList& items) + + m_pVecItems = &items; + m_bStop = false; +- m_bStartCalled = false; +- +- int nThreads = m_nRequestedThreads; +- if (nThreads == -1) +- nThreads = (m_vecItems.size() / (ITEMS_PER_THREAD+1)) + 1; + +- if (nThreads > g_advancedSettings.m_bgInfoLoaderMaxThreads) +- nThreads = g_advancedSettings.m_bgInfoLoaderMaxThreads; +- +- m_nActiveThreads = nThreads; +- for (int i=0; i < nThreads; i++) +- { +- CThread *pThread = new CThread(this, "Background Loader"); +- pThread->Create(); ++ m_thread = new CThread(this, "Background Loader"); ++ m_thread->Create(); + #ifndef _LINUX +- pThread->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); ++ m_thread->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); + #endif +- m_workers.push_back(pThread); +- } +- + } + + void CBackgroundInfoLoader::StopAsync() +@@ -154,21 +116,19 @@ void CBackgroundInfoLoader::StopThread() + { + StopAsync(); + +- for (int i=0; i<(int)m_workers.size(); i++) ++ if (m_thread) + { +- m_workers[i]->StopThread(); +- delete m_workers[i]; ++ m_thread->StopThread(); ++ delete m_thread; ++ m_thread = NULL; + } +- +- m_workers.clear(); + m_vecItems.clear(); + m_pVecItems = NULL; +- m_nActiveThreads = 0; + } + + bool CBackgroundInfoLoader::IsLoading() + { +- return m_nActiveThreads > 0; ++ return m_thread != NULL; + } + + void CBackgroundInfoLoader::SetObserver(IBackgroundLoaderObserver* pObserver) +diff --git a/xbmc/BackgroundInfoLoader.h b/xbmc/BackgroundInfoLoader.h +index c0c1580..a580605 100644 +--- a/xbmc/BackgroundInfoLoader.h ++++ b/xbmc/BackgroundInfoLoader.h +@@ -40,7 +40,7 @@ class IBackgroundLoaderObserver + class CBackgroundInfoLoader : public IRunnable + { + public: +- CBackgroundInfoLoader(int nThreads=-1); ++ CBackgroundInfoLoader(); + virtual ~CBackgroundInfoLoader(); + + void Load(CFileItemList& items); +@@ -50,11 +50,9 @@ class CBackgroundInfoLoader : public IRunnable + void SetProgressCallback(IProgressCallback* pCallback); + virtual bool LoadItem(CFileItem* pItem) { return false; }; + +- void StopThread(); // will actually stop all worker threads. ++ void StopThread(); // will actually stop the loader thread. + void StopAsync(); // will ask loader to stop as soon as possible, but not block + +- void SetNumOfWorkers(int nThreads); // -1 means auto compute num of required threads +- + protected: + virtual void OnLoaderStart() {}; + virtual void OnLoaderFinish() {}; +@@ -63,14 +61,10 @@ class CBackgroundInfoLoader : public IRunnable + std::vector m_vecItems; // FileItemList would delete the items and we only want to keep a reference. + CCriticalSection m_lock; + +- bool m_bStartCalled; + volatile bool m_bStop; +- int m_nRequestedThreads; +- int m_nActiveThreads; ++ CThread *m_thread; + + IBackgroundLoaderObserver* m_pObserver; + IProgressCallback* m_pProgressCallback; +- +- std::vector m_workers; + }; + +diff --git a/xbmc/ThumbLoader.cpp b/xbmc/ThumbLoader.cpp +index a6997c8..8382acf 100644 +--- a/xbmc/ThumbLoader.cpp ++++ b/xbmc/ThumbLoader.cpp +@@ -26,8 +26,8 @@ + using namespace std; + using namespace XFILE; + +-CThumbLoader::CThumbLoader(int nThreads) : +- CBackgroundInfoLoader(nThreads) ++CThumbLoader::CThumbLoader() : ++ CBackgroundInfoLoader() + { + } + +diff --git a/xbmc/ThumbLoader.h b/xbmc/ThumbLoader.h +index a06680f..655d528 100644 +--- a/xbmc/ThumbLoader.h ++++ b/xbmc/ThumbLoader.h +@@ -25,7 +25,7 @@ + class CThumbLoader : public CBackgroundInfoLoader + { + public: +- CThumbLoader(int nThreads=-1); ++ CThumbLoader(); + virtual ~CThumbLoader(); + + virtual void Initialize() { }; +diff --git a/xbmc/addons/GUIWindowAddonBrowser.cpp b/xbmc/addons/GUIWindowAddonBrowser.cpp +index e6303e2..dddce48 100644 +--- a/xbmc/addons/GUIWindowAddonBrowser.cpp ++++ b/xbmc/addons/GUIWindowAddonBrowser.cpp +@@ -59,7 +59,6 @@ + CGUIWindowAddonBrowser::CGUIWindowAddonBrowser(void) + : CGUIMediaWindow(WINDOW_ADDON_BROWSER, "AddonBrowser.xml") + { +- m_thumbLoader.SetNumOfWorkers(1); + } + + CGUIWindowAddonBrowser::~CGUIWindowAddonBrowser() +diff --git a/xbmc/music/MusicInfoLoader.cpp b/xbmc/music/MusicInfoLoader.cpp +index 4cb41c2..9256e89 100644 +--- a/xbmc/music/MusicInfoLoader.cpp ++++ b/xbmc/music/MusicInfoLoader.cpp +@@ -41,7 +41,7 @@ + using namespace MUSIC_INFO; + + // HACK until we make this threadable - specify 1 thread only for now +-CMusicInfoLoader::CMusicInfoLoader() : CBackgroundInfoLoader(1) ++CMusicInfoLoader::CMusicInfoLoader() : CBackgroundInfoLoader() + { + m_mapFileItems = new CFileItemList; + +diff --git a/xbmc/music/MusicThumbLoader.cpp b/xbmc/music/MusicThumbLoader.cpp +index 5d66e1c..dc21ccc 100644 +--- a/xbmc/music/MusicThumbLoader.cpp ++++ b/xbmc/music/MusicThumbLoader.cpp +@@ -30,7 +30,7 @@ + using namespace std; + using namespace MUSIC_INFO; + +-CMusicThumbLoader::CMusicThumbLoader() : CThumbLoader(1) ++CMusicThumbLoader::CMusicThumbLoader() : CThumbLoader() + { + m_database = new CMusicDatabase; + } +diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp +index 2eb57f6..8e690d2 100644 +--- a/xbmc/pictures/PictureThumbLoader.cpp ++++ b/xbmc/pictures/PictureThumbLoader.cpp +@@ -35,7 +35,7 @@ + using namespace XFILE; + using namespace std; + +-CPictureThumbLoader::CPictureThumbLoader() : CThumbLoader(1), CJobQueue(true) ++CPictureThumbLoader::CPictureThumbLoader() : CThumbLoader(), CJobQueue(true) + { + m_regenerateThumbs = false; + } +diff --git a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp +index 369a775..a49ba32 100644 +--- a/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp ++++ b/xbmc/pvr/windows/GUIWindowPVRRecordings.cpp +@@ -42,7 +42,6 @@ + CGUIWindowPVRCommon(parent, PVR_WINDOW_RECORDINGS, CONTROL_BTNRECORDINGS, CONTROL_LIST_RECORDINGS) + { + m_strSelectedPath = "pvr://recordings/"; +- m_thumbLoader.SetNumOfWorkers(1); + } + + void CGUIWindowPVRRecordings::UnregisterObservers(void) +diff --git a/xbmc/settings/AdvancedSettings.cpp b/xbmc/settings/AdvancedSettings.cpp +index 3189ad9..bbbdb01 100644 +--- a/xbmc/settings/AdvancedSettings.cpp ++++ b/xbmc/settings/AdvancedSettings.cpp +@@ -346,8 +346,6 @@ void CAdvancedSettings::Initialize() + m_alwaysOnTop = false; + #endif + +- m_bgInfoLoaderMaxThreads = 5; +- + m_iPVRTimeCorrection = 0; + m_iPVRInfoToggleInterval = 3000; + m_bPVRShowEpgInfoOnEpgItemSelect = true; +@@ -1053,9 +1051,6 @@ void CAdvancedSettings::ParseSettingsFile(const CStdString &file) + + XMLUtils::GetBoolean(pRootElement, "alwaysontop", m_alwaysOnTop); + +- XMLUtils::GetInt(pRootElement, "bginfoloadermaxthreads", m_bgInfoLoaderMaxThreads); +- m_bgInfoLoaderMaxThreads = std::max(1, m_bgInfoLoaderMaxThreads); +- + TiXmlElement *pPVR = pRootElement->FirstChildElement("pvr"); + if (pPVR) + { +diff --git a/xbmc/settings/AdvancedSettings.h b/xbmc/settings/AdvancedSettings.h +index dc0c854..2385d2f 100644 +--- a/xbmc/settings/AdvancedSettings.h ++++ b/xbmc/settings/AdvancedSettings.h +@@ -337,7 +337,6 @@ class CAdvancedSettings : public ISettingCallback, public ISettingsHandler + + CStdString m_cpuTempCmd; + CStdString m_gpuTempCmd; +- int m_bgInfoLoaderMaxThreads; + + /* PVR/TV related advanced settings */ + int m_iPVRTimeCorrection; /*!< @brief correct all times (epg tags, timer tags, recording tags) by this amount of minutes. defaults to 0. */ +diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp +index a130f57..0801d6b 100644 +--- a/xbmc/video/VideoThumbLoader.cpp ++++ b/xbmc/video/VideoThumbLoader.cpp +@@ -116,7 +116,7 @@ bool CThumbExtractor::DoWork() + } + + CVideoThumbLoader::CVideoThumbLoader() : +- CThumbLoader(1), CJobQueue(true), m_pStreamDetailsObs(NULL) ++ CThumbLoader(), CJobQueue(true), m_pStreamDetailsObs(NULL) + { + m_database = new CVideoDatabase(); + } +-- +1.8.1.6 + + +From 8f3a951e751d8cd7d8e1cbfa2c3732c48f1639c7 Mon Sep 17 00:00:00 2001 +From: arnova +Date: Fri, 14 Jun 2013 13:44:23 +0200 +Subject: [PATCH 2/6] changed: Split background info loading into a 2 stages + +This allows us to first perform loading of cached (fast) stuff and after that load the lookup (slow) stuff (partially fixes #14071) +--- + xbmc/BackgroundInfoLoader.cpp | 32 +++++++++++++++------- + xbmc/BackgroundInfoLoader.h | 2 ++ + xbmc/ThumbLoader.cpp | 17 +++++++++++- + xbmc/ThumbLoader.h | 2 ++ + xbmc/music/MusicInfoLoader.cpp | 22 +++++++++++++-- + xbmc/music/MusicInfoLoader.h | 2 ++ + xbmc/music/MusicThumbLoader.cpp | 33 ++++++++++++++++++++-- + xbmc/music/MusicThumbLoader.h | 4 ++- + xbmc/pictures/PictureInfoLoader.cpp | 25 +++++++++++++++-- + xbmc/pictures/PictureInfoLoader.h | 2 ++ + xbmc/pictures/PictureThumbLoader.cpp | 18 ++++++++++-- + xbmc/pictures/PictureThumbLoader.h | 2 ++ + xbmc/video/VideoThumbLoader.cpp | 53 +++++++++++++++++++++++++++++++----- + xbmc/video/VideoThumbLoader.h | 2 ++ + 14 files changed, 186 insertions(+), 30 deletions(-) + +diff --git a/xbmc/BackgroundInfoLoader.cpp b/xbmc/BackgroundInfoLoader.cpp +index 0c6de8d..8e488d0 100644 +--- a/xbmc/BackgroundInfoLoader.cpp ++++ b/xbmc/BackgroundInfoLoader.cpp +@@ -47,18 +47,30 @@ void CBackgroundInfoLoader::Run() + { + OnLoaderStart(); + +- while (!m_bStop) ++ // Stage 1: All "fast" stuff we have already cached ++ for (vector::const_iterator iter = m_vecItems.begin(); iter != m_vecItems.end(); ++iter) + { +- CFileItemPtr pItem; +- vector::iterator iter = m_vecItems.begin(); +- if (iter != m_vecItems.end()) ++ CFileItemPtr pItem = *iter; ++ ++ // Ask the callback if we should abort ++ if ((m_pProgressCallback && m_pProgressCallback->Abort()) || m_bStop) ++ break; ++ ++ try + { +- pItem = *iter; +- m_vecItems.erase(iter); ++ if (LoadItemCached(pItem.get()) && m_pObserver) ++ m_pObserver->OnItemLoaded(pItem.get()); + } ++ catch (...) ++ { ++ CLog::Log(LOGERROR, "CBackgroundInfoLoader::LoadItemCached - Unhandled exception for item %s", pItem->GetPath().c_str()); ++ } ++ } + +- if (pItem == NULL) +- break; ++ // Stage 2: All "slow" stuff that we need to lookup ++ for (vector::const_iterator iter = m_vecItems.begin(); iter != m_vecItems.end(); ++iter) ++ { ++ CFileItemPtr pItem = *iter; + + // Ask the callback if we should abort + if ((m_pProgressCallback && m_pProgressCallback->Abort()) || m_bStop) +@@ -66,12 +78,12 @@ void CBackgroundInfoLoader::Run() + + try + { +- if (LoadItem(pItem.get()) && m_pObserver) ++ if (LoadItemLookup(pItem.get()) && m_pObserver) + m_pObserver->OnItemLoaded(pItem.get()); + } + catch (...) + { +- CLog::Log(LOGERROR, "%s::LoadItem - Unhandled exception for item %s", __FUNCTION__, pItem->GetPath().c_str()); ++ CLog::Log(LOGERROR, "CBackgroundInfoLoader::LoadItemLookup - Unhandled exception for item %s", pItem->GetPath().c_str()); + } + } + } +diff --git a/xbmc/BackgroundInfoLoader.h b/xbmc/BackgroundInfoLoader.h +index a580605..3a214a3 100644 +--- a/xbmc/BackgroundInfoLoader.h ++++ b/xbmc/BackgroundInfoLoader.h +@@ -49,6 +49,8 @@ class CBackgroundInfoLoader : public IRunnable + void SetObserver(IBackgroundLoaderObserver* pObserver); + void SetProgressCallback(IProgressCallback* pCallback); + virtual bool LoadItem(CFileItem* pItem) { return false; }; ++ virtual bool LoadItemCached(CFileItem* pItem) { return false; }; ++ virtual bool LoadItemLookup(CFileItem* pItem) { return false; }; + + void StopThread(); // will actually stop the loader thread. + void StopAsync(); // will ask loader to stop as soon as possible, but not block +diff --git a/xbmc/ThumbLoader.cpp b/xbmc/ThumbLoader.cpp +index 8382acf..aa4cb82 100644 +--- a/xbmc/ThumbLoader.cpp ++++ b/xbmc/ThumbLoader.cpp +@@ -60,10 +60,25 @@ void CThumbLoader::SetCachedImage(const CFileItem &item, const CStdString &type, + + bool CProgramThumbLoader::LoadItem(CFileItem *pItem) + { +- if (pItem->IsParentFolder()) return true; ++ bool result = LoadItemCached(pItem); ++ result |= LoadItemLookup(pItem); ++ ++ return result; ++} ++ ++bool CProgramThumbLoader::LoadItemCached(CFileItem *pItem) ++{ ++ if (pItem->IsParentFolder()) ++ return false; ++ + return FillThumb(*pItem); + } + ++bool CProgramThumbLoader::LoadItemLookup(CFileItem *pItem) ++{ ++ return false; ++} ++ + bool CProgramThumbLoader::FillThumb(CFileItem &item) + { + // no need to do anything if we already have a thumb set +diff --git a/xbmc/ThumbLoader.h b/xbmc/ThumbLoader.h +index 655d528..2ee06d1 100644 +--- a/xbmc/ThumbLoader.h ++++ b/xbmc/ThumbLoader.h +@@ -57,6 +57,8 @@ class CProgramThumbLoader : public CThumbLoader + CProgramThumbLoader(); + virtual ~CProgramThumbLoader(); + virtual bool LoadItem(CFileItem* pItem); ++ virtual bool LoadItemCached(CFileItem* pItem); ++ virtual bool LoadItemLookup(CFileItem* pItem); + + /*! \brief Fill the thumb of a programs item + First uses a cached thumb from a previous run, then checks for a local thumb +diff --git a/xbmc/music/MusicInfoLoader.cpp b/xbmc/music/MusicInfoLoader.cpp +index 9256e89..5924f47 100644 +--- a/xbmc/music/MusicInfoLoader.cpp ++++ b/xbmc/music/MusicInfoLoader.cpp +@@ -125,6 +125,25 @@ bool CMusicInfoLoader::LoadAdditionalTagInfo(CFileItem* pItem) + + bool CMusicInfoLoader::LoadItem(CFileItem* pItem) + { ++ bool result = LoadItemCached(pItem); ++ result |= LoadItemLookup(pItem); ++ ++ return result; ++} ++ ++bool CMusicInfoLoader::LoadItemCached(CFileItem* pItem) ++{ ++ if (pItem->m_bIsFolder || pItem->IsPlayList() || pItem->IsNFO() || pItem->IsInternetStream()) ++ return false; ++ ++ // Get thumb for item ++ m_thumbLoader->LoadItem(pItem); ++ ++ return true; ++} ++ ++bool CMusicInfoLoader::LoadItemLookup(CFileItem* pItem) ++{ + if (m_pProgressCallback && !pItem->m_bIsFolder) + m_pProgressCallback->SetProgressAdvance(); + +@@ -188,9 +207,6 @@ bool CMusicInfoLoader::LoadItem(CFileItem* pItem) + } + } + +- // Get thumb for item +- m_thumbLoader->LoadItem(pItem); +- + return true; + } + +diff --git a/xbmc/music/MusicInfoLoader.h b/xbmc/music/MusicInfoLoader.h +index 7715cba..543a8bf 100644 +--- a/xbmc/music/MusicInfoLoader.h ++++ b/xbmc/music/MusicInfoLoader.h +@@ -34,6 +34,8 @@ class CMusicInfoLoader : public CBackgroundInfoLoader + + void UseCacheOnHD(const CStdString& strFileName); + virtual bool LoadItem(CFileItem* pItem); ++ virtual bool LoadItemCached(CFileItem* pItem); ++ virtual bool LoadItemLookup(CFileItem* pItem); + static bool LoadAdditionalTagInfo(CFileItem* pItem); + + protected: +diff --git a/xbmc/music/MusicThumbLoader.cpp b/xbmc/music/MusicThumbLoader.cpp +index dc21ccc..bc1d84a 100644 +--- a/xbmc/music/MusicThumbLoader.cpp ++++ b/xbmc/music/MusicThumbLoader.cpp +@@ -64,21 +64,30 @@ void CMusicThumbLoader::OnLoaderFinish() + + bool CMusicThumbLoader::LoadItem(CFileItem* pItem) + { ++ bool result = LoadItemCached(pItem); ++ result |= LoadItemLookup(pItem); ++ ++ return result; ++} ++ ++bool CMusicThumbLoader::LoadItemCached(CFileItem* pItem) ++{ + if (pItem->m_bIsShareOrDrive) +- return true; ++ return false; + + if (pItem->HasMusicInfoTag() && pItem->GetArt().empty()) + { + if (FillLibraryArt(*pItem)) + return true; ++ + if (pItem->GetMusicInfoTag()->GetType() == "artist") +- return true; // no fallback ++ return false; // No fallback + } + + if (pItem->HasVideoInfoTag() && pItem->GetArt().empty()) + { // music video + CVideoThumbLoader loader; +- if (loader.LoadItem(pItem)) ++ if (loader.LoadItemCached(pItem)) + return true; + } + +@@ -102,6 +111,24 @@ bool CMusicThumbLoader::LoadItem(CFileItem* pItem) + } + } + ++ return false; ++} ++ ++bool CMusicThumbLoader::LoadItemLookup(CFileItem* pItem) ++{ ++ if (pItem->m_bIsShareOrDrive) ++ return false; ++ ++ if (pItem->HasMusicInfoTag() && pItem->GetMusicInfoTag()->GetType() == "artist") // No fallback for artist ++ return false; ++ ++ if (pItem->HasVideoInfoTag()) ++ { // music video ++ CVideoThumbLoader loader; ++ if (loader.LoadItemLookup(pItem)) ++ return true; ++ } ++ + if (!pItem->HasArt("thumb")) + { + // Look for embedded art +diff --git a/xbmc/music/MusicThumbLoader.h b/xbmc/music/MusicThumbLoader.h +index 6351789..f8bbd29 100644 +--- a/xbmc/music/MusicThumbLoader.h ++++ b/xbmc/music/MusicThumbLoader.h +@@ -40,7 +40,9 @@ class CMusicThumbLoader : public CThumbLoader + virtual void Deinitialize(); + + virtual bool LoadItem(CFileItem* pItem); +- ++ virtual bool LoadItemCached(CFileItem* pItem); ++ virtual bool LoadItemLookup(CFileItem* pItem); ++ + /*! \brief helper function to fill the art for a video library item + \param item a video CFileItem + \return true if we fill art, false otherwise +diff --git a/xbmc/pictures/PictureInfoLoader.cpp b/xbmc/pictures/PictureInfoLoader.cpp +index 00b30d3..f92f307 100644 +--- a/xbmc/pictures/PictureInfoLoader.cpp ++++ b/xbmc/pictures/PictureInfoLoader.cpp +@@ -50,16 +50,21 @@ void CPictureInfoLoader::OnLoaderStart() + + bool CPictureInfoLoader::LoadItem(CFileItem* pItem) + { +- if (m_pProgressCallback && !pItem->m_bIsFolder) +- m_pProgressCallback->SetProgressAdvance(); ++ bool result = LoadItemCached(pItem); ++ result |= LoadItemLookup(pItem); + ++ return result; ++} ++ ++bool CPictureInfoLoader::LoadItemCached(CFileItem* pItem) ++{ + if (!pItem->IsPicture() || pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBR() || pItem->IsCBZ() || pItem->IsInternetStream() || pItem->IsVideo()) + return false; + + if (pItem->HasPictureInfoTag()) + return true; + +- // first check the cached item ++ // Check the cached item + CFileItemPtr mapItem = (*m_mapFileItems)[pItem->GetPath()]; + if (mapItem && mapItem->m_dateTime==pItem->m_dateTime && mapItem->HasPictureInfoTag()) + { // Query map if we previously cached the file on HD +@@ -68,6 +73,20 @@ bool CPictureInfoLoader::LoadItem(CFileItem* pItem) + return true; + } + ++ return true; ++} ++ ++bool CPictureInfoLoader::LoadItemLookup(CFileItem* pItem) ++{ ++ if (m_pProgressCallback && !pItem->m_bIsFolder) ++ m_pProgressCallback->SetProgressAdvance(); ++ ++ if (!pItem->IsPicture() || pItem->IsZIP() || pItem->IsRAR() || pItem->IsCBR() || pItem->IsCBZ() || pItem->IsInternetStream() || pItem->IsVideo()) ++ return false; ++ ++ if (pItem->HasPictureInfoTag()) ++ return false; ++ + if (m_loadTags) + { // Nothing found, load tag from file + pItem->GetPictureInfoTag()->Load(pItem->GetPath()); +diff --git a/xbmc/pictures/PictureInfoLoader.h b/xbmc/pictures/PictureInfoLoader.h +index 7308413..d390318 100644 +--- a/xbmc/pictures/PictureInfoLoader.h ++++ b/xbmc/pictures/PictureInfoLoader.h +@@ -30,6 +30,8 @@ class CPictureInfoLoader : public CBackgroundInfoLoader + + void UseCacheOnHD(const CStdString& strFileName); + virtual bool LoadItem(CFileItem* pItem); ++ virtual bool LoadItemCached(CFileItem* pItem); ++ virtual bool LoadItemLookup(CFileItem* pItem); + + protected: + virtual void OnLoaderStart(); +diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp +index 8e690d2..3943a11 100644 +--- a/xbmc/pictures/PictureThumbLoader.cpp ++++ b/xbmc/pictures/PictureThumbLoader.cpp +@@ -47,8 +47,17 @@ + + bool CPictureThumbLoader::LoadItem(CFileItem* pItem) + { +- if (pItem->m_bIsShareOrDrive) return true; +- if (pItem->IsParentFolder()) return true; ++ bool result = LoadItemCached(pItem); ++ result |= LoadItemLookup(pItem); ++ ++ return result; ++} ++ ++bool CPictureThumbLoader::LoadItemCached(CFileItem* pItem) ++{ ++ if (pItem->m_bIsShareOrDrive ++ || pItem->IsParentFolder()) ++ return false; + + if (pItem->HasArt("thumb") && m_regenerateThumbs) + { +@@ -95,6 +104,11 @@ bool CPictureThumbLoader::LoadItem(CFileItem* pItem) + return true; + } + ++bool CPictureThumbLoader::LoadItemLookup(CFileItem* pItem) ++{ ++ return false; ++} ++ + void CPictureThumbLoader::OnJobComplete(unsigned int jobID, bool success, CJob* job) + { + if (success) +diff --git a/xbmc/pictures/PictureThumbLoader.h b/xbmc/pictures/PictureThumbLoader.h +index 5191834..e7ad872 100644 +--- a/xbmc/pictures/PictureThumbLoader.h ++++ b/xbmc/pictures/PictureThumbLoader.h +@@ -29,6 +29,8 @@ class CPictureThumbLoader : public CThumbLoader, public CJobQueue + CPictureThumbLoader(); + virtual ~CPictureThumbLoader(); + virtual bool LoadItem(CFileItem* pItem); ++ virtual bool LoadItemCached(CFileItem* pItem); ++ virtual bool LoadItemLookup(CFileItem* pItem); + void SetRegenerateThumbs(bool regenerate) { m_regenerateThumbs = regenerate; }; + static void ProcessFoldersAndArchives(CFileItem *pItem); + +diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp +index 0801d6b..4f3fea2 100644 +--- a/xbmc/video/VideoThumbLoader.cpp ++++ b/xbmc/video/VideoThumbLoader.cpp +@@ -199,6 +199,14 @@ static void SetupRarOptions(CFileItem& item, const CStdString& path) + */ + bool CVideoThumbLoader::LoadItem(CFileItem* pItem) + { ++ bool result = LoadItemCached(pItem); ++ result |= LoadItemLookup(pItem); ++ ++ return result; ++} ++ ++bool CVideoThumbLoader::LoadItemCached(CFileItem* pItem) ++{ + if (pItem->m_bIsShareOrDrive + || pItem->IsParentFolder()) + return false; +@@ -242,20 +250,51 @@ bool CVideoThumbLoader::LoadItem(CFileItem* pItem) + { + std::string type = *i; + std::string art = GetCachedImage(*pItem, type); +- if (art.empty()) +- { +- art = GetLocalArt(*pItem, type, type=="fanart"); +- if (!art.empty()) // cache it +- SetCachedImage(*pItem, type, art); +- } + if (!art.empty()) ++ artwork.insert(make_pair(type, art)); ++ } ++ SetArt(*pItem, artwork); ++ } ++ ++ m_database->Close(); ++ ++ return true; ++} ++ ++bool CVideoThumbLoader::LoadItemLookup(CFileItem* pItem) ++{ ++ if (pItem->m_bIsShareOrDrive ++ || pItem->IsParentFolder()) ++ return false; ++ ++ if (pItem->HasVideoInfoTag() && ++ !pItem->GetVideoInfoTag()->m_type.empty() && ++ pItem->GetVideoInfoTag()->m_type != "movie" && ++ pItem->GetVideoInfoTag()->m_type != "tvshow" && ++ pItem->GetVideoInfoTag()->m_type != "episode" && ++ pItem->GetVideoInfoTag()->m_type != "musicvideo") ++ return false; // Nothing to do here ++ ++ m_database->Open(); ++ map artwork = pItem->GetArt(); ++ vector artTypes = GetArtTypes(pItem->HasVideoInfoTag() ? pItem->GetVideoInfoTag()->m_type : ""); ++ if (find(artTypes.begin(), artTypes.end(), "thumb") == artTypes.end()) ++ artTypes.push_back("thumb"); // always look for "thumb" art for files ++ for (vector::const_iterator i = artTypes.begin(); i != artTypes.end(); ++i) ++ { ++ std::string type = *i; ++ if (!pItem->HasArt(type)) ++ { ++ std::string art = GetLocalArt(*pItem, type, type=="fanart"); ++ if (!art.empty()) // cache it + { ++ SetCachedImage(*pItem, type, art); + CTextureCache::Get().BackgroundCacheImage(art); + artwork.insert(make_pair(type, art)); + } + } +- SetArt(*pItem, artwork); + } ++ SetArt(*pItem, artwork); + + // We can only extract flags/thumbs for file-like items + if (!pItem->m_bIsFolder && pItem->IsVideo()) +diff --git a/xbmc/video/VideoThumbLoader.h b/xbmc/video/VideoThumbLoader.h +index 4befd6c..97ac22d 100644 +--- a/xbmc/video/VideoThumbLoader.h ++++ b/xbmc/video/VideoThumbLoader.h +@@ -68,6 +68,8 @@ class CVideoThumbLoader : public CThumbLoader, public CJobQueue + + virtual void Initialize(); + virtual bool LoadItem(CFileItem* pItem); ++ virtual bool LoadItemCached(CFileItem* pItem); ++ virtual bool LoadItemLookup(CFileItem* pItem); + void SetStreamDetailsObserver(IStreamDetailsObserver *pObs) { m_pStreamDetailsObs = pObs; } + + /*! \brief Fill the thumb of a video item +-- +1.8.1.6 + + +From 7ea5521c4477d095cecbfd570de7972ee2b1b3f8 Mon Sep 17 00:00:00 2001 +From: arnova +Date: Thu, 20 Jun 2013 12:41:21 +0200 +Subject: [PATCH 3/6] changed: Renamed m_database to m_video/m_musicDatabase + for clarity + +--- + xbmc/music/MusicThumbLoader.cpp | 26 +++++++++++++------------- + xbmc/music/MusicThumbLoader.h | 2 +- + xbmc/video/VideoThumbLoader.cpp | 33 +++++++++++++++++---------------- + xbmc/video/VideoThumbLoader.h | 2 +- + 4 files changed, 32 insertions(+), 31 deletions(-) + +diff --git a/xbmc/music/MusicThumbLoader.cpp b/xbmc/music/MusicThumbLoader.cpp +index bc1d84a..8272834 100644 +--- a/xbmc/music/MusicThumbLoader.cpp ++++ b/xbmc/music/MusicThumbLoader.cpp +@@ -32,23 +32,23 @@ + + CMusicThumbLoader::CMusicThumbLoader() : CThumbLoader() + { +- m_database = new CMusicDatabase; ++ m_musicDatabase = new CMusicDatabase; + } + + CMusicThumbLoader::~CMusicThumbLoader() + { +- delete m_database; ++ delete m_musicDatabase; + } + + void CMusicThumbLoader::Initialize() + { +- m_database->Open(); ++ m_musicDatabase->Open(); + m_albumArt.clear(); + } + + void CMusicThumbLoader::Deinitialize() + { +- m_database->Close(); ++ m_musicDatabase->Close(); + m_albumArt.clear(); + } + +@@ -96,18 +96,18 @@ bool CMusicThumbLoader::LoadItemCached(CFileItem* pItem) + if (pItem->HasMusicInfoTag() && !pItem->GetMusicInfoTag()->GetArtist().empty()) + { + std::string artist = pItem->GetMusicInfoTag()->GetArtist()[0]; +- m_database->Open(); +- int idArtist = m_database->GetArtistByName(artist); ++ m_musicDatabase->Open(); ++ int idArtist = m_musicDatabase->GetArtistByName(artist); + if (idArtist >= 0) + { +- string fanart = m_database->GetArtForItem(idArtist, "artist", "fanart"); ++ string fanart = m_musicDatabase->GetArtForItem(idArtist, "artist", "fanart"); + if (!fanart.empty()) + { + pItem->SetArt("artist.fanart", fanart); + pItem->SetArtFallback("fanart", "artist.fanart"); + } + } +- m_database->Close(); ++ m_musicDatabase->Close(); + } + } + +@@ -172,16 +172,16 @@ bool CMusicThumbLoader::FillLibraryArt(CFileItem &item) + CMusicInfoTag &tag = *item.GetMusicInfoTag(); + if (tag.GetDatabaseId() > -1 && !tag.GetType().empty()) + { +- m_database->Open(); ++ m_musicDatabase->Open(); + map artwork; +- if (m_database->GetArtForItem(tag.GetDatabaseId(), tag.GetType(), artwork)) ++ if (m_musicDatabase->GetArtForItem(tag.GetDatabaseId(), tag.GetType(), artwork)) + item.SetArt(artwork); + else if (tag.GetType() == "song") + { // no art for the song, try the album + ArtCache::const_iterator i = m_albumArt.find(tag.GetAlbumId()); + if (i == m_albumArt.end()) + { +- m_database->GetArtForItem(tag.GetAlbumId(), "album", artwork); ++ m_musicDatabase->GetArtForItem(tag.GetAlbumId(), "album", artwork); + i = m_albumArt.insert(make_pair(tag.GetAlbumId(), artwork)).first; + } + if (i != m_albumArt.end()) +@@ -193,14 +193,14 @@ bool CMusicThumbLoader::FillLibraryArt(CFileItem &item) + } + if (tag.GetType() == "song" || tag.GetType() == "album") + { // fanart from the artist +- string fanart = m_database->GetArtistArtForItem(tag.GetDatabaseId(), tag.GetType(), "fanart"); ++ string fanart = m_musicDatabase->GetArtistArtForItem(tag.GetDatabaseId(), tag.GetType(), "fanart"); + if (!fanart.empty()) + { + item.SetArt("artist.fanart", fanart); + item.SetArtFallback("fanart", "artist.fanart"); + } + } +- m_database->Close(); ++ m_musicDatabase->Close(); + } + return !item.GetArt().empty(); + } +diff --git a/xbmc/music/MusicThumbLoader.h b/xbmc/music/MusicThumbLoader.h +index f8bbd29..7bdad72 100644 +--- a/xbmc/music/MusicThumbLoader.h ++++ b/xbmc/music/MusicThumbLoader.h +@@ -63,7 +63,7 @@ class CMusicThumbLoader : public CThumbLoader + virtual void OnLoaderStart(); + virtual void OnLoaderFinish(); + +- CMusicDatabase *m_database; ++ CMusicDatabase *m_musicDatabase; + typedef std::map > ArtCache; + ArtCache m_albumArt; + }; +diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp +index 4f3fea2..e92fc3f 100644 +--- a/xbmc/video/VideoThumbLoader.cpp ++++ b/xbmc/video/VideoThumbLoader.cpp +@@ -118,18 +118,18 @@ bool CThumbExtractor::DoWork() + CVideoThumbLoader::CVideoThumbLoader() : + CThumbLoader(), CJobQueue(true), m_pStreamDetailsObs(NULL) + { +- m_database = new CVideoDatabase(); ++ m_videoDatabase = new CVideoDatabase(); + } + + CVideoThumbLoader::~CVideoThumbLoader() + { + StopThread(); +- delete m_database; ++ delete m_videoDatabase; + } + + void CVideoThumbLoader::Initialize() + { +- m_database->Open(); ++ m_videoDatabase->Open(); + m_showArt.clear(); + } + +@@ -140,7 +140,7 @@ void CVideoThumbLoader::OnLoaderStart() + + void CVideoThumbLoader::OnLoaderFinish() + { +- m_database->Close(); ++ m_videoDatabase->Close(); + m_showArt.clear(); + } + +@@ -211,14 +211,14 @@ bool CVideoThumbLoader::LoadItemCached(CFileItem* pItem) + || pItem->IsParentFolder()) + return false; + +- m_database->Open(); ++ m_videoDatabase->Open(); + + if (!pItem->HasVideoInfoTag() || !pItem->GetVideoInfoTag()->HasStreamDetails()) // no stream details + { + if ((pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_iFileId >= 0) // file (or maybe folder) is in the database + || (!pItem->m_bIsFolder && pItem->IsVideo())) // Some other video file for which we haven't yet got any database details + { +- if (m_database->GetStreamDetails(*pItem)) ++ if (m_videoDatabase->GetStreamDetails(*pItem)) + pItem->SetInvalid(); + } + } +@@ -234,7 +234,7 @@ bool CVideoThumbLoader::LoadItemCached(CFileItem* pItem) + pItem->GetVideoInfoTag()->m_type != "episode" && + pItem->GetVideoInfoTag()->m_type != "musicvideo") + { +- m_database->Close(); ++ m_videoDatabase->Close(); + return true; // nothing else to be done + } + } +@@ -256,7 +256,7 @@ bool CVideoThumbLoader::LoadItemCached(CFileItem* pItem) + SetArt(*pItem, artwork); + } + +- m_database->Close(); ++ m_videoDatabase->Close(); + + return true; + } +@@ -275,7 +275,8 @@ bool CVideoThumbLoader::LoadItemLookup(CFileItem* pItem) + pItem->GetVideoInfoTag()->m_type != "musicvideo") + return false; // Nothing to do here + +- m_database->Open(); ++ m_videoDatabase->Open(); ++ + map artwork = pItem->GetArt(); + vector artTypes = GetArtTypes(pItem->HasVideoInfoTag() ? pItem->GetVideoInfoTag()->m_type : ""); + if (find(artTypes.begin(), artTypes.end(), "thumb") == artTypes.end()) +@@ -320,7 +321,7 @@ bool CVideoThumbLoader::LoadItemLookup(CFileItem* pItem) + // Item has cached autogen image but no art entry. Save it to db. + CVideoInfoTag* info = pItem->GetVideoInfoTag(); + if (info->m_iDbId > 0 && !info->m_type.empty()) +- m_database->SetArtForItem(info->m_iDbId, info->m_type, "thumb", thumbURL); ++ m_videoDatabase->SetArtForItem(info->m_iDbId, info->m_type, "thumb", thumbURL); + } + } + else if (CSettings::Get().GetBool("myvideos.extractthumb") && +@@ -334,7 +335,7 @@ bool CVideoThumbLoader::LoadItemLookup(CFileItem* pItem) + CThumbExtractor* extract = new CThumbExtractor(item, path, true, thumbURL); + AddJob(extract); + +- m_database->Close(); ++ m_videoDatabase->Close(); + return true; + } + } +@@ -354,7 +355,7 @@ bool CVideoThumbLoader::LoadItemLookup(CFileItem* pItem) + } + } + +- m_database->Close(); ++ m_videoDatabase->Close(); + return true; + } + +@@ -376,8 +377,8 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) + if (tag.m_iDbId > -1 && !tag.m_type.IsEmpty()) + { + map artwork; +- m_database->Open(); +- if (m_database->GetArtForItem(tag.m_iDbId, tag.m_type, artwork)) ++ m_videoDatabase->Open(); ++ if (m_videoDatabase->GetArtForItem(tag.m_iDbId, tag.m_type, artwork)) + SetArt(item, artwork); + else if (tag.m_type == "artist") + { // we retrieve music video art from the music database (no backward compat) +@@ -402,7 +403,7 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) + if (i == m_showArt.end()) + { + map showArt; +- m_database->GetArtForItem(tag.m_iIdShow, "tvshow", showArt); ++ m_videoDatabase->GetArtForItem(tag.m_iIdShow, "tvshow", showArt); + i = m_showArt.insert(make_pair(tag.m_iIdShow, showArt)).first; + } + if (i != m_showArt.end()) +@@ -412,7 +413,7 @@ bool CVideoThumbLoader::FillLibraryArt(CFileItem &item) + item.SetArtFallback("tvshow.thumb", "tvshow.poster"); + } + } +- m_database->Close(); ++ m_videoDatabase->Close(); + } + return !item.GetArt().empty(); + } +diff --git a/xbmc/video/VideoThumbLoader.h b/xbmc/video/VideoThumbLoader.h +index 97ac22d..4a06073 100644 +--- a/xbmc/video/VideoThumbLoader.h ++++ b/xbmc/video/VideoThumbLoader.h +@@ -128,7 +128,7 @@ class CVideoThumbLoader : public CThumbLoader, public CJobQueue + virtual void OnLoaderFinish(); + + IStreamDetailsObserver *m_pStreamDetailsObs; +- CVideoDatabase *m_database; ++ CVideoDatabase *m_videoDatabase; + typedef std::map > ArtCache; + ArtCache m_showArt; + }; +-- +1.8.1.6 + + +From 59c6386ee7af83fe3e8e18c4b28bde42c399bbf2 Mon Sep 17 00:00:00 2001 +From: arnova +Date: Thu, 20 Jun 2013 13:29:22 +0200 +Subject: [PATCH 4/6] changed: Use a member variable for the texture database + +This speeds up thumb loading considerably. This also gets rid of the Initialize/Deinitialize ThumbLoader functions +--- + xbmc/GUIInfoManager.cpp | 8 +++++-- + xbmc/ThumbLoader.cpp | 34 +++++++++++++++++++++------- + xbmc/ThumbLoader.h | 14 ++++++++---- + xbmc/interfaces/json-rpc/FileItemHandler.cpp | 4 ++-- + xbmc/music/MusicInfoLoader.cpp | 4 ++-- + xbmc/music/MusicThumbLoader.cpp | 16 ++++--------- + xbmc/music/MusicThumbLoader.h | 11 ++++----- + xbmc/music/infoscanner/MusicInfoScanner.cpp | 3 ++- + xbmc/music/windows/GUIWindowMusicBase.cpp | 8 +++++-- + xbmc/network/upnp/UPnPServer.cpp | 4 ++-- + xbmc/pictures/GUIWindowPictures.cpp | 4 +++- + xbmc/pictures/PictureInfoLoader.h | 2 +- + xbmc/pictures/PictureThumbLoader.cpp | 23 +++++++++++-------- + xbmc/pictures/PictureThumbLoader.h | 3 +++ + xbmc/utils/RecentlyAddedJob.cpp | 4 ++-- + xbmc/video/VideoInfoScanner.cpp | 3 ++- + xbmc/video/VideoThumbLoader.cpp | 9 +++----- + xbmc/video/VideoThumbLoader.h | 9 ++++---- + 18 files changed, 95 insertions(+), 68 deletions(-) + +diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp +index fba60ae..c9c616d 100644 +--- a/xbmc/GUIInfoManager.cpp ++++ b/xbmc/GUIInfoManager.cpp +@@ -3892,7 +3892,9 @@ void CGUIInfoManager::SetCurrentSong(CFileItem &item) + { + CLog::Log(LOGDEBUG,"Streaming media detected... using %s to find a thumb", g_application.m_strPlayListFile.c_str()); + CFileItem streamingItem(g_application.m_strPlayListFile,false); +- CMusicThumbLoader::FillThumb(streamingItem); ++ ++ CMusicThumbLoader loader; ++ loader.FillThumb(streamingItem); + if (streamingItem.HasArt("thumb")) + m_currentFile->SetArt("thumb", streamingItem.GetArt("thumb")); + } +@@ -3945,7 +3947,9 @@ void CGUIInfoManager::SetCurrentMovie(CFileItem &item) + { + CLog::Log(LOGDEBUG,"Streaming media detected... using %s to find a thumb", g_application.m_strPlayListFile.c_str()); + CFileItem thumbItem(g_application.m_strPlayListFile,false); +- if (CVideoThumbLoader::FillThumb(thumbItem)) ++ ++ CVideoThumbLoader loader; ++ if (loader.FillThumb(thumbItem)) + item.SetArt("thumb", thumbItem.GetArt("thumb")); + } + } +diff --git a/xbmc/ThumbLoader.cpp b/xbmc/ThumbLoader.cpp +index aa4cb82..98ce95c 100644 +--- a/xbmc/ThumbLoader.cpp ++++ b/xbmc/ThumbLoader.cpp +@@ -29,25 +29,42 @@ + CThumbLoader::CThumbLoader() : + CBackgroundInfoLoader() + { ++ m_textureDatabase = new CTextureDatabase(); + } + + CThumbLoader::~CThumbLoader() + { ++ delete m_textureDatabase; ++} ++ ++void CThumbLoader::OnLoaderStart() ++{ ++ m_textureDatabase->Open(); ++} ++ ++void CThumbLoader::OnLoaderFinish() ++{ ++ m_textureDatabase->Close(); + } + + CStdString CThumbLoader::GetCachedImage(const CFileItem &item, const CStdString &type) + { +- CTextureDatabase db; +- if (!item.GetPath().empty() && db.Open()) +- return db.GetTextureForPath(item.GetPath(), type); ++ if (!item.GetPath().empty() && m_textureDatabase->Open()) ++ { ++ CStdString image = m_textureDatabase->GetTextureForPath(item.GetPath(), type); ++ m_textureDatabase->Close(); ++ return image; ++ } + return ""; + } + + void CThumbLoader::SetCachedImage(const CFileItem &item, const CStdString &type, const CStdString &image) + { +- CTextureDatabase db; +- if (!item.GetPath().empty() && db.Open()) +- db.SetTextureForPath(item.GetPath(), type, image); ++ if (!item.GetPath().empty() && m_textureDatabase->Open()) ++ { ++ m_textureDatabase->SetTextureForPath(item.GetPath(), type, image); ++ m_textureDatabase->Close(); ++ } + } + + CProgramThumbLoader::CProgramThumbLoader() +@@ -86,12 +103,13 @@ bool CProgramThumbLoader::FillThumb(CFileItem &item) + + if (thumb.IsEmpty()) + { // see whether we have a cached image for this item +- thumb = GetCachedImage(item, "thumb"); ++ CProgramThumbLoader loader; ++ thumb = loader.GetCachedImage(item, "thumb"); + if (thumb.IsEmpty()) + { + thumb = GetLocalThumb(item); + if (!thumb.IsEmpty()) +- SetCachedImage(item, "thumb", thumb); ++ loader.SetCachedImage(item, "thumb", thumb); + } + } + +diff --git a/xbmc/ThumbLoader.h b/xbmc/ThumbLoader.h +index 2ee06d1..28692c9 100644 +--- a/xbmc/ThumbLoader.h ++++ b/xbmc/ThumbLoader.h +@@ -22,13 +22,16 @@ + #include "BackgroundInfoLoader.h" + #include "utils/StdString.h" + ++class CTextureDatabase; ++ + class CThumbLoader : public CBackgroundInfoLoader + { + public: + CThumbLoader(); + virtual ~CThumbLoader(); + +- virtual void Initialize() { }; ++ virtual void OnLoaderStart(); ++ virtual void OnLoaderFinish(); + + /*! \brief helper function to fill the art for a library item + \param item a CFileItem +@@ -41,14 +44,17 @@ class CThumbLoader : public CBackgroundInfoLoader + \param type the type of image to retrieve + \return the image associated with this item + */ +- static CStdString GetCachedImage(const CFileItem &item, const CStdString &type); ++ virtual CStdString GetCachedImage(const CFileItem &item, const CStdString &type); + + /*! \brief Associate an image with the given item in the texture database + \param item CFileItem to associate the image with + \param type the type of image + \param image the URL of the image + */ +- static void SetCachedImage(const CFileItem &item, const CStdString &type, const CStdString &image); ++ virtual void SetCachedImage(const CFileItem &item, const CStdString &type, const CStdString &image); ++ ++protected: ++ CTextureDatabase *m_textureDatabase; + }; + + class CProgramThumbLoader : public CThumbLoader +@@ -67,7 +73,7 @@ class CProgramThumbLoader : public CThumbLoader + \return true if we fill the thumb, false otherwise + \sa GetLocalThumb + */ +- static bool FillThumb(CFileItem &item); ++ virtual bool FillThumb(CFileItem &item); + + /*! \brief Get a local thumb for a programs item + Shortcuts are checked, then we check for a file or folder thumb +diff --git a/xbmc/interfaces/json-rpc/FileItemHandler.cpp b/xbmc/interfaces/json-rpc/FileItemHandler.cpp +index 28e1e0b..0d7117b 100644 +--- a/xbmc/interfaces/json-rpc/FileItemHandler.cpp ++++ b/xbmc/interfaces/json-rpc/FileItemHandler.cpp +@@ -221,7 +221,7 @@ void CFileItemHandler::HandleFileItemList(const char *ID, bool allowFile, const + thumbLoader = new CMusicThumbLoader(); + + if (thumbLoader != NULL) +- thumbLoader->Initialize(); ++ thumbLoader->OnLoaderStart(); + } + + std::set fields; +@@ -329,7 +329,7 @@ void CFileItemHandler::HandleFileItem(const char *ID, bool allowFile, const char + if (thumbLoader != NULL) + { + deleteThumbloader = true; +- thumbLoader->Initialize(); ++ thumbLoader->OnLoaderStart(); + } + } + +diff --git a/xbmc/music/MusicInfoLoader.cpp b/xbmc/music/MusicInfoLoader.cpp +index 5924f47..d6e1afa 100644 +--- a/xbmc/music/MusicInfoLoader.cpp ++++ b/xbmc/music/MusicInfoLoader.cpp +@@ -77,7 +77,7 @@ void CMusicInfoLoader::OnLoaderStart() + m_musicDatabase.Open(); + + if (m_thumbLoader) +- m_thumbLoader->Initialize(); ++ m_thumbLoader->OnLoaderStart(); + } + + bool CMusicInfoLoader::LoadAdditionalTagInfo(CFileItem* pItem) +@@ -227,7 +227,7 @@ void CMusicInfoLoader::OnLoaderFinish() + m_musicDatabase.Close(); + + if (m_thumbLoader) +- m_thumbLoader->Deinitialize(); ++ m_thumbLoader->OnLoaderFinish(); + } + + void CMusicInfoLoader::UseCacheOnHD(const CStdString& strFileName) +diff --git a/xbmc/music/MusicThumbLoader.cpp b/xbmc/music/MusicThumbLoader.cpp +index 8272834..88cd10a 100644 +--- a/xbmc/music/MusicThumbLoader.cpp ++++ b/xbmc/music/MusicThumbLoader.cpp +@@ -40,26 +40,18 @@ + delete m_musicDatabase; + } + +-void CMusicThumbLoader::Initialize() ++void CMusicThumbLoader::OnLoaderStart() + { + m_musicDatabase->Open(); + m_albumArt.clear(); ++ CThumbLoader::OnLoaderStart(); + } + +-void CMusicThumbLoader::Deinitialize() ++void CMusicThumbLoader::OnLoaderFinish() + { + m_musicDatabase->Close(); + m_albumArt.clear(); +-} +- +-void CMusicThumbLoader::OnLoaderStart() +-{ +- Initialize(); +-} +- +-void CMusicThumbLoader::OnLoaderFinish() +-{ +- Deinitialize(); ++ CThumbLoader::OnLoaderFinish(); + } + + bool CMusicThumbLoader::LoadItem(CFileItem* pItem) +diff --git a/xbmc/music/MusicThumbLoader.h b/xbmc/music/MusicThumbLoader.h +index 7bdad72..69205a3 100644 +--- a/xbmc/music/MusicThumbLoader.h ++++ b/xbmc/music/MusicThumbLoader.h +@@ -35,9 +35,9 @@ class CMusicThumbLoader : public CThumbLoader + public: + CMusicThumbLoader(); + virtual ~CMusicThumbLoader(); +- +- virtual void Initialize(); +- virtual void Deinitialize(); ++ ++ virtual void OnLoaderStart(); ++ virtual void OnLoaderFinish(); + + virtual bool LoadItem(CFileItem* pItem); + virtual bool LoadItemCached(CFileItem* pItem); +@@ -55,14 +55,11 @@ class CMusicThumbLoader : public CThumbLoader + \param item the CFileItem object to fill + \return true if we fill the thumb, false otherwise + */ +- static bool FillThumb(CFileItem &item, bool folderThumbs = true); ++ virtual bool FillThumb(CFileItem &item, bool folderThumbs = true); + + static bool GetEmbeddedThumb(const std::string &path, MUSIC_INFO::EmbeddedArt &art); + + protected: +- virtual void OnLoaderStart(); +- virtual void OnLoaderFinish(); +- + CMusicDatabase *m_musicDatabase; + typedef std::map > ArtCache; + ArtCache m_albumArt; +diff --git a/xbmc/music/infoscanner/MusicInfoScanner.cpp b/xbmc/music/infoscanner/MusicInfoScanner.cpp +index fb9b16a..9583e48 100644 +--- a/xbmc/music/infoscanner/MusicInfoScanner.cpp ++++ b/xbmc/music/infoscanner/MusicInfoScanner.cpp +@@ -1016,7 +1016,8 @@ void CMusicInfoScanner::FindArtForAlbums(VECALBUMS &albums, const CStdString &pa + { + // assign to folder thumb as well + CFileItem albumItem(path, true); +- CMusicThumbLoader::SetCachedImage(albumItem, "thumb", albumArt); ++ CMusicThumbLoader loader; ++ loader.SetCachedImage(albumItem, "thumb", albumArt); + } + } + +diff --git a/xbmc/music/windows/GUIWindowMusicBase.cpp b/xbmc/music/windows/GUIWindowMusicBase.cpp +index cf8ae67..d16b31b 100644 +--- a/xbmc/music/windows/GUIWindowMusicBase.cpp ++++ b/xbmc/music/windows/GUIWindowMusicBase.cpp +@@ -1038,7 +1038,8 @@ void CGUIWindowMusicBase::UpdateThumb(const CAlbum &album, const CStdString &pat + CMusicInfoScanner::FileItemsToAlbums(items, albums); + if (albums.size() == 1) + { // set as folder thumb as well +- CThumbLoader::SetCachedImage(items, "thumb", albumPath); ++ CMusicThumbLoader loader; ++ loader.SetCachedImage(items, "thumb", albumPath); + } + } + +@@ -1105,7 +1106,10 @@ bool CGUIWindowMusicBase::GetDirectory(const CStdString &strDirectory, CFileItem + items.SetArt("thumb", ""); + bool bResult = CGUIMediaWindow::GetDirectory(strDirectory, items); + if (bResult) +- CMusicThumbLoader::FillThumb(items); ++ { ++ CMusicThumbLoader loader; ++ loader.FillThumb(items); ++ } + + // add in the "New Playlist" item if we're in the playlists folder + if ((items.GetPath() == "special://musicplaylists/") && !items.Contains("newplaylist://")) +diff --git a/xbmc/network/upnp/UPnPServer.cpp b/xbmc/network/upnp/UPnPServer.cpp +index 2549a70..7158cb7 100644 +--- a/xbmc/network/upnp/UPnPServer.cpp ++++ b/xbmc/network/upnp/UPnPServer.cpp +@@ -545,7 +545,7 @@ static NPT_String TranslateWMPObjectId(NPT_String id) + thumb_loader = NPT_Reference(new CMusicThumbLoader()); + } + if (!thumb_loader.IsNull()) { +- thumb_loader->Initialize(); ++ thumb_loader->OnLoaderStart(); + } + object = Build(item, true, context, thumb_loader, parent.empty()?NULL:parent.c_str()); + } +@@ -710,7 +710,7 @@ static NPT_String TranslateWMPObjectId(NPT_String id) + thumb_loader = NPT_Reference(new CMusicThumbLoader()); + } + if (!thumb_loader.IsNull()) { +- thumb_loader->Initialize(); ++ thumb_loader->OnLoaderStart(); + } + + // this isn't pretty but needed to properly hide the addons node from clients +diff --git a/xbmc/pictures/GUIWindowPictures.cpp b/xbmc/pictures/GUIWindowPictures.cpp +index 0dbe98c..8668b1d 100644 +--- a/xbmc/pictures/GUIWindowPictures.cpp ++++ b/xbmc/pictures/GUIWindowPictures.cpp +@@ -271,7 +271,9 @@ bool CGUIWindowPictures::Update(const CStdString &strDirectory, bool updateFilte + m_vecItems->SetArt("thumb", ""); + if (CSettings::Get().GetBool("pictures.generatethumbs")) + m_thumbLoader.Load(*m_vecItems); +- m_vecItems->SetArt("thumb", CPictureThumbLoader::GetCachedImage(*m_vecItems, "thumb")); ++ ++ CStdString thumb = m_thumbLoader.GetCachedImage(*m_vecItems, "thumb"); ++ m_vecItems->SetArt("thumb", thumb); + + return true; + } +diff --git a/xbmc/pictures/PictureInfoLoader.h b/xbmc/pictures/PictureInfoLoader.h +index d390318..8ad7678 100644 +--- a/xbmc/pictures/PictureInfoLoader.h ++++ b/xbmc/pictures/PictureInfoLoader.h +@@ -36,7 +36,7 @@ class CPictureInfoLoader : public CBackgroundInfoLoader + protected: + virtual void OnLoaderStart(); + virtual void OnLoaderFinish(); +-protected: ++ + CFileItemList* m_mapFileItems; + unsigned int m_tagReads; + bool m_loadTags; +diff --git a/xbmc/pictures/PictureThumbLoader.cpp b/xbmc/pictures/PictureThumbLoader.cpp +index 3943a11..1ad3a79 100644 +--- a/xbmc/pictures/PictureThumbLoader.cpp ++++ b/xbmc/pictures/PictureThumbLoader.cpp +@@ -45,6 +45,12 @@ + StopThread(); + } + ++void CPictureThumbLoader::OnLoaderFinish() ++{ ++ m_regenerateThumbs = false; ++ CThumbLoader::OnLoaderFinish(); ++} ++ + bool CPictureThumbLoader::LoadItem(CFileItem* pItem) + { + bool result = LoadItemCached(pItem); +@@ -62,9 +68,11 @@ bool CPictureThumbLoader::LoadItemCached(CFileItem* pItem) + if (pItem->HasArt("thumb") && m_regenerateThumbs) + { + CTextureCache::Get().ClearCachedImage(pItem->GetArt("thumb")); +- CTextureDatabase db; +- if (db.Open()) +- db.ClearTextureForPath(pItem->GetPath(), "thumb"); ++ if (m_textureDatabase->Open()) ++ { ++ m_textureDatabase->ClearTextureForPath(pItem->GetPath(), "thumb"); ++ m_textureDatabase->Close(); ++ } + pItem->SetArt("thumb", ""); + } + +@@ -75,7 +83,8 @@ bool CPictureThumbLoader::LoadItemCached(CFileItem* pItem) + } + else if (pItem->IsVideo() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList()) + { // video +- if (!CVideoThumbLoader::FillThumb(*pItem)) ++ CVideoThumbLoader loader; ++ if (!loader.FillThumb(*pItem)) + { + CStdString thumbURL = CVideoThumbLoader::GetEmbeddedThumbURL(*pItem); + if (CTextureCache::Get().HasCachedImage(thumbURL)) +@@ -122,12 +131,6 @@ void CPictureThumbLoader::OnJobComplete(unsigned int jobID, bool success, CJob* + CJobQueue::OnJobComplete(jobID, success, job); + } + +- +-void CPictureThumbLoader::OnLoaderFinish() +-{ +- m_regenerateThumbs = false; +-} +- + void CPictureThumbLoader::ProcessFoldersAndArchives(CFileItem *pItem) + { + if (pItem->HasArt("thumb")) +diff --git a/xbmc/pictures/PictureThumbLoader.h b/xbmc/pictures/PictureThumbLoader.h +index e7ad872..76d2aee 100644 +--- a/xbmc/pictures/PictureThumbLoader.h ++++ b/xbmc/pictures/PictureThumbLoader.h +@@ -28,6 +28,7 @@ class CPictureThumbLoader : public CThumbLoader, public CJobQueue + public: + CPictureThumbLoader(); + virtual ~CPictureThumbLoader(); ++ + virtual bool LoadItem(CFileItem* pItem); + virtual bool LoadItemCached(CFileItem* pItem); + virtual bool LoadItemLookup(CFileItem* pItem); +@@ -42,8 +43,10 @@ class CPictureThumbLoader : public CThumbLoader, public CJobQueue + \sa CImageLoader, IJobCallback + */ + virtual void OnJobComplete(unsigned int jobID, bool success, CJob *job); ++ + protected: + virtual void OnLoaderFinish(); ++ + private: + bool m_regenerateThumbs; + }; +diff --git a/xbmc/utils/RecentlyAddedJob.cpp b/xbmc/utils/RecentlyAddedJob.cpp +index 9bae92b..4d724a7 100644 +--- a/xbmc/utils/RecentlyAddedJob.cpp ++++ b/xbmc/utils/RecentlyAddedJob.cpp +@@ -54,7 +54,7 @@ bool CRecentlyAddedJob::UpdateVideo() + CFileItemList items; + CVideoDatabase videodatabase; + CVideoThumbLoader loader; +- loader.Initialize(); ++ loader.OnLoaderStart(); + + videodatabase.Open(); + +@@ -213,7 +213,7 @@ bool CRecentlyAddedJob::UpdateMusic() + CFileItemList musicItems; + CMusicDatabase musicdatabase; + CMusicThumbLoader loader; +- loader.Initialize(); ++ loader.OnLoaderStart(); + + musicdatabase.Open(); + +diff --git a/xbmc/video/VideoInfoScanner.cpp b/xbmc/video/VideoInfoScanner.cpp +index 3c56881..26e9219 100644 +--- a/xbmc/video/VideoInfoScanner.cpp ++++ b/xbmc/video/VideoInfoScanner.cpp +@@ -1632,7 +1632,8 @@ + if (!imdbThumb.IsEmpty()) + { + CFileItem folderItem(folder, true); +- CThumbLoader::SetCachedImage(folderItem, "thumb", imdbThumb); ++ CThumbLoader loader; ++ loader.SetCachedImage(folderItem, "thumb", imdbThumb); + } + } + +diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp +index e92fc3f..714a67a 100644 +--- a/xbmc/video/VideoThumbLoader.cpp ++++ b/xbmc/video/VideoThumbLoader.cpp +@@ -127,21 +127,18 @@ bool CThumbExtractor::DoWork() + delete m_videoDatabase; + } + +-void CVideoThumbLoader::Initialize() ++void CVideoThumbLoader::OnLoaderStart() + { + m_videoDatabase->Open(); + m_showArt.clear(); +-} +- +-void CVideoThumbLoader::OnLoaderStart() +-{ +- Initialize(); ++ CThumbLoader::OnLoaderStart(); + } + + void CVideoThumbLoader::OnLoaderFinish() + { + m_videoDatabase->Close(); + m_showArt.clear(); ++ CThumbLoader::OnLoaderFinish(); + } + + static void SetupRarOptions(CFileItem& item, const CStdString& path) +diff --git a/xbmc/video/VideoThumbLoader.h b/xbmc/video/VideoThumbLoader.h +index 4a06073..6567a98 100644 +--- a/xbmc/video/VideoThumbLoader.h ++++ b/xbmc/video/VideoThumbLoader.h +@@ -66,7 +66,9 @@ class CVideoThumbLoader : public CThumbLoader, public CJobQueue + CVideoThumbLoader(); + virtual ~CVideoThumbLoader(); + +- virtual void Initialize(); ++ virtual void OnLoaderStart(); ++ virtual void OnLoaderFinish(); ++ + virtual bool LoadItem(CFileItem* pItem); + virtual bool LoadItemCached(CFileItem* pItem); + virtual bool LoadItemLookup(CFileItem* pItem); +@@ -78,7 +80,7 @@ class CVideoThumbLoader : public CThumbLoader, public CJobQueue + \param item the CFileItem object to fill + \return true if we fill the thumb, false otherwise + */ +- static bool FillThumb(CFileItem &item); ++ virtual bool FillThumb(CFileItem &item); + + /*! \brief Find a particular art type for a given item, optionally checking at the folder level + \param item the CFileItem to search. +@@ -124,9 +126,6 @@ class CVideoThumbLoader : public CThumbLoader, public CJobQueue + static void SetArt(CFileItem &item, const std::map &artwork); + + protected: +- virtual void OnLoaderStart(); +- virtual void OnLoaderFinish(); +- + IStreamDetailsObserver *m_pStreamDetailsObs; + CVideoDatabase *m_videoDatabase; + typedef std::map > ArtCache; +-- +1.8.1.6 + + +From 428b580064c5b7a14444d66bb18bdfe94b4046ab Mon Sep 17 00:00:00 2001 +From: arnova +Date: Tue, 2 Jul 2013 22:49:55 +0200 +Subject: [PATCH 5/6] fixed: Music thumb loading for files view was slow + +This was caused by the fact that we never checked for cached images for music items +--- + xbmc/music/MusicThumbLoader.cpp | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/xbmc/music/MusicThumbLoader.cpp b/xbmc/music/MusicThumbLoader.cpp +index 88cd10a..1330ff9 100644 +--- a/xbmc/music/MusicThumbLoader.cpp ++++ b/xbmc/music/MusicThumbLoader.cpp +@@ -83,9 +83,21 @@ bool CMusicThumbLoader::LoadItemCached(CFileItem* pItem) + return true; + } + ++ if (!pItem->HasArt("thumb")) ++ { ++ std::string art = GetCachedImage(*pItem, "thumb"); ++ if (!art.empty()) ++ pItem->SetArt("thumb", art); ++ } ++ + if (!pItem->HasArt("fanart")) + { +- if (pItem->HasMusicInfoTag() && !pItem->GetMusicInfoTag()->GetArtist().empty()) ++ std::string art = GetCachedImage(*pItem, "fanart"); ++ if (!art.empty()) ++ { ++ pItem->SetArt("fanart", art); ++ } ++ else if (pItem->HasMusicInfoTag() && !pItem->GetMusicInfoTag()->GetArtist().empty()) + { + std::string artist = pItem->GetMusicInfoTag()->GetArtist()[0]; + m_musicDatabase->Open(); +-- +1.8.1.6 + + +From 487cd9f6b568f3af71b73ce03afb405dbf8fb511 Mon Sep 17 00:00:00 2001 +From: arnova +Date: Wed, 3 Jul 2013 10:25:34 +0200 +Subject: [PATCH 6/6] fixed: Thumb/flag extractions were never stored when used + outside the bg infoloader + +Also factored out some (obsolote?) code as a bonus +--- + xbmc/utils/StreamDetails.h | 7 ----- + xbmc/video/VideoThumbLoader.cpp | 45 ++++++++++++++++++++----------- + xbmc/video/VideoThumbLoader.h | 3 --- + xbmc/video/windows/GUIWindowVideoBase.cpp | 15 ----------- + xbmc/video/windows/GUIWindowVideoBase.h | 3 +-- + 5 files changed, 30 insertions(+), 43 deletions(-) + +diff --git a/xbmc/utils/StreamDetails.h b/xbmc/utils/StreamDetails.h +index 5d5e205..b531c00 100644 +--- a/xbmc/utils/StreamDetails.h ++++ b/xbmc/utils/StreamDetails.h +@@ -134,10 +134,3 @@ class CStreamDetails : public IArchivable, public ISerializable + CStreamDetailAudio *m_pBestAudio; + CStreamDetailSubtitle *m_pBestSubtitle; + }; +- +-class IStreamDetailsObserver +-{ +-public: +- virtual ~IStreamDetailsObserver() {} +- virtual void OnStreamDetails(const CStreamDetails &details, const CStdString &strFileName, long lFileId) = 0; +-}; +diff --git a/xbmc/video/VideoThumbLoader.cpp b/xbmc/video/VideoThumbLoader.cpp +index 714a67a..8b30ee7 100644 +--- a/xbmc/video/VideoThumbLoader.cpp ++++ b/xbmc/video/VideoThumbLoader.cpp +@@ -103,6 +103,17 @@ bool CThumbExtractor::DoWork() + m_item.SetProperty("HasAutoThumb", true); + m_item.SetProperty("AutoThumbImage", m_target); + m_item.SetArt("thumb", m_target); ++ ++ CVideoInfoTag* info = m_item.GetVideoInfoTag(); ++ if (info->m_iDbId > 0 && !info->m_type.empty()) ++ { ++ CVideoDatabase db; ++ if (db.Open()) ++ { ++ db.SetArtForItem(info->m_iDbId, info->m_type, "thumb", m_item.GetArt("thumb")); ++ db.Close(); ++ } ++ } + } + } + else if (!m_item.HasVideoInfoTag() || !m_item.GetVideoInfoTag()->HasStreamDetails()) +@@ -112,11 +123,27 @@ bool CThumbExtractor::DoWork() + result = CDVDFileInfo::GetFileStreamDetails(&m_item); + } + +- return result; ++ if (result) ++ { ++ CVideoInfoTag* info = m_item.GetVideoInfoTag(); ++ CVideoDatabase db; ++ if (db.Open()) ++ { ++ if (info->m_iFileId < 0) ++ db.SetStreamDetailsForFile(info->m_streamDetails, !info->m_strFileNameAndPath.IsEmpty() ? info->m_strFileNameAndPath : m_item.GetPath()); ++ else ++ db.SetStreamDetailsForFileId(info->m_streamDetails, info->m_iFileId); ++ ++ db.Close(); ++ } ++ return true; ++ } ++ ++ return false; + } + + CVideoThumbLoader::CVideoThumbLoader() : +- CThumbLoader(), CJobQueue(true), m_pStreamDetailsObs(NULL) ++ CThumbLoader(), CJobQueue(true) + { + m_videoDatabase = new CVideoDatabase(); + } +@@ -481,21 +508,7 @@ void CVideoThumbLoader::OnJobComplete(unsigned int jobID, bool success, CJob* jo + { + CThumbExtractor* loader = (CThumbExtractor*)job; + loader->m_item.SetPath(loader->m_listpath); +- CVideoInfoTag* info = loader->m_item.GetVideoInfoTag(); +- +- if (loader->m_thumb && info->m_iDbId > 0 && !info->m_type.empty()) +- { +- // This runs in a different thread than the CVideoThumbLoader object. +- CVideoDatabase db; +- if (db.Open()) +- { +- db.SetArtForItem(info->m_iDbId, info->m_type, "thumb", loader->m_item.GetArt("thumb")); +- db.Close(); +- } +- } + +- if (m_pStreamDetailsObs) +- m_pStreamDetailsObs->OnStreamDetails(info->m_streamDetails, !info->m_strFileNameAndPath.IsEmpty() ? info->m_strFileNameAndPath : loader->m_item.GetPath(), info->m_iFileId); + if (m_pObserver) + m_pObserver->OnItemLoaded(&loader->m_item); + CFileItemPtr pItem(new CFileItem(loader->m_item)); +diff --git a/xbmc/video/VideoThumbLoader.h b/xbmc/video/VideoThumbLoader.h +index 6567a98..906c82c 100644 +--- a/xbmc/video/VideoThumbLoader.h ++++ b/xbmc/video/VideoThumbLoader.h +@@ -25,7 +25,6 @@ + #include "FileItem.h" + + class CStreamDetails; +-class IStreamDetailsObserver; + class CVideoDatabase; + + /*! +@@ -72,7 +71,6 @@ class CVideoThumbLoader : public CThumbLoader, public CJobQueue + virtual bool LoadItem(CFileItem* pItem); + virtual bool LoadItemCached(CFileItem* pItem); + virtual bool LoadItemLookup(CFileItem* pItem); +- void SetStreamDetailsObserver(IStreamDetailsObserver *pObs) { m_pStreamDetailsObs = pObs; } + + /*! \brief Fill the thumb of a video item + First uses a cached thumb from a previous run, then checks for a local thumb +@@ -126,7 +124,6 @@ class CVideoThumbLoader : public CThumbLoader, public CJobQueue + static void SetArt(CFileItem &item, const std::map &artwork); + + protected: +- IStreamDetailsObserver *m_pStreamDetailsObs; + CVideoDatabase *m_videoDatabase; + typedef std::map > ArtCache; + ArtCache m_showArt; +diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp +index b881699..119e1d4 100644 +--- a/xbmc/video/windows/GUIWindowVideoBase.cpp ++++ b/xbmc/video/windows/GUIWindowVideoBase.cpp +@@ -102,7 +102,6 @@ + : CGUIMediaWindow(id, xmlFile) + { + m_thumbLoader.SetObserver(this); +- m_thumbLoader.SetStreamDetailsObserver(this); + m_stackingAvailable = true; + } + +@@ -1191,20 +1190,6 @@ bool CGUIWindowVideoBase::OnResumeItem(int iItem) + return OnFileAction(iItem, SELECT_ACTION_PLAY); + } + +-void CGUIWindowVideoBase::OnStreamDetails(const CStreamDetails &details, const CStdString &strFileName, long lFileId) +-{ +- CVideoDatabase db; +- if (db.Open()) +- { +- if (lFileId < 0) +- db.SetStreamDetailsForFile(details, strFileName); +- else +- db.SetStreamDetailsForFileId(details, lFileId); +- +- db.Close(); +- } +-} +- + void CGUIWindowVideoBase::GetContextButtons(int itemNumber, CContextButtons &buttons) + { + CFileItemPtr item; +diff --git a/xbmc/video/windows/GUIWindowVideoBase.h b/xbmc/video/windows/GUIWindowVideoBase.h +index c77a2ac..d994ac7 100644 +--- a/xbmc/video/windows/GUIWindowVideoBase.h ++++ b/xbmc/video/windows/GUIWindowVideoBase.h +@@ -36,7 +36,7 @@ enum VideoSelectAction + SELECT_ACTION_PLAYPART + }; + +-class CGUIWindowVideoBase : public CGUIMediaWindow, public IBackgroundLoaderObserver, public IStreamDetailsObserver ++class CGUIWindowVideoBase : public CGUIMediaWindow, public IBackgroundLoaderObserver + { + public: + CGUIWindowVideoBase(int id, const CStdString &xmlFile); +@@ -50,7 +50,6 @@ class CGUIWindowVideoBase : public CGUIMediaWindow, public IBackgroundLoaderObse + + void AddToDatabase(int iItem); + virtual void OnInfo(CFileItem* pItem, const ADDON::ScraperPtr& scraper); +- virtual void OnStreamDetails(const CStreamDetails &details, const CStdString &strFileName, long lFileId); + static void MarkWatched(const CFileItemPtr &pItem, bool bMark); + static void UpdateVideoTitle(const CFileItem* pItem); + +-- +1.8.1.6 + From cd12caa968520c7f83f75ef17c8b9da7aa4cf620 Mon Sep 17 00:00:00 2001 From: Christian Hewitt Date: Sat, 6 Jul 2013 07:59:39 +0400 Subject: [PATCH 39/61] nvidia-legacy: fix build on 3.10 kernel fixed build errors on 3.10 kernel, thanks to vpeter --- ...-video-nvidia-legacy-001-kernel-3.10.patch | 605 ++++++++++++++++++ ...-video-nvidia-legacy-002-kernel-3.10.patch | 29 + 2 files changed, 634 insertions(+) create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches.upstream/xf86-video-nvidia-legacy-001-kernel-3.10.patch create mode 100644 packages/x11/driver/xf86-video-nvidia-legacy/patches.upstream/xf86-video-nvidia-legacy-002-kernel-3.10.patch diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches.upstream/xf86-video-nvidia-legacy-001-kernel-3.10.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches.upstream/xf86-video-nvidia-legacy-001-kernel-3.10.patch new file mode 100644 index 0000000000..5574b33e5a --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches.upstream/xf86-video-nvidia-legacy-001-kernel-3.10.patch @@ -0,0 +1,605 @@ +https://devtalk.nvidia.com/default/topic/543728/linux/building-nvidia-driver-on-kernel-3-9-0/post/3814531/#3814531 +http://pastie.org/7942599 + +--- a/kernel/nv-i2c.c 2013-04-26 00:22:30.000000000 -0400 ++++ b/kernel/nv-i2c.c 2013-05-13 05:20:55.571981365 -0400 +@@ -311,8 +311,6 @@ + BOOL NV_API_CALL nv_i2c_del_adapter(nv_state_t *nv, void *data) + { + struct i2c_adapter *pI2cAdapter = (struct i2c_adapter *)data; +- int osstatus = 0; +- BOOL wasReleased = FALSE; + + #if defined(KERNEL_2_4) + if (!NV_WEAK_SYMBOL_PRESENT(i2c_add_adapter)) +@@ -324,15 +322,10 @@ + if (!pI2cAdapter) return FALSE; + + // attempt release with the OS +- osstatus = i2c_del_adapter(pI2cAdapter); ++ i2c_del_adapter(pI2cAdapter); ++ os_free_mem(pI2cAdapter); + +- if (!osstatus) +- { +- os_free_mem(pI2cAdapter); +- wasReleased = TRUE; +- } +- +- return wasReleased; ++ return TRUE; + } + + #else // (defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)) + +--- a/kernel/nv-procfs.c 2013-04-26 00:22:30.000000000 -0400 ++++ b/kernel/nv-procfs.c 2013-05-22 04:52:45.229495748 -0400 +@@ -60,60 +60,41 @@ + __entry; \ + }) + +-#define NV_CREATE_PROC_FILE(name,parent,__read_proc, \ +- __write_proc,__fops,__data) \ +- ({ \ +- struct proc_dir_entry *__entry; \ +- int __mode = (S_IFREG | S_IRUGO); \ +- if ((NvUPtr)(__write_proc) != 0) \ +- __mode |= S_IWUSR; \ +- __entry = NV_CREATE_PROC_ENTRY(name, __mode, parent); \ +- if (__entry != NULL) \ +- { \ +- if ((NvUPtr)(__read_proc) != 0) \ +- __entry->read_proc = (__read_proc); \ +- if ((NvUPtr)(__write_proc) != 0) \ +- { \ +- __entry->write_proc = (__write_proc); \ +- __entry->proc_fops = (__fops); \ +- } \ +- __entry->data = (__data); \ +- } \ +- __entry; \ +- }) ++#define NV_PROC_RW (S_IFREG|S_IRUGO|S_IWUSR) ++#define NV_PROC_RO (S_IFREG|S_IRUGO) + + #define NV_CREATE_PROC_DIR(name,parent) \ + ({ \ + struct proc_dir_entry *__entry; \ + int __mode = (S_IFDIR | S_IRUGO | S_IXUGO); \ +- __entry = NV_CREATE_PROC_ENTRY(name, __mode, parent); \ ++ __entry = proc_mkdir_mode(name, __mode, parent); \ + __entry; \ + }) + ++#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,9,255) ++static inline void *PDE_DATA(const struct inode *inode) { ++ return PDE(inode)->data; ++} ++#endif ++ + #define NV_PROC_WRITE_BUFFER_SIZE (64 * RM_PAGE_SIZE) + + static int +-nv_procfs_read_gpu_info( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data ++nv_procfs_show_gpu_info( ++ struct seq_file *m, ++ void *v + ) + { +- nv_state_t *nv = data; ++ nv_state_t *nv = m->private; + nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv); + struct pci_dev *dev = nvl->dev; + char *type, *fmt, tmpstr[NV_DEVICE_NAME_LENGTH]; +- int len = 0, status; ++ int status; + NvU8 *uuid; + NvU32 vbios_rev1, vbios_rev2, vbios_rev3, vbios_rev4, vbios_rev5; + NvU32 fpga_rev1, fpga_rev2, fpga_rev3; + nv_stack_t *sp = NULL; + +- *eof = 1; +- + NV_KMEM_CACHE_ALLOC_STACK(sp); + if (sp == NULL) + { +@@ -134,31 +115,31 @@ + if (rm_get_device_name(sp, nv, dev->device, dev->subsystem_vendor, + dev->subsystem_device, NV_DEVICE_NAME_LENGTH, + tmpstr) != RM_OK) +- { ++ { + strcpy (tmpstr, "Unknown"); + } + } + +- len += sprintf(page+len, "Model: \t\t %s\n", tmpstr); +- len += sprintf(page+len, "IRQ: \t\t %d\n", nv->interrupt_line); ++ seq_printf(m, "Model: \t\t %s\n", tmpstr); ++ seq_printf(m, "IRQ: \t\t %d\n", nv->interrupt_line); + + if (NV_IS_GVI_DEVICE(nv)) + { + status = rm_gvi_get_firmware_version(sp, nv, &fpga_rev1, &fpga_rev2, + &fpga_rev3); + if (status != RM_OK) +- len += sprintf(page+len, "Firmware: \t ????.??.??\n"); ++ seq_printf(m, "Firmware: \t ????.??.??\n"); + else + { + fmt = "Firmware: \t %x.%x.%x\n"; +- len += sprintf(page+len, fmt, fpga_rev1, fpga_rev2, fpga_rev3); ++ seq_printf(m, fmt, fpga_rev1, fpga_rev2, fpga_rev3); + } + } + else + { + if (rm_get_gpu_uuid(sp, nv, &uuid, NULL) == RM_OK) + { +- len += sprintf(page+len, "GPU UUID: \t %s\n", (char *)uuid); ++ seq_printf(m, "GPU UUID: \t %s\n", (char *)uuid); + os_free_mem(uuid); + } + +@@ -166,12 +147,12 @@ + &vbios_rev3, &vbios_rev4, + &vbios_rev5) != RM_OK) + { +- len += sprintf(page+len, "Video BIOS: \t ??.??.??.??.??\n"); ++ seq_printf(m, "Video BIOS: \t ??.??.??.??.??\n"); + } + else + { + fmt = "Video BIOS: \t %02x.%02x.%02x.%02x.%02x\n"; +- len += sprintf(page+len, fmt, vbios_rev1, vbios_rev2, vbios_rev3, ++ seq_printf(m, fmt, vbios_rev1, vbios_rev2, vbios_rev3, + vbios_rev4, vbios_rev5); + } + } +@@ -180,12 +161,12 @@ + type = "PCI-E"; + else + type = "PCI"; +- len += sprintf(page+len, "Bus Type: \t %s\n", type); ++ seq_printf(m, "Bus Type: \t %s\n", type); + +- len += sprintf(page+len, "DMA Size: \t %d bits\n", ++ seq_printf(m, "DMA Size: \t %d bits\n", + nv_count_bits(dev->dma_mask)); +- len += sprintf(page+len, "DMA Mask: \t 0x%llx\n", dev->dma_mask); +- len += sprintf(page+len, "Bus Location: \t %04x:%02x.%02x.%x\n", ++ seq_printf(m, "DMA Mask: \t 0x%llx\n", dev->dma_mask); ++ seq_printf(m, "Bus Location: \t %04x:%02x.%02x.%x\n", + nv->domain, nv->bus, nv->slot, PCI_FUNC(dev->devfn)); + #if defined(DEBUG) + do +@@ -193,7 +174,7 @@ + int j; + for (j = 0; j < NV_GPU_NUM_BARS; j++) + { +- len += sprintf(page+len, "BAR%u: \t\t 0x%llx (%lluMB)\n", ++ seq_printf(m, "BAR%u: \t\t 0x%llx (%lluMB)\n", + j, nv->bars[j].address, (nv->bars[j].size >> 20)); + } + } while (0); +@@ -201,26 +182,120 @@ + + NV_KMEM_CACHE_FREE_STACK(sp); + +- return len; ++ return 0; + } + + static int +-nv_procfs_read_version( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data ++nv_procfs_open_gpu_info( ++ struct inode *inode, ++ struct file *file ++) ++{ ++ return single_open(file, nv_procfs_show_gpu_info, PDE_DATA(inode)); ++} ++ ++static const struct file_operations nv_procfs_gpu_info_fops = { ++ .owner = THIS_MODULE, ++ .open = nv_procfs_open_gpu_info, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int ++nv_procfs_show_version( ++ struct seq_file *m, ++ void *v ++) ++{ ++ seq_printf(m, "NVRM version: %s\n", pNVRM_ID); ++ seq_printf(m, "GCC version: %s\n", NV_COMPILER); ++ ++ return 0; ++} ++ ++static int ++nv_procfs_open_version( ++ struct inode *inode, ++ struct file *file ++) ++{ ++ return single_open(file, nv_procfs_show_version, NULL); ++} ++ ++static const struct file_operations nv_procfs_version_fops = { ++ .owner = THIS_MODULE, ++ .open = nv_procfs_open_version, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ ++static int ++nv_procfs_show_registry( ++ struct seq_file *m, ++ void *v ++) ++{ ++ nv_state_t *nv = m->private; ++ nv_linux_state_t *nvl = NULL; ++ char *registry_keys; ++ ++ if (nv != NULL) ++ nvl = NV_GET_NVL_FROM_NV_STATE(nv); ++ registry_keys = ((nvl != NULL) ? ++ nvl->registry_keys : nv_registry_keys); ++ ++ seq_printf(m, "Binary: \"%s\"\n", registry_keys); ++ ++ return 0; ++} ++ ++static ssize_t ++nv_procfs_write_registry( ++ struct file *file, ++ const char __user *buffer, ++ size_t count, ++ loff_t *pos + ) + { +- int len = 0; +- *eof = 1; ++ int status = 0; ++ nv_file_private_t *nvfp = NV_GET_FILE_PRIVATE(file); ++ char *proc_buffer; ++ unsigned long bytes_left; ++ ++ down(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_PROCFS]); ++ ++ bytes_left = (NV_PROC_WRITE_BUFFER_SIZE - nvfp->off - 1); ++ ++ if (count == 0) ++ { ++ status = -EINVAL; ++ goto done; ++ } ++ else if ((bytes_left == 0) || (count > bytes_left)) ++ { ++ status = -ENOSPC; ++ goto done; ++ } ++ ++ proc_buffer = &((char *)nvfp->data)[nvfp->off]; ++ ++ if (copy_from_user(proc_buffer, buffer, count)) ++ { ++ nv_printf(NV_DBG_ERRORS, "NVRM: failed to copy in proc data!\n"); ++ status = -EFAULT; ++ } ++ else ++ { ++ nvfp->proc_data = PDE_DATA(file->f_inode); ++ nvfp->off += count; ++ } + +- len += sprintf(page+len, "NVRM version: %s\n", pNVRM_ID); +- len += sprintf(page+len, "GCC version: %s\n", NV_COMPILER); ++done: ++ up(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_PROCFS]); + +- return len; ++ return ((status < 0) ? status : count); + } + + static int +@@ -233,7 +308,7 @@ + nv_stack_t *sp = NULL; + + if (0 == (file->f_mode & FMODE_WRITE)) +- return 0; ++ return single_open(file, nv_procfs_show_registry, PDE_DATA(inode)); + + nvfp = nv_alloc_file_private(); + if (nvfp == NULL) +@@ -282,6 +357,9 @@ + RM_STATUS rm_status; + int rc = 0; + ++ if (0 == (file->f_mode & FMODE_WRITE)) ++ return single_release(inode, file); ++ + nvfp = NV_GET_FILE_PRIVATE(file); + if (nvfp == NULL) + return 0; +@@ -346,122 +424,81 @@ + return rc; + } + +-static struct file_operations nv_procfs_registry_fops = { ++static const struct file_operations nv_procfs_registry_fops = { + .open = nv_procfs_open_registry, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .write = nv_procfs_write_registry, + .release = nv_procfs_close_registry, + }; + + static int +-nv_procfs_read_params( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data ++nv_procfs_show_params( ++ struct seq_file *m, ++ void *v + ) + { + unsigned int i; +- int len = 0; + nv_parm_t *entry; + +- *eof = 1; + + for (i = 0; (entry = &nv_parms[i])->name != NULL; i++) +- len += sprintf(page+len, "%s: %u\n", entry->name, *entry->data); ++ seq_printf(m, "%s: %u\n", entry->name, *entry->data); + +- len += sprintf(page+len, "RegistryDwords: \"%s\"\n", ++ seq_printf(m, "RegistryDwords: \"%s\"\n", + (NVreg_RegistryDwords != NULL) ? NVreg_RegistryDwords : ""); +- len += sprintf(page+len, "RmMsg: \"%s\"\n", ++ seq_printf(m, "RmMsg: \"%s\"\n", + (NVreg_RmMsg != NULL) ? NVreg_RmMsg : ""); + +- return len; ++ return 0; + } + + static int +-nv_procfs_read_registry( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data +-) ++nv_procfs_open_params( ++ struct inode *inode, ++ struct file *file ++) + { +- nv_state_t *nv = data; +- nv_linux_state_t *nvl = NULL; +- char *registry_keys; ++ return single_open(file, nv_procfs_show_params, NULL); ++} + +- if (nv != NULL) +- nvl = NV_GET_NVL_FROM_NV_STATE(nv); +- registry_keys = ((nvl != NULL) ? +- nvl->registry_keys : nv_registry_keys); ++static const struct file_operations nv_procfs_params_fops = { ++ .owner = THIS_MODULE, ++ .open = nv_procfs_open_params, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; + +- *eof = 1; +- return sprintf(page, "Binary: \"%s\"\n", registry_keys); +-} + + static int +-nv_procfs_write_registry( +- struct file *file, +- const char *buffer, +- unsigned long count, +- void *data ++nv_procfs_show_text_file( ++ struct seq_file *m, ++ void *v + ) + { +- int status = 0; +- nv_file_private_t *nvfp = NV_GET_FILE_PRIVATE(file); +- char *proc_buffer; +- unsigned long bytes_left; +- +- down(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_PROCFS]); +- +- bytes_left = (NV_PROC_WRITE_BUFFER_SIZE - nvfp->off - 1); ++ seq_printf(m, "%s", (char *)m->private); + +- if (count == 0) +- { +- status = -EINVAL; +- goto done; +- } +- else if ((bytes_left == 0) || (count > bytes_left)) +- { +- status = -ENOSPC; +- goto done; +- } +- +- proc_buffer = &((char *)nvfp->data)[nvfp->off]; +- +- if (copy_from_user(proc_buffer, buffer, count)) +- { +- nv_printf(NV_DBG_ERRORS, "NVRM: failed to copy in proc data!\n"); +- status = -EFAULT; +- } +- else +- { +- nvfp->proc_data = data; +- nvfp->off += count; +- } +- +-done: +- up(&nvfp->fops_sp_lock[NV_FOPS_STACK_INDEX_PROCFS]); +- +- return ((status < 0) ? status : (int)count); ++ return 0; + } + + static int +-nv_procfs_read_text_file( +- char *page, +- char **start, +- off_t off, +- int count, +- int *eof, +- void *data ++nv_procfs_open_text_file( ++ struct inode *inode, ++ struct file *file + ) + { +- *eof = 1; +- return sprintf(page, "%s", (char *)data); ++ return single_open(file, nv_procfs_show_text_file, PDE_DATA(inode)); + } + ++static const struct file_operations nv_procfs_text_fops = { ++ .owner = THIS_MODULE, ++ .open = nv_procfs_open_text_file, ++ .read = seq_read, ++ .llseek = seq_lseek, ++ .release = single_release, ++}; ++ + static void + nv_procfs_add_text_file( + struct proc_dir_entry *parent, +@@ -469,22 +506,7 @@ + const char *text + ) + { +- NV_CREATE_PROC_FILE(filename, parent, +- nv_procfs_read_text_file, NULL, NULL, (void *)text); +-} +- +-static void nv_procfs_unregister_all(struct proc_dir_entry *entry) +-{ +- while (entry) +- { +- struct proc_dir_entry *next = entry->next; +- if (entry->subdir) +- nv_procfs_unregister_all(entry->subdir); +- remove_proc_entry(entry->name, entry->parent); +- if (entry == proc_nvidia) +- break; +- entry = next; +- } ++ proc_create_data(filename, NV_PROC_RO, parent, &nv_procfs_text_fops, (void *)text); + } + #endif + +@@ -513,26 +535,11 @@ + if (!proc_nvidia) + goto failed; + +- entry = NV_CREATE_PROC_FILE("params", proc_nvidia, +- nv_procfs_read_params, NULL, NULL, NULL); ++ entry = proc_create("params", NV_PROC_RO, proc_nvidia, &nv_procfs_params_fops); + if (!entry) + goto failed; + +- /* +- * entry->proc_fops originally points to a constant +- * structure, so to add more methods for the +- * binary registry write path, we need to replace the +- * said entry->proc_fops with a new fops structure. +- * However, in preparation for this, we need to preserve +- * the procfs read() and write() operations. +- */ +- nv_procfs_registry_fops.read = entry->proc_fops->read; +- nv_procfs_registry_fops.write = entry->proc_fops->write; +- +- entry = NV_CREATE_PROC_FILE("registry", proc_nvidia, +- nv_procfs_read_registry, +- nv_procfs_write_registry, +- &nv_procfs_registry_fops, NULL); ++ entry = proc_create("registry", NV_PROC_RW, proc_nvidia, &nv_procfs_registry_fops); + if (!entry) + goto failed; + +@@ -553,8 +560,7 @@ + + nv_procfs_add_text_file(proc_nvidia_patches, "README", __README_patches); + +- entry = NV_CREATE_PROC_FILE("version", proc_nvidia, +- nv_procfs_read_version, NULL, NULL, NULL); ++ entry = proc_create("version", NV_PROC_RO, proc_nvidia, &nv_procfs_version_fops); + if (!entry) + goto failed; + +@@ -571,15 +577,11 @@ + if (!proc_nvidia_gpu) + goto failed; + +- entry = NV_CREATE_PROC_FILE("information", proc_nvidia_gpu, +- nv_procfs_read_gpu_info, NULL, NULL, nv); ++ entry = proc_create_data("information", NV_PROC_RO, proc_nvidia_gpu, &nv_procfs_gpu_info_fops, nv); + if (!entry) + goto failed; + +- entry = NV_CREATE_PROC_FILE("registry", proc_nvidia_gpu, +- nv_procfs_read_registry, +- nv_procfs_write_registry, +- &nv_procfs_registry_fops, nv); ++ entry = proc_create_data("registry", NV_PROC_RW, proc_nvidia_gpu, &nv_procfs_registry_fops, nv); + if (!entry) + goto failed; + } +@@ -587,7 +589,7 @@ + return 0; + #if defined(CONFIG_PROC_FS) + failed: +- nv_procfs_unregister_all(proc_nvidia); ++ remove_proc_subtree("nvidia", proc_nvidia); + return -1; + #endif + } +@@ -595,6 +597,6 @@ + void nv_unregister_procfs(void) + { + #if defined(CONFIG_PROC_FS) +- nv_procfs_unregister_all(proc_nvidia); ++ remove_proc_subtree("nvidia", proc_nvidia); + #endif + } diff --git a/packages/x11/driver/xf86-video-nvidia-legacy/patches.upstream/xf86-video-nvidia-legacy-002-kernel-3.10.patch b/packages/x11/driver/xf86-video-nvidia-legacy/patches.upstream/xf86-video-nvidia-legacy-002-kernel-3.10.patch new file mode 100644 index 0000000000..af29267fb9 --- /dev/null +++ b/packages/x11/driver/xf86-video-nvidia-legacy/patches.upstream/xf86-video-nvidia-legacy-002-kernel-3.10.patch @@ -0,0 +1,29 @@ +by ultraman + +--- a/kernel/nv-procfs.c 2013-03-27 22:26:51.000000000 +0100 ++++ b/kernel/nv-procfs.c 2013-07-05 12:08:43.000000000 +0200 +@@ -789,18 +791,18 @@ + if (!proc_nvidia_agp) + goto failed; + +- entry = NV_CREATE_PROC_FILE("status", proc_nvidia_agp, +- nv_procfs_read_agp_status, NULL, NULL, nv); ++ entry = proc_create_data("status", NV_PROC_RO, proc_nvidia_agp, ++ nv_procfs_read_agp_status, nv); + if (!entry) + goto failed; + +- entry = NV_CREATE_PROC_FILE("host-bridge", proc_nvidia_agp, +- nv_procfs_read_agp_info, NULL, NULL, NULL); ++ entry = proc_create_data("host-bridge", NV_PROC_RO, proc_nvidia_agp, ++ nv_procfs_read_agp_info, NULL); + if (!entry) + goto failed; + +- entry = NV_CREATE_PROC_FILE("gpu", proc_nvidia_agp, +- nv_procfs_read_agp_info, NULL, NULL, nv); ++ entry = proc_create_data("gpu", NV_PROC_RO, proc_nvidia_agp, ++ nv_procfs_read_agp_info, nv); + if (!entry) + goto failed; + } From 87a1e4c22568e8af4ebe4f8af9c56b4e6754ca25 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sat, 6 Jul 2013 18:43:47 +0200 Subject: [PATCH 40/61] util-linux: update to util-linux-2.23.1 Signed-off-by: Stephan Raue --- packages/sysutils/util-linux/build | 9 +++++++-- packages/sysutils/util-linux/meta | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/sysutils/util-linux/build b/packages/sysutils/util-linux/build index 5a96a5d676..526e5b44b5 100755 --- a/packages/sysutils/util-linux/build +++ b/packages/sysutils/util-linux/build @@ -48,7 +48,7 @@ cd $PKG_BUILD --disable-unshare \ --disable-arch \ --disable-ddate \ - --disable-eject \ + --disable-eject \ --disable-agetty \ --disable-cramfs \ --disable-switch-root \ @@ -56,7 +56,7 @@ cd $PKG_BUILD --disable-elvtune \ --disable-kill \ --disable-last \ - --disable-utmpdump \ + --disable-utmpdump \ --disable-line \ --disable-mesg \ --disable-raw \ @@ -71,6 +71,11 @@ cd $PKG_BUILD --disable-login-stat-mail \ --disable-sulogin \ --disable-su \ + --disable-runuser \ + --disable-ul \ + --disable-more \ + --disable-pg \ + --disable-setterm \ --disable-schedutils \ --disable-wall \ --disable-write \ diff --git a/packages/sysutils/util-linux/meta b/packages/sysutils/util-linux/meta index f91a9eb013..f65b7287f0 100644 --- a/packages/sysutils/util-linux/meta +++ b/packages/sysutils/util-linux/meta @@ -19,11 +19,11 @@ ################################################################################ PKG_NAME="util-linux" -PKG_VERSION="2.22.2" +PKG_VERSION="2.23.1" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" -PKG_URL="http://www.kernel.org/pub/linux/utils/util-linux/v2.22/$PKG_NAME-$PKG_VERSION.tar.xz" +PKG_URL="http://www.kernel.org/pub/linux/utils/util-linux/v2.23/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_DEPENDS="" PKG_BUILD_DEPENDS="toolchain" PKG_PRIORITY="optional" From 67416aed159cad1c2739ea2caf0556992ea12c96 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sat, 6 Jul 2013 18:43:47 +0200 Subject: [PATCH 41/61] procps-ng: update to procps-ng-3.3.8 Signed-off-by: Stephan Raue --- packages/sysutils/procps-ng/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sysutils/procps-ng/meta b/packages/sysutils/procps-ng/meta index e022797c68..c3fcfedcc3 100644 --- a/packages/sysutils/procps-ng/meta +++ b/packages/sysutils/procps-ng/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="procps-ng" -PKG_VERSION="3.3.7" +PKG_VERSION="3.3.8" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From 240db6fe76560f463084fbb64448a50c28d2f1c5 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sat, 6 Jul 2013 18:43:47 +0200 Subject: [PATCH 42/61] bluez: update to bluez-5.7 Signed-off-by: Stephan Raue --- packages/network/bluez/meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/network/bluez/meta b/packages/network/bluez/meta index d0d358e7ba..8ae04883a2 100644 --- a/packages/network/bluez/meta +++ b/packages/network/bluez/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="bluez" -PKG_VERSION="5.6" +PKG_VERSION="5.7" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From 7d0b16f17ecb7d2a4204d71f8cfe9d3dd7bf378c Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sat, 6 Jul 2013 18:43:47 +0200 Subject: [PATCH 43/61] zlib: update to zlib-1.2.8 Signed-off-by: Stephan Raue --- packages/compress/zlib/meta | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/compress/zlib/meta b/packages/compress/zlib/meta index a1dff3281d..d24d2a6b6e 100644 --- a/packages/compress/zlib/meta +++ b/packages/compress/zlib/meta @@ -19,12 +19,12 @@ ################################################################################ PKG_NAME="zlib" -PKG_VERSION="1.2.7" +PKG_VERSION="1.2.8" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="OSS" PKG_SITE="http://www.zlib.net" -PKG_URL="http://www.zlib.net/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_URL="http://www.zlib.net/$PKG_NAME-$PKG_VERSION.tar.xz" PKG_DEPENDS="" PKG_BUILD_DEPENDS="toolchain" PKG_PRIORITY="optional" From 2219252dc87b181f5d07c576ea8541f85687a9ce Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sat, 6 Jul 2013 18:43:47 +0200 Subject: [PATCH 44/61] xbmc-pvr-addons: fix patch to support patch-2.7, which rejects git binary diff's Signed-off-by: Stephan Raue --- .../xbmc-pvr-addons-frodo-01-PR200.patch | Bin 418368 -> 401087 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-01-PR200.patch b/packages/mediacenter/xbmc-pvr-addons/patches/frodo-78b0aae/xbmc-pvr-addons-frodo-01-PR200.patch index 41fbc236e83cae76395985e0bb0420773a4eadf3..97bd56c9951d9c0136bf0bcd1286d9a38ae21539 100644 GIT binary patch delta 71434 zcmb@t1yCJ9v^IE=Ai>=|K;QzoxI4juy9RfM;4-)*xLa^{g1bX-cez-A1b2t!)%)M8 z`fLB%eOt9tQ#JRV>OOP&>(kT6y1SpKtAh|QwK6xSWL7Y8b*A(%wliUNbaQ4lGBtIu zcVRYnb})5d=H@Ym7#W#;`cL8~c_SM$b1Pdj79+d==MF56M&C><{}0{XGcz;)cURzl z`Z8oT2rD}?go~M#mlDFo$H~dZ!O8;puZt24VS_;4gTdhc=KOzT{C^XQ>Awc^zxZ>% zy@HaJhmVzukDZf+m5r5`infVVf$Qk}uhyNKC08Nvji1hX=+v2s(2h`a|!C@Dyxy$2J&2ZKN$G#P0L6%YvK?I#Qf3E}Ob=UieA z0#SlwBt+FbGLJeu=j^oADIPLxj(sN<*G_M40S#qleNnu3iT*SBy*aAJa$~a+;dch*ji>TbV|>(ynuRDK?d?D(a5GoooB1I&^wfxXSDpT?5} z0fd_WAUZ9ZfZixRcqxMa-w7vj+z|(Wn()oY*JbdnDz9qeDG^aOTythL`>|6+$AxfS zW^~?5@o4#Lb^wfAL^>U`c(HtA8SMQ>1sBMAYB+V1*D{C2uq-+gF$0x{XVF15eTz;{ zSOYtp8AcK}k5B&!oeNcZ+`_1mTcR2!earTn`L4LomWv0 z*DOZJ13BiOfL>71%qr6Ii}`aFm2Y(R*X+L#b9mKp!|J0X6b4mlu3n0(N3kx92jEfc zm5n$kT+T@67HZjIiEvhw?F}Bg(nfvfyBL5}5+WKQ^5Ltrxuh(-i?s8*ug~94`G4wA z6ne!-9tirk_&qp0H#z`ENt*gDeVvt+<=oud)mqS{W^B-dpIiH3>+_gMC7uMb$map-2sq_2df?;xZlCt)L49GdVM}1T0J(vaywj%cw+uCebPC8BLM`TzF zGF4jfd$24rFPykh4r~&*m1UR*5kdUl7O^=>a3XvsC^zwYVnQ@YNs_4P4)6wucqDIca7-FYF;1~h|A$VGG(b^jgry41OeM~isNgb~@ZQX^`?#O1b zFGZ+xxzuL8#vgBwY_lJ**^MkL9xv%n_|HSUPdoPOvR{uXDITK?9w#Y6Fkhnm@GT>a z0%{u}oOoxm!mnIat}7NfKw@BKU2jod^7pFA6;01O#IHBL&8cD*@4;A^UkK08gdg$0 zX&1qdSBQK%T$7Ih3I`o}!RZ@WAg&x>a^ko=0WIYEb$ejD7-v(yao+p)f|n6-Kb zn^zMTS(`+pBqABCal)vpE>;SnA1bj1qx~dXi7Lge<&0;EC zkcy;&SY}@ywS^di%8(MH^GMDI)NaD?Nkpt>;<{2p1m_9EWG_aP^P#quGggN>*MA)ka_V*hi0d6Xp zzV-4Mya(f8eq^vmfema4glT^;`=s+ZIp0~5xJwJ+Y%tpw0D~yqMVLio#ne7y@nHoZ zZ>pRJMV$qhWe8!vkaqL=N4;ShT%LV@wC{WPrsdCT%RVoL5Z)Ae%xH4K$i6W2owMBM zrLG1H#2W_~O55Yr{)dMZ?Z^LEnad-k$98Mpr^ujg&65^_+YRqeC!PD`K7Vic&k9#h zL7?44B|tlM`R3-PSlIor^7MK05&C#YaX*Uz;CIU)i9?Pl*#b-OK%k8)7YDp#8QfH0 z7B$KU`)3A%V;7r$_Jg~FI-cU(dZIM#doVX=ivMDCq2GrW%h5>~ThNlv3AgX4yrTEu zB5)d)Ka@4B*TbZDdNAGRaW=2H^Bqw?6io3A;C*-r*dAO08$_AaYHeN`+);O)EjDc} zOakOhz&%R`jZXhh_l@%a;iu}Z+s50@M{Z%*P559U2}#4w;5e(Z1mS0twcFtatVID; z_EONM`lsiOx|?%9GmyhwngJ+{cm!|r44qwtuKi!(m&Q(+XLQj4#F}en;C40puAd$d zJ~l%{C-n$i9>~Zz^yu%S2qhsucO(^bKB(~3Q8%`w3$Zy&wFmK)LgHa zoj-vRay0r4JYYWXp+Ty@Gs~~0H)@JQ^TYZ!c=f;D)lXnop_!|CWK~rJetzN)sqFEd z_YR)FG&hk2`{{BH&7N!XYG#K28FdHNLSlgJPfnxsuh_Ti?%33|>?bYzCm65iua}R) zw})L1*{?|59fTQ3gYc3o-6R`N_z3+HkwuuG>qCg&86MC__a8)!eT4=MR{`V$1}wkL zLMZ?BkyNQe*-NLCz(r{J%LWwKviSr|;Z1Ts{`s2_dipg;)kzj+UiE;9OP9Yp6?dEixN7a~qV zn);5efz7-Qy@4&Xhl5sy1UlDBoEd<7WF$JR18&V6@TgF?a|@^=jJ#-`r$Qe$Wnl~7 z0k>2-po<4ZtzZe=_&<(N!x`q?mCJf{BO zGQKUO;ELlk=sU!QnL_aaQ&Gl9jf{N#xeLm3j((C;)Tm1ygC~i1k4hbP{3USO* zTEmgEdOT0Ihh$)U*^G5@rWh(WcmbWk%)JL+?~VkkS9y$sHOijM_a`a)yD++6fT!o` z7sQy>E!Jvj{f!jtt%I#TkCB8df1Bz~XHN*IvD_o_3k)NB^Y<_g_hquEzMO>p4VxQp zghYh7J!X8L5A;B6VhJxSj_C8_woe(_&WHGJm}%)$85kA(7(VHrGKGv6P9n}db8D_A z%^Z2~WkMN=J>joG(;Eas`mTtDSoxllU>xW8=yV)8dv)$*+ldfE;!G9Uk4YhMYSaHx zLmUOl^0VA78+wted(z^&@iFOtj(=p2ZG%tUi9*s(snG(E@o*e7~3v!C}j^URK!#Iqkkq(`rNqO=s^Ss&8r@dtZ#2VLuB+a+KDIFJ5G30_T^@&KA%cP3F7dU4JB;>5t zeS&nTN473!gK+rT)YyU2-!~--BxLB-JBo`WvF7xw-h*>I7h4uKhd#=B$cQ;vN(;wN zjg>G>y&UZ%o@{o64F9E zmOy2)yo>nQN}>O3=W|0Gn;7*(m*(#IS&jaIkz-yOqPej7%$A;|*{?4aIhx?Z72Tg;!r~OWUb9}9S z!{HAeJCmIuVa7V~mde$B_s|-gGkV~GfRvRelEUX+cAI;+3&9Yl`^7@|^qr#D$)&-W zN!|U*pRq_O{Z}NP=h;qlo6DBP4p2=83V;e1)B>6_?k-eQ3Y0bF*-q`xPZas!mLlN6`&hA+`*8T?VEge<}qlC6AC!db$@P~LbGi6wUP!( zj)0Q-W`NNB_EEY{b+fMKieE1iXDbf*1RhDULJ!GrFsofaj?ReWu&gqZ0^Ri74ZEbG z0&x%cL(w-*bkdsA+c#J;5x)!ND%EM7h`&TK{r-SVL>fM)<}m#+GPSMB1t`!*4Wdz| zh6U%Bt{JZ;Vvi`P4IBr$ncTFQ;dO}TloFYx-#fzRV?DyHjMxc!=Yy57tM6E@!m zhRA&axewEam_UogOB_?VOXA@*L9_G2%A@Kw6xQ*M_S0*?so%D07I4EyolYj?feF38 zeQCr2U>u2tE+82)3hSA*cLdLb^oO2ztZ?uFkbrWlw;zjC*ll(d8p>uO_A&+S;h%wW8Ikng@Y0KMR;0%;%D+mIJS}9PpC2p zfhrTCD6xJh7iiJDKm!{ip_EZ;u-0pLofu&Z3O_}61&u~i zh);OlG${Iv9DaTJrRmG<-zN*Uk>$_7x}oqH_#yq^W`E_`=sb;@W0{fYUqBU|SUgR%AMI`jqtE zar(mrGFc@8XvI{CE8$D2B1FNebzb$f`y#x683>Pm6@^wpy=Ok#a7KYJs$|o&v^bL0 zgpwy9Sta(@%6#7@_Uh0VW6AKF+`S~e!{D@Tbu;fFj^J$~=e&6IA4*-;aLI<$ZcJ?n zl~!uK-&(79`*u5d_97vu3WG@FGHGm9k|lDPSViT)>c4!$D0FIhhHf&x7DS$;1GJq?p`9k2dBr_ zuy#XmE!JS0VEFm*+_MaA!2%fMOEC_w{GYnTDV)(-I~8O6j&|NQAI;a<6q7M{ugEme z*T)ec1+#6lwfPNEO4?qVPM~nzf$LQW6xMlK2z}L$@tKSIM2l(PzQy-cxi9=hu%>$$ zHj{^zH2YTxcb)bpE(XqirXbmRY*nRsx{$JlGGQDIL|Ig5kn{GJTgLee3Owj`eEGFPc*m0+(({H~%4Z%)XFG>nXB z89apAR4urh%7GfjHF=&mvlCPH|1PPWL1ez=>$l)RwgkN5G)h>V`cfZ>v zp}$s>cLat7Lu(#_S(jtQkE6Fouzi62xeP@pOv~u+e`*X3tx|$4bbni!RCswBKSq4F zjLh})8RFenF{ne)MJ3%ZUzl1qX63m6;p5NUrivOCBnqk>L=X?p@VpIaxH-_8Ve*3% zrFO+!#0u%0ney#`l+p;SJ~z9~=fMGW((j!8oAcrhjh*9WKTc6{neh1!9@79w!ORDZ zMR#T$*pffX4|YQ67QI!`2gVPaUrV7+mC&1qszY;(mOVzFQEovJiC{7iy`si`RUyY@xqPdu&`sY5 z!<4#mpNU+&8Yf!f93yt~t7TGc*d8O+98Cv1hR7;{uw+W^+`|>v{92$dPEdileD60^ z4_^9}Q5h{qC~2k~s5^KL`4_slXz@z44T4TF@ABB-@k7C4e94UKGBOLTNJwsdA^Mcg z4lJP?f_Xok3v+rB@0oMsXU-W5m#jfZI^&H+ zLPxUl2qi==12;;pzI=^y&n}Me(n$*#TTHC8b~79^XSc1uF@G52-?-$z+btG?t7?CY ze!T#?_TaiMbpenOEIq^=mQ=`s>6RX@2GKY)`_Cms`@erS6u=E!^>ePl!Nbc^ZGPDK z&)3nWyhAoOm^F6;tP`eM0n|SK&Qqf_mxWGN*tjg}h%qa=VH#|j(?|3->zRw7cxu9} z$Cyy*OOLS@QV@(`?T030m=9>5euW@L<%PqFE0+p!6mibM)K%dWp#N*8YNy>-GdE2_ z{b3{m%PF%Rp9ZW`eI^d#Moj3Du_vKn6pbP%kn8E>`fH|xMpRq(!TP>=ojVsbaqCNr zu24v4*+joKw5_f>eb+)Vg&)G$tkq8yD$DLn$0YYhf$AJlX*NHEJ;HRr^gY;-)|%Ys z6nCsRUryMVuF309`g5p^A3Lk+h_$T9@$>gNv$02_JsZF#buxtEh{fMX+2db@I8v^+ay*!v8uewT`i0KE>lr1EBr;rR>5 zJ-?DBoG1tlshHu-st+%FMHPEO1d+Z%zuxY=4%P0Y2)i!0dTa^bwei#dD8-C59qR&v zoonA_k^%k{+c=Mdn6MCMd_WW6x96zO-m9=STaX^wWo8F?aVgxS2}0I z;8%a969w`(!{5o=>j6Ipbf$(;A`s{CXOaF&A>h>eu(5mxy*bvz@Ysb=^+5c`Ja?*x zmMTAPge7fzAx=%&k27sAt~naij2hq-#@60`y9`|2kEf|0C8g(1M(#bk<9OV#XlRl@ zG{I8SR#(0yOyz7?p&gM-hZ;ClKU^#Pd1HA^E>&EE^krrhz-#OCUv+rgrg%CPzWL;b z1azl>eBSlKyVX)lZGQXnVhk!*d*uW@!jL|1q_l6hb?u!SJeKJYL7&zvw&NBBao=_8 z-=f>+v$zomMc4;j65cyc5RNhIF!~M-dWkV~8$8b!pLgDN5}bNNz0ZafeXxt&+#pQ& zsnwMcz8To@e1V2H?yyRB@wP-Uyk3m|fDvzd7ZoJmzw9 zi7d2dS(yx^(NHAIHaF=u*ZPW&jT!B)(#WMO!iTp~$6`j@HzG|2)JKCmQHtNSzdcy! zQUtIb>9m=U^ZL5I2M+~HY`2#e|1}Z&EI)jj{;x~x$k^SRq~*(-G+S7U`eFM5!2Z3* z#$|R`c~vU{FOD05dN8p+i$%|BE-&FYJUe@j526{ij$qBFd^pET`j_|MQ!gl@|H$2e z)XVO;!=o_tNdsgM`T@mmM?fy%F#|>`IeYn8s>=6FyxM!-1~`E3XL38VZ((_y)MddS zINr)6f54Zm(N~CsXKITmaZ=3%?spYZRTvi*%n#VM@+qE?UY=JsLT_IuPB;4_aI{vJ z`UeLQ;`u^E3jWbBC}2w`1b}j!<3mUbq$k+UewpvKegQ3>6AbB$k3Wz3$3&P8y3ILbiX_% zxubDiuw3b5c565sNT~q*W$u~{UrI`_lJkWYv5GR(IRahUt8XjTc{bEt;9-^O0lLVm zuV#{^@8}gX`zMAUYg$?`pm$>y+uohGkB+nQ20^`%>#A)VaOdhv2uxU$s#CB!(XzrB zxu^U`1_}00H;BO7$BzKuHnFhS@1JbnqVL>anDqIF13D48MC^BkLjt7!ycqt6I=Y7c z1D0)Gm%Dt{=NG>|9^Ko95_FvL*EDhs`JxzFH07W&XPRW$tEMsOv7u$4_4zk6a8``t z2wj&>Zpu6O2yQ%|xSM>83_`@nJ>)M)j8l#j|z>FIz-P3Ns5znw|ovO!`ZToO*>EmSsV&V)nbz zg>mXMtyB81_?t4>@AAzn7ctr4K8o_{FBEKjuew%7^Yu;vQD#`NF`!aLRzG`?n?2au za@Sf)0JIHV2ebK!O*jap8euUm;-HO-ydrvQ*_J@dn`6I{S zM`Z((ckF=Loe3ajUtBrdk%RvJ+L1b6BB_>waoi5(c?#FP_+Iirs?pFer61WbVIg?Z zdZ_Sp5c33XKm2*x8z3&_xExdkf=jKoGqkZ0=DIx{@^PWqTPJQ!3_v$bK4NyMeHM>&!afpA6pSun=~Op!lYwnATY^H*IWajr^g+wBg6aoE;}D zVN~!MkT07*v%QK}EHq%6_2wXl!|^ArmKg+Tgx2Iu6rSg>jxwE^6Zd%{Ygk=WO%kO` zik#gG<_}_r@mLY$>dUeTnMaJHRAG7nV=(5nhA6sb-4i#k{PZV15jeM-8{VCP^}cW4 z&re;jtMrQ7QowH5`4+}2>&t!DlhIpj8h({O{@esi4%6IC6EBVJpNu~q-=d>%Z0yU` zXX4OK4!qRro-G2tx?VG?+2=7EubsC~$b;TU9Q(Wk& zf!~`e^$#Z-MBQ5&GLVz;OtY1hyDVzOG;Zs@Ha<>d|9n;H@ds=W8smFpP6|vV#b-b# zYh2GTZ^(FpeIFaACe6Q}86QTx2W$2hm`HL4PY072A?^Mv_!rSjE5}ya%E0O_Dq%ss zhA9m%Q}X2$lTh!db$L%kQxz~Np8X?H898)F++b7P;Ff_u(W*r!J$sotRWgW^HY$HO z^I4SZtFFza^_iJ#v{gdXZ2c?cb79kxc~hM@y30$`!?`N_*|y_ejgy$ zH1NecX>;JNcn`)aHXuTXA@8?LLDe1fH74Pyk@UD&6h!a3$><7!Lqy-WnzQiPS$ygV z6Y{|LKy0}BUEfjR?4Hg4BfZ?iE#}{@>qrNm8{vw=?WJiNj|1_lp3*n3v3AG0gE_he zPgjW^rB=pj!8^FJk{7V=yvJ`pqWv^z*8~t@v|bQnB9UY~I&S`EwIve>zW4F%SGOTE zb;0BWqw@1&2Vy}JEzy2h*C9upr4C`!VE4-+U~c>*uAqW#!ghMj!eU)%^CR0p>lt&( zo_tI8%I(u4Y!Y{;ex1HiCIn-a58=r9-<_lxa{eSB>FUrOngp^4;E+zMGV`$?Q3;qL zkkpVVo%;7AeqVBqncFO_E%iPO(seoy9rJi@3ke*I*u0q(0P&}%s?+|-=eF#jYi_-m zwo{>i&chYsI!qYD@mvtr2xVMwCcB$E!BW<($3aka&$)@z*}$s(kZSfz6!aRA;$bt} zIFk@p-hWnp02p!3rSo5YC4U6^uVcIp-fTs|fVA`7YHw1I@^i)q;{WoVwiASQio-P&5=|67^s($r4px${eQiV=1xYq1kyTf>Z|j9^Z11r7F#6Nh+m6$JzLTRK<~R`0X70(KLGPq4{NpzkAPy`q6BvF#Fx- zG*PrI%9veB%cNPDX?U*yn0}~yYp)*#mQuxZxfRsP*%v)~J|yLZ>H1P{wPCqlk+NC+ znMYN4(n_E>;MLT$*v|byuWbP)xE6EvV4c0k4S68|X5q~_VgAKaft$$4V*%U^q3%}o zy@(?^U0swr-u-qeNOZcoV_m!X({}bfr32M{!-@VuD2nv35Et!7j8*=>vfnE2!ESDD zHTq`vXM1}H;U9hb>areT>qErc*peqV?-MVLKv?p54{tH>%XAxxCk~LuSUx#2b?=12 zbLTNsgB`H3HRN~YdUrSE(DODo0V=&ceM62{zYvW~phB3Y>Uu;7 zYP2sp2->K5C~6<}P_$+Qh+NY(FsJ>u{Rq}46K=s3&PV>6 zF!6P!A}PD;##XWHmg|;l=td=Y18p(2v0PZKK16t<|2r4U0DU)!C9rXd@F{Y29;!FE z+AP+Ux>L7u$``P#Ev)ky?NovgMu=Mv+>ASioz^XuuZv9b*ywn5hsX16m+&JkDZd|) zedizir=^$|$im)FwPH`kll%P$b^+S@29n^PWVsnb8yZeEgx0`r}>bKyM*XiKhn}r-2}Qja-+c zb7ACkv($j)oxYGCzlnBD&zCpDrO1IkVrdlv7uWQ32F{~bG; z4OidZETxg@KBGD$B&DTlEcDy-)v zz7Cr2QZ@aGYQDi0v!8Z9=4-pd3`$|m43ddh!N1pn+LV@vi;}?;gsq44KiLed3?iVD zcaT0}kV?Wj0&g}#Z`<3r+MhKyqMvnLlux5-9Y@_+wN*x@#>}ZR1zg{QSMi#+;xG`| zO?-WKe$flv|BVq_<>)^+_nQYr-sL|CBi5XkND1G_!1vbDggM>N6sohk1o);6|;h)c2bJq#iM-FQJ|a%O}|WlVI=f1^Hf6JOp$ zpu~IJr^SsS_XY%w2y3VXp^^wwbZYL=Ni6-#YB#yYmMrr+{G$8n@Q4~oOD`z^JXNqp zAO#g6t35-??v!9Nt&d(UclTe<-F=ygt!y}?jvVz`_l7-+E~B&-n<++lupj(obXE1z z>Q!5S_h53yujqYZ_&Mr>Z>|nH8E^EpukLS#oz1O$k699^zpleG(}VWuJp?t98YD(y zRQv%S=V8umVC!wk?w(PpRW+Zpatjh|`(*D>kNKk*fo79{!=Y$>H@L#!Fu^OGhAzV$D8(nY3>Ektx zRE!`tsH%P2`3U{&r;as)NF~is7=Xr6)t)}?^|YM*%DZu2b-Q_RJ{l{s#OH|grl7EY zWy?hEsz$bV>wfR6jp%u#El_`?Sx?mX*RqSuPK+JmUg>5`E^KqF_k~BdYw$FB#1rga z`OAL~oYDNvF}kv1=F{NV-){~qugz?o}n7OZTM~k6DmewUBFxR>tipf zv+Uc7rfftfMNl4`-bvZgKlQ^9dO7dvetCXeH5w z7c9&2-h;5!WPaIkv0?SQpH$A{n7rVq&ay(T>kZ*75=5CBI2Y!UVe+LTp@1|BgS|Gn6r5#B2r5`MZBz6zMk zO9Lsx7V%XOo4i?e(jpsh#1WQQSsh zM(eB+F_+fJttLT=5Xll3k(rTI=8WRuJkb7O^%Z z!!cz@EUcu*V~H^L9x{Z2h)W*eEOTasbz+k2O|hV#(P2btT9=P7O0ccL4N<;JOML#v z>-wa;-v}vufY-AC^%wbP;3QzLK(wD-SyadsnTX0a0C{qvnb%(2Rx7vIcWFl{?C( zpBu9j>o3LZJ`lgGkCx09B#erF0_$JO4PDHAwx(08I`)HY2-Nfrg~WM3jqckPh?d*W zU~^bqMLmJxtoQISbxAF7e zbt3`Cs6BA*d5XyZU@8xcSN>qXk^I4+dI zm;#<+prKvX??JguB;acFF2;L(jQxgvo=pVs@sTUnMVp;2qc4w`gQgL?UTr zI2hacQh*Fy4nab9ZCyVGPO2QRsj2MD2!CPQM!;ZVxw#WcMU%o}8TtA?m&|OH>G=aL zj0C^%DcJ(-?d+Z*pd;u?;Bm*NwJ%&}CFwcF8{;0~pBLSmj~gd6e7AWb@ZNZo+YoXFl9gecU z%KEfF?d_&hwOYnG7c^(?0&sAMFZs_&SR&X^_Ls_&Vm2vYYCeoPO8G0pa~sw;u~;}B zA7V49ST3gKD+F{`v5wC7;}T#i6FQjGkGkLwnjA-OXBGXeXheu)h#Ob7UDO&(bnxUi zI!RORrX2amOXEuRa8K-f66+GCTHJX4R;E(y(F1M8r&nC!x+)-s1E}`V`-}->2&Q4M zS;2+IZ)Js@hqt*hK)TOFX{G~icP9y)G{ZD1>aKQ-k=9)Rwgg{l;#?@Lyd$R6rg1F_ z_2yoNaKK2g1krPa6m$}AUv`x8hd(*MYbQlCs)V^W(ZiBLpD)P0o|izJC7%^lR7WLU zBD0tjlVwm8@3cw^3}K#Brz)gB9Zc5Vq2@90`?59m%~?}(gxZb9d#WIYy-t4UFu^r0 zeGJA&%llK??{4XeRy=T4c%P<6qDB)bWp<%@ut$`Xlypm!`1qvYk{;^2Uzo9yuL@Yj1V*B{at^o%`FX5}adV6o?g!2E7G+%H5G`8Q-S z1Lu5DD0^0Q`k5szgxf3eb5F7GB~e9XbrANHJ9_~OoY7VY1+c5ORN$uyOVU5YNS%Db z8Cb?btM)Z|=BXDKJ-pf(PeVv;GRg#m4vWng|n438N2z&vqgH3t$r#$Nsy;MVKxBRwwa;NDBjKKvd$Po4WOF=V&ZFZ9!f z8%gLuG}7m8MR{0u>t8`y*0V(s-xLEje5~p2f#RE2T5cFgamh^{^`?_}aX|%6DM`D- z*JoRv-`~3w8vOY{?$BqvZ>1?FS$x_%7`oj-^Wnc2;NIQMq`zP?QCO{miuhqG0~6Is z(F(MB>czxahRpBt&pptuqYf8@%I#zWAd>vB4NTdN?o6RY&_VZi^m)XqUh*_cX|e*& zK#ukrG;OMRPlPr>xr${}p)1FmNO@?LW1d}MR>9}@{pxOu*@&R8{+0zf>sld9?pAjh zVh)Oos}mosU@uGVq4%2W;`-)HOmZ?W z+seh#ESM97RMktzr9-fOipX`J7{kP7B6g2`bPH$tX!`CwSnucv^%5}{kXtQz$<}O1 zl^2!z3HQy$A!(`*7cu7%)_Gq+1ap+wZ~k)SY09$W5gQJve_svvsQNt^zJZI+L8CNA z{zamzM$M|s!-Q$puhp06y9~kkZtB%EKaRI)X%&O`W>E-5=$=8h(?q;`3>1@GY+Sa1`l2P*=6} zvt`l(jC0nPEXlV8{`tai_%#fBbDmzhBSDRM2RV@wsqN$+$}rrMQBEnTp;`I9(?Rf<8d} z)kC=0`r*5f6iy5Y(8n)$nd78Spsl6(9{fNQXlWwNOQkBwfJ{kAKb;(Aq_jN=S|SVi zY7yM`Iq`=D$lqaXTH!)FQXb}AtBZ^Ik?pDB9tt5noDl*dCx^4u>q$7j=X`7gZUFMh znGLzkbSk{TkUeKY4Q_VNlKi5M@;F$6u)Ld$!yGks4G-4#lPNcw zoz!0Y_r0P|OtqbB>EFo{=J@{X1QWDhWj^cYaxe*U`$?v8#aOU!-yC?_cn@EEuVW|A z7AE%mq!IaC@7w;{c#oK~Yl=t5eAu4RQaYN1+lXPs)LEXgFc^1&ygl`;&Z?UyZkf)> zlLo64u^w*~fJ6It&%uq$?gOTiVF=|>fVfKk>#83t8O@aoaS)GB#hm zA^f#Zyjc$46DdI?Vij(Oqm8mnm+4jY;R>1dV0dN0k{VCZ=^DM_D$7BhC-C??s#I%bLrr|<3RjZf+=?H3Z_(7|y1 zltCTfNto$hyChra8hdzqnX=A2#=txJmMeS zD#@PJvV=a#Nqjb+oRXsli`M<3I-!;U{EKfxHyl)2#UGm1+&s+g5z<;Mnc=eJh$Tvg z=Y^-VGS?B&E7loqH_rE}gfpxiPt%vF|IFYwZdrtwu1*&Ez0BtJXBsHn8%={7Bd`S` zDyR$YmZ8_%nyMiALQmX*=bhg+Dv4cg^t2G&Gp5bF0!z@%lg}ze@AMO=5lto)km|r3 zB$xiY%4)nj&9BOqiOIhDWH~#sXctGl?L^CJ4Jb@rudh?<(=zw%noJOts#t3qR6LA`(SxGpcKn-;Fu1 zsf*9SJI0+R%Z@VXh)d%De`C!5@$@pVQ#QjB@HAI{ad7IC0+iZILFcY!NU1-nIgHyLqohoP)&|f<4b-$smQxA z)8pf+coG72q~plYe?R;p@!Ap;1)mz3wffDHYP)|U`eUIRShm~&5Xy#**HrCA*27NF z7>$95tX0UZGaHioy(Asm-Wts+sFTu&dFRiTCBxpDe zwk9VE(;;h92=a(Qxb)n!Y)%0&T3TN9^~yhiRD9|&2}w&v2q_oMU*7l?(Tmczv$CNy zaebB&wyLGPRNK?Q!@GX2<}5!^hB--tnRtSFij68;Swn>9+&cXoipqr=GF|wUa4l^>nP5G=mJh@t z{Ht=j_3>&~hO*7&18gvnvAyG<$6`|Z;BXDtPhrE2Yn5lXuh{=Q@R_v_J&E$$ zRX^>%Pi_Dj1^jeEx18Tj#ey!)S$D&~<>UM;E{HZvG^ftMsrkocL?>WVdGIiyxR8ek z3-_CMl-IYR@I^AC>lh^Ab!V}(FBid8_LTI4eDXtMf=ndV*O+9Vf4))dZxe=df~^#h zEl-?|tJ#nNQX{sDdsiRgUzMzh@N1r4RWFI^0}VWYJ%k||b2#%TQAXu2;9X1G5Kh1J z3l@0qKJ$!DN1zxM?m^^k{Vswp8TAals$&3nR@J&~wVrnG4c5Z`N6+y~a zLU8UZ9$@-TECZ&$Ojfl$%QB3nRB#$o@;Gx(rw7}R;Jj)?tYNm3w{-q3L*94$lHv+; z%mD^McR~LAm`KkRePY}_AuKOgXx_2m+VMYwn03!!;*gP~x5e~o42Ol{?(DAPpEZ0F z6gm1it?S`<@)Lzq4OPUcyAVqc-L zQ=0U|nZ?`F8~TCz!QQsq{ZmQE+H(QK@(9f_p=>Owfx^sU+=B!N&U->beg|#E+%Wb0 z=U&JfV5yqzuk0zPr#kvKBr#dlg%3v5bn|txK6SUg`DCFIm}+NVZQl+Wzooe56s!R7 zi$F56^h+HZ;ws7%PsX_e)NUTVH?r}ukva+hIz-vSO#A9e(Z%=(aNKha-u+}O!M{2zi8{{lRn zme?;zJNwJtgIzF>$A#RU$SDSW-|cSoJD}>I)I#EPVEQCS^)Xm2)L>I z(NR%#i*VAAhcCim=*A!LBn{gPWTgh62p#660blQ%#4uIWWA}!nWGXF<>TUAI!hU}$ zIbl2TX#1oZLDIU4tk~jAsMH~$Lq`=g6DrS;kw9Gm&k|7Ak!l5}T?};q4Krk%0w+nf zp-K?uAWp%=3}TWKi9n#1=d2om_0fb1D>rC~ki=3JVQp9N+M)_8Obxa+YITH|V^4Ss zyC7=|ug;D$7gCsQyl5GgVF1xPFz$bX&QT3MozY#mWHx+^HiR*NX{{?d7{a;?chEAq zRx9UPsvl1$b*MWV*xlYn zKVQSXeLZ&W+(FtAhgmHZJQNTzn2I2eN?liZCD^SQYcOhnv4?SG`k4t1c{%m}g#{IJ1kvl^}yMYOf9GToQF~=G} za~it7(YQiGKdmrckMj|x&PZWej@v9QW3KSL01!~>07epxAZMhU{pfIu3M;!7pdt6F zr)h!qVTMh>!| zBCkpgaz-#R3808gs+}Y!G&2VT?K3EKU?NZ^Wl0NklOixal=C*&5ANEtAth=Tn2v>t|+=IkW@>~L>%ul zEY|qH+Q!M$*8(7Ex}<>I(srGBC@0Z*ki|e1;=EHc!Iy1NLSnK11y2)*I;1=YrF9@@ zP@hq1#!zQi3=3?RjE%Jexc<5;@%S4L;nCM$g{zLNVV0#we|b;AKs_pTsGL#QRDU@? zLBfa1(3IGkG9Q1`bW@EL6w$C5JG3a&q1j}?3=*N##HO!VH)f!D%W4fY5sQ|yPaKdk zBq)w4rLkuYgzQWzq*>Y;ghs+{!hv2gG%j&z0b{pgre$x|XMjk&h;mB36U z#)0?Qs;;O^D7q4`!uGl>lHI6bK12y0B!0}Z0W+#@yO)1+_LH|Srd+Zu!6-F5#U!X@ zG{uO3^UrEtPXV_oND}Y1eE}fIFJ5zq8qScII-vK^gdCs?*2IxU&Vf~`yWk*~_RU5X z$DSl%*iOq(4{eh1PzL7?z#J)cNPPx2Hi5bY0&pT#EM{9cx^);|d&41If5TBc{$ZEl zL0cWx0StctwgK!wkRvmL^ClAAjhZc8S`wzj&j8~{Fy&Q{t-^OD^82=ADoPiOguLl7 zZNW>^%*+P1^_fj-V!Zm=3C5TTD?6dY9{P`!l*dF>yA_#F8(mw#ozFUPswOiKJ;zdx0O?`$i0TJ{X%0ouZ3ALL6w2nT{P%^NM4Q#C)#}&u-XF-zjJz6AgWJhZ}y_YreZ1wa$h03)X+2tplO(XnQVJI87F6>quNJ2>q25U=f^s z-)pn%S+o=!>Au{4C|E2O4-6lG?Q;eYa_+Gh762e8p7j05rUBq4LPL()q`t69XBKjw z8-LIpFU)~5I(jQk0;w%;`e0N=ZM7^l%|L%}MqnBOH2gx;AyY4>7Ii&9bJV`FZH_zVX-A@IO@6f%IZ7TX1FfE?G$#4e%ob7GxsLMH1Y*F@dJs~7omTTrz8l# zNmTMm83QEAXDB_s>3NUG^B;W#q<}QyK9dk4DBk6~Hw49!De zkm}`C`!Az41Qf!NLw*`z+jsxP_$9kVJ(h;9C3qDcV{hhETd6>#hgO7p(2!S@)~rm~ z{PH#pO(>W%*5*GXDU<0p&B1?6#^cA_qv1=G;-i~3*TI7y<+rXrB%l#4s8wlReV<%* zTx~iPqb35ED!C#xEDsKZpHjv!EcB4jupkH`WQQ_SSVOJ(xGpV;vn@z-4f8ex;0+O}s2#2nAhFy3p4c3fHfZ0aav z1Sk1LluP0Ru(&^gFbqQEg&DmbgJd0zD*=;j4r-D|OBBk0sce5_xY`iVFZ3b1riKVU zi)Io`2p&*BMN+39Ng6Mu4pb8;1C)EYP90L;p`WdRv4L6MLf7?vHuLNPV3!H#W^3U2 z9I4La;E0YvW#JO0VRaR*Vfp`_=MacF3F8t^DBAC$Dgd5F42P!^b!v~cx_R`xi*~Eo z?dK`UVLS(;*PMUs0BTjb8gKV0R5D^D)VyqL>Dk7H0boKDv0X~z>Xi(eQz3Rw`!^a> z%dKd?8Drt``x9`CancxSQjL@S>_1yHXG?x5XRv1cb*lDH_Xxb0a?uRH)D=75%$ERj z+s%|M`!94_HU~9Nx57|Q$aQnG8c&W84I*4IE6ztdPE3DH5Mlf@nv59!B0~&hea4)C zgi7N5CrUs{;MAi_YoLCHytauhcj(X#XFs1}&({nTN+>leA|^1YZea||B%rFh1{I27 zGB;8sY02JUiy#CK9Xrwo2BR{nK^17Z@5Th8dflYCXvZAB$4b!DZNM`ME9LbRZrCED ziB{rBPOX0`p5j4NhocftPTzJZyx;1yH5UNc)=V7R37rQNKW$7Jxv+H@5ed1$jsW+8 zk)M$nQrQ7LJaoJQ5D+0*7L6HLPC+dN!(xF;Q7)PR*b?7T3x<#ZXnuiYharTVX4~!? zww1Vr{g_ef-~h8FvOX`YwqKAAW99(JvQ0yON!Ne%4KW~+!c|eL!x2<|ul8s)mO}s% zl7q_Rp63=#ab}*auq0RA#FQi62O=V5kR`DkuO9-akvwU>K*+B?W;15aqg`_SpTRGz%;zkZbE-H z2Q9rr7?Y}v3a z7_xH$fkw{)!=~zZ_8;0GBm7a=Cu)C#;Riz+L2v@Q3lT6?pUw7HQ$W=H3}XnS5}#6* zY`@ea@=%gAyYpR?}9wUJ~LY<7$aPRn`_V zk*cu-^MlBi2Dz!+qW?;L(dLKdX;6Z0ya%^;ZM{H}3M(4OjW7^Q=&>pe8hd}l&DGzW zgVKR^-QY4({ry@~o+iCLv4b*RH2 z>P=vfvO5YZoZy`!hL5g-01$svG?xs`?)QLKSlHsl7Y%V^&W>!Btw_H3NWwH0g{T+` zD}gGIDxrWuRaP~Yp`z{%dbsI@7b0N3K11Eu02Uh<78MKLk)anON}*&Mhpia&;ZPFM zrWufx8C(=O89GLFc9{e=dPI}R4R%3w2H=aTya(|4a)r!8T1MR*-fw?!Z>u{onk%6j z#z?~Jot7;cn0nA4>|dMrVBWN*{6Et$Wmlsx9)|;uani@ZBPL)2YpK)CWMGQ#vf`K~ zxz$*Ib>ULVj+mCZ;?HscVj`Vw2?jLN`(n!_bpqO^pGL%~iZqGoz*(6BR}G6WWD77O z{#t!YFi!`CDO85J7E*t*&|R}dU79O0HiVMNqeuWc36&EpPR%U+q6#Zes@g{a)g;F_ zpzzIJPS(zvA>J zO?WeBwXBgbv)Fd|83tJ!U~~mw}&u6oB`O1K!af|rWrf{Gyp(4TJE7G+|U^^brR4G<_uVut3pQpfdAsK*zXxTHwf)=WpgV_CU|5F0xW_zWi z4!@j{QYTKpltH;im)0dWV7>u#(Wh`>g}NR{9gsVu+#`2A5@vEfoY(?NV->!SG^rhG z_-AlW49PQ8LD0AW6XC867;UuBAkegA%hFWm zqCrd@2hPCR^fPl3k}@1>b?Z1ymy?K&R$xRknr#`E!-yoYih~wt0!0)i>9kp(KGZN) z0#x%exU%{WOsZq)$a?!!Hod@-f~qbzZyK;g1B`YoCqVoGjIPt&gDM000gwokQo=9{ zqaA;MVkpCYvn(g`8Kl7FU_{Rn1{Cw3!HWC>+?G|?q)<>5b=fa7wVV*0H0eW@9GZ}V z$%#Noh@2?9DqSI}cV%Eu^P~VrvyY&=y zb_XP6YXL-Zwp~oEME?LF(tn`|46~UMGmF}TDvmb>tMgCO zB@O6_g$exs>!vR4lX2@p_F1pXD;16Jb0DIUEwuhTr%~eqp7jS}Kt?*P2bth=2SeqS|uBVQQb)XU&f+tI5=H0dIpXfRlzBI7Dox7au?d zQ>naCWJKZ?Cy6o&E2(SBvJ&S*nlz=CqUQoQ508-HE`fE{^w)h%tdLj9=@hV#5L$uU+ zSFgVbir!ZZ6A+wOwM$fb%uA^P#kemmgr0*cK}%>bP+wa{?MkwHJqQ4*+UzUsSIUwY zRG^cCTBpJ7uV4Gd!G#nMo~4Foq+ zWTF9s&PCK`+nq|mX+eLb(z?|+1HIq$`rTVq2a9 zKdB(EIE$08+z^5~k1!B|BM*+kh);r(i82Z+MK%m6pkbys8}ERp424{^HdjDQhXT#@ zGHbf}1CX+-D+gEJ%!6i-+~BZR9Dh5v_WBpOVr9mjHSWLB=S_b|gb*mIq!`g$kUJ0& zcn8vg&kVyzim}Hjd++hy6Pv4|OEM!1N&UR}l1-a!UVyW;0h|3;=h7Kfa!GZq6}UMY zOkQozraIQ01LvyUy@6qac(d(&5X5b9!x7>O!^Yz|kKb=>c_>S2;CML&F1I-3}04INg;Va$8L$RQ+V7tEP z+JE0?v=G-;rRE%dkmYRwHS z_eT59?Y28o8K_iupU9F9dqZE+PJy zI9QU<*NVeBz$;vx;V60Lal@$}EH4}ryWojo!^R&G!ZqemDfi`4}_Cw!^x+Lzzi)J&{!`eYmcNmixD$?_><2{5C7dE(IOW9n&4VNrS z(eV}yC+6z&N;wAAD{SHsM;8h!r*~aO^2mS2!}d0N&wG#!oZAjuz3U1qd2+}soJe4I z*N*wci;N_Wx4&R_LGaIAVyhGG_>>$xMLgr_vy`JfssVW^F!Cbl!VIU!cru&eMW!P~ zUpgYhJ=t9&RgZ$tJCeL;;8TovV#O9fG9Y;ozOGJk7W1y7^j#lrd!Px~MMJIvV(owL zYg`0vF2tr7yXDxH3rs55=c>>i1_)cUYz@CT4wQ0?M9+AXDdz@scf^<`7$&k8#BUg< ztHiLQWRKq~UI!QxG61Kikj)%Ymo0FonvCQI!Y;sHn|h0iv~UV5+Jx=%cclT)WMloV zubH&Xw$FVH8O%{@ZPdH~ExUHkw@-foZtafo0Gh3zQuP3=A^;V-Z?hqtEr%eSHQUb` z_KRU9tLddLbL+OL6|J}c~#kLP4y8=w$xtBR8ISD?2cXu%dAPOsk0$zW~Vy~sV zmEtVNoMgdMD4|e_$7RJyCOIHGq+~LMsF0H~c=+^}p5Wj8&1cyhDIrEwCNddU6g1m; z%MyiX3%_YuRdwz$z4gWpRMWFI|LV0!ADeFTV*z8OB!sO@h<-D zfBEM)?{Ihq5eBa?2xQ|(;4FXJuBwBSh+3G7kfM^ZB3t;(-+h_S{^kE_n2yv8RW6%} zP_d21{Xcs*?a2*q{T4vFT&rbCb^A&sqlv49b+9sFvGD+O!Pv^{K?7){AJ_c0E7U*E zbAP@*zMBUk9SKz}My)Mr$p+NeQ_$(UtpJ5hx@w~}oS`Lb==NAuJ!^kIi8Q3P`nbij zIX>Yx-+G?&TXXAggdXGH6L-{W_ec-_y%TLK@cs+-JYkw{uFsnwYy0hCwEKepDh{_Y zM9RS{D1=V?FAV+sbN#JLmmlTRpZ^}yFP^nsl>!M{fMrdwm1?WESM9Uq|8D2rc$pkZ z<$f+%VjO4~K;HxDTz!9O+>8O-hLlD=_GcgBBk#UK!IH7GF$?RTt7pkr*i^=nvQ7zh z3M;!)_#d8n67hjTt;NuhewG~{n}eOE-nR0Ux^FhjA{_f|mxeEt`qzqtP<;0Sh;x*> z$eTcDk+AFRzuGkFO1Qh-cH3tVSxOn9+9`@X|Nknjag$yh2YK(#B?~DpZQ8Po>sgPs!3MN6o|pIh%)|ZD?L?@(im-Tkvb4@GsH)>M^pU z7;D$z&%9n=mp}9Qjb4WvJSgzc<-kWi@NRaxMg2&^*$$blB5_v8YR^?|fi@SNbz3D= zbpau(F*-YDZdrfW)fKxgv#yPtRoOk-#Ba^UtZoDun2Y1SH$BMjfAAqv9k+ImXZvP= z4%BwWMuC!H6!_v-p5)u#`5uZVrA)4cX;i86kL7i@>sRx!u*}b**WY{HjQaO!=Ptc`7d>BO6RR6j;T9;YBzDhex_Hrk*871IhUS}1A_Y*D9_>J|zs&NDa|9c-NKByBfY z@BaVNO;{FfYx*+BzSh?ErBr{XIZQtOdvE8n|L{XL`%@;}L3FrTael6ZB&j}gp%Idd zoosOwO-+BcMZAJwpsLT*&sq$B)0rzR7mR-(9#0hN$$kl^%fj4aLkb@c793 zf#i(lDu$jkZD1(`VprJ`={91WUlrGpJD`8|uiNdPt*Y&`IA$juy-X=}HN~}oS0gf% zQu>Xy9ltaczAUQJTBTnfd!0(g`j|7{t;H7`i>l!ZsT5MqmYa`7ZG1f}{(s3PEDL7@ zjy?Rzzj}}ujwl+;W#~Kwht^8SE%|3t|Bcr!bt2c-x;76MGof0)RZCnlFE{gG{kngs zn%Pm!53TmUN4xrrQBeCvAFV7S95gv-um@g^F@t#g*M;6EZMWP0TB<{3vac}3_+Iud1*k)>b-welm^|Y)F+71T~!Jzc$-We@~V>Bo|l@>cP@KF z001BWNkltEDp$hFwYYbN#lzp*tTkT5OagYUe^!wlBTQQbo%d7Bm ztp%^i^15I#0HqYfFCo08&UsUO93cea90@}}F_T$Ujk>NaiH4vYWaPdd+|}S*XFtYvq5Pk~{dY&VOZ7$6-sv{KEaljw z25q&4FB}H&)Pd+R22?lTiu$YK>Zv`*VCmS0fE*o>PEYu)cfN)9z3qQ81#`u|nhD%I zAON5E^!M3ady#OiCRNk5XQk>cx{8~q_hA&3hUnYTJ?gSa3x$Qvw6fc4E&xj;no$j= z?d046zvdxp>!_$j2zu9owo2y(_}7IO0Lu#~Z9=SAOv0fzpb3k$3M=2vVFy*gpa<4e zJKZ81+8fOb==Rq_-RytB41$z8xXuV2y*_|5p^`HswTTc}J8=HL-FSDpY1<*mV4&R2ZMD&e|e z#Dyb#IKpj@`NKc@El!37^}p3Uuz`RIEBx$5<;TzW}2WLKC&(Zo((~K@iQz|b&w1&mn9ztob^wQxf4OpqbA%$GSF(oCO ziwH9@CZbw}9#?}YT#B|?%Ic|s{AW+Zmk8_#%O||l`Ak|TzMY2>Rk{L4lj;f6z;$03M(Ie z?>%G;`F}O4f5bE$0Y3To5BdHNe#AxDGndIKS*M6pO|*aeJgFN}O>x)UbA30u(ciUd zTHiM^m2o3W*8&!5Z%6mxIrA<`~UF6o;=>Z(D_v zb$+uZ{TwULP+R<3dIw3Nqq2Q@bjb`Ibyg6`Xz{2kP>Xw1>(lhNI1`6}%$XrZv_$4) z#1N?lqKbb_n6|^ThdcAQQ>|?@dG-8e!@It&hH}5w$i!aTK;Vzw_Xa-o_z$5>_~8`E z6V7MI$^7)rfm+7lCA~VB`d$qvReEs}U4&Fi#^M^PE_N<3ms=@j^LJ{njEtKTw&%}N zhV%US@Baq(U63xcZdCv@)jtDQ_sYNf^glyNh|GT$JSEfso3@bK1s56#Kx>t%>otJd zk4<}}WdvIJu$nrdi(pxwqb=|dLKg-hgag8yRR6!C47KKFc|Gs|%+3$A%&PNjR#s8P z`z13_^K~|VrgT;Dz=Xek$8C$g_nREr^-AsR)!<3#6Kfqay)0xqR>VSJV}Uu*g?RSH z3M+r~D{!#=Jxi*&?f%0iXPcl+2%J?O&$hKtYS+~MzFI-hDjQu>c-I>?y!&l$DawF_fuX}Z*+2`eVnwKyAhOLc8TLtj;Y?P|Zp_*+z; zge~Lt9ASHbdoJD2$3FDNLxFXR_t%(@0r-E%Cw|WNfBZDZqsK+X*ZI`3Av682@BBK? z+AiM$fZFp#6If<-o4TUSA5uMK70m+3d2JRiRe@WfP|IK8x)-gf{<$UFz0GzB3W&QEwoT>&e(6)o-_v|i}tUV0)fFxA)%)_zJY6(~zdJF$us@gPw&`_Jw^WA?H z)MZK$G!-O7vO4A%+0V9kW(Tu3PJowc>ej#29Ze9UntNv;)NADoD5hoXfmjTK$O+<8VHh#MulV_ZIB8!}uvM*KxKY#2A5c>V}+8#W&P?fc;)_q;aGK?Z&@ z!GHBBC_7M5=A@hx$I+n7E>nM!BV@(7LUNFkFjV(c^bVN=<2)0Om7R>-8wURCkHf{9 zYxP#^6*d77#1_g2A34wc_g?0ipFB_T1Bw+cDL9&mY*D*4db8?Tt>~y!EpHiN*MCXZ zCP7i8GXENP!pn6wo$?OuQ-iHPD67w}F^?P9~g z$gpw5^CzH}h}VR7K60K%A3jGersdo!MY|#Yv6!p(Q=k0~sykzWA`GPv-ApRrQ*|=0 z>Jv!2$4uurlxBb8sJ5whcrD#jSl(JN5c^N6#(IzofyHCi1Lf+6-5dx3REa6kh)K8G zZr=ouRdG-jjlh5t!v&i9(wTrM8Q@V9c`o<5(h4iu57hS?{kPSFGvQh%o0_;d`}@)W z!Vb#RiK>c_OjAgKjn6pQ;l&Y(FqBiAQwFDOrkTJCY?yx;isN{`it`i4;m9z>RY%^6 zMb=dRjH&!rPT%2yN5{QVYbHPtTPz=a?-l<2KVISam-hHEBXJLI!Y9y>XlcVmwB{3R zp{!IPTo-@(!D2AfqVrc=#RNQv3j{ad-H6+cY{&E9PRK6sryqV77mw^zuXgv3_2+-^ z%f#c~{3++gE&Kf`_=0-rA-}y4QUf51&94^NuuRdjTB&x8p$WGBx&jI-eYal+N>uIL z`9_Ie#E1f=a%cczobZ0A0%BD{yw@Up?d^_K2C{!;&=GFv2L;DkuBIHxJx<6&Vdx1R7#M8)W zevyCK&6MmQDTzo5D;PSdiui1KtGD>D_$bO~Q;}8MnG)HUY3# zc<`>kdw=5%JobfW31I|3prvNnsZo5Yu4-S<%4t=L0NX{y#^8Xlw$cb{U{G#wrZ_9N z=0-$Dvh&<^-`#xpy>B38IP%vAOubx7RP}$~QY`U_FFegJUw9txB4wH&%{5ZA(Zmf= zHx0gK?xjWNl|_pzMlpBLu>w6104(@G!vs`os_@E%L1|&fr5H87ZHjT4@PpZKZNm&< ztfomj|Ds9XZo6X`KwH$)RK2YVE8?trZi@*p^w)JPpx;mjMk)rdsuql{qt4F;npA&~ z(6v+51e0yjDVY8SDmB4F)lASCa)456tZ7rdA{rA;C$dvgu@qXWGnA1sdR)3dP9t%? zn_MibY)fi%vxS!HU8L%HxcYqI=(%683%_7D&1_#%3M*Hc-JX&HIV)Zwvj@rE6i27z zn(4NnXd2Kt5?tZh)ff4zZv=kpfy;ju;}90g?9E#DD2Un2AARrr{N+D=gOme9c4Sqn zU|bx{E0&8nT?C~##R@BM&{=F+1BQSl>rVv&)O2b@s$aVZk{mumbnw#7@v+~1kOwZ= zIfA@8Ei0;NSwDYK`NS8VMA9{;bd~*nhwNv3o=HSX0?ipmHi1>JgeW%hbt8YW%)VM( zgJlK$^^D5xb^Y6oTGh&Obsgifl+0?S!B-%ltHpMynsRdqw$|cq+WNZPb_enSR7qA{ z8AA08l*Bwu2W%x1lnd~Y%FX!jmoerbK@dIefxRVrtoyZY?4wkm(iZXN$`&V_`h zBukR9bINdZi9i3y!@#omZ)L(Zx9U{upnT@*zu=i)yud~?CGE&5R?pSh`KR><7M-$H ztnNu`+8~}WS=)kFYG-Q;AUZs@HK}eK&82I{of#_vHI4>2vso?-+j7(ObMtoF0-%&) zDVbVMfO?TlBQT1ir-gqAJLf8Mu)66=?gF7LbU0k-FTc2MBo1_CBJ_TPYX6(8s7W2g zP;4m$N2;JzK}tfLk%A>>e5ngx6&DMEh!19hWINq0k$0+?qErC@aJ(tFtq=%oa>hAJ z$t5Y{$^<%5azy3`WkSnLNfFWvd5@Oavc#kbDLcd!u0FTpliz1#z>s_67uj z^Beg1dmh1Uwz#7$Za7C6k7^0C5$8ulEIDdl?BbAGQr(RE`f#ouYoCc&T6W9NI9R#$ zFd$p2x|Gu~zw@34c;}l2v{YUOH`f5P-fJud?EiWPpZdyEY-BQ3rC4e-C#mX_(j$=( z!Sys?tw&(t`E!5$-y00Na-)r^T^);?G^Y+J#JCjKY1(po9%Ed*V)gwyq5i`i;sJp9 zE?MpF<2Y8+yAY?Tsw>Jo&sE|XBP_BGg6R znQ8TTsnKVs*?ppofMK!NNgO4b3o0wjDwZ5WXUilTJvx8SsN1pM??}1WuE(;tZ#FE8 zkTiGNe0q&}ca5p+Nc$bch~{ZgO-rGW$r&?OQ1io!Af^490h+3y(IdX_*cYGS-@NA$ zuAG<<2>#Xpv`%z#u*>k#ciqE(f7eA`c=~yQ1hVBLCnFZFTkl_*wkA@w4XLJAiyCYt z+ZK0WOV@v%)xwSuM{$9~2(slbe&VFe{^%{CA`&g^$PD>LU>C~(Uh zY$?E+Sl$SI;JSg=N( zk(4PhnhGmffw)`hr}Yyt0Wi&pVcJt<&zvJVCCGbXh?LlP0Ez7AARxY2WuzFOL<1Fz z5|V!)LE!|R{L!!Y%(ouo-+XApoXyLY@llGENasFHCdp^|^mQpsuLUUE%}nTwr^(&JZ}4Zl?TS?I!a z^OB}T)PRYc6ERNAyHnzR-_`e=62W_tHja!(M3+p#El&VcT%ckGHO&5Y+nosquH*)& z2@IRt10ls|QC;Ge80T6>JmtPu08mP1+D$~+TkSLF2rew#@#-BAXSQdHOJB4D>f(QD z61Zt3%?(r43M*}xz4lBoDlInKY*X(9FD49fD)?gg_?>|F!VqeKh8xJFn|B&^AHeZA z;KvOr19M80Ia5lcFjI0cl~r2tNrz$U7=1rH;n*FM42hc!kz>33MQQZBhdVn8EF|J7P$f+qY&fsm}#tFiEWq(Ce91Qcz0C)bYc! zbnre#V{7epr%cmixzN|>ac$QVh*)&&s+O*4o88^0i=aYVjy4PdRz;k>wp82Mc3p9} zVv}1}V9{&sG*K9b1RKE-7z%$Yh>ND?cfNh2eJY}cQkV9cNG6kGLFO6N9f^#a3M=RR zp6@>WOP+YzVld_!@_Z|M#+nnL8Qyun=l$<{GbvnR9L^E88)V$z+y?IkBzW-EuCEbn zR=LL*`(`Gz1fM2g3s&jJhkyC1lhU zvI8xG=G-v=O_&WUVz(J5ru`{?Kj8G&>{NN|pN{#h2Ok83GrE6U@RcNg0|UKStN{)_ z`rf}!05kW@&O3E0+#DwZv%G}q{w5?tMYVD>()X7#o3-=fNX4o(0=ZU}j{I`*`C#F+$I>klXNODe=@uwv4)t^~1Xhqi5@S&dQ zqic@!Z@Z(FcdCEnOfHrctJJubby3_7ZtLP1P_*;@nOc)3>`4!ohk+sM{pjVeQ|TR9v=HZ+d2b-xJWm#Pu+Aj3%DdKb0cy+9 z*8REKLyi~!uHgcznXHA93M=G{O18ZsgDa7wGxJ=?`)Pkcaogi2ebog;J-#T+`vRvE zxttO;QX;sVQAu_kIiopJG@5{|uX9P1thk&(BdQ5a1>!`Cr^I>BkY>L4tsnEl=j}S1 zZG0?!&0RFf}>j}ksv}RJ&y1N^oC#aLU^H-9ObEvLgTS+g6 zqYT3AjyQkbUgFO`^sxE;on6Dt1eQ|${@Db80Dt|tpY!Z9&*93BoF~hB<}Df9(NK)hbBJ z!6Fyu$SL>tUKb!>lXNZlCV+FkrweZaVtq3rQe%Ib*TFs3r1I)|xbT@(<*GM9i;{Ar zNV1g9J|KP|)a){ycP-5a-fXGn;aRe|R^K4t7Mre$X)n$^6nF+7m|S6sg+U@x(rdQ@ zDs++NOvtkZGHD@r&nS)(gsjdAD|c$Ho6!O|p;iJUIKc(T&JnW5Ng?M5X~Kt@7f*%H zeD8ln-uj^{CIG^c7W|bKRnq`M)dDUa!5_T;LB95j=NPBNpr;fPk%&v#co89^C0GSx zff4}q1TEkT$q7gxP|#5*euLKye(?Cs3Avo({qKB)-+c24T3`sb7WtQ`8J)5T)n8pz zKKZ2|aWZ234Oi+|QcI<~o&&(NmWB&85q*Ein&?~pY z+|oX3f18liqQn%5)1Li)$9~!q=b4maFSe-7?$h>I@Bw2XE*XQ#1=Z9Uf=&xKB_n@G zRGh|Yi?4Qnz0vSqf8}d!lA?(0h)&5-k(3e1MsLoTo04R}YAT3E3M&-_&IRgjCY8A+ zm}a0cqH#}2r%0ap)YqQj+0z9XzZET@n*lZ4IA{3%cizkWm+wY41F}6v{E=Y*&I&7c zAT?!}ceQ-CWwfQG6O&*Z02dH9ShauRA&`eHa7+kW{_G)q`x>ZG+9F+;o-PYP)?mV72{Ab?u2*EP(gE+cbZMU~5M? zhhf0`Q0obW?RcHC@q`2m8U!{MX7St(Zk7Qx=h3`D|Q$F|I2l-DPJNh(=;(pGbw*XN=}rD@>(2wq2(476r7Q743LlLkjVtbTwPzc)108{@ulD- zF5#smp%Uwklq(>WyIpGPYO_@{MI)tTO3ILCvhMBPrWqHnQS>GL=F7k2rMargYK!J( z9s!{OfgT2L>iD0%_kM=WU4*hhMn~R^h}#gHvHG&Nd_5u#4Gw>mp+@`(Is|YdUIK3L z=(vG!!Wg#1?S?=8;G4PUd`rF-GRzLjuZ{;Z^buUt!Lhv0?tYIbvAl%OKBunl^~Jo*B4jQ zQ0qa@N$>1-)9{apegXaS8edEZx9=^o)zA=J7VQ>P2lJjWe=RKl|ld8T3 zk5kja2Je88Q6O&vGM-~77Z{E__uh9mfAPM1DZuD&jr*Ue0#e> z5uG!_k7j>zio|LQNtwyT7P}Sds5^Y^WBaq@>Tys(q+Mz7$EsQp|tN<`u}~;DLe*HD*0Q*=O9aXVPQC z2)G^txY3T)RsS_+Pzozr_N0<2F{3F#nMoDxCpYY3#RI3h-2_l8eQo|{qqQbLX9d}j zJj|28wQHP~XZghAPxIafAEJ~+0EC;U*&eg2gR>yC69<3(zAJp~i7f+LAfkRIl}6&O zA;5oXe0M4p*oMS-A<5O8|84{ycu5C7`p_GB>*dP(4>w2u`|h7@_g8@cwm?b0Z~gEZ zpa0T#3Db_adx^Ziij*BGPn5}sK)Ez5pf30}D9w`Z3;qxc?u!26!&{AZIdgSqChyBl z2mpi>XL7N`xs55i4xOi+LTU!?il4n)#KEg+cZ3IjV6pv+x?+Dh05E*bd2W&}qam2j zweDg~qiV#QJ{Sj`clMT7y{l)BsDo7fsaC74V38|}CEh^6MisW**IwrY#m$f%S)gbn zdWVLW*zO&1Ka=Y%ylQjI;0NaY4%tuSQprx)D5`~2Q)X3@L>G-_i85Qg#yke9kezun zBnxSO4`nwX?u5^N@k#!(KX?NV-8~o(SRmhIp*0-9JHrlk34ZrCF7Q9zb&;ok^&+?d zl@TX1EQdG`YhE#;S6)c+ebrTY96>?52` zCddExzkh;XKJzoec#VAR6u-ZQV@Jk>t7~q5K&=`4cj5p5AOJ~3K~!VB8hbrh@T=#2 z!7t>XMHJh>cixJulF+X9sWlVg`iR!jwcO?cYzH*&S-)>p+&EgH5FZZhir3g~TZdSq z={YZc%(fs}6jMuU)YN~#(uZBw&fL_243I@Bm(>9)Dcv{ygA%n%moEU$>J(yUc9`ma zinG@q#d!ti@#+Yo$Ogm>jOq>8iV!2jxjyoZ_k*q>tTqn?92-Uy7Zg0WA_OgnTd~n{ zW{E}DY8u$tf1-S2m@F(wk z6L~m-qjQKqA@~v53=l?~Z17EOkO3io*d`GI; zp~<|plBjB`{*+*v?XjOskUjPD#AhD=0T;$-q%8%niWe*TK`lYnyvuDaNKIdEIStBc zKCR|WpM%S5*XLRL@9bu^np_R3T`Q(_*AU!w*?pVY*DG$ZY^=H3{>Gz;+-|#nZ2=(l zVoIHami?FRYAdUSFE#ENj3@2<%ly1>W|80EN9z+4(hIeBF$3B$dgg0-@aPrm>u)*{ zdpN;+hsP7V;0A{e8@6mY*}!;VgRA%2f9VF37VLE_mI0_gW++h^M#nG&g0}(~KA7b9 z^*W>qE2S1w=c=jI(tR~>s)yZwi0w#5BQ|i5IOEbOLx}ue-+G$oPp$UeS^(Tg6t_NG zYXL(Ip7^6j@8$0M?qj%cneFi(fO)P)v4v6RDhN`w{hf#Z@U@?D?R4T~3~anG1|fKVTXjwqXO%gO zehjs^vGj3of4cx^gu&NRle==2S=}Ut!6s3 z=k@5WA+)WfescxX;EE-Gvsewjk;TkKR3wo~KvP0|WUfSzvv|cTHC@fEqL5Q&I(?Bi z?TBelns&%Mlk-f{Xc|(oge8sGq=;QB_PS-TQE^BO9MYOu*Km$Zx$2Pc0%6R2^Qj;6 zx$pgo|M)$36B9&P$Ue&=I2aAv@#<(fHP-CI_XOVc;AQ^)OD}SNqJm~e%t}gyk`khs zxhSs8W^*ef9OQ^-K$Byh;GXj%AAI|HQZ(0JqyE3Y6VPannOx4^ zz@naC*Hr2HTg3*hBVhF4qE%?-T19Jv(j<4&9Ha$el=`+kZ@Z2O0Y&p{F2kg_DK5z7 zYwNTcYfu=bnIbc(WI`@BX(d_usFXpH-A}3a;c9Gs5i(6`m z^mm`;dp~-AnsafY#FvO=M~R6LBdQT4qqzlF)qHYnHNz~h*nO4^;Pe)b$_*fZFA@BW+dyUi*|5!9*LfL-A^d} zb+x2waMBV7KsDh+7GS;Q(bV?7QWNRkqU!m73M=jQLBOgiJLjv4U2Xh|3#?6mmN2B* zLu;#d*0+1x1=l;nfe&8TvO4-{*T3M|8G3?0^j}aPdVpiL@Xh# zFW@bn8tQnuwkj3YrMwOzPusi_U9f?F)!d)~-U=%%FlcT1A8bZ1JGJZjaLcams&;IG zs=7*3M4a?Bqg6oU+}MjR{~NES-L?Q|`O8|}@?QL7wa81UnSoYG4waSK11xv5Lcdpb z)1sDDJFMGodU&iZpQ|=gU^%Rxv8(*rBfa`}w4f#T2tw7CI=Tj7)Cwyyw_yN(bQ5OU z?U<%LaZ2PENgA!nQZ6+$)S|L#S)$eK(o4U#cHO0N87yEWk#Zu(nH+b_amRdm4Vka< zAHMi)e)OE7$gOb3%OyB%z}GrBXfTQdAAReVqvI`m8At?j3lr9+Srp^xXCXx)6=Bc7 zJ_Y{x?Uy+oS9}D=N_Z{5-%PQ8mP|EO4@Ok@tIvFcUqAaS)3skS?Or0z6J<8qZ!VUN zT2rp$nOAeBbnn#xIMeW=Zu6h{>|hSA`s!f5E^~4nGThHeQ}9ecY1NF)J6V|LdC3jf zyZ}&x?kWbr8G-W}+ieQ~w<0cB39ywv6S~bGYwmNPn*$>L24}p*o4V)pSt(X2I~snR*V`;$|?{FQIB z8Eb&fG^2SkYP6a}lTux#Efl;9OalRpMAclWtuL4UUFOEBBiai&?4$)ayp^^@{Wa#S z#ZXutz;#?eSqYFk-EQBHP{FxY8!)A0sj_6LaN4S!`VgwNP$Qdvq)}K{b*41Ic(}+{ zHq_zox6juGa+R_o2VZN?7kV#UOKG^o@(Z%g5WS!c-s;#%UMjr4wth2pZy1i*gpm*i zTnKpQ4SVpW7P@+EbXQWlpVd8fz)TPCN1DB9*XmU9uHb!P93B7gPv7T-YsD6SUR-Rd z*SiJVZ+KY(go40-#=)Qd<_Raqmk7rf8ILb9ZqBnEH-w`tZagMzwuH?w;rN8j(G~pm zB7gd>`?>$bEi6NM`Q5)Q{tf_E{Oc2s|AgIc$0$l5;auZISX{8E<#}wwXj7xD=0oh{ z>_%Z0gZ3{T%(@$`!!y_2zgKOEHJ~W~&Nu*P(fpKcqm(*-wmr#CABQ`j_pjRR3xLYB zJInoV$Z6vGk8N)yr0^WxuSG?54Sg;*y4T&_tfaO3CS?@xMg}hRA`xzzT zfKlQ67Jl-7s~7mvlP}0lzqa- zJw^A-F_Nc9$rCwS*tvOY@@l8IUA}Kb>z%(zoRv9$NzMfHhtW;EAQQ*Us{nWiWu zr@s3GCEH*jD>!J%;0 z#jHAW%;EYI7S~EcO`AGV&!o%wq^tk-V}*qpETxcDDH%#hIEmntIE|2Yq%e?jZuEp# z*SdOts}{9aTEfVh8Mau>f>z7~DXTuv)+4LktlclB<`zM*Qs_7{3M-I|Xhfzx45tvT zl2hifFFnb>de;>;vJh)Rv4v=M=W^Mu&hbVHD+(($ZtC(8eE5;`eEDa>u?j0*0tHXf zL@a`+!>N$ebGnD$e&m?9-D6X4@YlQj)?-?KSP_5J1Xb|x>975aA3yz5w)?A0`6bGJ z5Ay`6rc=w=fYQpElvWgm3M-;ETt&5-No~HAAJJd+pWv<8)R__iqf`j8;W4kj{;8I9E$%i{gZPWm&sj`=Pas$=Hb6{tG zqWeo;&IGvb>FS{CcH*iouMN0^g{rGjtODUcxU5V7aiB&GCIAxfxbDh%%}oSkgD)UX zQD+2XS5Y^uyZdq-FLS?I>V#S*U+WvGJO^m0u8kN|Qs!6_|NPXCdE)1%AS*C%Wd@wp z0t``KA_PMXt@x97p5yYp=Skbkcz1z+?XW@5ji^5%xFh_yp`1IykN5E>zj@iJ{H{!i zgWX>af4^%0meZ5xcFJR4d6H0)RZ(JZ;8<>zo=VLCZ3SSOz-;fKR?chj2H3ctrHNlZ zrOu4@jSiCa+h@k>zyz=v+Oh$)_0ljiIkU5fSQR0y8{B%6y`6UZCIE*FCTk{t$y(rp zfg5yhz&cUr^+@LRH)Y8^SFXeLZqav*3M-yl^)5J+x(Rb+t5;bKWSy z!Q+R(5CX$6upPH}?`}&1h(H)UZrtF!MS@9Xe2KVz4bmR<+Qc;*e|4fZ@hZczsq2O# zxaw-ERA((XBHm^8(~eJm<7X&;OHz%r5(2LT20E!=V1YMZ@qFYR_rcK>HYb-DjxMl0 zzR336B{s*G*q*zHKe>yyK6IH6zBQQZ&#zQ}w;HM@gIB75Dz(^0fXAPFmLL4=7i?TH z_aTCp8iI^=&VNh$Wh2}&NUi@i7vG_aSo)K*0%5fv&vwfCyQ{Yk@TWe1N0$S<9}EXu zrTlg^lXj~C09Ct&T4%!%V|;xGfF+TE;Q&T!l>WM@{iaS@PJnfikn3AnDY+|kt3SKZ zccj04L&?4R{&iMHcLTK?Yt`rO6cxd#!=s2-)OiL1o6!+YER^+DaKM+nCWVv}v1D?t z!Biy@i&|A6ExlfSJCm7zEV8->U9uTB4@SicnpV{oeq)+xjFhxvnop7aDWCk}_xZ{5 zsSAOdxda;+*lhPuxdDIt@OeCrQ&CPCC~3oRbi#Q4BAat}A;V=p`VP-s$97F;7yq(- z*rQ<)Yxdth!vFc%uXFnRFPW$3nR7z2;?>frt=)DF50R<~ly!!G-=((}g{funV9BZH(J=SkYSUaT@KTE90w{%?Qm?LcyY05mFi-oA zIL8=!Ka>^er{xP=vjW>quDf#KRNKHU?l)b1MvoNhk6YY^+qoCl&Vm7)%@qjk8mx3w zscbE+yx5|d?h(9yMJ+&9kG7`gDU+sXf*@Hcv!Y9-WW%Ty%YV6N4*N$NaHst~I**}O zTh8PhNogWZd*c2YasMJuKm81U|K(rcL(LYX3o+=1%s>voz+i!qy#JoSz2`=*rVWvS z$pw--g5j9#k2pHo@Oy7Dd$^eo&Hits$~NWO;_tS90T?JNkmo>=SUzL*t<^Ox0JvpemH zK48Jl>IP(ey{sD%VV>ueM?mff9rzA-0hWxv!!Rs-{}mXRRyWxLgWBNS=#S}- zqreal8BFp!0r6dZw{5bS0sX?QceOlWWaU;fs&cA%Pn!f^_rP$U->!pj-C!P~5oQ~j zdkw@A+g6F-1;k+)fn?c{U$LDv4hsyZ*#25-IWr#QeT3vY72Ofu_j(R2`NQ{I?6m}QvG^nL zH58%smr#YtvWSB>5b;kRflq(?97A~{@j}LLt}p_6Uih;IJx5_76I}=X)z*YgTlBF` zo$o(0@x^cai1Qmq+*x3cYutG)h?EK|oQeqnS5H=jLo=2RcK!wmE3VRk*^bM>pxPdP zq08K>8_9b8Uq1&{^R~aWzS*|nNcZ`-`Pqa*7={j{TSDD{J3|z@op#$AfH+g>N-nj~ zN6i9M3M(ls2@ABUr;RS`LzO*x_A&}9eHQELkoI3U4-V;-YxQdx+eIC|?s;c?)!%C6 z#7jeETTu=pIOUwlDU(tpRW86B4^^;#8$ucfowba=0-Hf_5}C7-lLe9Z;PAsh2t%z_ zWbR09I=OW^EpPEsd57KuYkVL#^Cf3ev8p&FCQ6=(X(H|?@^s2{?Rg&i!uOftYRA=A z1_L`5;FmlB@3;aVc*LXU?_#sLn@I!D?;Yp8@H=;z=n5+@2mZAgpi9tCPx$G7;IAM5 zA?H_O8?dVFt=)F1vZ*@#eX_AnD+k54&yR0SE1tv z1k=@+l%`>$#n=j%WKtW$s?<}+Wv?`mK}*9-fX{!$wyQ|rMTnjL>%wTOFl$E_k-5qs3_-Ye~7U^hQAfcuQlHv@Us^ZkA3btjCoIrJLCGNh_*a`Id_4rt6C6i>aX_V9}CHAnHvq1 zK5Gu#K>D?gm+Kew^#`4OOAnssVikd#r);ee*gBaPAic$Uv}0e%OyT8RYxQgO1B=SM3_wH9 zMFfxFo#H%*_ju#P9c~zKGFXXd=MW!oQiG^!femvF z+Kowd@gXgS(N+7B`W`*=4b-SJp{uV(4bC_UD?uRcuJL!@_%W(~D|g__xCEOfBP$^= z)ZoYu-UAQb1O5stjF;iwE5gSfvES~lKX<+A4-4?vcmHBhf1mv7(>(L@=QwhTBO>JL z&a4@eT;(XNgnEzU>#u<`pI;}w52n+Zh1TcOY8J|BR<=3U$N20rJ@dNm1WkD7np2}a zZ-8X;oLNGU1wem)U6=r+6mm2P6~^Hp5J=T(`5llNRPnX8xwii9{DD^~(N>*(=wm(X z^s|!E4$;+XH51_Ae1NPLjmH4EQseU}>}zeqz6+oEd+>WK!l;pHHUaLtJi_(}?~e&C zAT|B2G~c~90or~4b=#CyyksS$q&nvpFtbh0`nn1$4p#(!D>@1*qK-im!R^^>9sl^< zU+~kb=HZAdA#fv?V7m{uG6RBxdynA#4}c$Gdmet{t? z6(y0JlwGNRauUU^q$)pBQ8`ML6(>sRhbxuIcDXYANJWF?h&C;ep#g~$2Z01Y%wwa0 zp3sf%e#5=zoV{0mthM%D``r5)4ZM~M2e|$2J;OeGSo5@>#Vo9Vki_km5&}u3B&qhr zQs&*((Cjn1A|=R+S<9$Z_%RWyJU8|2wh8`qRk{6tSz$~5*#ym%0crGXN>U6~#eb^~ zWIDc&uaUwa^zMoTv_O^2b(2GKItw$Gpam-cl34%xSgn@W+uOm;&Q)Bxa&4{Yx6&H}pgI1) zkvVXG$1%cwpCpYoGln5y=tm4`lmx5n#|IVVTl>dmz_h38*vjrroB>GX;XI7Us};s! z7sI&3*>i8=k*6<#V$Bjf$R%h9RO$sP5tw(tzj6z(+yyRO0)F@uaB?o!X2$(DNC3>P z=AQ-r%z&>wdlApP^eSTRvFvv-u9nEdO7`b}OG(0|bA_$q_Oq1nJhAzB)lX-rRPJpI zgkH5W_&|k`4eMNPZK1JVZ_ZX2&nbz)Py0BH0jT{#NfW;rH34sm1Q3F7BkSlm3`G*4 z=&6@{x55UkMHIE7m;7p9L~CC*9!1O})J3D(-g;=Tt$;1M>4$Q1{VrbvL0 znF48D6m>#qadY}h3?QkUgGcZ{?Bfp}JBO=FXADf6U4kVhz^MUq?c&Ey0H13rUFcv!X}kq?KptS+o`t_V#_O}Pfgix{hm_IneiKifJlnzs!Dw`(t~fx?!Xf1 zC*{6lh=mDBFa}^&%joi+E!)ktq;nS_#pl%B#R9rUr>BeJbuGJI?-IZN#wW;s(;qGi zM-Gt!S#eF0U4jE4b^_ts6tTNnp&x-oR|S@`zEj4G3Br(YyAQwj2u_|nj%(>EW+{WW zGUj1{A!cw2D~RJDc?S{TXv9GG1`I*mfVNj4SB0ml0UA*j>U9+ZK#(+H=7c~aLLRWi zBVK&%O+5PY5}*0dqU<7MEop>+ zCA$gX3~;LJu*R&k@Fujo4dFI-IZ#9DNkhiUhd$_kDbLTw)ER#Xd|17p7!{qArY+4mQA7`8(n0RXW|w;%URT&4-gd_12t!Q&as%1W~p2PmP4A zod0In01hnyNRW>}m}UQ24FF&0z*8`xX!;z><_xB~aga=|>XU7e_WD8(>;GIzey^Ki z6zMa=l08@fB3nO2{&%`x29S_BiUDdiBF=zIS9kE{-U=(XEEY9$4XrdV(ax*5tVnWv z8~CC7PvGk>5;{bG*;YG5Fn0h((HS@vDagV}vkg~O9NDfq!1hxVCU1c&RIrva>ppn^ zu^1PbMsVse4iVVjLEx+S=96de{HN~0NA8}BG0>{^Fp9^t7~Ier^FkCP{`3j?Jwl=d z$q|c2{MY5klfa)B&ky+WpFE2&Ttz?Zh*2T!BeRD74kIXk4M-S^ie{UlNY!60p~eyy zP}j2h`z`l`d_4ezkxdeU_q{v7tdA;$I?0pDX|-ap!kO)oWe9G#0n|7Eu5kc9Ne#fe zV|QSm(_gIA*0^?j)Z_)J$;O3P)MSP!nrt}jPE`?VDoRc`A44mwx@YYIfT{f8jlIS( z3-@NVS_jF0HtUEmjw_tLd<`L>`s;bxs?AL+{+GIX3HZs6-GMvrJdSbu7-Dx4^VtGn zu?3oMqw5yvx*6iUL+Iv+G(!lT?6N~MM3M|bbP+_IxDcbp5`<2oG}V(}V>aVwF^*|T zF-ikCuaMJ#-OJbT$YZY~lM4;bo239-6SHqva1e=quu}FFw6Xg&({41nzq$Ut_|0>; zdhsf@cm>7^D;OD+Mp%x&P!6ZpHwHYvAZkfB(~2b_81vW5k(Tgx{Qf#Nn(k(mIz z|MnUF^&fcdJE>;$1&SJDy6ixwh`wG%w}_R^DT7qIl9?gcj4JWoXyd7 zbHr|r(9IE|5Qz}&%S%!K03ZNKL_t)e#u8Y6#n~DzEHMrmMw_K}9`OiDBSKzbJNEe6 zGv{#bYOcEo@n)A`BMCS}U;Bh9!L9_L?DQkd8|SZOeEB;sb4Q$0@Q7Pfo5}1w?K$npl&XoxCM%Hgif~J3M<_l6lb8& zRW|JAiu`!9dIGX!B=XP$!ybS=oVjorUwiH{VstS96C&4)Z6f7Z{8F4;YsCNTBL8yD z`TxojXL07W*TC49t*}--a$bUY1ZUaIfO(WrlubQM63AuEiYLHyeE=vLT3fr#DfZHv##9n_vSlYo(`3Y7=moLIb$G4L8@C9gun3@-j82> zbHMqtdx&!&qZ{NT_NWM-WJVcL#1!q(-;N_r`5vJJc1KeJYUElU47Z*aaMYrt%vi3M;zn zK2@};0BS7E8R!ShL&Dk1Z{pSSd!XR-WK&N!tdFSy7C%3Wz*dyzKXg}zU;DQ{fKPnv zL5xRkLq2jRW?OgS$dO|RCr=_Q?!eaeZP-3`9Pz|Sbcf{;}=o&B6LMt>5c^FKxJY?TqRBgi@q5<+O(2r1l821-vVYf&zeTs9`zGaMU!E4L5uo{pkaZ$zl*OtegU6+=qP5qKE6%y{MRD_MZjj~_xBP2 z17H63ONgs~0Udf!7!XEAml+`4I!jA_>z>}Sd_W=ER#%7C-puWHo?fr8wP{S(BLUYx zHcXPeh3ZB*07Ny`&2zmU!Lk+2rnW|X-{EoidH@=qY)2Xfbh8<@wzkmsJ%CE#YM-Q1c=%h-;tN0i5ROELAi2i7PXUTZUK`jgfWpWsNnp{x@zGoG*$>@< z=g;1U=gwTlt5>h#%{NC3yL;fU!hCy)hsq5}=ZaLE``lD?QS%M8Dbr#fU%t?#p=o6Zhc5ch50oV3wUr z(4^b9!TOn9)*n~PKLy~amv-^ZKYbQ7?qb;A1uu7z(-JB5vafm`OL{L%4X}LwY2_cN zsN%$ZIBB6kS0V7OkCP6+9aQ6kzm$WNOpU#NYy#^u{g|`X%E(A+qag|_h+T(K!|Ex7 zX1{=UdK{VnSe-cwX0RH8%jHryrcyMZ#tewQV}T8X5<*sR(-sI7qe+n0WC5YbRhMUl z!bxzUb`r1@N&!8`Hav$1LtIQj#m9^sMsOyCBndP*5C|jkFo63#FbI!7@f@Cd@e+Q2 z!XNx1Yz^Dh!$4}62&mz|0a?D6KrePMVs1eH#>tz@1~6Q; zJ_kU>_S8u2Z8Rz1uT2kUx7tAT{Ru)_E3=0DN^)IJ)uRSf8=G|h=4=dqa#NClEDOuK zC+xc=Gjv^7sMyq(S-5#QsQuSXI@Js91Wz5z%~7)n>U*Y$@4>hJrYy!G3MQ{8Q6%o{T4fC6MbE?^eKD7c7@5X^w1GvLTfkpIZ6 zevZ2D3nd=&2%I=N$80fw1H}%JqHc3;WVXi516nIkw;z|7fB|4BvJv`(IW6(}`SW<> z@z*!*BGjl|Z*dg2AG^SxB!ut}zjFqcuU-O$jJO&Rc^{w=U`EUgg4h6TyCkdmUtP7< z5&d0k0v>KQuYWD~<+Xisx4j*y;KmPM`g^rnVX&%3sxrqIYP<}8By2b<)3u1(!yJbX z1@1az4O>jQ2z8^wO1%KojX-p8A!u@tYp=%UJK?Gjb#B+Exh}w5=!Fp?QrIAX$aH>v zlVo_ne8B{$Z7hJHs(`wbGclMgq-{WALJBL4F%v@A!sSZ?{^37<1i$)Me+HR>E@`;0 z8I~2cEDO*MBLb>_!4yd~lIqD>L7MAdf0Q5^YlneE!0|;VzWshg$|G_bMSms*pd=hM zW!7DYvS?y~flMM*Yfw+YnGk*VTPvWP4caRdVKv*fO!B93Aa$f*T3^E{Ndwg5F@ZZ0xSJkLXFR@ z->4E$4WKb;U>;Sh??f`#>Nb3$+&Ak)jR*ladUOl3umz+MiKN^(kExW<8pjMC&7d|) zPJJ3Mrj-ET{t7F3xr>Y?I3*m*1D=2R1$^W5MX^(V_=-V_#HBXEhL5bv#P6S^ovs7E z^1YYw(yM1M9|weS58xhPsa7PFoU>bZ+toJ%TH=hoLD1$@?KsWBE)<%lJ@ltrgfD>j zwgmyFJ~%a0%wAMv)1(NW6kiB}TS+TtSqwl7QQ|rnH307r$4$uvurlC{wci;uQmJWH zkuRlxglI+#OLvAir3A5SWgAfa-300T!!M5A1_0m*XW|WyRK2j3AnM051OqIuJb^eP za*|zkkkDbo|MJ^k!3$@XKoBCZ)X!?N>yBB$HxUAh6!d%W&D>x6bkmO!5CF#(Gt9SU zh{1LRBCRT95{Zm8SlKHJt7Y5uSoH2l2@wN-<`_Za5?}iEbLf?G_o)&B8<%$z`i~I{ zzst{%rQZLwec+2v|jJLj^DpYBC(fv{ocW$`Ttph;}}4{T9wT~WjnA`!{+q}T6VAN4)4W3Gy$-G zfqCvCUSc*5xOnC@{O14hRb1X3F#^~dlmO_bAWd=zavejV0WP6t{~BBc2WQPtGjL=v zL+lti%Ep{Em`U{v8(-E3tf)rTTnDv(anLFuq58KkHte*fxrJW>R9*l2pBKHs)KK%HzXK@K%kE;MuCXiRK#q`zEr2PD z?@0}OOhHmg0{|wu9{g(woJgRS0Z>NbjLZ@JIDo^5c%;LhKKdQ}xBpv@zxm6b$8ASD z><()9in29#io&f!t_d=w?mjzzpqWC?M7=auT1pd+n`Ip$5ypOn1g+4Nta?rc5=k6= zRNF?5YUhB43nz>mkOPB4CpGxufXn+MzWDX$@WG$|7?xx0Vqy&u&aUfjEf{U3Uz3bd z0Dk`~-@@LNiS*C+`+&r5f8GeSu6ztIgMhU$wml_P`llJOuJWq$$(2?8M&WP z3w#vYQ3FSHev2)s02S9;H}I}@k!tIl8RAiL?8|n8juETnQjlG7C&nl$QxXfQ?WWyz z5?GhV5gZTi2D~YefTI7`*=RNhA&EY-SZ3CVk!U*!hFF910^#Nc^ue5h%7vOUPy>Ec zG?Q1Nb;ndAf@%FtD69d0ks4e`jYXD$RRe`txQ|)r0s(mhB|$14cCk%c`1UuygZ~ms z{Pn;5d3^uf$FMt8J3tAfQQA{B$Cz;R1Mt7h52LN0H>g;>N|MiTbUw$G0Av+Iqt16C z2IYW|GfE&gi7P zTPgQX1U&Qd4jzB(DI8sl=&y~yst0%l4n6Wn2zdl(K!O+=Vpby{TSTBpGmKgps2G|d z>szp}*z|O5^?ZZJdS8K-w<&0rC&?|+h6WfYmV9H5C9sF6q|g(|MxjyN>ZTq<-F)}3 z$4%H7D69A~HU__c7^4hslt`x%%)q()PHD3Uvxx&zvrtYW^T0+HAY|v2Y>*YmsJAk> zKCFO1cHRJp05%DPGN`1!2+$FN>dYg+5i|}!zXakAjxM(Fykhn2}JQQ^!6f31& z^kLG5b1F$gA!mdzfS7=hu;2j~&%cVVefKne`cn^Jrc5OrdMz(FCJ#Y~kE!MzZP z6o3`BFz*(){Q4{S^}qXn;*pPk1b_Kwe+(bJ?>3BoQ4lqf8ty{1{+m1PdYY*rzfYqb zR3Bd^t-!NISS;p9{Sp*KbVg3K!fXZ@Sv_40aM1BV$IZwT5yuf6R!E$|eFpYAAOT-~ z`0MzIk3WE;a{!`2$YW}uEBI8WSJZcs@Z;GGc=gV4jR(L_frF6GDNNX{aY4C5u+7+}A1tSt3KduACXJ)VDv3;CkbY{UyM3 zxgy4~v-oqJa(Rix`a3QUfRRL}_gOpY7nk3Esl*YKHUI<;VAj}&ETOc_f(1+r$}5b# zkDQl?Sl}yP{pa|j?>&JZ`=KAj7k>O-!bcvw11Gi#BSai-418!yY`N(W7 zh`_i6&RyQaqu+ZGuf1{_$UPFP!BTVRg#ZX)@uM(;c~B*P zf$`iEkKup+?YnX7?YAKG5nEkCnghr)#0+#8(a!;lTbSnrjw4oqK;sM;M}&F8V^6<~ z3uj)&0@u*<9>(PW8kV5kBhx6p#WVsWdH+b}fw3}QhT!#kCDK5f8-T(^t9@_+M^hLq zV&e_!0dI>T%e#Y$U>4hN$Zt%uM*hivT7>xwR<*jg(GPLlgsQ;uk1t~km=VL#J|z+% ziV>rm&1Anj090k-)i1%NY^vR)hj=1>D?R3fVq6sZa;z*5Oq8g^p+I<;(whl!4b zI58x^gmjxi@n$qeBfBqandVN6R^SMbl-ic9ss?OtMJ#vUz(4(G598}!{RSR?{Lo$a zp&$Mze)ypW@qzcA#F0gZ#Z3J8rY{#VY2H#N+^kexUX3FzU0dRrm(Jpa=U>N*FFc3G zUwjg8p1X|MFyP2MqvsJqYNUp_h09tbo!MCeGY}YzAVx_fB#0!3l)+&@8iANPVA#k1 z^IQKHR^ce(YJqtiF&txz!$~ZEmW=KBHC#O&k#}yziE#Y~_%<~>b?4!>k zx|BiVE^^$L90$$_lwtXC!8UABi2BB&%v#7smHDC!Bj!NWkQxbuHfSX|iWG;mY zD~lmR2>~+~kw#`lsGOxgns8*ON%pTTf;Zrx)u7sg)_$!KV_hUtLs-431q1l3z|xu+ z!@#aKfF%_%gD}c7nWSbN^~foJ`h<`&G6sz35O~1Rz(Cr^Gf!Q@cVBoBzcsrX@4ID= z_k8en+;-b3+;!wQ?zm-tfvqDm03GH4_E&qzfpF#OJ}{1W^XfI6yZk23U$}~$H!kAB zwTrmAyTWi~4}o_PJH`wdF<1c!i2_8{O$=0}soYVBos`MaP+`g{^e~7=8Gi=C(1Umn z%!I`(Af$Z|4d}p#y%6DfN0`xoqj>~{E7h&YapcQ{nL|cZv-Hrz-1dSmaM-# zNuG-_Rx+X@x33v^nB(wnK-EnMqW9arb}0=2s;|;^47RucDRHO|XB; zkh%F&PF9hBdVMl~S?pYi2l$D_C1ylOx9iTNssO}=sPD;~L8C|-nHb=J%!HgG2oXpD zoMs^EG3pjzTNp5|Uc+nG20VA}DXe%4vtfZ_TN&d~!r0Fd_6IQbF+|3=&j>@0F)zV^ z5mLY+Bv6+?3@kzh=Mj1A!3rx_2%;x*()a~+m9fT1mrYZDSQW8EMKls46shhmXTt%TM)Sz;^Q`6cwNlIQZWaSaIh)oE4BMjkeUm-?ka9TBvM^QY8aXb2Q9D zM&zphSU50$#MWjif$ShWzB_UOEX$7pgh*fx7>1#AF1eUyPD#swiGJNiMm2Z~zd)A% z0jyKdO-~v?msK*+nT`9qYwR~6F{giax@X%|8j*qyBPCHy6sf%!3zjly90AT6JVZ(;vdBeXAVc=%OC;s36CyZ8 z#K0QRG((pN6b8xi8@D93qDvS9A&;Gu^r8`CX7DOWpF=8@yNL%Oyvc%+ETz{411WM= zx1WxGCub$vv=-m5Kwy9B_{+U-eN3NiIL#VxuAj8++)9Wt)o^;l8LJLNx`&)ce9Ii{ zy6)Xk5yG>%{8#9{+76~L^~j@wtAUtxi3zDc!C z0S$yGQjqtS z<6WTw_|#s&f`A~q*y!)se1g3c5%rqp zD`3bYxh^OaG0MA4EX?{k26BKUsu-XUXOJQ{r2q;mNeBzGpp{!khK{V-@ zoXBgElpUEsDOosyaA*KvNywp5WH$uVe1hqFYY7r#mPu=7_+p^8 z4*-=QH56iT*yAQt1(vP8ZD-(r>;_^3$QJNp3##?bjH-z=YP0C>MHQmzFSt3J>RWcb z-o3Vd)5TZGpR{r=D*%e`NEoCV5DBn!;>_Y2%p4Gikx0er5P&4& zJ_jIE56TjvEH*m=#*9EC#t85z2*_q5FV=81swT*_khOLR%gHi(tkau+-Mj;m*rfAS z^na=qgq_sDN>~yE!7@frvh-;JAvMpKm7IbAaULx#H&;8WZR=%g#;MwX-1ti6UvnE< z5|AqbT0z5BlS(@buJ81qpkuE_K)uQ4!g%-eS$jjFsjQqE6IBC>&{Gmn36%vX*-qO+ zH!5?j-T)o)yCxT)1pm~37=RE$p=3D;2M9rugMtnuP|&((a;)q2>&6s4z1a{zC?TBe z2=_Woo;08c-WL-80ob+Cp*C3M;Cpo&Yoa zc+U%Ko=6Gh)pdaR_6rG_toQoY>%xP7q`(zdg1G5k1C90$7zsJ(h%-S!BM_M-z{m9c z*mcEtZt*lB&<41FerLx`$p!F3WYj9B78z&-4x!i5ID%(c)B>1?-UDB%QhX!1nSiF& zYp(hh>lHsOjivxhX3Xm!C|p|zNN{oGPHtpn{Or$iksc^lkkNtb?>Tb^e2od z7*Vk|DzAK!zjM8N`GRaT6SrnG7{g>5qr2PdWH!xK1aUF%p*Q!x5BB?* z^f1mFos-Ed5zEuF52=|AP;k?LH}sgg2v@&WnlKHt$ncXAw)9DtTR*^+GmKVM zY_B%7aDXP(*vEGeo(=UnX8Ji$_UTrxDNPc5B}{r6uq0m~C%kZsPQA}($%LnyH#G!} z^O;dK%1Kak<6uSIV-S=CnW)w?sUCl1*BaA25#u|)zH)T62B zrG)5OeMXr?%EhLQ^r8%0o}--6mmbBa|(vB^)16 z5jns^`V|pn5XtKBz7zXvOJ8Q(_cAy_`Bz`CIq`o^PyXO+X)_D@RHV7$gofZ$Mr^c=qvnL?6~j@f#6G?XpvZ|%u-o;l3)g*ap4pP+X(l8+LHCMnuD>f4)}ycqNOK{ zub01~x=`vQr>`y84HFh52ywtCR;QCh*cC!cR&ExEz^hHA^Fsi-YPZ&`=C)3`1dR6;C(id?1VGfHrap#_p zKcklKt8rwC87wRldV9fL{4MB$J(PA$kavTFyn;xGxcR(>=?>iO?QBUa(rhpslS0T6 zKyeP9=~EG~met(XcnTzDWfNhGQozZzhv5^v%uTzNuj>fJ-+5+YL5pQ7pScD%K5E>ij+lF!6(+nOW1F;Jg)q6xQwndCmh~0gr`dvsYX$Iyr2(&J{o_e%MtzMfB|DFQ$&6 z#GNKFh>@s-QJ%HjTS<^-M4HH$by`ok1WC^`NgL+t-e>K^nI~^t2^yuCuSFW=Q)=dA1FeTq0bw%BcnYyN)r!xeL|!5}MJ`LE@s z?hebUHzh*G*04ag+3tGt4h6fXskh zBTB8fr6^1owMJ0H*EbEk2^VD@DrrAaS2L6Y=X5E+v{viqlaT1-H=?ep?`*0Fo$OSPF?k9^mFK;&f5Mb9#O&!?sg_F>!hD>>gwoWl?W;o9)c+9 zOn5m-y-NwNB^C!0q&l4M{!g-bF!^6lwqmO{~|5# z!_)awQub`nbKh{VZ{OsH$P9ag)%XhUxa?P{KFeO-)6b(uX)7_)C}>{9tyEfKuX9G# z=g`T=2T?+*>y4$uRWV-^1i>_T3LzrqDQ|)=eN3?da(B@{=eS(7UmiiXagMM2v#htu z4@$N=j>87HGg)z3D@I|-zFMQxPUbsuK9sJM^-#5AloW!B1Q$d1;?((05OlUFWnKqs zEVty9#q%~<88;>5*}cPx?9G$4ThMQ!PL%0!lV&-QH&-q}RI7L7Q&5jEy8v&w7Y)o> zxT+ulf{br8tW1hymD;i>(%4S>>d3rqkz z6ODUC;D$c65j?;A1~hP12V~jXjCr|_YE-?Qu+yS#&)qs{Jw#~F!zh#*yLK_J>X~~F ztRDJ{`Z-i!M13%}-BhIzud4|ZlrODc7cThW0fvU=S0gem@{AoijUzCuB=Ei|Het*M z`G5JkQgfUNKpgJxk%D;G+dNN-3K=NwN`mco%*lJ7VtBm^Nh#LxqxSVX)lNaeRnqOR ze-+|K$g~Epn@8hQi@`1egKhOysSvXSU@%Y+Scy7?=Os#j#=1;xAU!LH=RA2UMzG*4 z_G(216};y@dEL6KWlEs(K2Q3)7NGoK)qRPCo!I{U3>}{_>dVrH=Ymd6R*}g_uNAp$ zAS#I2{MxO9#vdhOq8*9Z>xKHOia?^@>`62j%M`n)d!H7j5Mebls`#w-xU59F0MCjK zb@hpLDOvNb1X?(aEM=wSu?<3hF)-EmRQZx;)>kL%9Uqr2ewTljGUrCRXb|C&-Swib zqZl|@GjOJ^JrF}Wa$$JFXnB^YRF830L0BQGeCoER#+5simBAPww4>*<>&p|QFLQJ@ z>8LzW`0E)7gm^_)s}fV?T_BP(9blVOQp-8ZoYjo+GVFA)nq59|N z3V0Ty$%OIS$e9yEDk1!v;f@6M@>o&Nf)KSOgzPx$N{t1nGi7M2ztwH zVGS=M*VnQM&bTS1Du&MFF>n}CpQE!YvH@Xp`JKOlh*TMdRrcjk$}Gy&1W*x;tdr$g zB3;ePW=6@YHp>AGPAhU$ObM5ZLRX2d!^EG@ovtr?rtshbk0-$fVKhjdRm5`1O-~y{ zZ^-wVnCosb?d}`YOsmrS&KPUVnYa<%N^OAK)>2qI&8n7_e}!;QrR1x-Bba8Xj|{Y7 zgfsk<#m+^sk{4S0`T<{U5iqyrvJA_`b^Gi96d|yE+=8y|3-=Kv&DpreV>!e@PWhcb z1_jy&er>G4eLg0{ip|F!+%;-xOq}D)+K!t@N&aPmU)*gcCMW8+hhsM4l~P+B=oEoF zx%&aWWZP%qgUTgJ0&l83qU;UPwoqOQ_rmucMRF%jRHdjFPg!%4sDOYtHoEIP9xQ03 zXkegM-Y*xY#6CGwRemgIbdEo}I_CS_y+M=IV#n_6@^j@cHv8<0I?R^s`>?xI#FitL zxZ3@hx>wm4qxlurYp@y9^Y(4XFIkHfcCccZ+nZF?1u$?E$ov(|%4%$+MQ2S{Kld%S zfQEGB)FPg0eD>p@%mF626K>YhKT?Qt5!SHv!7NT>KlJW+kJusz>S9=oS=;doCcqaf zgeL1UxLaM@kKFL#P<=`HhB%;m=7{QXYG&%Vag8XU|K`);fzP%QfX+|DG*{C)Q6t~U z9WEB#&va*7BC3u~^S;PPt7H32_*zr>fZqYN%(hH;@Lu~}J3V0K5oS6X>6B~};$~+@ zO9uO%%!32(T=&z4lXP&_F3y0cakf6b{S(Gx7#>P|vWP}q`gUt(ySF$_dYvz2D2Zoh zWj@z6RghP6y_xjI{}_VW|59B1S4L%IPn;VM^D5@*T3t+_6w&mf)`#a}hjYiOlW>a2^tDJFj+>ZLcl~3v7Z-cL2k8 zZpS<8W_jNtSZtBkt~GCu3?N@LyQyGEeT;!Ex8vI7H}~*JEh0dhe9dN<0wNV}+MqGu@6uMmG>< zDne7w-iu-5Hc~1HZ2xHPuEabdio3Es#@OXLf3sXl)M>(VcSdY~d@rqZf$8a+Ic7#? z)TPH>&g13+w0PHtgRkGBq|lvI*LX^p-U=Mj;XHLgnZ$m`|LpEFRr+4yzy&LHEtpN2 zSj2yc!9prQ#B|}gD8}L&+i&ts?^5n~7q=X>AW#)aau-ICm?sq-3jjkatSxSJ>yePd z&N=p_xt}*!*09r~N`024yP&vp!+vua!%XJsR}5kV6x}F}i9ET4C3r8=1irP_97AxO zizsTvv#E0k5{i_NM$4y}zq=$@ite}Qslz8RdKt+tn5EAiX{@|@>#b(7IB@dz9zAta z2?75Jw3Q+Dh@327Qj^zEcd}?Xo&o*<#7azY)NS^M1AWSnU&Vfq6cl7uSFQ zV@e2m&6Qc&D;fv+&LYOr{c=fUY20g{CC>l(=JTtK_!2d>R!v8>2R53?+1c#_)ZuI& z4eUYaJm$%>RE=Ei>NLZGZ-!l$;Wl5?RIU{^2q?wxcoFTc9MccaSOIPJblv08PC+HBt^tW)ByFiM&IW;!NJI?{fsvxWU*BTF$kb0f>O zaDvP~_xmRoZBsfYd0v-oA*n@t9r~To3kA^~3o6E zuA){URI$u9s$YO%>6#rA5xZ;jt+1Xlcnhd9c$5E4QUIa9x+7xjOSH$0;TWtp&qwLV z#Y6t&`&ozk#*ceZ&oIZ`#>|w__MKaX_c^~MJPoewx;X$qK8u#^x2dWePhdk0dG5jWZ8xS%Wm0bOY7~%!tbzUiOHz z!x(L(s?D!^ErlmJi#AeJX#%z}F3sye$BM7BbKgQ)lZW7(pqEeh>x}iYhK8Yen;@7t z6g#6KUPa}`_*BQ!ubAG4??^jqY$m(WmYS_-*e`r4E>-*AOHu6Z?fFBZ`1Z1;Lt7{* z4qXx3-!5SLah6{5Bt4xhHz>Pq5m0=nOSTkNbGLWHuUqgW+6NBBPD_0JqXoBtTI1)A z`J{#byEb1r0$uC@v+B<=C6epvJ0;03@*1!eoJIfl6M;$S`431J%9IeBlG?2nH3Q8^ zh=X2*qfp?7uhlT7Lp8(Nt+NH3y)NFoORq{s$I(tswTW+2<02SS9lIz>tvJmW=C75* zi+68+3>hDGi%f#UjTCzbXq2}(1PgB_cYKZwlQ$eT3Y^P{mH=MrB*Hf*(?Q3G z8eNp!sFlt8kfe@G@`0oTT3Vm<;gU8loL7Zc0vcNikMYwq#%|`d`Hp8g;8lCaRl|B| zS%U1i$EGZ|@73@FSoGtK5kR}PjpP|eP$BX&V8v`J<#c%7>NF_Qghn)m$;nY=RfsTH z)wFT8HPe1wbxw0U+z8BE)MAgrpDNE7=*C?Cq(@E3(BH8mdcr8UHzZB=vPg5+2qQmV zS9sI0n^ySBlwgbuPUO2UK!}Ob%WJK^H;@M^WS_)yH!mt)Z!h|S{QI0HsOC;Wmr+fB8XDNfiEm^t_5m7qZ(lA;K}gUjSB_8p>0U1quL z{9CPryf`7AQ;m-4@h{ns`dUKoBiPBl2HlMO+%9+ltFQA$6{!?7b5%QqN<9%MJ1}q2 z0Cmfqz@ zHB?l(ZEJvIjzI!#oG|b1?=B5BDKBG-oXeG-Ux>o4rMAnZ(TdH#W+QTCWY7>(6khYv zp{WdgpORk2e=QknK*XPqkH(*c;PH$8BKZlU9|a_*xech^;05+#s=)P&L=}}lBML8gabFlgk8|%R9Z*Y_v3-3}HM{ zw)uTH4x=wdPff_ZQj!nTjmUi|G~C7A?o3-^>;Wz_02r$Z-KmwzB}1a%D9w#W`OKMWH!i1HZv_p2JuZ|MsxEd8 ze$!NI#ETyQ9u09*F!JWGDS;=Od$a5Mr~<~?g>^eBrO4qBm0u|<5x6w*#HnV^%Rks* z8R(Q6*x=AFl1Eg0Kcp-q+h}Dz>B0-_6YqO1-Ww7;4$7HpP&M{CL(*yxuq(gd1{Rp)X>51fzA=&1>S%S3+JEf6$~48*aA%VlhN4mUQW zDsPQ*OXV`y(BXRVnXhp|$c=ylLgAa~;pNtg7Sf8gd(VzY9We#(yAK^3O2`Z^yD=P~ zc}Jo+pXX-1Y>9)OA%Y3WdHK!|o7az&sX@}XLgzO>kEJY@0`b%F>!k2^&W)_Q0mLDR zsNR>M0fjnj;gklRThzBJtoK-UEoU01@8EGGU>yY`VUibcHGesPo=wKRgv+6)3sEzbI2wabgZEcjod6DvbxL7t!z z#spU1Am`4jlg-K;UnPrjfrO~{ta$jD8hl51_mhTRs4^c(dfF}&+QNNn5CDk(D{(?k zdU}ohvaH-MlofTLsoXe#`&YZ3bfsf0jVH;CrS`meJ|+K;FT%aHBHVNzUxhd^jBuM+ zuJWgxN6)_+J1Pz99(3ofpWk(3SxtRgo-}FAV?A<_%fKqXeLHAoz7>On}xssLbR)nqiRORcPu2$T@yAlo~RDN|zunXn*?b!a9 z;y&@3i_NEO4MUfH+vLj!qNP~Z*$)2gjs1lY z`9>n{z(LQaDKsr~*PLLb4#?uAnRg&OXGOuc1B&1`yZf=mq=JECc-uNR=?hC()waqA zPH9a)OIH^1y$yTbF#zX`;vAF_@8S{t0(QVt9Kpt3UN=F1i2FIPisdaY2=PYSWxXxoS4ouk12?pd>zp)pn0ehgU$*9byppmD}peSsrdT(Ea%yE(HN zDrhszO;LFe4OGv(oVo~7(SK9(%4U_B`lM4RRWv11{yMJN9L|dzWVAD%Zv*niv@r;^F3&>zrs`twa$qn*=lup)TV4hc(T6 znsl#yKE1}bNLACNvY2bV=Dxn7)WMES1~r@?-B&_rIsNu$azL&>)euR!S~})?N<*E|jXz-qa;cct0W<-kBU$rF#4# z+;JC({$#elx3AYz)U@AOabNa8Xm8LEplRq+gVReM`RjUia`f{G8GGod_w`Rr$Fpr* zHV#8Uw~Z3eIT@@`pfxD97t*}$sKv8X_-uN9ah9)2XI}^o6zO|2yFC#cSgcJ)DeG4E zGXOz@yIDtqBi(bGzPr4u;*O{7c%-luTUyQYq|@%Ie!Y&sbO zZV?LY(d}u$w*lf-iqNJw5n@Vo@7I*L4;M8Z*7@$)LzBlAZx${>mF*cS9f4VquBbM0 z2)W6G%jHl`WWZCc{R82ewmN5cbqJfF_bdr$DJ>7iiyo>7nfjnfmQV!WPldqFpXbRztUBEtJ z6x~u7xv2Mje>l-*b%z~}Tqe{cykKPdrdyN20Iy{C&9Hn1?vm2ru`{-}F7S$npn+X^ z@hQy-@kHCr75zmo%#8J9)zusCc<$3lUe9rlCya2l0p+^EnB=a7}*xCzjz9B`dI z&X%pPOUWy9SX_v|Y@Gp6CZO~~V|_(U46l&@Bni#fLI(AL=HQoFK>J>YH@-{uZ(F+}gKH_BLs(nLJ-O6P~O{ zN#~*@h{my@xnP1R^umICCJc_Q!uG5 zDyjqz@*9KWd9?kt0jD$cWXArw(sPvOxSwQl1u3ZI3ZY4_1id78_awqMF&RD3BcdPZ z%k>&Q6r_7%mHaFYzSq^&#e!LlA|^uuER)PAajLX~_IkKmFMAgIb}HIF`qn($h7Ake zFM@edmr(o^K+yXP{*iEnD(*tW00OKZ8EhsD8-fFDyBx?30M}ovmAQFer(X!2l44;B zpB0gINuc{++?3$P-`wb|mNHZE`{0*&N#16|KoctuJJ5X)FWMe_F8kUpA`j8;?-%=0 zG#9$hD@_q`sPi~KJ3Rzr3`&SP@HT*xX!z+SUQA@K+L55SPfSvzQpn0_ltiIr9N)U8 zw=8%?kd@*B4-G?Ab8DB3pSXve6aSc(J6uJuZ+Cya6g(LiyIidR?%3PgZ7KvG+$!{1FA@DT!Knxi zaM=O&PH^$77T6%s_(lmvxH+^X63|7Ir>l*P1rnb_# z+{>SNDHFPqRj6zU+nsI;9<;to2)-Bz3+^z$0dSXbct|P~t}bHabyG;F7Q5=jjteF$ zlavHHY{QM;zB!per^i;hN3R%2PTkOp6-ixfP zstcMLgsMD}cpyXXY(93nX{?l;MTrxB5-0leS4R!TMuSx(=g6baMZac4GDB+=bCY~` zhz*mY`53HGWTOU#>0_h${q zC%ZHbN(}Fw3J6hr`B-;F!p`ulLJt(>MbHvpA-f#&Kx2=awv7d@9!#Tl5KwkSym&uR zci2LkE^1-WdOL^RwonoOBFE{W1Y_Uc5rnV-xz)z>Q>yjT1vewKw-oGqJPa?mZhGBQ zAYRT{iUc(sG$543tv$dL_DJZ%#wvw2s5xyAzR0{7+Hjt8T7f0GZAWmJOmka0-5P_Q zV*owdO6Zu)Kp0woFaE|$7T_cA<}>-#Ervk}8ZDl{72qib71D-q4{YR5AFfc&**A4` zYvsw{VwU`x#vvW#ugaTy8UNk52anxn0x_L)1OxOUms<##g{W%$MoH(pIwVmZx>acN z%4GD-QB}y6Cxk39JiC@IT9xosM+3PIopl&3C_=AJ`Y<(EWG^bg9VpzB8A3t|pQDA= zk?8d++k@M0y70LiuoQmx0=TAi*xqk)JX(=zK0fYuKlzS};$yh+gNb`IxBK`-#1bAf zEJ1cx5%K-ro^7+|HD~K_T!o)_`+Arqa4?sY0N@AQT7va@I~pG{_`sj7ss_EAnU{F| z1jvfpTP}d59KhBFxcPd)jEC%ff0EJnBd70ko8E*Rh?5@C{5jKk5?P0^f!-Id0d9x> zZ!z^d=(rio^*uuF%UyzD9@<0n% zK|4s1>xZy8+*K^i@z^s6aqnZN>n?P313A=T>1U(ao-oqJ1KF~1UoZ>Fuq`w9$(Q=* z(rV5`lYGSDxw_{#g=xh<4|1SPqcq^~y9iPv7`*uIORww+4c^&kv@pLl53NsH{4#*H zZq>5>96_owYkMdHmRP_SMK=s?zwt!K{b1g0^$uOoFVg$rVs*Ue71 zeI&*jfZ8qom@N7M>K(lFq-ndY`KF>BZLtZwmRkBR@?oexM= zAdL(+$TXFF^SvW+G69?}8%0s439@BSvqD~MsyX)fn-e9hxI&P{dWtEE6fl^aOH#v> z4APd)^t+mfuMg&2%o@Y6W(<=iANR4YmsbAR6>P`tOr2XTSno(;JA7>rVOnZc+?b|| zrwZLYD0=Ed7^Y_7m*iaD0X++g)gZP8%M@<_>z(J@=alQYTzlh)`4>pu+CPc5Ov5X4 zyC8T<46xL=luyZBIplC&8MexWXatE%(|40Ov+OVN2jRVqp-NQjlN1Y`jVB`>97q|o z_|=HkzmA2^YS6vjpWwK)BDGtl@#Wo%LID#%JJv>CPTuz>)fcgg!?gZAR4@5m^n;*C zq+;JsC$zo~!)G-i4k}?4x#_k?k$4bMdI+LQdvzFsc3Ff#dj)MCdi9(bIo=h{0-iZguO`N&^G5A|HX;#}CcmPz>ctB7YMcic-Y1G^y>}LiDnwkp_)zkdZWZ}gW2O%W&(5zoC5QLW zKeUTvV|p<;(h9Oa24>zoVcZC~1mN-0LAkN8+F#FWOuKm{BjINpkf?GOm2T!cD%E!$UMFhvh5X4 zZwvsWK8w&aVUrOB(@2csj+x+mOz{|!CYJa?K^asWlS~YBkQNhO;voMm02o3ua}D^Q zuqS#z7dClqZfAo$tzgHiw64Zq2Mr>JtWhA4`V+=O$@UURokU3cp4{LNjkuG#OG)92Z37c7H0$%s4Jq0(dc;i7XU8Fk)1~0w8+SZ)z~C-a^I|d84d;q&A8JS~y4|{e&=^z(~nI?^}q&5tejy zKBB!$*!Wp%=UE8!OwwAulMcIC z-omgsduV#N%69fzEt|MW8M})i=a8Rkx=}RuL#ZUw&IzjH*aa}_-sjjoF%ciTHQ{n} zaHwiL=>iS^x5~jVj`zlumL}|#A0UTCMVX&3C|{nKz%xO)?B!_<*~|d&_{>`!&QBkF zwmPRPvMC;jwD9lj>0k~$d3_Vp{Jl$*qA}D0M!<<}j`wFW;=h#Vj?%q+ueS;^q~(z^ zZr5n3IJM{-UjjZL{)VjGRBKnTnO|CmN_|%F7Y#j3c`}qM#Z=^dK|d_agw$j(hzu(r z2Zl*n)?%QpRS*^%lU%P&XGDHzKMd;CKv9qimB>LVs$|cY< zXO|?YARI%$K_1RPc5-%OewVPeze9t0S`+(KwAJefOwnEqgjYs02tZx3S0SY>a z&*JKs$o=Y+0n=x-;r2q}*;<8i8eX4h3PzQP4}NYn!2*@R0QUZji@xcrLt>rN&Qehe z;zTJ@7SB2yhNGJ=x_hny`2uA45|J>17DYn>z=odR^jj-39?8BLmeB|VlRo`7-eww} zL%|$Yv^E;rn9lRfoU#~m2B+*M#2*+O8{iVyOWrSg&(+q%P0N?gt1p`3Q3l9cjXCI% z-fvIN>pa$vUrI8EKSZ^f^PvKOC3r*Nh5j- z<)7obL;G`$H*>Ad*QY;A9EO(9zmFQm1LY5!!-oTHD8skU_b!0q+bZn6UbtYO%T?3Q zy&cxuw;jdX-NDu3e9Mqj`1!?0$oT0g=YsbRGjVFFq(SV|%uK-EnaT#A78A!AdEPYL zpqXzxj6$;gmc2)MUv9WonUCiT+Q+ zlkTKY51{Qe9PehrIm>rjEmT^_8PIoK-&FhIV$ln|PE&I^)wyJG-ra5My2fo;!iQ%G z^MQ*Kt{n#d!Cj5O?+wiUQ(W1=cJlGW_FbcmA|4Bi$a`rb(+E}f)j=M1;FL~pi;cm_ z@OgN0dW6B1ytve1ORl|Dw^7`%GHD#0kGeW$cNogr_IiJ5jqg*A5yKpdLO_M`5KS^V z&nSe3o-3QcLA9yK?^?bCZyrm(FL0~hOHi~Amcf)MltKoN0%QhHF%({i1G%Nl8K01C z8OOCWf+w&?uDAYfDh*M7qKfMs~QLn?sePvQqtxQWch z?_lO+eZ5(A(&t+c!B<$*+xacVef`vGib*0JpH4yKM|LzRhIe1R8w>EE)XcXAH{U|% zt)zvS+~QcEe>WG>EkC?^S^;ylk-GYbbPhwwhbx98!|S!#uF$h~vQ=qA;oC{cm}+jK zEr~DoRNphspR%KPv~reQ32VoDyfTDnlM_O>^~m@Rx6)5NTQ0*-=hr>ZgekCOSmufK zE1r@wBhypOFg4@QxrhO>BfyJU$wpsMRPXQiw>y4Netc>8+Dq#fW7S*$0dqL_TA|Xw7huq)r;24#wPdsx$}?m zzoMc3LJVswS{Y~S?M2Wn2lo41YEkm`U+vhSk5fzn{1>N3ix$8g4Dy7ISyE3DM_YRc zHZq-l;PM1p@~ADVlm#up>u|f?k$2O00?d8_KgMzI`N$MU$&9EdhD~UERlK^IP-a-J zJ;87<5b~?hRIv#%tzN&xX;pk1u6L59_xbG6UJVgw1oH=oLJSus>Q2$QjXcV-b-OI42`VF z;!l|+A&}6?kW6a05AJwZP2SSAGB~PWt$|Xhip6*A@V~vghDhPiy!H<%Lt5-r|B%y|=>OIZru*9d55QjUwQxJ2im}AG#wyZZ{)h;TJ}PB>3)F z?btz)18pv^*-mO}v={j{Y41~oBN`g`)Z$pPqc(eL2RgnY4oQLA@rPt`67|(T9Iv33 z5pp61LIeyUo-cPmsK5kFgbPaAyFz~pWYqN~BMG`!(iFkY1g0i5Da5zl!#aNMWmFk) zFr(E)DutT99CFSv)aIWy=v#N#Y4dS9 zGJ(b0+wdM5{2oCP3L2S7>6f?CYdt)=dk?CD3qeM~V1lHaeI!YG_$GiI^NRIz4jL)R z(t5&+)g;Rd)QE#IKcDQd&=8u@(;!tx6*7>KPEaUgdAftx5^eKqN+ueF0)#+u_!PD~ z)pmf@3FfuO)UPgqEIB#Y6tcumqRDSz%n-v6uj8^Ar~G)nUKF$|&BF=Hr1~=6 z5Wt=g96A1Ykr2?#(C^1M?z2vm->Xzy47&*wxikLgB!IKw(8A8og}L0A;Yt+&Nc#Kx zkFJ7JcJS?dZ_YBDD$a_Itd1*klGZ1`-^Q7Kubi%d`@F-JIZ-Aa;8yy{bWTe{P^OSk zYb__Drv$$(C6zEWna}BTuXGXEnE1|od$y|`PRi?N3XLagFzsU_Kp8o>39refgG>Q& zSK#zeOh5rYHXX=dHPxk8T^B=vNq@o@s-*})JH~% zyu5nuk#LavV1cQZDo7x@B(w8`BZ(F`YqHU!$%SZ|gKj0_Y^H0p^S zPVgruGVB5ZVGRupg^n2E6bNl-UfOsdYg^e*OQcC;a9gEZ1ZXnL^$^j$q8vkIMmR(y zY6o)VRKx&0TVm$mr9K5fUk4x%oYZ+I$eL-|Lj{vR^8Mx~FHH6aC(-atiOc+E(!fuW zm3+Ty@V>G8j}`{L5kVUNu95?5K#fPS=t!i}?;BQc{|eE)EUDxpL86(d}V`Ac_D`^pN1-CVst(PRZ+YQ8Q24EwpE z)Nz-WmNT`q`MRB9305t_e6=-zCX8()KkzrC}tfITnV3WYc@ zS!d_GD3|y^=*PAtx$&!n?DO^%x1Sb2!=P8xy+fmB2YrR!&r5(a1MYQ_g`#{!ANR6- zct}6DS;|lE#Q^sAY6s&%lfA>=GE3H&pFfD4gKKzibWP}<%hApNd@DY$^14qN5`Orp zElG=xED{g#m6k7j&>*yNJ1}uJh57yFVTI(jKUY*%&X)f@TWem+u*qR_Vze)38E`j!zwtc-VX(L zlp+yvmdd*u@SBD83px5$WQvV|&V1V2o3Vd^J|NMN_&L9kGq7gD7mpC%8blGS@gYtJ zr&b2ClIfy8j!_gTXPD@L6t2zT{q-r(tA*2mK#?T-Df@6P!5`er1vUB1^;Gg&Xbuqv z^d>ABafm?lrr1fodF1)~# zF~5bxmI-U8I1zKZE6Mkqs!WJ78}cS$JUfi+wKhcO>c|M?c$w|;wiRUka_w_|dc!0v z=1whDPM>edf%-;QS!bo5QaUzW;Drz0o!g_X^g)QzggPNBsEtE7rZd<{MMrHT@KV~MjD}+^PE40e zRVQDVuuI4ru0M#;^~l2My)zC$eqFZ84!wiw#3Cq>084r`py~i}A$W0Kh4cItg=}1Z zJi-Hk%Q^UHb>tFN<@1CQC!xni0xB_r_I$d_ESLX8p}s#`T79ik^~6i9SE0SFAMI2x zvmEX5j|e;}f|W+TqwLcXe-|Vz7l&qCH1ZIlX@;4+^|HBJSn0i<;TdXRe$Vy1vo`$= zASf&zb2NrwIDU=H+PbetP(j>x|1HF{s0AN{E^5o-Uk#rt6%}}=HHDTrL`{ILYj`Vy zJvp*Ma=h@&<&);606oh&^wfvxHV<1sMcQ?ic0&^H@(~2N>W$l-fCF!@R;z)4%!_AI;L73vzBC zK$mjC33xZ-6tZOy=zUn2;nQ0dk=eBeGjHbov6nLF@>aYl1H($s&*`r8vY!swoE(uR zP1rYg3*&%}@JtqI5b02IRg8Gqg)F-HRBzk{7Jt~uK4Anmf^lF~$wq`^BlmKFJyO2a zK79As5YZ;8NSvP$Visp-Ww&m4WlB6hj~fOL4q!!PnzCZ$s7c7+0&Y|7jvtP7wl+yq z&vihcJybF{@xXlZL!XQvUk(a$=0`4&{BL}eYlJ@cDY9CLAcEv5=xPTUGP$A}k)0&^ zTXQ~=!0%DPx<22!NUOEaxuXFAvI5$0?L*<|(ggh5zl>iIaU4|J3s^4x@WlmvnjuuH zAx7ZuJ@^%rm6qsf$l*nFCxYn5ef{IDsLZoHYL}4b&`uy2^Em>7i$#QXJqkt!RWD4e1c4Ru{ zR&Su^d)b;extP8tGqxp@G=6JtWe&~nWqD#|Wnn?atZeM!MCNW{Ys&24>cnhpW@c~a z%xvLgZ)VTT!)wB3Y;2yuZUJUX*fj)WQT@+^EDpwRO<(_;9Gje(nfZUd;@`Abib(8y zJZ#Kt?9e9}8#_N68}!M-_OA!@#5Hy{=;k&fh2A}+i(<*LqhD)Ac#LsezCt@bZ92}|6A(kP^o#? z*#0T?i3L~+;gM3aCD_@4u_^z@aq|Di9!iZx@#K;H|C{)42jPzv|7HLG83}27Fd^b2 zk)Tb8a08=07KuNoQ67oJKZyT!B>utnabrTv9h?UH2qa>TFeo0S2v9=G|EveU+5N3@ z|Ixm`(1Jhdew7O*3FL7C<0pvvfSDdE^&iyCj}rYKjQ?)=|JmHX0O8LHaNq+D#gqHn zW(+9$|M>L;);KWYe}x#+?@N&W3)ueniT@q!{?YnJ0oWM_=7Rg10W?Yh!^Y^tB0t8~ z{DJsCFL?3@bMq(qzaPDSwdAji4#yu85!XK_A~r&Z9_wRu@DJ8$ut@(MDrvBY{}n1w z`u`!M;^OCI|C8Sib+8}nxBtHw|6iUv)$>2ujwhm` zWX$Z`JWT9RulA33J~C0!I=WX76qp1+143G7uL02o|Ncl)2df3)0Y73aC5UN52p?l# zeiJ@@gkAZA?r+tiKREuC2K@=4x*=@{3i4y5UNU>6)KJ1lN&TDd@0I#D$G?)A^N%^@ zpG&$RTXRUAtvQTa)898KC-{-W5CwgtO?hj07@o@txG0{ z3!Qq*&``OCqk5d=P)h1YNdBAQ-z)haO?-^xbyL@H3>c4;8b5&)8UD$mYyq?Ze^4Vm z#vuHg_-_Z{A8q(6CHd1Bs4GT>KNEf|5-|q<4G;_R@J}8$4)CFjk^X)desg^s3Ni}t zyQq&rAww6Qf!4(M?PKQDgx|!}P~!hEpZ?xo`%U@+O8R#?7k@DQ-Pp&dL;^$y{^pSg zFh9-?KxJZiME^s{nE&3s|IP8Q`kng^3&{PCWk3>!cC?W8h>EDUdKY#o$F#6Lb(Qk~< Tm^s*fg9Ls34N{CF>dOBCZAu=S delta 87812 zcma&NNwfRfb{|&vSx>o5>4d)e?6}V7 zaP57PnNNcF<=4MYiXh03FJylCS#knUp|&=S?auiutgP?f#Ph`uck$|M`rjJvk^iWy zg7q&yhpXV{%g^j*^Wp#^B>hQpzhu~764Ym!UwuQk^M}A*5Cd2Kl|n{zWZ;nZ~pLKd};Rgo-ftN z+!sP$YW>T9_kaDPKm7CGs_>nu*G2#1AAj>F zfBLokmmy`yFGKpF5dWvYYC?P+=-)cEzj|K8VK1o0`t6oiyZ`4O z{r-RPweZWZezhdeKmGlm|H%)t1wVg&nFAmMe#ZVRxCOse@;z67cftY7{^Fni{y+Ph zAIiYLFAYDzs6Rd_?(++?`=7>kFUlhulTUDSYAbAE)^}qyI=b z;A{MM6aB*RZ@}>%ALh=oK5=}r3qDuB_+G$&>OZ`E>>P7_`^<1T2Izrrzg@F5v8J*= zaP1eJ@ar}o;OPCPohW|dH1TtANWf?I6MSv&{NU5Ie$W%2;V#(z5jYp#8uZ{8yS4wz z@BYJI|Nj5|{(Hmus(k*QQUP83!ykVbCPCz~8J+p|TZ7AFa=HI#n7^ah_e1`B1wZ|& zy8eCYn}7VxpMMU=<%&EQeipwfMRR?0KmV(LNB-ph{Qd7&>$|`E<8S`?SAF)4{_FQY z5I??X(Jx}*w@>)5he&*RzWsKUrB;;1d|kp{nCt5=oQrLLzlOgd^*@1e{Hve*R&Rg( zMKAv3^J{Nk-~aPEBeSeQuk;`5>?@^z|KI%H|NM`CyQ`01iIX3?d;jYDf5!a2PVztX z0rrSqW!FrOVn~{1Im*=8wN6tjoiSE9Mh6?XvbYtMF+S?@=u_W0tM@tj^j3kf{jhhz z`n)any&y!K{N&=(5>{^2@b@ZAd-4Hae@v4yrb5(5g91ilk0)ZFP{IK}q9D z-tTB(e^j~ST>6M_B9txq&fGZA%41F~qh*04GN}L_9gC%4S(qfW_^lOZ@#17TFJdsJ ztbKEMYj$(Z{iL`?CyS3*=3mA$$ze={V(~rNbhDLn%FP(UxoABL<&Cm(6NNap8(PkQSI@Vvjd5c_4xs%uNj`d7<55Z-2Osf1e3X0Rvxl@6S7xYeD$4SazrUB8dLwx# z)ax&D_2{gWRC7EO2R$?WY_&U&CZ8Myr&H?IvkB@W)=T$|<>gY1Xm)-Uw8(oNx!tmNo`o% z6}L2&TyNl$Iw_&)r(sL@qCcUoW#i|om<=&x=?kaKj`}X>D1`!vQ}tb&j@^0*7JEaLG%;w07i$+X|y@Zn`1s3+&uj#lfy z%Gcg~H&1%Qk2qU;S|^zmv|H#>F1GTO3K2W>JHr8;#nTMvlV&WM@?rz z&-eHK+pI2-?o|-=u703{>G)P*X8HN`0c20I&g;Rpv|RMJ1359@rb3#zvSox0sykCJ zT#%Zxx1vf)*s?T-cvEgTC{-6H3JI1`?N-;-kC^6^=c{*QGHaSjEg8De^6xa|Y%4dp z)M-Qy{ym+g>&a)bgr~1*6v*6Ou-$L)>nmR2oad}xAMwa)3<`xaUF4SO@*HyRjnj05 ztR|h+NG}A45>a#enWdN4xM`ere06~?!>9XjGUR%;f3hR}Bettk^wzEREPu7;5Gw8E zP*+T`m>R#mb7PiziPgyJp9bOVIE9BP9kY~s;@oFDh2C>NJWs7JQ%PsnaQb+En0)8d zuU6|Jw6>yw2NNx0vgZ;-v@)U35B?6#O9eU_CULcuujH{@!>|#kJmmmyq_llA3p3QM zFD@;SJ{6+3S`yg=8JF|}>Rr6K(Si$6F%XC1>@uzAcf&FU=gyVjrQp+1D1XHB6O%~0 zN-ZzVAGymN=AxQ?JVqUmsp)kBN>kPF$ar3F!I`+!U+4iYwN*bpvw!X@tSLBp8 z8M=Q42UaT3&-XTwq@#3SCE;?BRrj+|jzGlpbY!eGChDP5-z~)Q*61zv+w2^z6kjl; zrbZg+!-wrhTov#4Q?B%w$0fHvf8B45Ox!lx#!G%0C-c@7YXwq8 z>~NA{unJ6B+gt0s_lkT=1S;06Q^jq)Hmv0R{CI>L`DoY_D&*?GoQ@Z=QQ#g8EDPz~ zXj0DO2}j@6i0@xHi=OXT{-aAE+#TECVt3bGr(qlIGLqrHaix4rb(jY>UctR$(Pzeq$_=QcRy zRxUnkuf*KyZl39e+)Zf8V?j51RJ+>T$-T-)jLv*+s};|WS@L;1%wkm9k8PAWGW3Dk z+Z8j6$wo!4A0G0Jf3q#Ol18|FxI@N5dMk^}dAb1`o9AjJ=7te^(`{Ws+8&-tJ-9Qd z#JJOFq_rR)LkXw$BN**TOp~3K@tjBk2nmF3jgpYXj5H)0PbCqssGKbu$b1j$7 z)&0n8xd@yXm3INMOT0JRfT{WI(={8}Q5A099VyK{m!~eBxPHV(>O#mTV^kv4I_+Pa zr&?SaC?CL8F6myz@qr1dn-0xWVqrfm6!8eV)pz@BcM1oKp|P=( z%ptv-S1Yb2BzDVg!yCWbXjn*(u9vQ=N#25pYCQoaYeGA`w0G{(OjslGBlZzhbsEJX zKP6|kgqo&`i;5@m`8IBQ#G+ocBMv^?Xn~<2bVZWI#Fa%B<9IW1$b_^JMzxQ4Y!=9% zYotjnVr5gr`H`bemhJa=<>QO#T3JFbV|ej-LA=OEKbTAzE({znX* ziO|@J2#m5=JKYzc96g25&!U#bKr#x+i3p48 z;J1%>a!FrKWl}7)*_RVk-Rfyx8OM{6Vbq(LF~*i+gy-c`>aNF7zZxcUTm4$Quq`7_ z`_+PO>^@@5i7&Nd8gt(an;KUrF8{jL*4v8P9YB`ZMOooyqtGgf5hz-ms{>luGML!^xJ;}MM_Ht=`g@)TKjQMCy?OFOWvFr65{yA}W_DaKcE)ZgodI>0;eC`| zV0LF~F{*TcTiw+zx-(@iq3sEyZ1qkbaqGdxN4!zOOo5XgYkNPsBOT9MhRHFiLA9;n zDY1(pv&-g|8M&#vHcofukIZ`|keg#7sY^*vL?`6C@%s5RWEhx#gm@8Ct31C-y{9=^LMH_n6D`m!lE2Q%d zr>=-|wLs9^@YXHc^~KWJ9_LrVt{(RufZ>Z(I_V=vO$$!Ig3DtM8`2v4Cf0?t;w=t? z{QN%b^WlvtcUCS*L1V@lKw{~w9osB~zoF5_>V_$iBA4D|>eZ{slIt8Z zM#}}Z6S`KC3`=NJQ{Rfk3z?gXNbP)PGw$^{mY$ngM+7oNUM|dd8dWQaR(f7I?Irlk zO~P}Bs)Ly*HI%bf(lhVz^>Q~&-;AND02T%Nk*;LdS!&N!cuo*3D^r>GFj#6;OGD|AQ)fK0$&fZfmV3>?-CU1DZGk5~R9uDN*@&eiriN(cJ4CbB2=yqhc6C!ee)Jqd=Z35@dB#RM+DmPJpf z(f%rt2x}H%Hy~t}NdVoZkGVkO{9z$kFK4YsHYYlnU=yvCmdU49;k0695fiJ*^@^DD zDidqbFJJn;-#RKrQz3H0-bZ}i3wl5OX4|id9Vvxt*Oc2bDsb(+;z1OAVz<_L!}8Po zpfVrl&fKt$KU#mL(>bokD##8M@!DU+Y%f~w|wkkSvv$whaiOt25YUwEMp~dd3H48M} z$mAehQRbbo97{$)yFMT~Z5>qev0rYfh!9zXAL z`#h9w9PV@RWS*J;ihAgouC3@A-x`HpPJ8#f&8qQg7YM&*Ou>pW{Ls0i`O$L5tz9OC zZ|YSy<=i(?yXRrO@f6nc;~;IhXi8dHnxm_!)_Ub>MIzt4>yh~Qh^2uboKZc_VHq+{ zT&aFNOlEm<`ilqJe)R{lSUOd% zi>S$6#^(bc_Qj22?VlsarzbB8tKK$XGM!%J*pN0^*cgb`iL_# zoH&&X`8rVM^HF;?Rq$=?Fnhk-q2h< zgk$50_GB2WusYvErgQDgDdQv>zQj#;0c%Kb*YA*Tz6hh6Eb+cWh-x*1CrG<}>(-lx@P zVN_^em)UiF{t*+S{b>|uwUI)?jSh5~SiRX$gV%2*PvnS_DAHLOo0LQvk598acJW{+ zFYPx?yz^|;k*0GVe8lx_;goNCl@2L7-RC5$3=Z|vEXombrQV$Lc0W#Z&d?yg@2f=e zu9gaRYkw&yFh1k*Xi7N&kfh_ul|kr5mBeX{WgD~L4eh<#JkcRar|EPQt>s0tm>O7W z=gCy4PzfH1wK_V@wAtk(Ha&{_{}WU6H4C5kKJ=KTQBui|oNS4gN;e@pWmC-{x9+E&-m{?4z5I&+*Y zm*M!r!7J^RO0n&u2J75l#c7b9%s|0y`UL)xP)y{*yu>Ch1Gln-YwUeE-FDC7Jzvgi zt!g4?B@1a`B|K(<(duwm+jV`Hekqj`a{ro$-NQs2YD31nmji_L*=w79OVbqOzF8r z5rb+I1sdE_4Mm;s2pyJvay@=+x4qB~7E!6s-sEYLQ?qX!m|xpfZ)P#Vp~2SMlcMW& z^Nr{X_qw}A@jech!TeU_xhZ9X9upH(B(1{|Go;1BXSAkQc zJkLRba1z*uR%o}qgS~BY#a9;XaTA9%=}oo_JoPM=-s;15sM(}8$qH?-98{B%_y*qH zCq$vw-{<7(f^bdt&Qj@wL?-3Fww*nc(iJ;bZ&_<|OP>$uvDHy)zE!GWD_|_ld09tG zR$63yhdpRzWnSC&rz)bZHEq1`9^LRHR8Ci+ijowbpCz*IIy6YMA&K6l3B;V!zynQQ z!3t#*8Pc|XqY6{9m%6i9Y--WI=MLfiV$ZhM)TITlnTNyQ+~nli6O)5dYolE(cvZDN z;#2h!Rv2_p$?c1TkGWN=l}MqZ7&`VJ?UV2@a*OV9vG9f4`|5Og**mJH*!Fui{NR-M z0;RyF3~1WC=HPyMXh@LUm7HPa&X$JobllCz0)U#+Y1KQz>Y-py@o^bKT8)Fg8N+(% z6;mU!-vOJ_T-j+Qz)VY{Iyeqf_9@|wp=_ns0egHbj2_pwU%muwWW4gu_#=Dk;ZOVG zo!eax;O%P?h|wM6Gvf9!Doi%`9aEK4>~rs0oRxiOVxvyYpV;m!7Y4W-)2oC~{BWnF2%x2>_rrYURzRZ_dMsa$T1 zzamD=%|}ut3Tb*{r2x>cX0kfj-R$t5PLX$La~QKlrrGcCxm1fWcLh2#Y7}BZ**7*! z^HHgu41I<#a`f4mt=U{#TLPDU#qZZIXcp|UwlMRD$ZAnCr|)3^XS_}U$b$V&mNl=} zh+r*QR9mYSH22V4l-x}nJ7Za?1aO$fi6C8=-^BWGYf}d=CUla5%EE4`L{I;cnj^tV$rF z&Wqg}-a^4f$8Snx8V*0f-yiWUISVgnX6Q+pGOT;uwp(lv=F!nY$C zX0~Z9TvA22(QiyJ4TzSqK%PNj5D(Jk_?RM!C3c5aJf)_;iAMv~0)jKCgRd1qKSv{mA zhZvp^7MwQsDC6n%ma8^+`q}K14YbE5_r7^r*^@`MmPd3vzEK2#B(u4gTw?Yqm&osz zB(-R+sh+`es_)N{=lYzO%E9!~jl}ZANtJuTr6zJhsHxd%Ks#?HSg0VDvA)GktPu85 zUq0dMl6J7s8GjfRw1G35CCF0ip$S7GE#*%vq&9J(lF2celey$D@g82b4Iq1n%&fx^ z*8F(PJ?&?%jUaoky}GuyIq^ZMbEN|Sx4UkNxp8w@b&=}!Xxr91Cln|&6+x><641EM zxWnM)nzvW#d2Mu>t}YnNc9X7aRq{?S`Qmb@+Kox`BpFD*oVZLMOMk!gkbvylZTa>9 zHt{KU3PIene=yJ7DCPO6DO?EI5Q8gGvgV2H3z4i56yQW=Hu!+3lIO-l7 z$*hm*ngG0v^R+*^EDM)olpek^H?&7{_Kda~Azxz5k%`VTW8jCd@4l1NUrv1pCji(r zVFVd~9nDT*M*@XFR*R-LYY_`z2VboQJe?E+bs}(RdfMc6jJ*-?OSfl}_$#{t4$Ou~ zoAX+=hG0p3c}FD&V1agW(>xF*I_cn$xWbHG@4{RYqz=NnJ!2-z=8r;%x&Po~tk= z?O3zL8Dtd;$w7ZRt(TtNWe;hAz|MI$!1R5;){+aIx_OJsxOpfIj^4YtX=m+x2Yn?o zC3J1*omt9npxJ|e8w2<}q3j0p#<_zwLDUcK4?^aiN%f`q_+0U)6ZL-KqLNE?3QHg7 z((P?pQW}vyNgjHA+2|tM!f=*h6$3jNyM7CVG7b!+r3#aNet)Q+6N|ljes|qbmD)nr zDX*kUIUB%ha}XxBd&I4dtvT7uTczA)PxfY9@p{Yw{(_q0TzZ;=uf0a8{FHp90p$yD zp<3K02ik4R4USX}I!K*f%1ah4r{C>R<+9on2HgQhAfccAh(R0&dEoY>M%3P8?vc&x z9z+PyW3|Pgc@oJjJJ$`{=#{+sU?oRBhav=XLai(8+GM4~Z%WNNroYJAi>%4@jEzT}W#id}j<;0)^k#Q(=464)+a_N$h zn4!bbJzP!on8RNiWNdn=LwV5hs1-LeY%A6?~ z*|)gzCJm~6Na*-R+qWjQwIY+nf|w#i1_YQ^(&J`OnT1{TI+OtU>1rPQ+!`D^XOQt~JiZ?Ow9|!Vy_6=vlD7lvJZ0 z?`O4aD*K+1YhYLFw{#&Ai#+4BANR62ucc@8RF)3NwfVC0r%k)oTrdwDOII?2VKS{! zt}(jKs1vDXiOYzrg5XdIqe&h_Ch0U%tn?n${h@V$i|a>GYDRi=Upn2=@!T2mH(?IV zQu&SeELD8%ZHRr(?F+=d0*qpfu3svJXD*SphD^m=FRqA|SVs+MeXDPBHN30*6WD72@T+fG1J4$BB_C`whF*Dzoh+%D0S=UO|y3tkz}T` zE<+1_2ZMNS&*WH^uT=G?maW$bjFR(dUW$Up&4E_wConjc!X;A{jy(X7GVRWVNzJPh zW@s3t^jwIK>{xr#wAfC?kro%>$4#5SebP=8pE>bBqlk*_1CW2Ql$i~(R>OKmipJb! zFb2{rEY6aQA#q}p9Bzm!Grpt>s9+Zk^#j7?)=s}#*>2UOS}7Opj~L#Qt#fO4pey4V zOpJ?ek_aTKK4r4+c3WQN+vKICEot|(tg0n@(^g+;kh~Nb%LOZSvRQ@%0RSkzw~%}D zRTbiCIP^N~-0SB0uT7ZK&XK!nkk|73u~}dJ_8@HQ{R)6Led^k3+4eJYm^L-ADf8qK z$p%>&7|UWgX8R-7c@H-72*SD#yjc;D{jjt2XVkz4nhajyTWeKE(Oya>20Q6i*vx^Z zm$Uk@KG^OPz7Y6sUlR=*DG`4H{x3rl!8YVE6Cs)ZxS zGHiM6g_db&fZULXb$9;GsQcb?=iN0!iqLxA_t;$6NK$YI5hrK4k~!Inmn^ zAgAO|!Cv=SBr+oqB4<(ne*vBfv=~-5)&fEe)|YCdvu|x=XRaoPRHZG7M!e3~s+VT} zUbO@)_gs3TyIH8Xv!{1x^8>L4GFn!6vJu;@Cy#E@`)IgcR@5#VB$?{s(##C6T>%jy zQXZ~E>f)FZI;2rtu;I|D2JfnB<9rL?0+%XZsE<}5c8>Kda^Di$#q6l7b!+pm+N~B1 zY59(;u8j438*YG8#pN)5Dc{>Ab~?iOSe(Qz-cp?S~gIa%V@E7~qQU=jhUM!xi zc;ufK_h!V_f=7-kLQvbcWj5O_VKa-kKt73T4{+8n4WV-=dJwhl{8F+@Z=E&~2G^AAd!63oFzL znMsAe)){m%#UlNz1(3949<9?c@jkAumfjT^OogHOX02G0?sN(Oz5DhFjM2eRcudmx zaZ_?}6_qFRD_qhZnYCDQ6cxhD3w{`eVrjQ~g?4O8aBj4$z$FO@A~QV^=qUyAYRFAj z&+q3Ge3;=O<-qDQXu6P974PO=ySJIVgykhjotT|y8el_kUZV%K6a&10 zC910tR(r^g30K_Iw|J}+*)Z8Q#UpZ{`uLu;I`^UZ7{1CBdo0-}Az@E4xH)6@1Xm^V zAl$aUq>OScXk@0PXTQ>e;n~(X>iM^^5cBzA zsp=cazcqTsmjg@EqqdtIEkRx+CX6%h8~Uhlf~bv)U!4JSY@T&X8q7CG(n!jzA_xbs{kU=mg znnZQl4JE;bRVT&wkXM0=K|SKk36L=9>vJefZRx=-?I*@os&GgpTX#{2+xGVam8%WG&&w2V9C<) z5D#|61>Ian*n|Q1>rk9*Cl$*ghC zj%nj{k_G$7dn99@dQx3(!c7WAgiEQo9qyO@Rvle{L7QJTTh7tXi!({<4hAvnc&qt! ztLskn7L7;h08LAD9aV8j-XX>2?5rO0iD}}!r;Gj--DgWnV6+@=<)L1*!1jiNN6t*C zlHl8bx&voN%)QP*<5r3hwsGN` zULs7K*;;yRV^b2~Jm&Z3%(cG|u2ri?vE>gg8TQnfUpdNbguR4#pZGb!#% z(uVH4$vep58ZMWKDTwdbgfN+K)D!FGim|w@zjCN|Qk&U96C|M3%xsmP4;UGUuf18R z-&HS(z(;(@-b)KUyQ|qrcui#Fi?Oz8yD1QKvh<$SkZ4;^i69$cjL7ng#aF(<@F4#J z)}+D{B6q8f;PHevm|{|TMI_ewWjdcf9{}#d5mFy%NT;h3%#AC{O=|LjsOIp!S*qUm zU|*|2wz{%5k?(+*ZwEiZ{R89mi-$g1YA5Ad)33hqMMg@+)OIy%XW6KWA}h9hwWJu! zBJn5-%r65$09Z`8`P!OO;9RmO!{5czvK^r6qP>&-GJAGr2 zY`XkTIM(BjxXVP6nO#1rXK&grs4Eg=^z@&=o9;Z{l>ZtJ2u;LSz) zI)}1VD|2y$s>n_umj%Oc?gU&LK*plUhs_+F~NTLIO>%Uh&+$jw1KU5+H<}i`Y#pz@G5pNe>fH8@~4!_qzi( z*iP&v3gu(f89&I}b!fM^!EP6TVd(jiNt_PEQ`_CI@2Hy1w>D1obbN8kS6;x6)bJFx zyQv9<3xY5upRZ`r6h@urTG+ob*P2YtGd}Us~2TVo}&WGrN!} z1xFA>%7becEQuJ}VTSYDpS`+&7{B<)7 z`GTCNw4{^i)EEA|SyQE*Kc59Fd|oMxUimteO;8{JKn;71Ui5Djt|8eSN9q0yZ534QaFl6l9>x29NZu0iz)QV%gJ_igKG>bXTBy4Fbz( zS?unejpnme9;nlBMnR#}W^d3OrmJpr1=5@wd&u&@ z2OiMb>5XPaCYPjDm6!-k@YY#F$Wr9v*fpZ1*K_Lk78F}*Hv4T{bnTl316 zSVT@%HwU*B4=?$4i)&s1lnk$pf;q!4)f*er!zEo~6$&0{%FF3mJg0T0o)^~SHtM4j7&=S_$$g>mhHR*F*qEb=(yg~1 z(K+jm*X_std8>gW(VE-~0Xos{y|gt&dAuf+y&A3VQ}cnsEV>mMy0a4bm|rrQa8zrx zy1YJZoh-HGUpX?<)$6-wbr-lmwdMRJ&$SRdC5LdCRpUc2eC_D*@vY5*z|mT7?b=`&4a&7-i3ti!)T>_~GUC#r(=}7TjN_GF3IvsU+z2>^(@L!I;j^=2eV* z^ttKb7Po?GGShOKwInn_c6f=(mD>Kjm^%5xFE^N6;^sEo?4ZKq4^*08mm!z0b+XOV zcqeQSLowtPV!7>8&GgGl_&Jr6<$S8rlo^orf*?ZT40xkXDhCBvJnow=D+F>%W0U)O z8ZMrbK{3URrCMsi9-DUdR;s=ZM)gqdo1&rX_dK)2%y5_j3ITB>-@>EpG@oLP-{%Yg_~D*(!Nw@i?w@_y>h^GS|F9TcfAnCgaS8j ziW+~rOEo3$%YM$eatptnTZRxjTVAowqawd5he3PH_%bW)?&OO!@R!ie@b2APd|-qi$2K zk=czVGBtkYB=tCM3&2H~w=t4BSL!0U9&pdayl1}j#Ta{Xf}&?~lO!2j<;`;Ty3y6g zt8k^a>9f}MFRe{UIPOYj83^+v9;R!KZ>ZUb9EsG)y0K%|8Wx1Zz zobcchsJ;>t#wzY@#Hu?vu9A|_GrJWKUm7`*h1Zg`x@xaEYaUn)YuyQt2z8ULZ-ka| zBjP}f!oy`zEgwzPJuNcyVE;@=VFJXy)^!N*MxO6d%jQiHH!QQ7%tvhM#e^GXUgq;d zPt9OWbVe@g<83_P14q!0fqNKw6IigPWQS*%HSiw0W}j`ykFxKmFNg#3qT(ovw;~tA zt;KiGr;67dr=<4uF7%JL%AOcCsVF}I`RD?DnIcR*0x{4XH9sfM#7j*pBtJrq_nzRA zc-xA&%&MKfLaVWgSRnd!RE-#7sDSNaXoZoIaPN6VPq{r{uUW22+945n_@j(09P|^DXmD3+-Of0!4(>SaI`hQc=TWC2rn;@ z0+lZ*@wrP|TkeGUW_~i;?O@GcY{dIwc55g0%Yco~4Sq4zXN8iijzyr_AhJN~6!E5O z-Giz-)`Yt~GTZDBOUo03RB}&%DYOB&#U*H~V$oiBOaNB4Y`JIo|9 z<^bfK_o`Q3JfPs_)O5MEug_K5o5@KEae$|DPW0JrzsnW387mlU<_)vGRb3k(L%ZzK zwcm@RWdT@o#fg1o^y=n7^t-n#)F3Z!HTp0bX^P_w!mzH+&l5)WY`M}SZ96d-WKw)f z&RHF33;T!Z(7EU7iDRx)H_|ISo7gDuWnTpZK_(TcQ2ps0?I)Kx z@+|C*6SWKytNdH=aKGfdSC(GeMT*sWYuq|$L$%P_=V3GlE z${CNizXr(GP#An0rN+=2)%ojg0ZeljD+@P~?Jh2DqTD?-Z%KVPyLGeeFu80C@}&V= zs9H+BB?QWB>Rt6Zj4NfW(vE=#xx;Lp>I44j*XyH`aFQ?K!`yA6Q&Zl9o8G4al2>_l z85)z}24S<)7+#H~#iPAhl;IJ)&#V*JQZ=Cj*c297JLH^_nlrL|v74TIC?gA+pvZG0 z{g7was{j9SbnVN=vQhk6nrO&0lbpvfl+u|{{y@%^LyAga-}<-S?*`1?)w7hk!gVfVfAjstw&KF*~~c)1^cn-n;R3CdQ>`?}vo>?QbvQn37 z=wft-$}@cK``uS~Ulz-be+tYK9o_i+LjeW`c zEIQu_R-d;zNVhMTBI2zImf+HL1{|ryNad>^`m%F6`6^MsdQ{68mv>S4t;uMy+xr8M zcdviZ-)2yHNZO_e{8K|6%_gxyToE3dFN2JPu#F@C^QI@{;@2{2%Z;96H^aQjCcoO2 zlmXO@HP)cH{j*KBW+HOy|9Z0C8EeL@-mHl?Q4`DM+OhF&7ZIu_A8KEto=r(?fVu*eLrBYf;F|%XIS&*L(1!+%(7H8=GB&q>{VKPvj3-CkSmom5cUf{IdrMKUDF3|fn#lLZXQall}%;>zFN8K}qby45Hqkqnk zO6PE4Mi*zzd=Lvi51F=GoR@??4rSErBhBIcv>}FMFs5R0KXl89VJ`CXGuLbst%_u? zE*oh#LiYNZj1L22-%nG{r0f6~*o_HTpu--|2q{L{o1hXF+Q08Sj;s>p`^a2o{&2Tf zt+e#g%M4VTKznP`Us~P@&_4dI^y&gj)ZoyMHGdBdDS&8MA+(c4N1yQL*?J|I^zS#n zo~C>6^4P_qHBU_DC44wl?~d~2lin@{75#gLhNHja;je8>vbpwwa{5V4(e|CjA6j3f zrZy}zWc25*jveuE(~uNE11F^pVcwEita!_>FTxaVdct@-^PNMoCeP)vG&2f#jBQ}1 zzW3_KBd2s$0q%}LBrLbti&$6n2SCSs0>N-+a~@OU7#a@mxrtYk=F)M7TQ%DJb_Mk`uRZC~ZA=WDqHYBFcWdP0k0cJe*CoIL({@%3I6niX zkaaMtFY{_$$=?b&b8F6NFlsnJyHFKr zSO2+da_Eg%; z9*5P9pdv?CGLFH~lpl7@5l{1HcBi$^?MJdR_cU7)bvKIZok*B}E5-J>kT%wZzlBdj zQ!I7N46c615n~Oj7s8!Ug)&Su9z#4wqY$VGDdvke)qJft&^GuanEx zJ7(G(yD#oSTU!coO)Mc|Q* zy$FUcwOmvH3(U`FV$Y*Da?vWbfZAPb>x2U`pfZjYk1GE-OiYjk<{)xLl;Gd_V-Yst zoZPLbpMKg?SQmC6K})Nof6_3bJ7~>rzazO-iit#o((L~EnY_prS~Fp*E*{dB>Yti( zgjoG#<8rlYQ7=68SU7D56b8@U!nxk_nFSQv(rQafqs+`m59jvVNG@4Mqz2F3-#c(4 z_-G&ZgbrzWZH?B+;qs*ia3MUg9LS%O`dDmeyVfxCJPD~gkNGsfK?#ctqovHnZLNYkin$Z?t$-5Q`2Z z54&b-%Ude}&dhKL)O4?INwJoN?09W0rA#*XZA{3`!MdV|m*?~G#`=s4FwS57zw4$@ z{O)GSw~r=hx7EqtSCo5~lOHRVrn$~AY&_-tf+^!+^-E`9^lQb(<@(8(>WZHoJB_FK zSv($3;xfUW$6V_P5eVnwtceI?q`C6Ye&LmuSUP?@#aX*44n{x#u(eX-v^(Ry-17bx z`nPp4>{J)^&99wg+skZscSrKT%}7+<2tXe9ehe!E>y;g42^EGJ|E$1)ZBNnD$*%WJ zny({2qve-r#J|39b_%BRDyBzP#&j|4P$X9ax!;~X!xG*0i+)52+oE{eK`|Ffjobat zUi2ExXxSS&$K|H}w8q^(z5w2z51ivp& z^cQUZy^9Ly!x`2g69SD2a6sc0m(s>uymdr75$4D(3U8u^KT2wuIDtGuv_M^7(avE; z3;|Ch!*JFOF^Cc+3XizCEMc|MYuP(l>Gu9)2zj>GM}(O0S9N!l&%$Q1>hkw$qH2r3 zrg;Rq`T=<27E{Rk4(|F|sojiFJ)Zui;p?3NGMUCx?p znH0F2RQxRfg!AVhG&%`|y2EWU@5-S<50cLIb@x-0MC#U_zM6d2eBW#%kKmJ2=xzId zh)23HKe;yaGxq2LkZ0a3NY;sYgR1BFEQf-RRPL&$o7DcS9}}i}VxI3=NwS<}?L>!N zzO>jc46{*T<=6FGn?f_H+;Wd4Pi6=ASbaCL&ipu(#l`p>@X1!RTA6OjGV8VSy2?-K zFTYogpTX;*e-qQuu0Wp&F4UfIj~s=k`f$j1R$n9YoAI@+BHPJwj~8<}7{CtSS48i; zn&F#(#J<W{?@Yrp5pp{;)UmH&XObM)R%K^DneY5YL9(i7U5O?hG=7HDw ztNPp3szHtowP=TDZ8yT!=9x%&XG6hnT*G0pOHuWgO7QLLF#m3P%a^)Sr7YcrX3EAg zgXX1L>$gwcc3v14zR@zf*6B@hs-4|VWdr2n_OcHUH1e9*U2+$$!MggOnftch5?Nji z{+tmFx*|1Z_$)IqMfB227qY$rZV+1uedP3{p#(m^-^T>kO4G;jnoe7I`%T@OO}0O$ zQYr9-xtFgwxhVF6qKPuO*#$>jwC3XY8g^@+En6Da*MByZY#eVXb|N9RBuce^y89{<1;PvMW^aaz)^=>-s>qm1Q-?)rMcs!W{Q4*_KlJj9>c-u`aVLY5Qm89(%BMMHTkJO&nAJ;Y`xmU>z_u#g zHa(LX)022B=|RP3^E+Y{+;4;CchgB8Wd##hkD1@fp^zu@`S)!}h|7C_n2Zrk^8xNj zZ-3+YpfKOfXFXyuF}*a|;73=OG<8HLo0#oz@!yWO!@x7t7+xQ6h8+aD9rDrL~m>JID4Y2 ztN!0|1QBLbW>JBQDc&b_rZsK+Zhp5=Xz!c9={$ZOTEFJLRW{0J2!Wa&uNW~K47XZu zv%#N)ms(jznU25QqwNFvxEW*WnD*WG;#x=?ee>Mv2qWH^T{Fi!^Ul1S87|tFYWLt~ z_4WW6{{`pWwYHG<$Too8ZX|)2tQ)ed)l{ajW{{E<4vn6kOJrjo-?(7nS{rrG0)ow{@)sS6lN-SJ8y~_8Xw;4${H1!IigMw$;4h zr6>^w=3nCO(fwjM9>@LWSWU`X@>t(90Fp^bK>r^Y*k)#r(y&ULhO~U$#tD&akB@EgfG~@@3OId$~6OR^{q0=Y^x6fz_4XtiWSH2*!8ar!X*GYtF35;RhysTV6!NJH}w%T{LaLr_ojN>Hj~b|$2TA@G#OKk+6qTM zm|Jz-Vehu(qw*hpB zsxQ)#{`cAv->aOwkEcuypB_%tLMUL%ZM+-P1Gi8!8YXjmERqU$3P$w)G@z!9khY$F zy9e$zbL`wKsJ*?Y!5Ey-iy!&uw#l>RO7jay8M=dXze0G8O7{>jXF^!tOw?XDQBnT9ko>slR zm+4vWa8D%%2*+&MVedQQ)v_b-jCuQKmG$$jNsN?`<{KpsglrSSLMNrCp7kifEa{b< z{Gq(E_LmfJP~XFg4PLn5(1qNunys_fa$=({_}jeN3|+}20KXFmhZ^5vlcy1}{xJqJR` zHE84URt{KmUa0E5m}8^$ z^LIN3wb=i2s-!3FW1?E3g2tx(q}HSDBAXjd=>P*&z*hPe`Ya@J!l7s4l<1DRCPakV z#3DIvi3WtznGbGwukrKfxnRl6w9uZP(eaJCu9B6MD_SOB%3IP)0`&`Ak3m}+@mJy) z_G*&}*_rSDiuzAQh8Eqs7;q6HpNg=JORFqrmHOYJ*9`KLIf3T*aYi`LqEiGe0zLUW z3u8~l9!(<&3wdnDhS5ntB6kvA#ns?K)6RLht4}vk;$Tkwm$Gk6gUFnfGF;WEHVxm# zUA2|dOT5(nmhz&r%HjpJxLO|_Vva1Y?b4v4>tm*R7dK96MQ2LrMz3zlO?3uoTXiS4 z)=+}mXe?Fx1H1yc85;kr?1Fon&3f{$o`9evE;%|k2@lgz&l*%KM$CHYt-xju z$;9EI-zc_se}*V4z4x_C;$rQ%~}+{v5BNk0`V+JOc)ds5q*Z0}4rgV}2LYU@%)n;vht*YyRq zTaI5S+Za9r{cj7fc}D65AZkFBxKef+gBiVZ-Ydxm_4Motp^pS8D#n{=UaroQbPXvZ z3kN{996p(!Z+#T;@;Pxl(2=9L$%_RYs+F$&wRZ6!L*VAE-q|CPEUDsO!zqqO_Z zc@|l+UhxX)wEu>rC#Y@l?RC;bF~FQ z2?&WAvyM@(rqyHD*N{sovkjXhm!BsNpsS5dVK_+hK1<_l#q5ml73o1u+{Q0yiLrg0 zy}MQsl`*z6|J!`ycyI3NCrf4!iH#e8l%6A6s*K;h2=lpnn7@a~{vh&KQ-k$&Z z>f@Fn4Y1mLwc6jHKgucUhI6sWHJ1|V#QsLq%Ff*e*lG{=QbyyTjiI`2{=+;d&;k*Z zTEhEPQ&Y?$vt(^OcbGiud;FMWmWf*Gsf?~n_l4P7-iVie!K@gMTAM$0zmBe-T;UvaxV6>xeen1TC^T%x=cV<-VoX(0y9IDv5U2RkPH6vs{ta7?(wZU}YtC|v@<`Ot-=fQ%x zuE^;_P&Vm#_QGkw>`e6*EsAuhX!$EGpPcTPb5R|14)# z*6(tcJe~gJUI3u|DF;Wa@wT-uPKdVQh~Z?&8`$-C=^Mkr$IU>ZN*3!}9#bT5%D4E+ z*r(-Kn9NF<0|NdP8ZLw*QcrHn0Zy&%`2Gf)SP61^Y(r`v6?r0R)>?%VW0VRI$BU1%^=V-Gn{tn zr_ZW;FSI(%^X*+?Uw=QfsTJoP?9^E4&`BneBv*c?dQ|;rrCuj<9TDCE zvbg(gFsQD|0(3FM!S$EikmS><$HZ#0%x?wyQ)93p2krgzw||)GBhP6nL?;!)OD8B+ zhNnV-&8x0Ht}q9)B0>H~?-o`XNT2*+=Yv(w4^DPXt_=KH0L^GqqV2VL7YC5`YrW1p zCug7#c2xXgx%8&Xh0f(be^%gGIar@hKkKvSV#-ssQNLLaOp^L%@U`EN4A?OI=uY(~ z=?#*XYs+3mKiBuii#agDza`zzl()!mDN7rv)nlg(e1EGSCaddf`+UAPaN2|)8c3B6 zr$pOtt^V#<&1II9h4rT)tGN~>8>X)8Ymi;xx8qM7KUI3|-VdbfZ>lzFG%o;>ye%ep z&W0N z0aqK1Hfh&2g{hKfH9td6a)0xoLG?gbWrk524a%40;RSK7wl}X592OLmQKKs0Ek7Fj zQla^VYA%GvFkh-+7@ zt;I@Sx4xa)|>K*u+hLX9|g8v7M`0g+I?rtpqx7+i^8ic9S@e%I`Dz= zJ@U1~EPT1|^^Y-?6HpnleNFz3gK7R!DX;67@4C_5EX1a#dfvm-I=!*)M$id1f1_$X zgViT!Q!_?aw5@h z@$7Q~tzs*Y6`&?=w_>AUHWTp=nwD#8J8Q6n`c_Xbvw@UjWKXC0i|J!r3UcS-*grjc86a7>#q+-~Tyu&!nE=;C5n7T9c3O%2W?@uKYAbs$U7FMa|ri;l+1N`+h5vpa>VwtHzW~t<6zUx zYoai{aKWW!X6Gwx(LwspXw8-6MZ}RO;G;K3pn^EBM{SwOd%&rWdBxUZ>mH*Zd?+*h zlZclV>sq~6r>mK?6MNbGX6Lo3#^3kpgN#!}Z1!5`O}eDtPa}m#ijsVTo^mCXc5w+z zP~=1On#|NcQtsvga4*-xrR=IYU*blv0Yr(tdzeNV$dk;znA50O!8$~g-08yf5LNgL zsBm-b-AsDy8X2nyn7EzcD!;?5`S<0Pc@Qmg_Vd;rUAx|5HQm0B7tPC3`Rf*|m#yIB z_wM&N)Zl4+Ii1TYh%zq7>WN3WyYJW&AAiBdiydhr$MDP^24KUMIugJd+XsDCkJWFu z|8-GG`ON@%AN4c%DU-L2KL4~U**`|u?&j(F6KsOsDYf#aCcE}p4`gIKw9OhhVZ8+a zCLCi)Z!k)fPlyLS@l8ZGC*;Zwru-wzlxgQlt{mpdxVmZ4b40%UI4@oU{&z_)fcO!c zReJ7B$3}bHyv$-3exgXR`Mf&5{}sw%7wE)YMZSj=>{A(74#5=@_u3L$XSsLi(sy!Q ze~(A{Qx2jd?|M}lovuO^`X09YFjuA2KKt@)_bpWq$5*~u%}2vFBX(E&t{RN&DgAL@ z&@S%;o{Xk}nrT5OjmeFOFoDvO{kwd}UkZbn39aP%7H!GbAT9dmFYGGR^_C|FlwFzm zVbQz*Cv^Tbk7Dk{mh_{y4`%Y_pUV5uJ{wHU7B7P zUD9LPK!}ALgg$$_J0H*eQ3V{Oe*@P9ePU-CVgo1cN{|a^F+i?i*+cX|m9=}S#cxO8 zz9Qs##shtDMQdV;yZwt+Y!=b<}Dr_B)%>-g~({xKcByWPti8nq2UFa{bj5fU0n0 z1-M*@Rl0kmYaf%_!^#YN;;<0u)A<5|X$eUx=&b7FV)Yl}t^wuCohfp!53&Yyv4Vg& z+@eFT`lApmm{FONArt~H^SZ8rzr~HYxO|NmQWxnJI#U#1Zb_^~S)i3)p^az=IG=`#xw;ItTixlTy$3q-DF;tMR(?Y_%^XN?0PcPYRlbL_v9!ZFLjT9(AMdhPRo!-^SnyG z_oCsZLy&>cEo6Q~?;9|YRB0$X4g2^PY0;>@&MjBt^quKmj3x?RqdSC|uI!+0TCYQJ z}TQDO}81MRW@{72f|5My2}VdQqx z?#Es0WVLYV@QfUYfN@`0xaq0hm>E`@!l8H?YTX$%kRVjQB^>fLsA!()2hIv+d zAc3UXvx!jOvT^H4-R#O#O-d_Z>_}``l>ZL0D-KyPYL$`U5IJp-{Df7*dZvBA-R7}U zmLvcV*37oLYXc&rDh`!n?|r(c4sQo&7K+}rx5#_JnfF?rxfnMke6hBV?QE`;qm62} z_`Kbh#pKurHAsQWGILXE4M1e~wERp9_J@G}Vo4Z5=dv78iujYW8eK|COyK_dy425q zS-VbcH8YuJ1i#y_Oss@lm-Gd}CrUNV6xNb3gA!0spN<<@*4n%c3dB+EH((;cQde)Eu*6;BWmM$BK${~19(5;r^8_Neo z93f%(4ea?d_^_vJ*hi#?>Hjuh1pW*xw?K!-%YNK8rvKvYZa2V8C&Sw(6W^D&L!%B- z^Ht{U>^3Lodh$tpCw#LVNHUKs2&{nb4j}J`R>ljnWEM>M zS!7N|tKC5Fw^V(cR7M90-9Y$Hv-%4Tmty$0eKwssf6Z2x<25zzfMPS#gz?dzkH|e_ zM7&Uxl-%@;Mi4U2R1aUUfz5f85B?}0Vs6JcG2Oh(yvdcyg1MCdtS&5_vX z6(cNR=Dz99^XJ^fD10(S7i+3l}SI(UA z&w#mtlq^u(z!P0s?S}c%h<)uvc=-jWH9z#Qsy0#h^_P>z@LUPki@vAK{l?YdrV9~d zPrWl$8EvoN@2!1)p3Q$9@%`3mZC3c50C zGa|qF@b^{iyK6OIw-aE2Po6yNCFDqwrrLOre-5aK7P;{YKF3@wbG}5wBt+zCL+ydT zRGvzXb$Z0v$pBk(4yn)vz?xZHBJ0X-p{%?!PI3n5<+P#P!t~SI8a?wc1m6U*zwA;K z2t0o1`SB@qyj4Xv)&^F3RsXpb>u8rR$VZ@1U#z?bXYz3A233EKml`gm+ zU#Cp@*FmV-!2F#S`I$yVGx0`ji&vOHU(v1}w25;-ywyXDgQhhk8{Ni$Hh#r4(+3&M z;@Lrmdw!FY07>|5?J zTNL)>Z2I~2$^H@1NKwX&G|v>wvr@{ihb%{T;S-&(ugjNdv@&FFG7#z9!Xhm0TFOxT zVrzBbt_j!@d5iP{HrO`oR?%Av-|4PveIe76&KP0X{`aLdnOZkO!yV3YlS3xEiT2n%qvv$TDNV^93_It!w(!Pv4#KJE(&e#z z+$Q}nhnHZV^Wbv*-9J&YUf+WCZ)lbmqLnwca)mhkZH0byvg>{O09{4dym!+mZfDWi z3)k2zL(+XEpy?(y!DuBe?ZlLfD|p)q8&J)19&uZxm6^0f+7kg8O^WbhOJ$aRF?82s ztAH%~Zoc2yiYPDun%H=Env+X#$e$OXXuTiH>CLGA&Cbh=^qdq0p|RlGxhA}oV{_Mo zcqp?j$>-3x*Kxf5Hq~vtKU4jlem)-*H*;+kn4-~?VHXpZ+OzC^P`ZV!@Sb!ZvEX)`aG6`0}Hlg z-T}`S`qRsYg7J~To?m@!%}1xw)mgkR1EK5;js>SSX!+k=?|}7GzC2jG=&!$~>*4lS zV#@GHS7^Q1-GmHW2+JCZ)oPo#mt4oCg@V65<=uF4UDzD*x8`#E6oK_()gP%|9xtr8 zwX$JrAjEaK7N`Q_cWzlgzaHoJ&V-!#-M7jZSIlp|ho^v znzDs)+|KTH7cl!um;3y+Pj~4E!92uW8xX-{zbi9$>{2Zw|aX+4E_q` zsv1d6YG`7Xf-0|8D~7(?>$$A z?}xVLpGNNdoIo}Z63i4ZPw z^~C+1`Zz1Fl7pJHv|!9!Ch_<7+uIxmnc*OYK}AdQx?+2Zc974r-E7Q2q~|F$>z@(d z^m13EG3cgOj~q72lQK0awdRw_w|n002O@Ddw#yp<04*$n9J7Dlu3Rj8XZXKEr)taW zbUIy)%Q)vx>Pmf=tU<`I-`4tLNGx3tPe=H6r{i?Zt7ZXSY;l8BO?JzT&+@VZ35)%x z51N$HsOBD})v{lDHgiPbyq=~jms#JacUXrNrP;5#-h+zX*abM~FS-_mKT^FMvO4B( z2ip~VrjJWlZfpyUfDK2(f`X{wDiyl5d6vww8kR7k!O>__u6 zUO|RkTAAGJ>5VIA*be#o-lrRJ+iuJBYm9W2>1Z{)`!P`5lECHnf6u+yLg2-2#a!mw zfcVSy?)=zRz>8N}4?k(r7lZW`bbI@DUpK=QuKRMe-mUcH;vbr4=SG6CpXlB( zUqiS3c8ecgxX}O7g=Y)nkPL^r2P9t=yyx%Oi+ zCq~YCryu_=Y}&AyRnh@@A3nBS=lrC~<2IzuVf|~fQk;r03dlLi+O5O@t^M<-(=FpSqmo60Riu}1Z_*MCVCcMLCt;Xmk zPg&vRzAfLUFai3f51;XuH7;tQqlwgy@Y-bqPvc1G8U_DH@6g`2`KRdpjSI8EG5NBw z$QP(r?OrPi)y9&&)Gz7L(z*U3x*eJ^=oZ~w-axcI{6?*cE6lMq-_Vn-SHq+##3w_1 zfx6PkQY3vL{V1DWa`{UA6Ut!q2|3`DYlsljE z9bG%18xF5mr(0Uip5q#XC0sVQm-(dB=*6>_M8ue!vuJRWISOj0PbD`H1xP)|n%UB< zE8p&EfqYss)&!z^N6np5aUL*=Rw@VTZ+hLm#1_#EZm_Ynm-B1t3J8EtE&qqSa$5FV zA7uK;yq=$~H?!;O!Jt3AHAZE!L$-#4al3z7(RWi0FVn6B;yr56R`!`k{4WliIuMK9 z*dHgkm}2=e2pW_wGHMhFhQ3-0wHP%y82rUSbXs=5laZ?sn@|lfFH}Lk_tD zRkrEy5g<1L&wfpdI-~5_cz9;f8(Cu za0he@kE2$MZ>)#t_honfu;Z?gZ)OKqSjIM--0XZbwawZ{%)SN3HK1EYy2vAdc+IycbEwHD|*tzZ@O5#hVksVOOfJWAkn3w-YLhvul@B8 zgOFzDwP~Yr3W?XXcUrN%C&1<>TxwRCrL<7VmKec0C|KK}K9SqXuPgOC%TSZFJUrJl{dJvyJSv3ZTltM;%mkBr1qDA zO|;ciIfFpcC%EJ5J7^rAqL@(x`ra$a& zt}JVrDiMUKz*rY2qACxp3=8Xd_K5N;fg&n_`Rbt<}1HD z%K1i8x&d3vW!r!p%>#_&s+HIJnKnrm1*T(ii)RIY;>DKjK5o-FNB^L^Zxh?ov19!O zU*gn@a*D6k68Dg^5l}83i-|$&C@9^c-byWus9n}q6BQCA>Zcr^TuWS%#ZG;4-Wc^ zey(|#O+#=CB(Ln*didArdoQJPJjOX^6H7JiRPkKcvCu8{F7z1`wi82_<0w@IK~-wR z@NFDc+qwY2GVGu$6z%@B1;*;kbjC#UWw&MRSNC7!$|3|anV0kc(NL|uy!(*wgPazqhTd&Ki(`@I>`Vl;*O(S9W@0YvHM-*>-=8*K`Ur9La;7h@B~SCBlx|lmI}P zK)$S)tEJtE5Q`f{)j;3loNLcw>c|ZnXAQ+JY`%J?w-fgzmTcp z_OE`dqc|XizUOVI_gu->;QNZLXa?pP@#g8h4zg&As1|iQ*->-DewFgEvSl(Ph=}i% z{+^Q$C>;++w>=Mw>ZPiud|ElEqJf@AS?gZ;aa|_B6UUsEmiKMrXZ`bQf^9`luE6oyB^81@N8}n+O>-1c)KUpLY@U zLI0>}uoVM8QqlzP#YUlfK=&G&EQ$@a0BN+1E?uLrc5hBxNB&L+oOoQVD!JKroH^#E z5I%%HHE`weo?25T{Yx`#7pj|k(K)>D!14G|ve@kLxq^#22?qrBgc|T(@%}!DH~9o4 zS$}73>&$n{bMBtsG=J3z7sRDW``Za)toogAaNs7P=_wA5)GbplOgG;pT|xnC1`x<} zU}f3&G8yFyo0jxEl=gAS2JG(M)>Ac0n;_gNvs+l1}{k?Xr`ZqINM@#h9+Ccew zt-hPT^2=QsHWXWmA@fEN@@6YJd7E2()$Hm`>=#F8*Unf7ybQi^8+b&z)|;-^90Wmi z3-eOJueCgxdI}Bi9na~T8qV^qgEhXh(M^im<2=8<*1L4DZe@IMDSxLg>V~`fR zvwG+82Y&}-{`Zqy?x(PMX(?nz2%*$MrA%iFv{KVDKg^be9Zz=X*2yjE!+OV5e9_~#)*P_`DTHa>sixM*9RVH1>`go(F zlm6)e`}bJl{Tcy~hb@_qcy!ZGDcTm2gO(1m8Qf|IlVlx0+FhBHTaT8s{V=DcT(Z9p zgQ9G#@SS6~XLO)onFvgvb~tIoCS>H|@A77|uAWgeU++g_azT{8a%X;eO;iwXb~5bn zd!<+I;}7R1mIeB*#91E`u>jTFctp+DTP+VY*Bevdf^6-ts7Y;*Om#F&nAIS&d)CUy z&TiQ}nb*8@@G;jxUtZeni73qh{qnDZ{KFWgDVJWq?GpA>=GZ4Q`;;{0Ito#54P3Cg zmV@D0`Qs635rSXsAWO6<-msNhkRR|H$nrmy&b8@Oz76A_rLh?@W(p}oC6p4`M9K?^ zLXsjP;ri;&x$b#hte5w?tv3J8&2jt=bqm9;>uSAeTgi9#C0L09OAt4Ye%End$OFc% zo^hXKKB$Rl#2ye)cj??FB?{|gU!-bKev#lj-*bsq%9$5I+)MTG(mI}$&f=Duod_mqnd2l>X6AAKz~&7hmo)_(8jeN?qkN=E zPM&Sgsu!=O34KNLp782gV`lx4A5rH;k?O6w(5NVgJPD`r{O3@9U-t@X@)bOD0#Q$u z+Y$8Vl&c&TIX54GArjs1Xl_O@q#DRpj;n3j0a<`u1|{KX0oeJDRjU z5nx^nm{UlO;1=3jDCzlSw?^RRw@E+eUgXdBiN5OZ9jJR~&^9cG2OgrV(rJe~ z0spao7-XhSv--*b*K?OEirL^X_Gb;AvzeNGY+ehPI6|*Z53a_&#O3OupfBqhewMyl z>_yGMj5x+GX5jYAgTY|TuP+_ReI^o-cW1M~ZnQeg1RdFT^Rw3jK5ekeR3PB-_zl{* z9Pk&Drotlq4hi(h#nRnvl&3RBN2Ss7;k|!tumRC9EUg?YN2iDADVg1%%i!2N;>_$b zB7vsMos9#fi}|`|8Q@5r&3fP3Fz$R@LN>p>n23QBo?`5UfyIx2^*5iOxPsPCVypM@ zuKhatv`Ublygkulr})LTk2epZ znEGEI&0fbzdkYyfN$wljQJ|JPjw`F*(kV9ySJn&Iw$Wn=%AXapyG#9^qx8VTz3w8_%Sf7L zu2t+0qH5r!FHR>S;w_0_wU0(WrBoTSZ+8Wkw|ofKt~JT?7u7dybkH5uN5|$V?DtNzUd@%4h6A*Z6E1;b zpBEZ`Z9;q#d{dC>A?QwLq>#xlxk{oC=|3y5IJwU!;QM9E=T=45AVR<|A4R^S4~7zA zz(ij^17GLaNvpFkMWhM1LjraL7!G^JtwmHE;|pZJ#}~3<9>0Z@%Z~PgY*x*GpKy@i zx;Okoo5vk+z+1F2!>o*g=3oKPvx^C_`PF{v-t=SYeIxrf9J5aLLy`05_<8NSk?koa zWS})IfTU}=g;y5|b~g&TZnxNho(pS^%@fACd(=r9vuI`vG`Bh4y8sk5>i3vl_`Ve7UY0PfV;BWPUh2Di$YTQDun$Sq0mi^oD4MdWXkwqzb-D{Q zy6soy9m-y6GT?9RyesNYxQ&F0b@*X(BP`0!|7^=1FU;gLNnR_#gSo?|cO$lV&nJ&0glDgp!A1vSix zubpv)omH+*RdXiU%j0Gy2jt3!7o?yZ@0r;xS2^SWI#oGuCrqO-{888AKAJbTE2siV zP&2uI_!f-;8zgW?au#Eyxm@2>(cjlA0EiRZd&XWk;I-aRpPh7f02E^!e1$s#$oTOV zmfO~FlO$^g}+=s~Wxz8ZLxdAoGZ7U6n!x59HV@am^k)}D0kDM(2f!+{nfXUBIlMPnA;bvd+ zC&mWJpnqkPE%mjb_d17zbq~Ie1pWS<=|XllP`iEsg%`aw@iK6f2ieOixNCrb4Bp8D zfcSH*d`GFus-%1Gd9DF?u*_%=e?=f9HTQTf%OtP#e?9yy&qux6&MIu8@9o#iQi=Pa zhT`OKGs(ZwxqF~aR=2yUe#A_p9lOfn_^EY zaxPtG7^NOh+t^wO3RNN~-wk5V}k3E?Os0Y+ubk5g9S0V z)C%4U>sA8%@3rVo_eS%1xAa! z{WH!AtuC)2BlVqQ@XVWu%sTlvtvk*ExBVl&c)l}ac4d*>x<{_DE-19K)Z@%cJ^Rdd zwp@RDE6hN5llcoCM$p~m=k;Ynks7m1R2u|#JnzCBHE+qVX= z$`d#O&%~Sc<)-pS<;Fp!DY5rl9P@Krdm$Xzh_^66<)`b=-npY~>twGp-RRor`wbs< z)H)F9;3N*$h2^k+xL6j_tUQM4v5~t*Wi69^YvUXZ5c=1G9(i=prv)F<2WR#3)*9US zw$3;R+_wiu-I)^TLVv;P6xQvan&!b$&HRf&M)Ef z7wpg7W*&0luy4(EZje*i{K8g7Wn)~;wcL33E}!36^cx`V%(>QA>)9)7`=qpf(vq@8 zIvV#Xt;pqN8Xq-e_NVkAANO8{NjjWg!*a7pWgTu%yyzR3aIy3Pr;m++K#NQqya|2un*buDXc^z*qqkzVfXvpsO`F)d#Ki^pQW zA=2?aSpA6a<+J)YFaGAI#`-tl^th_!a!^7;7ppGP+os|`O3ShSZI#O3wpgN-A50|o z^sU(2{od)#G}GN}7v=mGvUra>=66FA`&^^b%)DnXPV8ukv!C`Z`}}d@daiwJm%ems zEcPh)v)TFbEW=NpKHL4vb#FOwaH^lmt@S1@uU5j^(rPo1DixGH1+>gOU3EQOZ@XqG zDqfC|7XdrR9uB+A7y_E&mKF30w{xyoEy+%vNZg>8dE~s`at?3Xh)rKpgj{ZsStF(z z`0suvcOr3KS8SGJBJ9Ne)k->lo9S+|Zu;`RP#XDY(VhXJy{y;J4}4V676wzU;ps`2 zvCqSWJ-{~W<}@pdk8tKy$5;1ijxF43)j1=q%-*Hn;!mQ6Pd}fg-W_b$aC`y%qP`BU zCC4Ka8ywLlUbc2hF0v8q@3Yb~pVqOmt=-}XIDO6e6urZ@(<-jB$0I7>)ouKQqUAD> zj^twg?K&4)aX*C6o6j;YHuoFzO_#R>~bQ0!_Kc29RBJ}r%#&sX^1SAQnW6Gw}f*T(<|l?VaFhp$j>O{GOxw%p(OcVXFAPt= zI|Z#@g`Z*QspJ{AxY4{8u|I;EUWTQ8SyX;gu zqQ(3_KNaMPQq&qgZ7yvY+UYN;P3+mb=`qicf{8aM%fDLu#lKo3%}0GyZfx-xOfkuK zo{VnMsWEYuQ)zJ>{4TJVHizvKcGm2*MokhRg7y3TX?l!+CuC#*y(au}KkC6NoSk0* zI(V1AO7Hk_$=boQan(+c$r<>+MHrqZo@K4c3im^|k2Ks6gsfyEP;wB3z?X6N3 z&vI)aq@I)F*|HZ1>}MI`^d?3tctjgz1cG;e!`H~W95+dx0UX+HHfNZ6$U)MoEnoSL$4ScbPs?&;;jrYc~U z6UW(a_-cxD09!9{%Ok$6JURue((w%dAVJ%)BeDw#^3xJ37siPc6cSxu zG&!vZ378#g!nH!)ZTLf&Xu8ZdrswD7!42|AuJZ!~I_y9Z`>vm_8e+#Q55lkvSHp1} z?G#J7WwGwJXg_>5t9~oh8vW;Ab8^0;vu>eDoHpyiyYbN^5ahjBE-rVF3j0f%$YN5v z2-#h-no^a@X-5IouJA~dS<4+3H|Kc4#}oGsL()#U+~?OFxw~{>G5vHba-XZWT83SY zga*@4)obOK6xG$$$0U2E-2tko{y7JjcBeD1WFO@zN|W=^&d@HC;rCyVaEBHaH}#Qy z#AvOqWWu_*$(=SJSG@WrQEzGGJ_D({&9%Q+)Ss|tzcN$@K+0+9ERWW=Tm{$y(e(FI zGs7Hvct5=QF0m@a@c0$O-qU_#1@7;%iu?ZS+EJKhmEa$7z0grhL9Tw8Ws-I&A87D1 zb}+)8JsZ`E1ZE)fSJ(#QP6^O*lMnx$zM~TO5pkA-aoty$NBL zwM_T$ge$7!Z9?Zp>`G?k5^}NIf{z_0_nX&!s$QWRZd5zxVdO4tJ$9LDXEXXO8Lit) zIzYAp*GVZ0pSJGumX9RiASv#=wTAr7n+Bid0HUzMa-G}E?N$>p3Dup(!|NX3nul8I z?R|!6=YMvNy8Y(Rs5qW{pJnjDpn7HQAny)qv+C{OKxlM* z4^JSSTWrrsy|*aI2|Ql3F{SazcT_F>fq+Sw(T56Wn}_24p;hP4?52K<5?S zW^1{2Cr392;!H2ub^RigNdKeOq3k)77Juzm;bu?Uy{J@D#_`=-^~GNMmcOXQ!Xbhn zuia9exCNe>R%g-OpkDlIc$*Q(jW1+gcuR_1(hDj+flu83x5%(VXXTM50n`+I8$E_PooAU}Uf0 z{%3b6hlvoh{pnl-s~&(i@oiA+#y;#-ie$J2KT-j9ps|D!rTH&QWpBjiHPF!RbHdE3 zo9H%*X4SWOSiP%|&u3+w>FitILw+lbpBVr3cdhSQ=(0^gQH(WGooGS7N5nvv$IAc1KQ?M z@iG3UE~F2buvJ>q07WnCHTp3w=Y>{1P%rV~ugZbXIhPIJvPJdjkOq2n6)i4i{o}`Q z+1eBwP%&WtsIQHjIktcui%^<)g{p&(qG2!(u-fcvaPZBn%2uX{v*8zhhR-QOe)+vJ zzO{lqs-mtR9dvU11O>Ddk@cca?J=FWGy3XpwLO-@Go5AGM4ZOs$t&~#Tn$?p(DYp0 z<=uH59kTHR^wywRUNB(~AtVgJn(=+5@}asc&wc4TB&xn!ShZKj!-s!X{5I$Up#1u9 zg@TUcfF(!WTPSne)h>^@7(q~uwCH?VORv`dqq#LzpHAkR^+~>Br%O~M7&vZv5VGK@ z0&IkL^n|6hJsqEQDvCtyG`ErOJs)}NtxB5L` ziytw9XXAL>W1A@!Y+I{yp16))oA_8H`#9xiDt|#*R2fG z_T_4;G}!AfXmLG7@G_Ut^$1KWpbv_AaLR|X-&x7_k~lLPR;K=xT5~<(>y{b-RF>)0 zn62D<(zbKP%IkkM@r_G!Q<7P-vz^#&UpEy1`2T_Jr&sLbW_dZ9b6J*oD@$3H=-GyY ztRdh>LwYX06K^G69>T0y2j=l-3ZeOwOp#$diE_z_49GD5PTd!4b9Vh;(5XlpW zhHO!9!JfBHms-}(4o&-XgO{ElYT8#-qr#_5`18L5>F%CZUqG|Z&xjJbOX<9o9V1f{ z(J@`=X)m-mU23|WRJW@orP}cpw1q-$2x%~(5hXdLcA){kI@>?V(h+?v(FR@7Mr*YF zkd3>v(9XrmtXA(vTSCVnRK?Hi*>DD>6DDrz-n#X7JuA;;brczTO;{R45 z=~=;S^!|CaaxG@TP+nSKG}#Q)H5l)K^X@fWtqIPKzj~d%=)G2-D=#X4eu7m5Hw7dSP&J zK4L5UXc~FjEA4CZeE~~nvMMb&CM=k^$`!NKD{Xe?)L+HQpw_o@Ec8POw#ug(x&(BE zB38Y|ADhd;$aCgN(H9n(Wm~HK#c9Uz%a=lXy+{Ec8-mPe*FTUO zJu`1l=5wx`HLmq>z;l=Rl376j@bN(L-cdZIMY8RlW$kO%42(y4~MDt>;0~9 z1OfqdQ@g81H)1y052Rm>%h((376+3$tamWb zQf|PU*b^mK+%6VOBeg>3pj#^C*!=3%pw~h1&Cvr=n=+HX%6V{FI$&Tpf6g{FuX==c zvMK|I`nLe6kMnVVRQ{3VDg|Wi9JR*zo(bVC;o*5WF4&`bVsh+tXgk4(m4 zh({kWJ@RBVVSmY?v3Id%t4zXuZUR8{wv7!dOZNSo=+jX9JBF(3#A>GeuG8C_Jkep6 zHyy@WiHBMFAU}nZm>zWxx5{zW`p7YnxzX1~Lr_M}i_o|VVu zb0pj5fm&zN>je3Jq&)R4{EnNPJ1T`R>L@tll2a9euQ;3~Q z9p-XCoQAy#yf38HTpE$s(*kI-GJOH>0l|qH__KZk zNxJgRhuhWGi~tCQcmW`F)z1UA`1l4p4u+PU;4g^#HWhQWzR&NrHf=zc@kYk+rpdVK ziXwtWOE#!qquPE4-T5&SGopMIoVqdm3@033P0X7p35zRUpCX4pgh1JTL50!6u|LbS z57Cn4>3;Y92cv~bjM0Ym65zIIABU&ff-On z9WJP_?vnE0{_Y-T3mp?R^dnL^(!JLYP3DNtJKJI0Erg`Yb^od&b=ztub)^yGY;pLI zJ-xud+curFM@fPlo1e{?FQYOtd`+AUUIF8%l3Ik%-1m4{g;Gl>JiYqx=a;XiseI+y zznG}fXBH$vE1cxV-ne>-x&u>HpJ;1WHejQ*RmkH)EVlIDH2rG@hJJgCXDwTnt5(FN z(EmOUA18*iYnTNN+Ak}ocYE~<86CS>-cEslxU0<>%?agH`b#J}<@mc@NX3BxFTLqB6&IP(S z4sH_cT}nZy-nopJW!>uszVz(=EHsky1~hGHt)Ty>?D;&ST1iLL<#oxe=4I-3AeQptO7Q{ z;sIA`1-#n3LY~BM`soYL;(JNgEwP=zXu-vv8KN@oxo91>GNBD0na7hl|XGSH2IPJ@ze?QhrEIghzOqx&5 zmbkq$-REP_|2OD(q3OAwU)bTEDeT9^NinX)by)THj>_hl9`~75d(mcl?5sBbRe#o{ zkAL=q&Gr?=S;!18o@=CZg?N}YiX~L+HDcrTBK(VahIgL4_lkzB&7l6yt#S`#ySM3I zexhrpa3+eUMR@zpm#?I_Xk=->(CmEsCQQS$%oSfZUOPw@xImZjlb-7H``ja>luZLJ zGt7?|D?PdI#n(xds#c#an+1?hRnl|qNtnXL`b*x&MT|@>V1_u44MxnMj98x%N%mg@7nH!XSS*zYp~=X76Yj>c2$tS z?tY8IX@L}O-kK%(laCImOxHDY#kBm~FTLvQ*%|F8lafnyN$ZM2A1>B+oxk7haiyd_ zd4GklD{FF(boiSwikl4L0d1$332X}7se|G*T*j~3`rW=*U2vFH#QEW`iXJ=K z5lAL{jxEpe#sK;@P(Ii44H25V*1Z7Ck_Pb z6m@9@)*o$u%p#lJ_40zc=l+8L_riA3;AU<~y?cEC7(>8vhrF%6ETFw$1A_GJ>U74u^!$?iah1f`PU_{&Kp>5ge|koU!jR+ zMsq-lOe3e4bv*O;j1q~1RV~`!&&>A1x39%vJZWM3*&L2h^U(|nO_BAeO8RJ7GUiMr zt9TNMEpa4FYNY2u_6+|oxFfCs6w2*ocf|KJXCKw#_%Z1IyBZ4{0(mREY{10kFLvIl zsLz+i_9sS<^A4}3o9Pd$O|C~}LYlfEwrXSKDvQnSJ_p(MaSXr#P)Xiee3|+7JpR_~ zAk%Hi93`6#qHtrEWh2bl>RBoC`vm@t-N4%^_nW*P`S&+v>3#a!U5nr-g{^X-q^SNz zt_BVgY)8E<1cK3gV-E0RW>`h?J7D4-?bwAyyto`vGNDZ%?$U#454MFxG}CK>{sJuq ziKRVg?BTiG0jmmB%9mWZFj2d)1!gz;qj~wbR)z&r z^A`UWNU@rfk*et~`OETkS>7PK<=w2q@MAc%!{j#v+st$h7Nn^>t@6AY9!b;r8?6c} zI6|OP+3kFG5GVyXy*BJ6tz9^oD`D1^e@N_ZSL~}YiGxO>=5gRwrw?v-~LEl==}(qSaB&VmsGEJy?{!qth(?DZE-9veVDz4{G^u zo1G5Hr$yl~CAp}9(T7f1l|fGs6T_VyZi{%->kWiaKd={hcNI=Q^kK2i&0aB8KyRJB zwfR14`^>y@f0A%hBzk@#i{0mUq48fG+=0w}ezW##x;35HoqIETT8k7c=;L|A`RtCnLz`-1k1+oEb-2tVT!tbKc%*EMqHGe3^q;p!|B}ySX%}Z)p7iN|^gbd>xFw*nT6MxA{li zlEwrZcs)v;P|`>t_?zA7$8rG!mi}~i%1>(%IS@K zZrvLa;q3kVSTdtMH@iWyKoGLt@cOQU3!rQ#JGh_+)1JRU;a3+_d!}SCe{P-zz5QRl z+|JVJyvR4MFbBx=P7Gn0sJi%Aqe{h$P6)~z>*-b1VF!wSH;Cue7kG_|^y>nsWp7wV zjiP*)+>!0}vJPMZDCUr-mQzZ@6{qn`5$ec-UXgy$Wrk|dAvCie$e)=?9g5%P_x-@ChY=HM758FoT= z*A3(hgBW~imsocHGM58ICHxp_xIIOWw`Kr@(Al=gOrO(Rvx`=sA3fiwa*8HA+}HV^ zlnV2gxn+{ZFzxQ*97G&eDuy1e*iYOAr(~S@u5W?BkAO()_kZ{67UD{}b70HoHZKvL zufwy(#_8myW;ec$a367a04(P6n0aqe%fuSvYNkH61iQ>nMu}2tkl$9dP!AvZZp<6$ z-`IqI$~8R2JGS$52~AXwWudDq4iwwNhv;%38Y|K08a<(R_pwg>9i3ln|0%ULVtdk% zhkl6c9#BcLLeVb9kmf6_*7=9uKgTEZ`RWy?k6I3yaVR1*G)+qEP8dO$n-l`GD-bo7whHtj5VI;48!Lj zRBRFrh~djFxvrAH^R-$B8(vQ!RZ%ZHNCrcBT$Ll8R{fy-k)a*?G z_W%1W>|fJ?rl>7YO6R9Cys_gOep$5ky%6ch>2#ypwGuv8+(+%ZJrTWM1go@QfN#w)9>uD{b|&{%!A#8mk9p;rz-)LlOg* zucDC(*>vywdC88ui|68L_ujp>O>6?I@gtyL3YleCyD!MC-2`o39XP=&>cZSD_WB_L z;jWa~zxttlwbGk}zc`9xou@m!U+<^GQjG;jfPm>eXnLmKmuVR6b6h#$6T|S(rkwy z)=$3gq`%o3dkDVYsScD!k2&tVk;y#x&8FvEj#X94Phr6rfi`FVvx9=?1+aR5u$Se9 zB%v@vS3;Dm-c!iWq?UzZmndp&%jt!u%6EcH*_W2%`8T7QQ3l9k^ML)Zb^K4^nBIor@vsC82VNA}%%O~rvlT2Bx?8-cH>O$ppENpm zD{oLK>2F1Hy*iwdx4@hkG+$X7jrnPQ21Z9EGySBn;`E#Ag7oguG!Q7byR@yQM-4s* zxMo4v!5@RJ+mPhgwiN`~$~yz?<%eC`E6d~ODM<&!t~C%Zb-#V2$Pb!szy3IAukH)4 z9KZz4(1qvmd;-UVW@cS$!g8gn7J)8$$u*q{)sspoxcwB`C%Mi^J?6YF5`)sKFx!^yL~|=I z)dZQAW`6~utN%0EJ;I6jWjEhEegrh{Vs*O$e{Z z@wW_+`~PsUl4Kz#i6FMW`MwjSkpwq38GVj5h`>^wV&*rXy?PZx-#hJmXFgk;SP=CsG(V zIXJ*zVZEPZmUvaX0&c~9rVEAdA>FqYJvy7ys@Y8pApb)JydvlwYGR1HXO(-6d0ezc zXC)Q}G?YD%_VPDx%X7YgJ<}XJ_1WPrF)+dxARd#Gh7^s+7PEG4>1zUu>G-r{u8-b6 zBhM6BT(IZj79Yida`ftku`XSME(nx;vX}#Kf=BtU>NDDH`BL&CJ~n$SG~mASp0xNr zUyw9)-bIxyr~kdh%C(26Z3G-t>wRr3);8H&Xx)BFapCpQD9#@$pNU@R&ah@Gv|!Jb z{=UO{s^a3c^&W2IT)RLa{pxl(mM`CE2efC~|MW)HIjsV#qqc})QB>%Eu;!8YvQoWM zfRT|MlTrSqV$At3gW?@;u~06>kijg(<`m};En5U=QpsbH5Umu4PLDx%t$lqh8cxwiw*WXAR7S}7HUru4 zw8v5}+l7fYZ3Ta40z6@@UhS?_7ALte%JLKNOp|PTj-VNzc{LTtXDpMq&)(T+)e~FU zoUL%~#U7keHhh=z)1=#;zmk5XETp&_e5k^fZ{{wQ272nBY7imZCIpvbHiet}Y0t5I zpWuuAf%L)Y$T7Bm|Lo2e0UOuvnT@tp*Rq@zu86(phfd+$+xAyK8UzMM61XUZ^uF+| zX&>=OHq;c>ejvq{P*F!Ocwy-m-dKltYi2uWu}(_` z=N(@li~C<_YPb2WTz-2nv3~2qmw-3rnSnSYn0~fb^wug3`5pR@+N8d0<$Axv4wUJV z)oQjudd)#f&e$>kHWB!0$E6%I7`q@(f*ad&Zdq4GJ>+U?suPlopi{1*vmC!S-|9sq)>f7r!WU64{>FSE_8!s1+gR*cw> zKUg-V_@;JB_Q-f^qU=^17)fp>R|_TS^pwuk zUN0R~Kks%BX0qH~Ed3oArF=R4l)Bp(RY#YzT+QY;5Y_kbbLUUpE&?-s3+pxp{e+E0 z$R8R^eMm&cil#S>^EEB%BYspg7Bjswd)*<&MrGhiulZy#J#s{VQ`Wd6e)sd<^wN;w zigrw9cy)X2eyv-c>b31fotv9>liDt1Z{CszCw_jd^0#=SdvWyQf`EalOBc*FH8))SXp>t&EZ`7`8a&18(w z?Bm|}40;WC%%7XYi$(9%;vFWj19KV4+ZLXgx2_dmdlkug*}VZ52Hhi|;)z`rwY_C- zTU)g4SAiPCS_~FDhwzCq;U9nyr{!+#(my)uywQg=>uMWf6E&|_yop!r6^6Tw|A@XF z&`uBDNM5+_f8wg%!Qt6RN+tBSjo0p|u3WYyJ;cXBr}OG?%O9ON(G5D~DfG6OqH!`C z9PD_i-uEbIdb97nXd1c%@BH7mf}s%0$4Qy(&krFYdWJN&(dvyuif@2tS^BEUd<&3M zMtA&uYr)e#ZWax_*{I4%_{w+y7bus8079wPqI+=bWL6H3Wvl6WlsP0@)nAA+76$6p zj3T&^ANmB;PyC=$+`U{&r_H}xxtxdg(P3_|S44NWiSgvQPcvTnu5q!s(>ZEFmTG}S zR;SW|*stHI{d7ijL#MTl5CxS9MG?s1U#2J+Os&4X?Fr>9bL<6BFZPW9c^o{Ay}x&Q zFOY{2ku#`xJx~8Nao(lejr6B~%l1m@EjzLl!j0AW5i?Ha)XaEI4`UnL5%XTA{Y>nhV*KLnz_eVZ`QzG@so!hx|>xv<_OI zdmvjfJ8?P!K{*y$)%%cXY}ihw(eiGs2R7=i81Nr6sQ=X96rF;3ZOp)ju(;NF3L=NI zbB?iN=Wt#W#P5CkZNFN63;(P11Eo@XlcPrSGOx>^9}Hs+VvX}q6QgtX>G!+m;etIZ zMm)Xk%&h@D<;faM{H`~4+SsB_-%54guT1K{wHOiudR_oZ<5`(aE;{^-*VA-gYeP|7 zSi}3kH49(%=j6NG{L`uQf4g4;3vRy}4E(xD;zerqn!m)MaNi!W4TMarW}kj_1Y)|? z>1@~MS+ZXo>uJ))$Y798uli@)KG%fDV9$(M63HBs!L!7{JF(oc9}ga2oPIev&FD8r8c7>m|dgUar=5myPj@v z%3vw5$9%U5$7q;2{IZo5h8wx()55}Pw9h#iaLol;iuw2BDA(I;ZbY%R8vRBU=aa1r znq#N021J|5Xh8!yP|r0zpU8h7)y`l3db~}eJX$DpPZyl~(6f@-YGhYtZnjJY3kaZk z9;wZB=B0H}Q>s@V_aqVCHlyYbhEvVHZugZe(Uj;CWQ&y3k<328<0@x$e|%Q!npX{h z){8%cV62AsNsccbYWI&kcVUi~Uuyi{03v1*Va~YZ3~18QFB2BZVtrC592c46;KU&+ zIy>JHyCmNStZ^@lZtK#`?Z0MQjDs$AHJsI@g4>)VQUsJC$(Haoa$Iu6X_*Ne?)?d< z>W>5x_pm@qWR;IUS<>pPZ=b0du>h9(g9(~q?ThSb2(0Z)_VB8{me2ZfmHO>S7!|^Z zXbt2<-_}9`e~_HF+aDp~HM=yLJaCk|CNg@WAjqrT-(kAEjGSEl-KgN}Jd!?U+Q7=^ zcox?RZx`K7hoeH)z1~-}`Z6*%ezRbkn?L<+w4qmppRp@fLL#Cfu~x%3so7s{xsrE% z-;&iH;;$C-HrFIS**l7K>KpVl>teUz1fp9h>b8^J#rB|s9kuEu0}1B`r7&qOmk!xY zKR_){rR$I`u#0Q(oQV2vCU%Y}AC=~#Zu#$#kG9>UE@QPWO`PFX>0GLVti7@}qa~3q z)r`1Zs01rwzq%$mfG|?|oO5RW^Ux8Rhlyu+fQ(2fK-6OyQ!hqb1tc8I6i>C=HXdRZ zp+@!UK9jjxw(&hyA)R+|=~maiUtiQb?Fg}n3%IfDF3%^J z*h-Y=`v?ecJCQvyx#b@8X}KP!+PK;_C!3?yQU%1WK?-E%;aflc9%9eWyms2cSfI;K zgL<`}y|WAF^kp#wtzun+fc&*yC~%Qy9gn%ciN4HE@T`*w7^z%s?+g8bGR?=5Vx}&9 zmk#pFth^DKiCg8l{5oU}m8#VGhmda3(@!ZX^lH|x^PSPh<-CK@M;f~|g>%He=8JnB zWNZca8TnTB!53&g_QL(MF*f<)5Xan7xfyioe_kR@Ak@G+MJwNG%k>OO%9^*@p!)lz z;5@{PS3y`qnH5Q8 zo}Nr~kITWL^IcrD4Gzyn5Hh7M2N?|2UvoJ4d!Vzt*A^b9pk@nFSz2WpJ;gh=fUPb< ze(G~a`a?+p$2c)8^2!}qLEZBpkMHwzZCnADx+uYtvW^|vD=<;r9=yLAW}Rd2b%4~^ z)&2)Z$2-=Ul8N59*UTWs%_%EEFMYuQ{*7&=zsU|+F-I;qGLtV=PO9w#W$sRrIGmtt zIugWHwshKGFy4I5b$#OQ_l2{pT>xnTG9v{Lv9bKhbby3>t@j`|l-)a*JS#lV9ZRmR z7sfK)@P&fa5Vw2kr8H*|1G)D$ktG~WBIq9A|6kai9!&z`7IKTrH2Rh8XW!13Htp#; z$WR6cY4np#SAyuS*Z1(y=7Vim&3JycPv{rChr`=eGCUqF4= z1R;;TQEKzj5r|K2K@`Rhk`U+*qc2DYG(=Q^Y4)YJldS(a)9P>7ew{I@z3)^nfHKU( zexlM)P1w%$Y_}uOZ%J)yqpx|vIFVCz5={LC- z`byw?sE}n1f}YDC7ICd4Na52H0Y{k33UQ+5nLqKU*PYqRt%^2sy4ICDjIP`)8>OwL z^{9p&8O?6MX*!2+9fOiRRjhMt$$cG{<+$6W`6TN$sm}P?vr0=Iz?mO%pCbQyu7}I0 zhs%789L5T*9Y`i!ydj$&GD|_JkgL5$Y}^se6#N(Jdh+Vfl!{5$=~Bl10hSDgHK-Os zZNwjnhTHWWZX~@TNQN1z-kTZsv~zvHj?8=8;HKr1^goWyed$;>jN->)#Gq-WC}m2K zh;}H1KafpSvPqHcbL!vqekbs5RQG*t*7~iAd@$ofwhB0+N#AAL$2HqQgbdtEkG_fC zy79Oj`j2I-ZMl`kuWl?zl!T^+zESzFH?4H%w<;#<_ej}7_7Fs&fJS8!%cn%BoZ&*a zKB(tCEmgg-hW73#I1G;?0YbWT=ode0NIqEhQfafkP%Ex{mcNt2cf!Lyy|XBNMjgxx z{(Z0x$c3@KvK}F``RsSpNp^iMS85pOzq;2uyaBvCOlF*N?`lqKK2P7HG~XGS`SNQv zX&h!>9_H2X4i=bR;Uf6;bXJa5J+7yCK5+sne|dicv5X5Xlg%l& z);H_vr%u9QUa-dWJ2+rfYv3>khh2T2f6L4(53HH2mQ^Y+H|}9OB0UVdOZD3G{YM_o zjW(<_@-7iF*Cz<_gzaba8>ypHd-nAfp<9_=L=82l2E~hoUwOS`h`UV%phQdGLpN)j zz%mTzk&k{FcVIiV0Uy7aUd@0oM_08w3Tt>w!b3@gZadDSTn3+(@{dS8^POR0>Wx9W8 zY%|#&@OEjC;^3oi-F|X(BCUU*aI`;n!Grvly7gFLEeD9@Uk6!iqZ3}=+FNJEymS^B z%U8CUeG2iu`dZryh@Q0{-_J)8by|RXiD|y)Sp5AEc%>SAmgMvxVC3bNhUE0?=#sWv z&eg{4bh22(tCkl*Nw8aXCKgCh{$RP7V(ce?kRc`$^3Yfm_-}qY5+l@ zx6qScxO&`A3U4;S&?e|sMYwJo+Mt46gNcGSpcwU^_I4*DWbTm_>gnZdSG|+N7hY?; zm;T-~B|BiXJ^Yv)sMB6y313H;h5c@Op8ivpJ*Bv;!7g@46a4IX!yp5}=k2*14#$HP z_1ug$B3HOrBkHwo7KR^e{H`Y8rDyV{{ZX1;vdYx9J^5egkO)L7Bm-S<{XFr{(fHwY z-;-Nx)vB#LS)5m0kg+ozlAYaJ#z@qdr?mPTrDuPt;j~>EwMh79#HBBWImmiEBj#hL z=k^PBbWGMmy$VjHwgNuu?3?*T>h`@UZN{!qQgV<#Q%d#%cYWA_96dX;JiEZ;4Xk1drH7I* z`$rszrZ>#q`cLYb7`YY56XSxnA~u$!&1RN6@K4EozJT@doxL%Df}Es_t+@xw&IDhr zU-I=Mj8c8~<#oc|ruo$Dqq7yWH^5Gs`HqY~@7rp)Gio+|JcuqN=C0{AF7?Gm>mot5 z0Oq}lsD4D}=q`=Nejr40zR|O5%oRB1!FAW6Ms(p+=7Oe~7`?q$={p~BQt3p-tXWan z!vSQ?&D&@+StY}TI)lB``aPc!`yIU4%h5B1{?~S;tzpygvinO5=hAEX6qb*wm1*}2 z@QcXf8_W}@+#qvvt!=$BF8DcI#31w&8{9Vrne=FXcvF)2*dD3EdLeHa$nRalL&5V6 z-hLsC+T>b-f@48qTZ_wcL92BuD)p>BgILZr^=Bl9?B)oNh&BHJtOUtj?fxA*4EvR? zN$K=_#$3)Pqn`{T=;_t*gF_mAk)MRO>iGmh-EHv(Xz$Ae85Vc;Jv=v;-{np%H@++` zT6CK+GuA=NO93%|Uo4PtY%^06v(>zjiMJi=3Hisliv22WpD%T~|AGKg8oph1aJp+$ zYJ!BM?3=dG-&@GG|1n!peK~~pE3_)dsJRwcc>HWbF#pyZ&VQehYZ97 zN?BmTzo^MC^O+y(1i=jzSyw}010QT_OP+oN1g8JlL~Fu^Hi%g$Mc&qRc6Ti477!Z=RS|+zTd#F{YL9g@Y=N9;RPgOR)*{Y zpndl$Y3VgzFUzo6%8axskA1o;CGGDdVz;@NXT4(=eAs6{<{Cv+j+Nk2Eb-!IC%D)Y-ayylhVkI413+R3cR zE?GJx1?BbZ5deo4u8-~Hu!aQdNi{8YmQGN-O@-2`C`F6>UxQE1?@Qp!5g3ggOZ|Aa zA6L=(bwFL!b~X2W>!!5S=f3}g`fpGs=x(*rH}=t?wi^UErCeH9rn<|%`|<~Y5B5T} z@@4f3m$fCTb~eXNqs`cXQf7)h#43L72a7(Wn9le?Ew5<{=Pw+uW%kj#tMu*pI31rb zU4{6O*uu-0yV2SC`E);`y~hKA3=>x=763|IcUyAVb)0ORv9h<Eu+A6{MVW$u%GeN!79TeIHV!-s>6Bq0-Wys zruv?EwO5<0^z)bvGb2V?M_G5Ai-qi^euh9lz)u}0{5+{V#!-P>tZSK3|5O7Q&2OM; z&z}?CvBg}St%tO5U9(W#6A5tp3z#BOcgGD^eeJE~;DXj3v-00^W8A=iH1COGHL&mr z-49xWDq3@f)!-E(w$ZTL0Lig#HZ{Fr*Nr#YB zhS^Ou54u_Bsnj6XWx-hAdDRSQGw!`!(1mE-xCtlmxfjpU+LIf{xOz|^nqytA44zY` z2eFB{T39VGg?&l2ubg1s)9&q3h2vLg#>e@n;GVG0bO9qH?Y5aKf2au=)(|_HTuvo0 z{GAr7ug$lj_iEWH#mI2K+&tQRE~1!rRSwptLw@JNp50&66F5c_*@4vrn?y^?e)()! zg6K%?fkw`8yq#^)ebtVLug8zee5yAxtD`)>YEia0@pYk2XIx-*{k?9+g8SMyM1|ku z-@fyX)d@XoB3(Yo_g|Ua+&Pt7r?X#l5@G;k^k97uZp6XnHcR#GO*S1UIG7z4o+yD% z`i&*04|B)jVE`be;`dUh+$YOgKxI&=W3F2D>k-0)?U|O`(q3(4!~QLTAe}1|9HmPw z*BSJV&jN0BBAWV4WoaRP5=;NBn!}OZ;cO#gO=m6OH`HWM8-aN27SxEX>VDf?+=ElJ z=Vyw1O3YphiQAUWNdx%z?1#t)6Mz(M8a8U>%CBwbb*LArhCd>~SdRRW-zumnUmx5N zBp7+C(QcqmZp5ye<>Oa_0PiEKEQ2w>w3wtkXH58*M&)3f(s2_Khm+#6U8&=eu_!_r znV1%cHJQ2$t3a~8-3}obJX0w^zMnuVA+esWzT46x)VQ>Nt*P%*oMZlqP`B;|&@a(L zZFyd7Gry<=BX7OqOxn{nHb&kild6%d1yv>J0=qFZ+jI0b{ycf`Q|Fld7~-n2YEK?> zL(cAb(TN_eZe6$@d7tFmk+MvX$?Ca6_8r!LR#76Xt@ig8EaI7W2PywenV=YE0b_!8 zS2;e@A_glmP)~%|gRP%5tA?-rUXIVJWSVVprvsJ>{=%yrpsu4`ojRrerkW&CX!d5S*{88;oz_ONC~<|^Gf7t6aCHIw>)j}I9qyf> zZs&Sl9J6KdHX@sep+8*}p#jSZtshv1)?BfY5QWTBSp$ZGa9(7e_lM;dvv~B0oC-BG zc43;Cq!G_9_1qXfN!ecm0;ZiFz7M!l>Y2_(7)HJ36mh!z{Wv)ewpmcAA z)nhGhj{5$Jz3rx^wC@nOAdgWlEx#`8)XTva`%0tov)mk%m(#C2LPE8L-7AHsE#WLz z^$qX$cq7m2;>X9L)NGpNith$H2)`3Yc&LsDCbOBg=swXOo(G63mf;k|?7z$9oEMe2 zy_&Y%-0gG!l?z|xHc*P$er}?kLw=&(OKu;iHz4~)+|sDBXupl^V-FUQIrQ{+YAJy> z?U)UWC))^Vt7~=)T<`;^aaTa-TUQV?-wcYrS^5X==^rae_(FA0H5P>c^xrl#fka}ZqDMZ~9=+q*>gln@+ZGpfMn10~$9pGoY$^H8)?iTauea{`+v~*sIfQ%Z zGBheF(Y3~-5Pf^hRQk@9eJBMf__sc;h^!kBZc${9U4UlId<6@@=sC-@@_)@Au|1`4 z3)V7Gfk0dCW_*lrzula4#Z|FsHiO-%obyU%IkPp6(kk<7s3(Bz_wLo#S-@~#LoR89 zhM`XzZfS-&YTT54jSrEW^@7T(Uc!6bZ7wrAG&axoS&t^GMxEYal^PI5h`0792Gp(e zIWEh#B3CCV7^xCdpRB~G{SG%Zx_Zxo$}%&~2~9}m`qi2Vis9OQFZibnGk-%I;;|$* zru*z_RXPk^%5A=(5vIjJp4)KsZi#q6{cMTL#@&|fzbe@R*I2OEIv|S|b(vfJE$0p; ze7*Ksa|L;MF6Kps%ONkApn1RE``@@Z7Y*myW4A%e+z!P6MpZ){P~Y~oZJK4#(OSqn z{8`ds4@=8f$&l?+AjpEDUkNtkh z_o((5{cQi#TxH(q^*e(4#vqHN4PC7KM6ljgE|X+;CAWbKRL2V*%{BJDSpHhVszbVK zqDw{^n*iS+t)7-Eyp{lF#Cm6AnKlh3^ z(rtwIQLEbLU*4lO+j^Dumv7vdU2W}8$A}I}ai=+ZaC{wuSR}N#I2k!--yIjlUG_$c z<5_uk4u6vWy+ZqS)gj>5YS`l(nk@*uNvYY@$vxP)Djl*!K`h~;eBB{~YSF(MH~eqk zOv#J2$d%4Zlm(8RH;X!N>nr(W^EVn!-^OdRYtG1LcH9N+*MK;cy6@`qZUXbU9pIme zC1ie&3H4&_x>fL=;6S0O^U8g6Z=3b+2>L#Foia^;TP_?(4^R;2|6t@q)S?G|u# zw2@y><8(i`BNaM0-ox$(VsjxN3j6`j(fYutS@qI!82;V+J>{TFd)j66EkYx#==cUY zr$2t8Z{~R98ww^$YIQVU(7`G|5Ed1ocnSKQm{hcWU9kFfAM9u=^0Op4pyNU*(o8Mz_R#68(J#;w(7HilD`%^*l7H?_SVblVmHm&ZKy$mLUjG~Fe ze#sRVM04GPhjJV%`wBv>2gZy#Am8%tr3V=`Gh1=rc_jfzywV2!xBC0(LMvHUj;6IfL z%q|bQ$>~ZLjqbK5F=}HrX$rRqT(Jp=%Go(AVA@E{tIfl;J&Z!VT4)v${XLT^C5`hR zgT-GC@C5l2@`%0_%sg<3E}D8SDNWsf_Yyq}Q(1hDfuTwsZpV0)=5obrp*ZMDmGK>n zMUa#k&uj=DL%Yq{=U$%irCE4WngOr2I(_KJH(gV?;8ac;$i|Aulu@K(@Y~rQrM%BK z^8)=}(DYNi(BZbu3|GS;i#KL|>lS^4=m60fwG?jpP6^FL?ULnGNdJhQU)Ell77=$2 zO+Tg=uiNs3v8!VfIYp&cD!;G4YFNMN?eh3IpMdrfrsmSQ`}3#z>VusK8L-j6AQ``o zPsra`ZYJZ^Fs=2$NrD!-EQH|BRzUmUgBsrLQ&hXs6k2ET2e0{p{{k%<*f~Dn8{{cr z0kh+alc;mLkzO`~yeAFubZRt%I-~WDWlKf&kNrqb>YgO#|u`%N|)G$*Es$UTWyA6O8hgMrO zipSL-`nZ;YrZjl1q)jK^>`G$AX9lf#@OF^P!{y_fU?yt0i7ipL<|xfl%SmXMenIf5 zScMR$wxOGIeDRoXGYE}#h!!NBpR-zv)auoZG5OYNVpPs_c-S-F8(Vo-%<8n){qXQm zuHaJs>u9ao(Z3YSjbW6JZ2qX|UXH{wz|bE6F&ev1dY`Ev-_OFgPm@NgpBl#~=CP9T zJ6%D;Ax*%W-xTiO#lt&%S?a!q)R?)=kxl#i$@G`CQEN6H9iu|^WBPVxWQ$5r8vQnj*orIaHfgq|N^v6HD{L!R&)(yw zUP<>)@^{D1S7?Ntg6X9zr!pM7rm20G`~GD{pMpw~C2X(`<4$2zB1cI3^0`%3L<*!% z>6dAdXY+4CYAi{~Dzpek8Jj3M<#oK|Gb+0))k0Qh7sGW6;jE^{!=7>by|=M6%O%sz zs4nxyM!D5rOU@U@ZSXh#Q^Khq>&b6OMTypEZ@BlUD~=20#)}vDX}1cR`WCn8rSdBa zMya!M+Wxi3_7`?NfTZOLgK^@3Z&_#O&I+J}FZ! zc#ZogUQ|O-sc}F~@gXzwiH*B*&3Hddjk_Rn(^{UMCitlIk;`7+1EDpgH_z8|IGY(2 z6Ur!79M+7#CW~&Rge{Ik3K54F^>8zD2Wk=9CtoiC{CKQsa0F7pL6Z&xzx=d5mpgAk zjlj|TwOQkc(XidzQY1U8$83{fuD;!*reWPRsm8Zm+nQYd*j|C(rW`$XTZ{SX7(Mp{}+^ zEYnB^$tcIl=cs`yr*AEe%G6%G>v-?^9=3 zQRM^k9(ihPV|>`(PmuN5!dP^@pmW29!a-2ree$HFB<>1K@=u)QG9GVs`=6=E28UcH zKj_pB;&!4R{{sFa+Q(%*|AF$}=1N_h&;QIOu71vJgUZnP>+U|R)4$6K-Cq%fr;f}@ zu+hq-!K-+_N9Wiko+&;!NpY6FDeNzuM7&R|%tBzG@_-b_Z>L%Y(rQy@cqCJfk)+ib z-MYc>9J}N|_=~~dt^nPJx;oi=#XOzi!2-8F+a-`z%>c6enj7Z1!bn?D%e81sTI)`g z`0!q7sdVxaZgz6_LX_WJGDkTnWo}RX-gja8#kIdnf1+#6h^0X@z0b*=-txqI8BN%} za#v)1)n3YRQ~O(3m8bcv;Em~oX?<>DW5pDy9)wsy``FtXL#0^L_tID{UJ(4Z&YA4)Eef{ARiL+r-Sft0;H zJW!Z)x@>u7vL&+X)R)qsq`iDSJTH_-y<`yh@4wMxn|XSc41B7x`Ywk#DEkl-~l_d%{nmBio9_HW1PzeJbN04fE3 z8eTTq>ddRiq~qQ-i0(2(_SdqTKeo~V=6@JzFP9R^ovm|uaK=39i#y~TNb`R(kSl!< zcA(ualiI0at6l~Cp93UUeu&ZFSPv!B*!?a>9X!8n@nvItX%M=#5IsKmwkcfH@jv7< zvmbK7qm_>*hg`uUw&267kf(x>Ju8#1R~yKE1{0fwny?~1Q>;>E3I*~SFSUvneljY{d8f8ba@7Y?YM$+;nIo4WJt0ufpIP>W_l z9-y10LBr8gek~%1tJIYx^(c5k{MJ@HCZR8vwM5j*UOJ3A-nqFM6g<~6MR#~^%!<%2 z(%sw(X~L#oKRSi?A7$!ji};M~*lB-%ZHE{LVdiixlY8pct*?!Bcq2-xtmf9@t21e~ny$ePwmd>2(HU8XGN(+H*B^ zJ3}|BbEod{AokUvb&meVym(*TVHevRjrFk(Tv&egLHbgoyBqWp{RK2(Ai1aFZsA<2 z?jtwtyM%-E;!Xs#>{aOkN#)SJ@vS`w@{FDMl3_{;dAkWPthSGZCd}z^mZLMCpLaiJ zWKOiKNwh7j-xXiFzf<~eVVEwmm4qmZmoyCa5C9axE#r9G2X&XfK&q0T@8XB)7ny6H zYVB}ogEe~g4W>?a4TIO8TQBt>mQN$dcLfqzi!lB2)$pBP4-0L2&CDWjzN z>9j64(AssC;wn0w3;o&tZ{}|A2EXTPxqv&wz$je~U!eW!0!|t8*{)Fa~DmAEIWoh(2H78ZCig9jqil?lN8sCRQt>YT=beQBT1EY5Hva7j>w^oHh&EUO-LSXu6kH{DA}@QhAew87@f{r0S3`I zu7dKuv(5@jnt{?OA<~&PmYu)!#&-9Z{Olg)mE<>KDxK-`;ci@ETcLFUTU~RMx7Vjn zrOH+C506`bD5|a&u(9i1e#S-p+%w{-S4yx&MsRZ3Es%<2MDBU%pv`m#IDVG2r1^M9 z=~c=Sk)*|i;}3&ydfXesWFh&>isM_B=wWF*`K^nM%qB-qm?zP`ZKGEI*!A@$A=|%l zVl2S8IDOJ~US0s744c)h)}RQ@G<9sUF6du#%riS0yhY?I*+}Uq4T%qHEPY52MPwNI zzWX3(uu)MFyFt-TOEbgauIAy7c)~AwQy1;ZY}VuuJg6BN?moQPTAT}p9{H|+D$MfO zlEvuG6k`u+m@A!2V-p}3YlsQLlHJ8Z!5vbbiBZEC6Cllae7Ed~(8zFpxXI&oLAYD|6XceCCj8l6z{(c-msd@3O&3 z>5iIfd$e&{#Q00T_R| zRBVPoW|1=fg;lLC*;BtW-VJ7d?G4r{t#E@mPVSOAZ9Njfv?Sz*owGcmm8c- zs54}E-6HUt7`Wm8U>wh(F+G(6l!^ujQv;1SVBX9u9v|b-zZV;r0uSYo8w*%R0NsT< zFCR7{4XFU7FQ;Iv>D>J*Ksf%I>w5QFu1WH4{itcWmw^%XE!}R%VfLpIFg73LRxKS` zng%8#?5)^5f;H;U7ms9xZVijw$AHRY@~G3CQ`Tn8R)%@#Pvv!PGXr+(|JqFOfiB}h zRIWsm;82tF9=A2lAW8ks`)U7gALLK9{ZFSV& z1+K^Hc*nOcSNuT|w;A5MD|ULa8A#XtP?38X|Zc`JBiq|B{zXMq;0S=zj zZYpAYgg~k>QT~Wx4Y=Cq0-cYjOf)d3qaJ6{|_WEgi`7h!?PgzZI6o_DFbE6p*cb?(m+;)QAFS&9U51VE<+f}(IEZdr6 z^n^N-*9j7rD~AD1x^jy(bD#O+cC!9*#d2MOS+h8HMHsRuz1m{vlC^x6m$gL|GNDH0 zJ=Wb-m;n>=goUaw-Ener1q@a3^Eyw#4y2%uSr*=nqRi{R8w@XCwqwzC5?}i7nLuW1 z@83mH-ct5AYSGQ|mvI6Q?}gy(Jgxqim}yJTVDa7;#_*0VH)IfUW6?oC+OnD`H?Ji< z6i>fpTlt&Sx~jUDhmG8zy*dsj_&GUo3L^p3sf`O}a#8wu($(z6{>Y%m9u+{x=NXiRUze zb&Uf_9yg@*k=hTGhCP24nP;XnYTM7h8_pw(H8NiA=wc+j&vS^#4urE`Kf^5W{FD&9 z#$Q^c*`_?FYR7C+TBy{im~yGIQ+J$wtCTWBE5~X@p{&4~k6!P4Vb+-B9Vn^(kz#0U ze%oECCOqC60$3(ajupV~7&{hWTOZIr&hn=^Tb1~XbY-}>QWctn56dME>ol4Yui*CAZaFKpD+7CWBT`crky$rtEyA`|;lIb!slIi^aRNPaev|vHNHBP6{au z{MxDhgVTK7V~Pvh^6(NtJkMzj!lwIL0`NEOtld#}Jl@;⩔C7&r(Q6d1LwlZj;yj zMtvOZ9Cj4UdwTr?2p#Ofse69aD>MDCce$EQCoCm`(rjdun~ zT@5s!nducsEK=xgf9{VWu_A-{8+4?9w|o;B8_jj=7If>+)#n+OFWJ+jp2e1p^6`l^ z-t^16xFpd?4!z(F^F&oG4b8y$v|&^Z_tH44%5i&J{wl{GnLYk4T)#YCLImQf@Vv9Z zk7h&YZ@9^9#Zz;SI%Tq09(HrvLUt6c#6JJNtO)_e^EGl=?j&6fEtJU%iD0 zJd|>K-;&;jUY-D`q4+v8+-yItY*#GF`9*G`d+?gCg)p^e*gm{=Ke)$-nxR$Q!@NmF zQC*mU^sVy)U$VDY?7px0=$sW>mcXyB>R%=V*!PWE!VvE8BZ|#UzTf;z%Fc`K6j$Y+ zq*Yo`^qff9e6Bc$(9_>6YA_q_cq`(~{bp5lMZ&6*11TT$_JDh;r44ruXl$HD5$)Ku34IC{YZ(aPV2&$x?K9rAb1A+l*oFbk|HqTe)@0`&c zbyt!xD7Gdph(Fq;Cxqk0=232+Bziz~~`WO%K=_ok8 z|JmsouE5t%%_|_jeX;vksDfc&d-@BxP}gcsFn9X>HM+?(T~dXYo^4>6!Bix-%NH3{ zUT@xn=@-5JUP2a5(t}eUliSmwmQ=cJQ)kOL?r)NLnFnU8L5jq&Mk((?ZrfUr=9tR$<{CQb5rZnGLtm=rQ9Bw zmq6kwZB_aEIklk33XJG`QDJ~)rN>~%s*5pQk>mH@B8gnKI3@8W{QX7F2Uutg2$u>ta13at(6w+N}#+{;3!+ zsQA5h(^08$dQQ~9)&k6jrOHp*q>o(BR4;ESg0koDeXsY5qo6sTPJ20F`I_BFr(ytM zHr!&joFgE%Q$DAH6Xehw z+vx2Hba(7ipNlT$;WG}>Ph@nimC0gp#@|Pez8vTEKlK|}Q1=KjQj51QZ0GO!n^Y=I zi^@CJjv{+#PvTQ}kq@nMVqrbLFaOkT1mpPrwzyVFW4?Sa4EZm$Tg=P{hSc8Y@hYI?J z^sw){hzd*RylECKf0Ps|Zr50^i!8aDsfb^h+bAS{02PUasv^)8$D9&G)l zB#1I$k(5<$8ACNkgMja?+!%>_BNK7XRQ>%J9lPK4R!(j=7&O~qIKgIs&S zI-~{JlMhfTq)2A|7+V3mFrl_8FQIYdzwPmdHsnPK_Mrtr-N6 zf{}9A&OwKe+4v>5W=s_`DP%Oai6YHeNhkcbM@rDY5B`{^o97s6(z)y}!Qc(OQ5bcn z7B-zXu3#dr!aHih%VkD80T$@Obj=Kze-4z=qrsPkEk2wmf_s?OA>;f zwgBQCEBZQCn9kN7RUPZCZCieU9gOWk90Y1G1sk9N=} zE}8Y)&H`-LaRzaYt?x$4s*38(N^vOSBY&91K2#Nfsrdu^KeiKEkmfp2uz9D5hvg(j zy8}_>U-+E(bT`elaWZl8nk|aTJ;l4Vz%DLN!L0Ne;GPOSy-*qb9;en*zs@fs$Ys9h zeyK>0u`p?$0|<#f+9$<{_&#OTJoIrM(amn^@&jEZ9goLpY{UNFrHcb!6Ltq_ccAQT_je!ngTH&t#g z>1o+m4XFO}Eno*o0W5NtpNP$mm#9^zU$r)vP3{u}DHrD(+5AIrG~H$uC^(ogjHfTR zEznZ<5@_C6&|b4ut$o;{H!pC#a5i6=1U@$z^sG7#^X6NwR2KPz*p;qIg@UsuCmiH@ z7rrh3fminPcBxJFQeq;MZ^6PeyruGe@sH|d$Sxa42bJ?w@CRCJ_Gz7=jTaoM2Xld2 z`lIX~D-W@Sk2lx28Fs5;AUnK&e@m~LY zSciT69Q;pC%P4J@2roC^OqciUd$Z|mKn~O3S7m|ZCqRYYXZ{M)cp_2|PZM;m_w_0- zObeng+oyfw?!bec_qr=e%Fm>j+V!bY;WoL)gKG7f2ch#J)fV6Q^I%BCzfb#{&bUyL zYF+juI(9BP*I9dO-89x^>$$FFmnY{OqXj4p>1-BLAx`*m zJf5s|mvd7~4{lSHfpA&W*@f_y+wC?eP0_qXD7F{?2xX=;PVc{Z4#b`-P<5qt%OdmN z5;op_yILQ=ZyKu$5F8(A4RlCaiI0k&po=M(= zG>D)wPInykzHUCh(izEMn@W>H`@*cWgH_ozDX~{ErK|qAEUQoxicGjZJ|0hbSqY#DJavQUK6ZjXdZ)tXPz_XPf?pE&qx02GGo*1U{39FE+{ZP@7-Ahg{{ov&tY*EJ>La)4bus6 z$QQ?NvbZ-_wIOfu{^aUgnJ3?Q%h={ftTr|LAhg9Uh|!LF4J)1!7SC@_ zVyA7z`o)4$F*}|0B#R$Wa^;A)lF-jau$5!sMcTh77WCsL6zkE5^N8Z7sb{GFMVFjs+9Y^>-< z{G%7XrccGUh8E_h6tQ}m%cK2dN;YEMwJicuwTFTYOSeyUrFXnU`D<-+WN^aJLJE6` z-gn-lgYxm%7-ZMWdZ$_cmSy&+AdaA6Dd{`)wwz~n#~VI7pPo~r=%d40SYOsIlPF!j zx6nO4JgEiZ8>P7&ImM+W$zI+Xck=eG(tl(sx}Q6>EbU`9qvIod*6qKdQ&Lqstrgg` z1ncj*2A>Mad=1;Yx@8ek0%MwLSv&Ss1bcY18X5@lH29w@FKf{Vz8qwBtRIyHQu7P?|H3@mz}6Im+Grtb?i!P zwf5N#^1X-4!IIn=VjtoX=wb|Y&-TfJEyJ=})ar3*fa1Sip`Y=$sr&&DwSxCE2~K2% z4$+GjYj!|+`2mq^77pIO@r=+yRG5C{A!}W(c6j*}pS!?*3GWPQ03&6INoV)D{;K3m z{c`*2_J-vvo+s_N_`Zc1`a>PCkv+{oqjEt+UX*od| zjJG_~gO!ER7>=vA^>}MFVK$c6jg^ZH9#q})HuV=i?H-}-d9HtzRkR zD>4cfDLNOEGSyV}ziRY)IsNLoSWT_7f@YN(eT4+};)74#QXPr~vHI~+$ba^p@v@is z)Noa$^?8FSoI2b&>iB%RkIslfU3&!%&jvN73s!fL)RYyW*Y}0nWouL~pv~Fz zBxy}K{<-{mMPAsL`om6a)ent$*S->ujn;e|K#b1n4kvhH=CvmK=UG}%(%zr+vol=^ zs!_MrFr96wnStHLs?b>W_3AHdJPdz-@}T3XrJ6IS#1%@H((Rl-%d($%f*xYj-` z%<4Gw<8$5q4cd=;1r_Gj%YSrsws%)4x;{xipKi3Az}0lFi4A$VdGo$!)%^Nj{;+O{ z3(gC*td0pKhiJdyGz&MFbckMIesRCR_9U4eES8ruY&1$So|90Di zL*kmn+%wI)ces>`U|@r-U#%o`s^}1&1OggoR*HTWedW;uk13f-7GKBLz^A2)`|}3dp(_Qu3PBQe%*gB~oOKUI2T=t6r&FM> zQlcgr1wR2Za3F1ILBI2be(MW8eK0D?POtEpXTwPY%kok>{;#nw>3JPX&%>?mDtD^8 z6L)vuw%ayx*_0GYY*mvK2hkd-d7ft*A}J1{C`uG1QUj?0S=lhM$;Pz`f-JL4faET+ z^dB&gjkj536J!wtFoI;2_p9o%+i+KKFFst6-*65Od3eq{Jn!?!vC9KJ9hyx+U6ii! zX<@DPq$-GVPmXs&;oRhLe1=LUxzesg1>lL-j$0boXRRQR)9R{TU2Qr|;?Z=5dpL>LSKGbbB6pLk-nq5g`9w$H8(Ma33L`i399*`={uE+HQI?HOJ@MMaX5QUd z@N2PPqE&e9Lk@?`W=VP`w#Z5)DzKXe+JflNbul)i3KM7xkI&`cO{oD-G%i!Ax(>;A z_EveZxP>ejHx?U*Zheqg3vB$tJXYwkMV=r4oUoDkJRz7_(ThyZ>Wu{y?zA3XFYT0} zK&~xU$Tg!GHa>>9MoXwyW@xB!iTOm8m(P7yeOywH&}FINEa*{md(`3D-J7rk_7&Kl zrT*^lBC?_q8Ws?M#FM)OP^=>TPOUXj%87Wsb9nBPmto$d3b7Tj##Yj}bdYkBb9VzP zadm(2u6|A&oOGxZtc!SvM++vXYB~;w)R4-qToj z50DBl7SvZ62_sk)s5i&-A#dF>u}575)v>rk=7c0FFGRI@su4HrgtUl-GpolR4q91< z*cl+pqqDcDdHks;*2QuIgAn7)sJUJ0DNu&aIF$rY52k3L9!ZmJGN#-ou%*_joQkre_Mg`5&@k$Z&;fovFl z02V?bN6h_Kc4jZc41deQWyBWg>;Op&DtW>=l-+ztKs>f|mRCz~jn!VyGYFIjk18VlFkm)!DLQA>rmzPC@p$*gU5SX40R+M<{y z*46qtl*)Rkd?lxI4Y5x(j@iM(cMOR?2d89!b%6g=Vy4cG%NLpPHalMRj~gYm+7)4bWk!_lKzrd%wFC zH>m0u)=FauOqghE$cjC*60gh%eptYx<)&8&p$Tx(fxmyI^-IxROSoV9r7Ypi$K^oo zhV0l`P(}~-C}~iCZpierWiIdz9?FsHR=shLpUr3|-(5uQ3#?zs9r0BA*%3nzugkqt z&pKTgErjD}RR@QT(|pkO0G6&pjVw>fW(g4C`yTwv>`03(~B?0M4%OEQxQF%j$* z2eS61;+T@7L+yWp?roD}9v8e0$| z-wMU&HLDqs)d}?x@zv=f7O+k>halLwKYPGsaW-M@leb`cTyI6Mn=2}i8PSrILW75( z&A9IPgh!=|usfgUwW9>$q1jOT1|p#@Rr6zHXK{9-neF_EF9s#ENg{PzFmv2xx(7Xt z03r+8B4C4&PC1Oi4`0entQw`L+dfHHbFL||z7}do8<`xDpeHorO^1liR0YkD+;q6C z(u>#z7LKSi0~2!ql_Nl?F!pNqW<90IRHwF$W9A|#wcAEl$+=S*BIPHv`=DD2E>9Er z37>5({Cc|%>5#{>m)yLRDK|P(R#$K8f&CB;Xe@{>@krCz^$2;mw@%Z`qEgLL)Wi20 zD!y|IB{@M7V^A{emUIIT z;nihJkxCCmu6d)wRn_)&jf?|*#b{w>+F%7XbOU5eI6UCP(X6+b;#wgDJQ^c}8nOxh zlA3dB5jbdbY{MbPbfY|#q0U3=j?_7@)YOgkOz49rFyWVIFb)4x!xWy)D6$+Co$EY|AXXj|mwjX?asW1Rt z^>=*4ym#8MMB^}Q4C~|&v-L(S`-=4Z&8q2qsT~ogZRZN>RNIM4iOj^EKZR#(mx*qv9bdpCq7sidyB$ZgpF=$Smt9 z{K*USJPprh$33UO3+>Kn|1MK1x8Rs1@NoBv^K*Hs_kijL2$^lJ7p_Jiq$%Bxj+N-1@ zwaLET${&pO`j%E2k=iq)k2#>&oyM1`+cI)5nP|R}1!uYqneljX8xc(1K=ZR8>6|HX zw7;d})i^#3=?uf9eLX!2WI>(F>->mW*u1E}l2tY*=>ri^F@+Vu<)G(sIf$Z7znhONg+*G z8`9Mf5dY((l{#1$^BClu$vbf962qOtsObTMd#|2eOqFUSCT@^O^?WqZN&JyoCLnVN zHQe)UWk*wnS4j(prj=mU*n__xr<7H*T)^bG$r~kCk=l5iznr*kgxB?O0uwO_Zg;2* z6#)Bj5x6&p>U8X5e7|(OO_A*+pf-%1)fPADDd8{rmIFJ})kwUZndCBsQY?y{5iAPq zwP*#L=>i+gw6CG%#4C=Im-4!xhFXPUt~C%_k?MiW_jZ?DxC^jQWJ!cimF|fJ-LxE} zCbtMpOqu~0lBygF9UG`~PDxgww5u#0D5S{L7}jsBUwDRm1f@}-sEM=Ws!~>}Ue3y* zs-;oWXw=$Wv*{S*KqW@+1D8pr;(7n4j~pXCFG}w8JqmwLM{BIb<|g#cqgt+E~8r-^xQ-|f`tbiKYp>gi@4 z>`&}g%`_WSs609)F!>Trc~K|7@UF0YE%I`j8|v2$1AGj{7X<9W`|BCBYVDmWy9ch& zYvEK_&XG*9u%T-*vZ9i?D3j@?n^&mwhiWbG$495VfgNr2vKbr(F+tM>|FWHQx=FR6 zBZ6P-l|k&(2#v5@Eo=9?i~CmN>gim&sgx2-&V}ci9(71UAHSxxSXTrrHbOVGhqufC>y##v@blkO6kx#;x9N*nPW<#v1evR>k2k*Y6s>v=~XJ z9pChm{?pf^x{$0~cb6N^1_D?cXeI`9`sIjpoZZiC{idZDnB_0MF68#U1P!IC8EiPe zKI>XpzarB>d`1{-Dugh99UI+16{}F4Zmf89U+)ep<3Soj!pHOqg>*Kkp zis8m|1r###8Q?GIg}1=D<8s=K&4Hw0cx+Wsb_-P;u9G*?2io489NLdA0*iUr^&;8C z`cLY}26wN!0weGQBbiU*(V9gT`)+j^IW7mKO*gyk#rJEb$&Kr&i!+_c2NdkjRPLFf zk=wYrFta1g3yw%p?#qS@n+m%u_ToaWv3c^<$xR>iOC1W)2DyjC~ z+Nh4tAWuBtBi%MRo-t}L3$EeLs55`#zbHR%NI7Yi_62=d)o)0#{q{@oRCSUfx(Ucb z9U%tq%#C#6w-f*@Y3u||`v;mQa0;EBg2kRV@oA;7V=MVFkIy$V;U#DJaSa(hut zAe7OX&8V=C1mUH4TGV0`M(>>#;u*oy27&_`&1J)v)`B-V*rjiwN8%Q16_$wT8F32M zjTsh>13|>DzB*3@Z|k%m)T~UZbZTr?72y4hwOA&f?(Vj^x{_Q&VrS3KTGdGGnn+$= zll-OVNQ3yU;8oOE@2XD{euU?;^$NMXCzx1c+RAJy$*zHS4GC@;*uxNnU#QfGP;KPW@dRSKNtRx%rXY~s;HWVBI%W!cvr43r^c z4(As*JCl$WcFo6hRK%M}XV99VI#a%fLQwFXC{GV7AYy z_r#zH$h4LQz=vQk?#st>WqxDJPQJMX{V#$@kV3wmVRJ;Ly4@qhZbAnJh0fxmz5sQr zX`oiAy<%osf@&hTqeeQ5K4nyEBd28Y8lG4n6DhVGt5-zxID3$j^=_mlF5J*AF-=v* z%B<(NIK&6ht}1Y1J<%iFQA@p)pf2DkZt}zg7&mij`#O^@O7#fR@GWGJjXBA7x1oEu zzLI;ZUG;Tg1VL*fo#C{-Js z>FuIZyvK+>=H0MVgUq+9550n{dD!Wlq>qi+QMNDUYp8O$rt7TYPJ|P`3p@Dl^Is3-f>?D9JZ?y!4ZTosHH4b@^IE?Jd z-lWU29R)L`2%@);sok&Z^BN%?WWeC&?-SV@v1=w+d&O|Z`M?9RoH7w>glP|Z*L#GzY zsJZ3hI;n0RH2=aGKc?JhYsOv|j-iTXVk<*d%eeqg`VlOwwahuaacBNKzL{`?GlL(a zLd)12K$1H`u0yeH4)=X_t!?pTK|SzT9xb52A>@r4wsl!??x?0P5pH0Jv>5|5%AGo1 zYhYDbD8SwI=!-d4?ggi=rSs*-h-Z&IG=c!8qo*!3wS+ot@R%q6e@cAi#Uz#tB`w%XVaA#zpt&#Ny=%J+P%7U05(%8Vi7OA`lrNp2a|G zhbZ5zmbo5&rFZs%XprhImrreNH!DHC7`5qC_S9%P10NI%oY>BlA8rfk#c{7C zD>nkRn?Y%5AA_Ub@4dDK8;q81&#x$5I-bfxPFT2fUGkFQ*d;hAEuulJRyze7-nA|` zI@A@3`lov>7gj(KPSP^M^5PJXql)O!^$2sygZaHhBad)&1QVurV@izok&B&Ro7-qO;s%WAQxTDg3RaT5?#kLrFbeyJ) z)gu*`&}|}Hqhs~dETF6uIeMy9C?~#iHyb%~nX#PAZ9tu7{m5saiG7k`f=prF+k)Pc zcufNHJ+Gwpbg`1};EPeZ{t~lt$gr>bD`l)CVepvcC*f0f_FOIG$Z_<>SW_YkNzh@K z+1>OmoZh%beJxf2uFFlIx@qQ1bb5U(E{lay6N`hc$9ACU$|h%XP*+_J2`C0$hI(-K zEeLt#8ymo|2*MJO>V-F(g zleC*FAByp|Hi*RwXZq@cg3KX}L|qW7PqtrBC?dmdw z6K737WhXF2OM!$;*lx&JmK@3l!nZgekET9~09%?vE=KLd>e)@+*NC+62l_)y7WR2n z$QHU1PY0Uv)S2z@l)pj5+oGEn>6MpNtEVazzOlUON1NU!S)-jfIsGv|65?fTOYCp~ zxPD7S8&@$RpH|x3KHi{*>hJ-9yx8{iR8^Y@xn8)7u%}XLaxN4*z(hGi_RCYu3 zBta*WyiqgioL)XOE+4j!eI|hpR?2-%_9o_)9~eXh5{EulGY?})#EYFxWFITm){S(G zOrhOQzbir_lYxMy!>>C?Zg=PdP>`+XUX9DZPpAXT-1&7J-~!f}RI&IY!fmRa?oYiJc;ob^IR_$Iq&YvK;%_%dXc|CQc`ms|2 zTIMt|T8wL0eZQ>&cTwQAyZr!ZH?9GBXn_7V$hpr}jqtWD_itu%LV2S*M8DMf#4VLJ zxS~vIbGv6Kuw8D8c8Tq5+?;Q&>I=}hWh!yBo7MvST&Z6#A%wIfJCo1op&Zl*Bc1HB z*scJJbEG$PLA591Zc?sEma4vv^%`uzbozr=zLwFsA>fG|7tfzc(=AS`=MDJFUX}qb zBRTJ#CQ<^k`F^He9dYvvSqK{-I%3$4SXrNWb(ic#CZTqQ~77ulE||&1Q4D z!VcdWhI;5Sq>PfKN5m6m_7g56ajuw!UZ$)bFZ6Ooy#x(PC2Thk$Yc_v;-j&()3HE( z9b#I8)BdEpGfH_}ho{tdcn{YL986KPXROT8WXS8|Y`~G*qdh!G-ugz6)G>x$SN(ub z^t7imqQklrA)V!;Bop3)0n^L$5r2FCG%q>DuP+vV<#3tlGb@A2cpQlNvHEc{GBWk!)TRqfd zV=0^D=D-Kil&`rNRTDGS_N5T?4vVu%Jrb2EllIcr{pk$pTn-_z3)DhNr(&9+F^Ss6 zItKX)Ln85Ee_e7j9mXPLb-Jt6HCJE|TRBJeum&3v_Cf!&kv zifQ$Pb2A%HPJB9#P5ovb=pI6~C_ipz%2skyW>qWgL8aD_4!JLPpBmf&#lYu5&%=M- zVSkibJxk*V|5l9&&$8FgRrzYAOvmj_f`0}HDxd8jopS$CTP4{pGp%6_qVROG^Ll!~ zf(#*+gDHBMObZ)@>IQp4z8#lyMJqJGnXg?hQO{!rbadd)l|!C;u}l){434?ozFxaL z+>sGac9MSZmi0@AEoFQ>@ds+Zi3Y+ozisN#RBc{924lY4Hku}f6&Ik4Q;l7w%;72> zo%$MyZgOYdfW01qaGAj}F}FIGa(d()H^uB3I z?DI63TDgnmKUbs2;&=@0lG3pY>5wUUCfUfvuj`jAkU6-Ib~mA&9>AYxyar3dvzIq6 z8xoRhqz$a-W^flJ?UYucdGzTc>2$FINd(d5YH4Co*;cIRy^Ci?vOa8dA$k~XG}pz7 zHH=W>=5E~E7q^qJ=^o6CIZKv+KGLdN|^mKGR0n)hE9vEU= zcya{k)q(7-?bol&Jh45njq0#A9>quT@{y?Kw^DfDyA{Ha9NN|I-9>7)4Qg8O8Wgp{ z%mhyClAJO?S1cQfHg8gSgN@Q6bKG4eV3~ERB{ZYe4>QtfJKbT%5J|Dirx(9f zL>jDNxji^HLl3B69P1#PUN9zZ&08wlRXgIwLX$&SK*{BB-npDJhMj~MuX84dZSHk* zAv-#j2AiYAx18gB)t(T2E4rN(mUto3m9W?tNb6!>?aghfL~LM<$r$7Ky#qs;E$Pfv zFF|y+ATVCK;A30hCLGXc{x%7ZSw2RS%QKmu=c4U)w-upE%i})k3@)n!HcL*i0uK0# z0@$MVju3Lyc1*g?S2tB;PV36i-4iq7KJ-9GBUwFoB^ER^a}c{VI{5`Vxe?a9`)KXm zHv#g3w1Ga;=@Yf*)c1Kq`indeTPvbjaBT_QA+Q{(jW z7_K0h{e>uuW)R`gbGW1ZT)9cAoVNx1(`nJr`yjGKwW?m@dd?fe;^>f0WA^U2CAFY; zbQANP3>u`Db#cEQN2@9=10Zjavj^Q79omsG33bD0n7^{~qgbmLgQ30K+Gg3O;(meL z^rKJb6=|fg8QW7*Dc|KGgnDVLWx)5)>&Q-gGREfIR?jIRK2bS%!*6raS1DKV=Js&z1;=k|~;HFYHP z#3SogTf3&NsjAr@7MyKG_0U5vmF=b0HPH?tYdyS$X@0p#y+@PC=qwhea$RYhzo&Bt z-+_2ohov^J(!hLjv*Dw*fbf_~6;@ZnV3eXjUysQ=gf|6900bgBmC7uwh{96h?$wP1aWr ztlCe`->hErr5GM}&pF=CqO92Ca3vC9cRB?sZX(&pFP|rg#M5FSQ(b=UQ`S}w8L+w9 z(Mns15blktN8+VIthuqe#I#p<-myHC9RbyK#}4BaVkq)4bm}A*t?Y7MU&1aOU6vbw zo6G~-XmwWx4A=`7PCY!*?l+LdG1vDV7s#or!$zV$@rSG&2U6%ID8J^WP>WJO=tX$j zl#oDgZbfsojUJzwf=G|lFfdK`4>f7Bu0$#io@;uHa4l6uj0=PcK3l8UNp}` zfr<`X_-WilbK$}2^OJeotXHSuvTd#M^$0p2&%+$ZL*S(QF_-UxR_(N z*-jcXOm_8=R!&3Q{&VZ+8&?ClruW3>HDx!+sencx$j?7lL1_4WJigwz@8vK5>ua_ZKJRX1lOI17na_?Ez=QxgkeRW?q_2Gw~ zzx(f>e)e~R5I*_($HK>T!X;QXp|Ic9iSXgS{ODczw|=dC;>*AKy>~zURVQDa{3Q1= zcSq)QhU4^a>*(v2KK!4bz5BiI{aSDT{L4Q^-~I6Gd-v7x4?b>KY(k|e`CEtebyFYy zQ|R5l{_d~!_R}x_P5Ip~el@nQPd=_YomUcilK-~BecjZD|M;hzx%Uy|IPg7LHz2wKlqOEcb)w}Fh1&?;b~gt z67>JCw;#MSK795!@Ba6XeyzXouf_!oAs_LguabmLCllY+N#sMK^X`v-`D@Mp{F|Zt z{3D04Qj(;mt-h^?pTiLT*Yh3sz1P?8{Vx@JuW#1gQTswx-mm`N>91C)q@t-wp8Dd8 z6`^Xh%zm?my)7>C-~WTJR+zv4t$hA{oMgFQki>iZt55ztd~2h>d;jI^^H09`EcMVaJLmuWv2RuH-+%f$pM7B*4saQ7$ECO9kDBND zih_suo2TGgOW%EK=}-UUufOx*PyYJ5fBx6sj2V6udK)u*hCgb|a+2aS{#*MAf9U>) zPouy6P4n;n^3(Tk&A)wq+#@4ojarev`F(wB<-=e7<)?p>{ic1m?4N%5Kfm+YKl;@e zzCQW5o)Vlw@c@SUO}pvew)^1^zx&z$_~AF*-GBU9{H-VW{NkhT7R&MqPyOZz_}0jm zfAN#g{_n4~9{be2x?gt?E5hMNJ$hMzeH7TSf73vqlh}8lp)dd7cRu@<-*oh&>bswQ z`OBYv_LH}kAAA2SLcm((T+d=#rvOs@x`COmkgPM4}bK#pMC$6-+EuQ?3HYN f`LBNV8UEq$v(MyDehACY=j0d3FUT+0&p-cvfgH@^ From 9b4349f5f939bea60bdb69e425b69ab82a2f31b5 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sat, 6 Jul 2013 18:57:56 +0200 Subject: [PATCH 45/61] kmod: update to kmod-14 Signed-off-by: Stephan Raue --- packages/sysutils/kmod/build | 2 +- packages/sysutils/kmod/meta | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sysutils/kmod/build b/packages/sysutils/kmod/build index 37c1fe40aa..835fa6bba7 100755 --- a/packages/sysutils/kmod/build +++ b/packages/sysutils/kmod/build @@ -40,4 +40,4 @@ cd $PKG_BUILD --without-zlib make -$MAKEINSTALL \ No newline at end of file +$MAKEINSTALL diff --git a/packages/sysutils/kmod/meta b/packages/sysutils/kmod/meta index ccf1e046c4..cfe021034e 100644 --- a/packages/sysutils/kmod/meta +++ b/packages/sysutils/kmod/meta @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="kmod" -PKG_VERSION="12" +PKG_VERSION="14" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" From c091925c8b42d694d6f63b7082c1f33d8cb7033d Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 15:22:17 +0200 Subject: [PATCH 46/61] use $CONFIG_CACHE where possible instead hardcoding '/storage/.cache' Signed-off-by: Stephan Raue --- .../service.openelec.settings/init.d/00_reset | 4 ++-- .../service.openelec.settings/init.d/00_restore | 2 +- packages/network/connman/init.d/21_network | 10 +++++----- packages/network/connman/profile.d/connman.conf | 4 ++-- packages/network/openssh/init.d/51_sshd | 12 ++++++------ packages/sysutils/busybox/init.d/23_syslogd | 4 ++-- packages/x11/app/setxkbmap/init.d/72_keyboard | 4 ++-- packages/x11/app/setxkbmap/scripts/xkb-setup | 4 ++-- 8 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/mediacenter/service.openelec.settings/init.d/00_reset b/packages/mediacenter/service.openelec.settings/init.d/00_reset index 4766e0be92..a01db38402 100644 --- a/packages/mediacenter/service.openelec.settings/init.d/00_reset +++ b/packages/mediacenter/service.openelec.settings/init.d/00_reset @@ -45,7 +45,7 @@ get_target() { } # hard reset -if [ -f /storage/.cache/reset_oe ] ; then +if [ -f $CONFIG_CACHE/reset_oe ] ; then get_target if [ ! -z $target ] ; then echo "hard resetting..." @@ -62,7 +62,7 @@ if [ -f /storage/.cache/reset_oe ] ; then fi # soft reset -if [ -f /storage/.cache/reset_xbmc ] ; then +if [ -f $CONFIG_CACHE/reset_xbmc ] ; then get_target if [ ! -z $target ] ; then echo "soft resetting..." diff --git a/packages/mediacenter/service.openelec.settings/init.d/00_restore b/packages/mediacenter/service.openelec.settings/init.d/00_restore index a80f1b1603..84794a7a87 100644 --- a/packages/mediacenter/service.openelec.settings/init.d/00_restore +++ b/packages/mediacenter/service.openelec.settings/init.d/00_restore @@ -31,7 +31,7 @@ if [ -e "$BACKUP_FILE" ] ; then echo OK echo -en "restoring.. this may take long time to complete, please wait.. " rm -rf /storage/.xbmc &>/dev/null - rm -rf /storage/.cache &>/dev/null + rm -rf $CONFIG_CACHE &>/dev/null rm -rf /storage/.config &>/dev/null tar xf $BACKUP_FILE -C / &>/dev/null rm -f $BACKUP_FILE &>/dev/null diff --git a/packages/network/connman/init.d/21_network b/packages/network/connman/init.d/21_network index 2dc47681b3..d03509951d 100644 --- a/packages/network/connman/init.d/21_network +++ b/packages/network/connman/init.d/21_network @@ -22,7 +22,7 @@ # # runlevels: openelec, textmode -mkdir -p /storage/.cache/connman +mkdir -p $CONFIG_CACHE/connman mkdir -p /storage/.config/vpn-config mkdir -p /run/connman @@ -36,15 +36,15 @@ fi # creating initial settings file progress "creating initial connman settings file" - if [ ! -f /storage/.cache/connman/settings ]; then - cp /usr/share/connman/settings /storage/.cache/connman + if [ ! -f $CONFIG_CACHE/connman/settings ]; then + cp /usr/share/connman/settings $CONFIG_CACHE/connman fi ( # setup hostname - if [ -f /storage/.cache/hostname ] ; then + if [ -f $CONFIG_CACHE/hostname ] ; then progress "Setup hostname" - cat /storage/.cache/hostname > /proc/sys/kernel/hostname + cat $CONFIG_CACHE/hostname > /proc/sys/kernel/hostname fi # starting Connection manager diff --git a/packages/network/connman/profile.d/connman.conf b/packages/network/connman/profile.d/connman.conf index 7c24b7e46b..262ea9bb50 100644 --- a/packages/network/connman/profile.d/connman.conf +++ b/packages/network/connman/profile.d/connman.conf @@ -19,8 +19,8 @@ ################################################################################ wait_for_inet_addr () { - if [ -f /storage/.cache/openelec/network_wait ]; then - . /storage/.cache/openelec/network_wait + if [ -f $CONFIG_CACHE/openelec/network_wait ]; then + . $CONFIG_CACHE/openelec/network_wait if [ "$WAIT_NETWORK" = "true" ] ; then progress "Wait for network" diff --git a/packages/network/openssh/init.d/51_sshd b/packages/network/openssh/init.d/51_sshd index 1b2c4eecfa..f2a5d02d0e 100644 --- a/packages/network/openssh/init.d/51_sshd +++ b/packages/network/openssh/init.d/51_sshd @@ -35,9 +35,9 @@ OPTIONS="-o 'PasswordAuthentication no'" fi - RSA1_KEY="/storage/.cache/ssh/ssh_host_key" - RSA2_KEY="/storage/.cache/ssh/ssh_host_rsa_key" - DSA2_KEY="/storage/.cache/ssh/ssh_host_dsa_key" + RSA1_KEY="$CONFIG_CACHE/ssh/ssh_host_key" + RSA2_KEY="$CONFIG_CACHE/ssh/ssh_host_rsa_key" + DSA2_KEY="$CONFIG_CACHE/ssh/ssh_host_dsa_key" KEYGEN="/usr/bin/ssh-keygen" SSHD="/usr/sbin/sshd" @@ -51,7 +51,7 @@ if [ ! -s $RSA1_KEY ] ; then progress "SSH: generating SSH1 RSA key" - mkdir -p /storage/.cache/ssh + mkdir -p $CONFIG_CACHE/ssh $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/null chmod 600 $RSA1_KEY fi @@ -60,7 +60,7 @@ if [ ! -s $RSA2_KEY ] ; then progress "SSH: generating SSH2 RSA key" - mkdir -p /storage/.cache/ssh + mkdir -p $CONFIG_CACHE/ssh $KEYGEN -q -t rsa -f $RSA2_KEY -C '' -N '' >&/dev/null chmod 600 $RSA2_KEY fi @@ -69,7 +69,7 @@ if [ ! -s $DSA2_KEY ] ; then progress "SSH: generating SSH2 DSA key" - mkdir -p /storage/.cache/ssh + mkdir -p $CONFIG_CACHE/ssh $KEYGEN -q -t dsa -f $DSA2_KEY -C '' -N '' >&/dev/null chmod 600 $DSA2_KEY fi diff --git a/packages/sysutils/busybox/init.d/23_syslogd b/packages/sysutils/busybox/init.d/23_syslogd index 3f391ff877..4b26b023ef 100644 --- a/packages/sysutils/busybox/init.d/23_syslogd +++ b/packages/sysutils/busybox/init.d/23_syslogd @@ -26,8 +26,8 @@ ( progress "Starting Syslog daemon" - if [ -e /storage/.cache/syslog/remote ] ; then - source /storage/.cache/syslog/remote + if [ -e $CONFIG_CACHE/syslog/remote ] ; then + source $CONFIG_CACHE/syslog/remote fi SYSLOGD_OPTIONS="-L" diff --git a/packages/x11/app/setxkbmap/init.d/72_keyboard b/packages/x11/app/setxkbmap/init.d/72_keyboard index 3bbfa64500..b1431b4b75 100644 --- a/packages/x11/app/setxkbmap/init.d/72_keyboard +++ b/packages/x11/app/setxkbmap/init.d/72_keyboard @@ -23,8 +23,8 @@ # runlevels: openelec ( - if [ -f /storage/.cache/xkb/layout ]; then - . /storage/.cache/xkb/layout + if [ -f $CONFIG_CACHE/xkb/layout ]; then + . $CONFIG_CACHE/xkb/layout progress "setup keyboard layout" diff --git a/packages/x11/app/setxkbmap/scripts/xkb-setup b/packages/x11/app/setxkbmap/scripts/xkb-setup index 04a8c4017e..6ecdea34b7 100755 --- a/packages/x11/app/setxkbmap/scripts/xkb-setup +++ b/packages/x11/app/setxkbmap/scripts/xkb-setup @@ -20,6 +20,6 @@ # http://www.gnu.org/copyleft/gpl.html ################################################################################ -if [ -f /storage/.cache/xkb/layout ] ; then - cat /storage/.cache/xkb/layout +if [ -f $CONFIG_CACHE/xkb/layout ] ; then + cat $CONFIG_CACHE/xkb/layout fi From f1c6f969729992e116ac1042317e6af6ca316550 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 15:46:10 +0200 Subject: [PATCH 47/61] busybox: rename some profile config files Signed-off-by: Stephan Raue --- .../sysutils/busybox/profile.d/{home.conf => 00-home-path.conf} | 0 .../busybox/profile.d/{configcache.conf => 01-cache-path.conf} | 0 .../busybox/profile.d/{hostname.conf => 01-hostname.conf} | 0 .../busybox/profile.d/{runlevel.conf => 01-runlevel.conf} | 0 .../profile.d/{safe-shutdown.conf => 01-safe-shutdown.conf} | 0 packages/sysutils/busybox/profile.d/{shell.conf => 02-shell.conf} | 0 .../busybox/profile.d/{systemid.conf => 02-systemid.conf} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename packages/sysutils/busybox/profile.d/{home.conf => 00-home-path.conf} (100%) rename packages/sysutils/busybox/profile.d/{configcache.conf => 01-cache-path.conf} (100%) rename packages/sysutils/busybox/profile.d/{hostname.conf => 01-hostname.conf} (100%) rename packages/sysutils/busybox/profile.d/{runlevel.conf => 01-runlevel.conf} (100%) rename packages/sysutils/busybox/profile.d/{safe-shutdown.conf => 01-safe-shutdown.conf} (100%) rename packages/sysutils/busybox/profile.d/{shell.conf => 02-shell.conf} (100%) rename packages/sysutils/busybox/profile.d/{systemid.conf => 02-systemid.conf} (100%) diff --git a/packages/sysutils/busybox/profile.d/home.conf b/packages/sysutils/busybox/profile.d/00-home-path.conf similarity index 100% rename from packages/sysutils/busybox/profile.d/home.conf rename to packages/sysutils/busybox/profile.d/00-home-path.conf diff --git a/packages/sysutils/busybox/profile.d/configcache.conf b/packages/sysutils/busybox/profile.d/01-cache-path.conf similarity index 100% rename from packages/sysutils/busybox/profile.d/configcache.conf rename to packages/sysutils/busybox/profile.d/01-cache-path.conf diff --git a/packages/sysutils/busybox/profile.d/hostname.conf b/packages/sysutils/busybox/profile.d/01-hostname.conf similarity index 100% rename from packages/sysutils/busybox/profile.d/hostname.conf rename to packages/sysutils/busybox/profile.d/01-hostname.conf diff --git a/packages/sysutils/busybox/profile.d/runlevel.conf b/packages/sysutils/busybox/profile.d/01-runlevel.conf similarity index 100% rename from packages/sysutils/busybox/profile.d/runlevel.conf rename to packages/sysutils/busybox/profile.d/01-runlevel.conf diff --git a/packages/sysutils/busybox/profile.d/safe-shutdown.conf b/packages/sysutils/busybox/profile.d/01-safe-shutdown.conf similarity index 100% rename from packages/sysutils/busybox/profile.d/safe-shutdown.conf rename to packages/sysutils/busybox/profile.d/01-safe-shutdown.conf diff --git a/packages/sysutils/busybox/profile.d/shell.conf b/packages/sysutils/busybox/profile.d/02-shell.conf similarity index 100% rename from packages/sysutils/busybox/profile.d/shell.conf rename to packages/sysutils/busybox/profile.d/02-shell.conf diff --git a/packages/sysutils/busybox/profile.d/systemid.conf b/packages/sysutils/busybox/profile.d/02-systemid.conf similarity index 100% rename from packages/sysutils/busybox/profile.d/systemid.conf rename to packages/sysutils/busybox/profile.d/02-systemid.conf From 5157f5e9b6613b7f82f3d68c57be4d0b88279132 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 15:51:39 +0200 Subject: [PATCH 48/61] xbmc: rework, rename and cleanup profile.d config files Signed-off-by: Stephan Raue --- .../xbmc/profile.d/01-xbmc-path.conf | 30 +++++++++++++++++++ .../xbmc/profile.d/02-xbmc-addon-path.conf} | 4 +-- .../xbmc/profile.d/02-xbmc-library-path.conf} | 0 .../xbmc/profile.d/91-xbmc-startdelay.conf | 28 +++++++++++++++++ .../{xbmc.conf => 92-xbmc-gputype.conf} | 8 ----- .../busybox/profile.d/00-path-variable.conf | 28 +++++++++++++++++ 6 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 packages/mediacenter/xbmc/profile.d/01-xbmc-path.conf rename packages/{sysutils/busybox/profile.d/path.conf => mediacenter/xbmc/profile.d/02-xbmc-addon-path.conf} (94%) rename packages/{sysutils/busybox/profile.d/librarypath.conf => mediacenter/xbmc/profile.d/02-xbmc-library-path.conf} (100%) create mode 100644 packages/mediacenter/xbmc/profile.d/91-xbmc-startdelay.conf rename packages/mediacenter/xbmc/profile.d/{xbmc.conf => 92-xbmc-gputype.conf} (93%) create mode 100644 packages/sysutils/busybox/profile.d/00-path-variable.conf diff --git a/packages/mediacenter/xbmc/profile.d/01-xbmc-path.conf b/packages/mediacenter/xbmc/profile.d/01-xbmc-path.conf new file mode 100644 index 0000000000..0724ee3329 --- /dev/null +++ b/packages/mediacenter/xbmc/profile.d/01-xbmc-path.conf @@ -0,0 +1,30 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This Program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ +# Mediacenter environment variables. +# +# This file contains non-OpenELEC evironment variables as well as OpenELEC +# evironment variables that are not user defined. +################################################################################ + +XBMC_HOME="/usr/share/xbmc" +XBMC_USER_HOME="$HOME/.xbmc" + +export XBMC_HOME +export XBMC_USER_HOME diff --git a/packages/sysutils/busybox/profile.d/path.conf b/packages/mediacenter/xbmc/profile.d/02-xbmc-addon-path.conf similarity index 94% rename from packages/sysutils/busybox/profile.d/path.conf rename to packages/mediacenter/xbmc/profile.d/02-xbmc-addon-path.conf index afbebc3dc5..f991a07560 100644 --- a/packages/sysutils/busybox/profile.d/path.conf +++ b/packages/mediacenter/xbmc/profile.d/02-xbmc-addon-path.conf @@ -23,10 +23,8 @@ # evironment variables that are not user defined. ################################################################################ -PATH="/bin:/sbin:/usr/bin:/usr/sbin" - # hack: add addons to $PATH - for addon in /storage/.xbmc/addons/*/bin; do + for addon in $XBMC_USER_HOME/addons/*/bin; do if [ -d "$addon" ] ; then PATH="$PATH:$addon" fi diff --git a/packages/sysutils/busybox/profile.d/librarypath.conf b/packages/mediacenter/xbmc/profile.d/02-xbmc-library-path.conf similarity index 100% rename from packages/sysutils/busybox/profile.d/librarypath.conf rename to packages/mediacenter/xbmc/profile.d/02-xbmc-library-path.conf diff --git a/packages/mediacenter/xbmc/profile.d/91-xbmc-startdelay.conf b/packages/mediacenter/xbmc/profile.d/91-xbmc-startdelay.conf new file mode 100644 index 0000000000..dccfb87280 --- /dev/null +++ b/packages/mediacenter/xbmc/profile.d/91-xbmc-startdelay.conf @@ -0,0 +1,28 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This Program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ +# Mediacenter environment variables. +# +# This file contains non-OpenELEC evironment variables as well as OpenELEC +# evironment variables that are not user defined. +################################################################################ + +if [ -z "$XBMC_STARTDELAY" ]; then + XBMC_STARTDELAY="1000000" +fi diff --git a/packages/mediacenter/xbmc/profile.d/xbmc.conf b/packages/mediacenter/xbmc/profile.d/92-xbmc-gputype.conf similarity index 93% rename from packages/mediacenter/xbmc/profile.d/xbmc.conf rename to packages/mediacenter/xbmc/profile.d/92-xbmc-gputype.conf index 7029bf1bd3..775cb74d2a 100644 --- a/packages/mediacenter/xbmc/profile.d/xbmc.conf +++ b/packages/mediacenter/xbmc/profile.d/92-xbmc-gputype.conf @@ -23,14 +23,6 @@ # evironment variables that are not user defined. ################################################################################ -if [ -z "$XBMC_STARTDELAY" ]; then - XBMC_STARTDELAY="1000000" -fi - -XBMC_HOME="/usr/share/xbmc" - -export XBMC_HOME - GPUTYPE="OTHER" if [ -x /usr/bin/lspci ]; then diff --git a/packages/sysutils/busybox/profile.d/00-path-variable.conf b/packages/sysutils/busybox/profile.d/00-path-variable.conf new file mode 100644 index 0000000000..0866b8bc0a --- /dev/null +++ b/packages/sysutils/busybox/profile.d/00-path-variable.conf @@ -0,0 +1,28 @@ +################################################################################ +# This file is part of OpenELEC - http://www.openelec.tv +# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) +# +# This Program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This Program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenELEC.tv; see the file COPYING. If not, write to +# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. +# http://www.gnu.org/copyleft/gpl.html +################################################################################ +# Core (PATH) environment variables. +# +# This file contains non-OpenELEC evironment variables as well as OpenELEC +# evironment variables that are not user defined. +################################################################################ + +PATH="/bin:/sbin:/usr/bin:/usr/sbin" + +export PATH From 4175621c8d85cba64cdb7d18939fd6a8499b93b4 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:07:46 +0200 Subject: [PATCH 49/61] connman: rename profile.d config file Signed-off-by: Stephan Raue --- .../network/connman/profile.d/{connman.conf => 21-connman.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/network/connman/profile.d/{connman.conf => 21-connman.conf} (100%) diff --git a/packages/network/connman/profile.d/connman.conf b/packages/network/connman/profile.d/21-connman.conf similarity index 100% rename from packages/network/connman/profile.d/connman.conf rename to packages/network/connman/profile.d/21-connman.conf From e8ded3ad5d35ac7e915a9828a644dfea4ed6ba1d Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:07:59 +0200 Subject: [PATCH 50/61] dbus: rename profile.d config file Signed-off-by: Stephan Raue --- packages/sysutils/dbus/profile.d/{dbus.conf => 14-dbus.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/sysutils/dbus/profile.d/{dbus.conf => 14-dbus.conf} (100%) diff --git a/packages/sysutils/dbus/profile.d/dbus.conf b/packages/sysutils/dbus/profile.d/14-dbus.conf similarity index 100% rename from packages/sysutils/dbus/profile.d/dbus.conf rename to packages/sysutils/dbus/profile.d/14-dbus.conf From 5692fcebb3fc94fba306670032cb08e44bd62432 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:08:14 +0200 Subject: [PATCH 51/61] systemd: rename profile.d config file Signed-off-by: Stephan Raue --- packages/sysutils/systemd/profile.d/{udev.conf => 11-udev.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/sysutils/systemd/profile.d/{udev.conf => 11-udev.conf} (100%) diff --git a/packages/sysutils/systemd/profile.d/udev.conf b/packages/sysutils/systemd/profile.d/11-udev.conf similarity index 100% rename from packages/sysutils/systemd/profile.d/udev.conf rename to packages/sysutils/systemd/profile.d/11-udev.conf From 51cfdc2d64f3ea8709fea2c71026101c5d8f16a9 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:08:28 +0200 Subject: [PATCH 52/61] nano: rename profile.d config file Signed-off-by: Stephan Raue --- packages/tools/nano/profile.d/{nano.conf => 52-nano.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/tools/nano/profile.d/{nano.conf => 52-nano.conf} (100%) diff --git a/packages/tools/nano/profile.d/nano.conf b/packages/tools/nano/profile.d/52-nano.conf similarity index 100% rename from packages/tools/nano/profile.d/nano.conf rename to packages/tools/nano/profile.d/52-nano.conf From 5744dae7a858cc5afd592dcde1b88e06924a8a18 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:08:45 +0200 Subject: [PATCH 53/61] xorg-server: rename profile.d config file Signed-off-by: Stephan Raue --- .../xorg-server/profile.d/{display.conf => 51-display.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/x11/xserver/xorg-server/profile.d/{display.conf => 51-display.conf} (100%) diff --git a/packages/x11/xserver/xorg-server/profile.d/display.conf b/packages/x11/xserver/xorg-server/profile.d/51-display.conf similarity index 100% rename from packages/x11/xserver/xorg-server/profile.d/display.conf rename to packages/x11/xserver/xorg-server/profile.d/51-display.conf From 521c56c5b19cc93889aecb8a837943500a36efed Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:09:51 +0200 Subject: [PATCH 54/61] mrxvt: rename profile.d config file Signed-off-by: Stephan Raue --- .../debug/mrxvt/profile.d/{terminal.conf => 52-terminal.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/debug/mrxvt/profile.d/{terminal.conf => 52-terminal.conf} (100%) diff --git a/packages/debug/mrxvt/profile.d/terminal.conf b/packages/debug/mrxvt/profile.d/52-terminal.conf similarity index 100% rename from packages/debug/mrxvt/profile.d/terminal.conf rename to packages/debug/mrxvt/profile.d/52-terminal.conf From 6472ef074ebe766773d30b9dae8c969d4b701ad9 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:30:34 +0200 Subject: [PATCH 55/61] xbmc: add patch to support Upower without ConsoleKit Signed-off-by: Stephan Raue --- .../xbmc/patches/xbmc-458-no_ConsoleKit.patch | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 packages/mediacenter/xbmc/patches/xbmc-458-no_ConsoleKit.patch diff --git a/packages/mediacenter/xbmc/patches/xbmc-458-no_ConsoleKit.patch b/packages/mediacenter/xbmc/patches/xbmc-458-no_ConsoleKit.patch new file mode 100644 index 0000000000..b3b81cb65a --- /dev/null +++ b/packages/mediacenter/xbmc/patches/xbmc-458-no_ConsoleKit.patch @@ -0,0 +1,14 @@ +diff -Naur xbmc-12.2.0/xbmc/powermanagement/linux/UPowerSyscall.cpp xbmc-12.2.0.patch/xbmc/powermanagement/linux/UPowerSyscall.cpp +--- xbmc-12.2.0/xbmc/powermanagement/linux/UPowerSyscall.cpp 2013-05-02 17:00:05.000000000 +0200 ++++ xbmc-12.2.0.patch/xbmc/powermanagement/linux/UPowerSyscall.cpp 2013-07-07 17:05:46.921656229 +0200 +@@ -85,8 +85,8 @@ + m_connection = NULL; + } + +- m_CanPowerdown = false; +- m_CanReboot = false; ++ m_CanPowerdown = true; ++ m_CanReboot = true; + + UpdateCapabilities(); + From 3c17768471bd06a3d2d861991e84233910444ebc Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:31:23 +0200 Subject: [PATCH 56/61] ConsoleKit: remove package ConsoleKit Signed-off-by: Stephan Raue --- packages/mediacenter/xbmc/init.d/93_xbmc | 57 +++++++++++----- packages/mediacenter/xbmc/install | 1 - .../xbmc/scripts/wait_on_xbmc_exit | 29 -------- packages/sysutils/ConsoleKit/build | 41 ------------ .../sysutils/ConsoleKit/init.d/34_ConsoleKit | 33 --------- packages/sysutils/ConsoleKit/install | 67 ------------------- packages/sysutils/ConsoleKit/meta | 36 ---------- ...oleKit-do-not-spawn-too-much-threads.patch | 25 ------- .../ConsoleKit/scripts/ck-system-restart | 31 --------- .../ConsoleKit/scripts/ck-system-stop | 31 --------- .../busybox/profile.d/01-safe-shutdown.conf | 52 -------------- scripts/image | 1 - 12 files changed, 42 insertions(+), 362 deletions(-) delete mode 100755 packages/mediacenter/xbmc/scripts/wait_on_xbmc_exit delete mode 100755 packages/sysutils/ConsoleKit/build delete mode 100644 packages/sysutils/ConsoleKit/init.d/34_ConsoleKit delete mode 100755 packages/sysutils/ConsoleKit/install delete mode 100644 packages/sysutils/ConsoleKit/meta delete mode 100644 packages/sysutils/ConsoleKit/patches/ConsoleKit-do-not-spawn-too-much-threads.patch delete mode 100755 packages/sysutils/ConsoleKit/scripts/ck-system-restart delete mode 100755 packages/sysutils/ConsoleKit/scripts/ck-system-stop delete mode 100644 packages/sysutils/busybox/profile.d/01-safe-shutdown.conf diff --git a/packages/mediacenter/xbmc/init.d/93_xbmc b/packages/mediacenter/xbmc/init.d/93_xbmc index cc18732dc0..a5732968ef 100644 --- a/packages/mediacenter/xbmc/init.d/93_xbmc +++ b/packages/mediacenter/xbmc/init.d/93_xbmc @@ -22,6 +22,35 @@ # # runlevels: openelec +# needed functions + add_omit_pids() { + omit_pids="$omit_pids -o $1" + } + + _shutdown_script () { + SHUTDOWN="/storage/.config/shutdown.sh" + if [ -f $SHUTDOWN ]; then + echo '!!! SHUTDOWN script detected !!!' | logger -t shutdown.sh + cat "$SHUTDOWN" | logger -t shutdown.sh + echo '!!! -End of shutdown script- !!!' | logger -t shutdown.sh + sh $SHUTDOWN + fi + } + + _safe_shutdown () { + _shutdown_script + add_omit_pids $(pidof connmand) + add_omit_pids $(pidof dbus-daemon) + killall5 -15 $omit_pids + for seq in `seq 1 10` ; do + usleep 500000 + clear > /dev/tty1 + killall5 -18 $omit_pids || break + done + sync + umount -a >/dev/null 2>&1 + } + LIRCDEV="/var/run/lirc/lircd" [ -e /var/run/lirc/lircd.irtrans ] && LIRCDEV="/var/run/lirc/lircd.irtrans" XBMC_ARGS="--standalone -fs --lircdev $LIRCDEV" @@ -52,6 +81,7 @@ fi sh $AUTOSTART fi + wait_for_dbus # waiting for Xorg to start @@ -81,25 +111,22 @@ fi case "$RET" in 0) - if [ ! $(pidof console-kit-daemon) ]; then - touch "$LOCKDIR/$LOCKFILE" - _safe_shutdown - poweroff -f - fi + touch "$LOCKDIR/$LOCKFILE" + killall sshd + _safe_shutdown + poweroff -f ;; 64) - if [ ! $(pidof console-kit-daemon) ]; then - touch "$LOCKDIR/$LOCKFILE" - _safe_shutdown - poweroff -f - fi + touch "$LOCKDIR/$LOCKFILE" + killall sshd + _safe_shutdown + poweroff -f ;; 66) - if [ ! $(pidof console-kit-daemon) ]; then - touch "$LOCKDIR/$LOCKFILE" - _safe_shutdown - reboot - fi + touch "$LOCKDIR/$LOCKFILE" + killall sshd + _safe_shutdown + reboot ;; 255) echo "Abnormal Exit. Exited with code $RET" diff --git a/packages/mediacenter/xbmc/install b/packages/mediacenter/xbmc/install index 37bfa71b3b..399c6acdf2 100755 --- a/packages/mediacenter/xbmc/install +++ b/packages/mediacenter/xbmc/install @@ -27,7 +27,6 @@ PYTHON_LIBDIR="`ls -d $INSTALL/usr/lib/python*`" mkdir -p $INSTALL/usr/bin cp $PKG_DIR/scripts/cputemp $INSTALL/usr/bin cp $PKG_DIR/scripts/gputemp $INSTALL/usr/bin - cp $PKG_DIR/scripts/wait_on_xbmc_exit $INSTALL/usr/bin cp $PKG_BUILD/tools/EventClients/Clients/XBMC\ Send/xbmc-send.py $INSTALL/usr/bin/xbmc-send cp $PKG_DIR/scripts/setwakeup.sh $INSTALL/usr/bin diff --git a/packages/mediacenter/xbmc/scripts/wait_on_xbmc_exit b/packages/mediacenter/xbmc/scripts/wait_on_xbmc_exit deleted file mode 100755 index 60efb36402..0000000000 --- a/packages/mediacenter/xbmc/scripts/wait_on_xbmc_exit +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -count=0 - -while [ $(pidof xbmc.bin) -a $count -le 20 ]; do - usleep 250000 - logger -t wait_on_xbmc_exit "### Waiting for XBMC to Exit - $count ###" - count=$((count+1)) -done diff --git a/packages/sysutils/ConsoleKit/build b/packages/sysutils/ConsoleKit/build deleted file mode 100755 index 491df81986..0000000000 --- a/packages/sysutils/ConsoleKit/build +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -. config/options $1 - -cd $PKG_BUILD -./configure --host=$TARGET_NAME \ - --build=$HOST_NAME \ - --prefix=/usr \ - --bindir=/usr/bin \ - --sbindir=/usr/bin \ - --sysconfdir=/etc \ - --libexecdir=/usr/lib/ConsoleKit \ - --localstatedir=/var \ - --disable-static \ - --enable-shared \ - --disable-pam-module \ - --disable-docbook-docs \ - -make - -$MAKEINSTALL diff --git a/packages/sysutils/ConsoleKit/init.d/34_ConsoleKit b/packages/sysutils/ConsoleKit/init.d/34_ConsoleKit deleted file mode 100644 index 598862d7e0..0000000000 --- a/packages/sysutils/ConsoleKit/init.d/34_ConsoleKit +++ /dev/null @@ -1,33 +0,0 @@ -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -# start ConsoleKit daemon -# -# runlevels: openelec, textmode - -progress "starting ConsoleKit daemon" - - install -m 755 -d /var/log/ConsoleKit - install -m 755 -d /var/run/ConsoleKit - while true; do - wait_for_dbus - console-kit-daemon --no-daemon &>/dev/null - usleep 500000 - done & diff --git a/packages/sysutils/ConsoleKit/install b/packages/sysutils/ConsoleKit/install deleted file mode 100755 index f0202cf4dd..0000000000 --- a/packages/sysutils/ConsoleKit/install +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -. config/options $1 - -mkdir -p $INSTALL/etc/ConsoleKit/run-seat.d -mkdir -p $INSTALL/etc/ConsoleKit/run-session.d -mkdir -p $INSTALL/etc/ConsoleKit/seats.d - cp -P $PKG_BUILD/data/00-primary.seat $INSTALL/etc/ConsoleKit/seats.d - -mkdir -p $INSTALL/etc/dbus-1/system.d - cp -P $PKG_BUILD/data/ConsoleKit.conf $INSTALL/etc/dbus-1/system.d - -mkdir -p $INSTALL/usr/bin - cp -P $PKG_BUILD/tools/ck-log-system-restart $INSTALL/usr/bin - cp -P $PKG_BUILD/tools/ck-log-system-start $INSTALL/usr/bin - cp -P $PKG_BUILD/tools/ck-log-system-stop $INSTALL/usr/bin - cp -P $PKG_BUILD/src/console-kit-daemon $INSTALL/usr/bin - cp -P $PKG_BUILD/tools/.libs/ck-launch-session $INSTALL/usr/bin - cp -P $PKG_BUILD/tools/ck-list-sessions $INSTALL/usr/bin - cp -P $PKG_BUILD/tools/ck-history $INSTALL/usr/bin - -mkdir -p $INSTALL/usr/lib - cp -P $PKG_BUILD/libck-connector/.libs/*.so* $INSTALL/usr/lib - -mkdir -p $INSTALL/usr/lib/ConsoleKit - cp -P $PKG_BUILD/tools/ck-collect-session-info $INSTALL/usr/lib/ConsoleKit - cp -P $PKG_BUILD/tools/ck-get-x11-display-device $INSTALL/usr/lib/ConsoleKit - cp -P $PKG_BUILD/tools/ck-get-x11-server-pid $INSTALL/usr/lib/ConsoleKit - -mkdir -p $INSTALL/usr/lib/ConsoleKit/run-seat.d -mkdir -p $INSTALL/usr/lib/ConsoleKit/run-session.d -mkdir -p $INSTALL/usr/lib/ConsoleKit/scripts -# cp -P $PKG_BUILD/tools/linux/ck-system-restart $INSTALL/usr/lib/ConsoleKit/scripts -# cp -P $PKG_BUILD/tools/linux/ck-system-stop $INSTALL/usr/lib/ConsoleKit/scripts - cp -P $PKG_DIR/scripts/ck-system-restart $INSTALL/usr/lib/ConsoleKit/scripts - cp -P $PKG_DIR/scripts/ck-system-stop $INSTALL/usr/lib/ConsoleKit/scripts - -mkdir -p $INSTALL/usr/share/dbus-1/interfaces - cp -P $PKG_BUILD/src/org.freedesktop.ConsoleKit.Manager.xml $INSTALL/usr/share/dbus-1/interfaces - cp -P $PKG_BUILD/src/org.freedesktop.ConsoleKit.Seat.xml $INSTALL/usr/share/dbus-1/interfaces - cp -P $PKG_BUILD/src/org.freedesktop.ConsoleKit.Session.xml $INSTALL/usr/share/dbus-1/interfaces - -mkdir -p $INSTALL/usr/share/dbus-1/system-services - cp -P $PKG_BUILD/data/org.freedesktop.ConsoleKit.service $INSTALL/usr/share/dbus-1/system-services - -mkdir -p $INSTALL/usr/share/polkit-1/actions - cp -P $PKG_BUILD/data/org.freedesktop.consolekit.policy $INSTALL/usr/share/polkit-1/actions diff --git a/packages/sysutils/ConsoleKit/meta b/packages/sysutils/ConsoleKit/meta deleted file mode 100644 index e7cc97427b..0000000000 --- a/packages/sysutils/ConsoleKit/meta +++ /dev/null @@ -1,36 +0,0 @@ -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -PKG_NAME="ConsoleKit" -PKG_VERSION="0.4.5" -PKG_REV="1" -PKG_ARCH="any" -PKG_LICENSE="GPL" -PKG_SITE="http://www.freedesktop.org/wiki/Software/ConsoleKit" -PKG_URL="http://www.freedesktop.org/software/ConsoleKit/dist/$PKG_NAME-$PKG_VERSION.tar.bz2" -PKG_DEPENDS="dbus polkit libX11" -PKG_BUILD_DEPENDS="toolchain dbus dbus-glib polkit libX11" -PKG_PRIORITY="optional" -PKG_SECTION="system" -PKG_SHORTDESC="ConsoleKit: a framework for defining and tracking users, login sessions, and seats." -PKG_LONGDESC="ConsoleKit is a framework for defining and tracking users, login sessions, and seats." -PKG_IS_ADDON="no" - -PKG_AUTORECONF="yes" diff --git a/packages/sysutils/ConsoleKit/patches/ConsoleKit-do-not-spawn-too-much-threads.patch b/packages/sysutils/ConsoleKit/patches/ConsoleKit-do-not-spawn-too-much-threads.patch deleted file mode 100644 index bc0df554d2..0000000000 --- a/packages/sysutils/ConsoleKit/patches/ConsoleKit-do-not-spawn-too-much-threads.patch +++ /dev/null @@ -1,25 +0,0 @@ -From e8d8a3dadcaa32eeb9f2f27f9774e52e5ec70dde Mon Sep 17 00:00:00 2001 -From: Stefan Saraev -Date: Sat, 8 Jun 2013 22:21:41 +0300 -Subject: [PATCH] do not spawn too much threads - ---- - src/ck-sysdeps-linux.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/src/ck-sysdeps-linux.c b/src/ck-sysdeps-linux.c -index a95272e..264fe22 100644 ---- a/src/ck-sysdeps-linux.c -+++ b/src/ck-sysdeps-linux.c -@@ -687,7 +687,7 @@ gboolean - ck_get_max_num_consoles (guint *num) - { - if (num != NULL) { -- *num = MAX_NR_CONSOLES; -+ *num = 1; - } - - return TRUE; --- -1.7.2.5 - diff --git a/packages/sysutils/ConsoleKit/scripts/ck-system-restart b/packages/sysutils/ConsoleKit/scripts/ck-system-restart deleted file mode 100755 index ff2001be08..0000000000 --- a/packages/sysutils/ConsoleKit/scripts/ck-system-restart +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -. /etc/profile.d/safe-shutdown.conf - -LOCKDIR="/var/lock/" -LOCKFILE="xbmc.disabled" -touch "$LOCKDIR/$LOCKFILE" -wait_on_xbmc_exit -killall sshd -_safe_shutdown -reboot diff --git a/packages/sysutils/ConsoleKit/scripts/ck-system-stop b/packages/sysutils/ConsoleKit/scripts/ck-system-stop deleted file mode 100755 index d729536d6c..0000000000 --- a/packages/sysutils/ConsoleKit/scripts/ck-system-stop +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -. /etc/profile.d/safe-shutdown.conf - -LOCKDIR="/var/lock/" -LOCKFILE="xbmc.disabled" -touch "$LOCKDIR/$LOCKFILE" -wait_on_xbmc_exit -killall sshd -_safe_shutdown -poweroff diff --git a/packages/sysutils/busybox/profile.d/01-safe-shutdown.conf b/packages/sysutils/busybox/profile.d/01-safe-shutdown.conf deleted file mode 100644 index 71214d9187..0000000000 --- a/packages/sysutils/busybox/profile.d/01-safe-shutdown.conf +++ /dev/null @@ -1,52 +0,0 @@ -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ -# Core (PATH) environment variables. -# -# This file contains non-OpenELEC evironment variables as well as OpenELEC -# evironment variables that are not user defined. -################################################################################ - - add_omit_pids() { - omit_pids="$omit_pids -o $1" - } - - _shutdown_script () { - SHUTDOWN="/storage/.config/shutdown.sh" - if [ -f $SHUTDOWN ]; then - echo '!!! SHUTDOWN script detected !!!' | logger -t shutdown.sh - cat "$SHUTDOWN" | logger -t shutdown.sh - echo '!!! -End of shutdown script- !!!' | logger -t shutdown.sh - sh $SHUTDOWN - fi - } - - _safe_shutdown () { - _shutdown_script - add_omit_pids $(pidof connmand) - add_omit_pids $(pidof dbus-daemon) - killall5 -15 $omit_pids - for seq in `seq 1 10` ; do - usleep 500000 - clear > /dev/tty1 - killall5 -18 $omit_pids || break - done - sync - umount -a >/dev/null 2>&1 - } diff --git a/scripts/image b/scripts/image index 3fd8aa9cec..f1b62b31bf 100755 --- a/scripts/image +++ b/scripts/image @@ -124,7 +124,6 @@ IMAGE_NAME="$DISTRONAME-$TARGET_VERSION" # Powermanagement support [ "$UPOWER" = "yes" ] && $SCRIPTS/install upower - [ "$UPOWER" = "yes" ] && $SCRIPTS/install ConsoleKit # NTFS 3G support [ "$EXFAT" = "yes" ] && $SCRIPTS/install fuse-exfat From 746eb2d51105e5a452e0d8c6927be80437c35d35 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Sun, 7 Jul 2013 17:46:50 +0200 Subject: [PATCH 57/61] sshguard: remove package sshguard Signed-off-by: Stephan Raue --- config/functions | 1 - packages/network/openssh/meta | 4 --- packages/security/sshguard/build | 36 ------------------- packages/security/sshguard/install | 26 -------------- packages/security/sshguard/meta | 36 ------------------- .../patches/sshguard-1.5-automake-1.13.patch | 12 ------- projects/ARCTIC_MC/options | 3 -- projects/ATV/options | 3 -- projects/Fusion/options | 3 -- projects/Generic/options | 3 -- projects/Generic_OSS/options | 3 -- projects/ION/options | 3 -- projects/Intel/options | 3 -- projects/RPi/options | 3 -- projects/Ultra/options | 3 -- projects/Virtual/options | 3 -- 16 files changed, 145 deletions(-) delete mode 100755 packages/security/sshguard/build delete mode 100755 packages/security/sshguard/install delete mode 100644 packages/security/sshguard/meta delete mode 100644 packages/security/sshguard/patches/sshguard-1.5-automake-1.13.patch diff --git a/config/functions b/config/functions index 16c7feedf8..6c687ecc59 100644 --- a/config/functions +++ b/config/functions @@ -322,7 +322,6 @@ show_config() { config_message="$config_message\n - Avahi (Zeroconf) support:\t\t $AVAHI_DAEMON" config_message="$config_message\n - SAMBA server support:\t\t $SAMBA_SERVER" config_message="$config_message\n - SFTP server support:\t\t\t $SFTP_SERVER" - config_message="$config_message\n - SSH Guard support:\t\t\t $SSHGUARD_SUPPORT" config_message="$config_message\n - PPTP support:\t\t\t $PPTP_SUPPORT" config_message="$config_message\n - OpenVPN support:\t\t\t $OPENVPN_SUPPORT" config_message="$config_message\n - XBMC Airplay support:\t\t $AIRPLAY_SUPPORT" diff --git a/packages/network/openssh/meta b/packages/network/openssh/meta index 711113ae98..9c51c715a6 100644 --- a/packages/network/openssh/meta +++ b/packages/network/openssh/meta @@ -35,7 +35,3 @@ PKG_IS_ADDON="no" PKG_AUTORECONF="yes" -if [ "$SSHGUARD_SUPPORT" = yes ]; then - PKG_DEPENDS="$PKG_DEPENDS sshguard" -fi - diff --git a/packages/security/sshguard/build b/packages/security/sshguard/build deleted file mode 100755 index 1ebab49e9d..0000000000 --- a/packages/security/sshguard/build +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -. config/options $1 - -cd $PKG_BUILD -ac_cv_func_malloc_0_nonnull=yes \ -./configure --host=$TARGET_NAME \ - --build=$HOST_NAME \ - --prefix=/usr \ - --sysconfdir=/etc \ - --datadir=/usr/share \ - --localstatedir=/var \ - --with-firewall="iptables" \ - --with-iptables="/usr/sbin/iptables" \ - -make diff --git a/packages/security/sshguard/install b/packages/security/sshguard/install deleted file mode 100755 index 3907d81821..0000000000 --- a/packages/security/sshguard/install +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -. config/options $1 - -mkdir -p $INSTALL/usr/sbin - cp -P $PKG_BUILD/src/sshguard $INSTALL/usr/sbin diff --git a/packages/security/sshguard/meta b/packages/security/sshguard/meta deleted file mode 100644 index 9f0fa731fe..0000000000 --- a/packages/security/sshguard/meta +++ /dev/null @@ -1,36 +0,0 @@ -################################################################################ -# This file is part of OpenELEC - http://www.openelec.tv -# Copyright (C) 2009-2012 Stephan Raue (stephan@openelec.tv) -# -# This Program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This Program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenELEC.tv; see the file COPYING. If not, write to -# the Free Software Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110, USA. -# http://www.gnu.org/copyleft/gpl.html -################################################################################ - -PKG_NAME="sshguard" -PKG_VERSION="1.5" -PKG_REV="1" -PKG_ARCH="any" -PKG_LICENSE="BSD" -PKG_SITE="http://www.sshguard.net/" -PKG_URL="$SOURCEFORGE_SRC/project/sshguard/sshguard/$PKG_NAME-$PKG_VERSION/$PKG_NAME-$PKG_VERSION.tar.bz2" -PKG_DEPENDS="iptables" -PKG_BUILD_DEPENDS="toolchain" -PKG_PRIORITY="optional" -PKG_SECTION="security" -PKG_SHORTDESC="sshguard: monitors servers from their logging activity." -PKG_LONGDESC="Sshguard monitors servers from their logging activity. When logs convey that someone is doing a Bad Thing, sshguard reacts by blocking he/she/it for a bit. Sshguard has a touchy personality: when a naughty tyke insists disturbing your host, it reacts firmer and firmer." -PKG_IS_ADDON="no" - -PKG_AUTORECONF="yes" diff --git a/packages/security/sshguard/patches/sshguard-1.5-automake-1.13.patch b/packages/security/sshguard/patches/sshguard-1.5-automake-1.13.patch deleted file mode 100644 index bcf8073342..0000000000 --- a/packages/security/sshguard/patches/sshguard-1.5-automake-1.13.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -Naur sshguard-1.5/configure.ac sshguard-1.5.patch/configure.ac ---- sshguard-1.5/configure.ac 2011-02-09 13:01:47.000000000 +0100 -+++ sshguard-1.5.patch/configure.ac 2013-01-12 01:13:22.735102536 +0100 -@@ -5,7 +5,7 @@ - AC_INIT(sshguard, 1.5, mij@sshguard.net) - AM_INIT_AUTOMAKE - AC_CONFIG_SRCDIR([src/simclist.c]) --AM_CONFIG_HEADER([src/config.h]) -+AC_CONFIG_HEADERS([src/config.h]) - # test if we are on Solaris, which requires outstanding practices - AC_CANONICAL_BUILD - AS_CASE([$build_os], diff --git a/projects/ARCTIC_MC/options b/projects/ARCTIC_MC/options index 88fdc8ef7b..0354a845ba 100755 --- a/projects/ARCTIC_MC/options +++ b/projects/ARCTIC_MC/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="no" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/ATV/options b/projects/ATV/options index 4b928f86d0..e2a64d04cf 100755 --- a/projects/ATV/options +++ b/projects/ATV/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="yes" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/Fusion/options b/projects/Fusion/options index 68774c960a..072d5a9c64 100755 --- a/projects/Fusion/options +++ b/projects/Fusion/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="yes" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/Generic/options b/projects/Generic/options index 1ecc1bb60a..78898fe200 100755 --- a/projects/Generic/options +++ b/projects/Generic/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="yes" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/Generic_OSS/options b/projects/Generic_OSS/options index 7af2c75347..fffa5a516f 100755 --- a/projects/Generic_OSS/options +++ b/projects/Generic_OSS/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="yes" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/ION/options b/projects/ION/options index 24f5cdbf24..5fd73b495c 100755 --- a/projects/ION/options +++ b/projects/ION/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="yes" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/Intel/options b/projects/Intel/options index bf4b486d1b..d7ace6ff90 100755 --- a/projects/Intel/options +++ b/projects/Intel/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="yes" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/RPi/options b/projects/RPi/options index c77db212d2..adf2ff9724 100755 --- a/projects/RPi/options +++ b/projects/RPi/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="no" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/Ultra/options b/projects/Ultra/options index 669719f069..e4f9e6d949 100755 --- a/projects/Ultra/options +++ b/projects/Ultra/options @@ -219,9 +219,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="yes" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" diff --git a/projects/Virtual/options b/projects/Virtual/options index 2ac310246d..a6251569c9 100755 --- a/projects/Virtual/options +++ b/projects/Virtual/options @@ -214,9 +214,6 @@ # build and install SFTP Server (yes / no) SFTP_SERVER="yes" -# build and install SSH Guard (yes / no) - SSHGUARD_SUPPORT="yes" - # build and install PPP support (yes / no) PPTP_SUPPORT="yes" From 35d9d7350e86cdfe84b69f299481e779d9ed4c0b Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Sun, 7 Jul 2013 19:16:12 +0300 Subject: [PATCH 58/61] safe_shutdown: pass poweroff/reboot to shutdown script --- packages/mediacenter/xbmc/init.d/93_xbmc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/mediacenter/xbmc/init.d/93_xbmc b/packages/mediacenter/xbmc/init.d/93_xbmc index a5732968ef..62e5c2a83b 100644 --- a/packages/mediacenter/xbmc/init.d/93_xbmc +++ b/packages/mediacenter/xbmc/init.d/93_xbmc @@ -33,12 +33,12 @@ echo '!!! SHUTDOWN script detected !!!' | logger -t shutdown.sh cat "$SHUTDOWN" | logger -t shutdown.sh echo '!!! -End of shutdown script- !!!' | logger -t shutdown.sh - sh $SHUTDOWN + sh $SHUTDOWN $1 fi } _safe_shutdown () { - _shutdown_script + _shutdown_script $1 add_omit_pids $(pidof connmand) add_omit_pids $(pidof dbus-daemon) killall5 -15 $omit_pids @@ -113,19 +113,19 @@ fi 0) touch "$LOCKDIR/$LOCKFILE" killall sshd - _safe_shutdown + _safe_shutdown poweroff poweroff -f ;; 64) touch "$LOCKDIR/$LOCKFILE" killall sshd - _safe_shutdown + _safe_shutdown poweroff poweroff -f ;; 66) touch "$LOCKDIR/$LOCKFILE" killall sshd - _safe_shutdown + _safe_shutdown reboot reboot ;; 255) From 5617ad7b8367963a57460ff450ebf2ff14ca87b1 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Sun, 7 Jul 2013 19:17:04 +0300 Subject: [PATCH 59/61] xbmc: init: no need to kill sshd on poweroff/reboot, handled by safe_shutdown --- packages/mediacenter/xbmc/init.d/93_xbmc | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/mediacenter/xbmc/init.d/93_xbmc b/packages/mediacenter/xbmc/init.d/93_xbmc index 62e5c2a83b..267039e4d1 100644 --- a/packages/mediacenter/xbmc/init.d/93_xbmc +++ b/packages/mediacenter/xbmc/init.d/93_xbmc @@ -112,19 +112,16 @@ fi case "$RET" in 0) touch "$LOCKDIR/$LOCKFILE" - killall sshd _safe_shutdown poweroff poweroff -f ;; 64) touch "$LOCKDIR/$LOCKFILE" - killall sshd _safe_shutdown poweroff poweroff -f ;; 66) touch "$LOCKDIR/$LOCKFILE" - killall sshd _safe_shutdown reboot reboot ;; From 7de90c7658e59e9962f80ab32643e08dfd772b0c Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Sun, 7 Jul 2013 19:19:26 +0300 Subject: [PATCH 60/61] xbmc: init: move wait for dbus/udevadm/network before autostart.sh --- packages/mediacenter/xbmc/init.d/93_xbmc | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/mediacenter/xbmc/init.d/93_xbmc b/packages/mediacenter/xbmc/init.d/93_xbmc index 267039e4d1..58d3224b79 100644 --- a/packages/mediacenter/xbmc/init.d/93_xbmc +++ b/packages/mediacenter/xbmc/init.d/93_xbmc @@ -71,6 +71,15 @@ fi -i /storage/.xbmc/userdata/RssFeeds.xml fi +# wait for dbus to start + wait_for_dbus + +# wait for network + wait_for_inet_addr + +# wait for udevadm settle to finish + wait_for_udevadm_settle + # starting autostart script (will be removed later again, dont use it!!!) AUTOSTART="/storage/.config/autostart.sh" if [ -f $AUTOSTART ]; then @@ -81,17 +90,9 @@ fi sh $AUTOSTART fi - - wait_for_dbus - # waiting for Xorg to start wait_for_xorg -# wait for network - wait_for_inet_addr - -# wait for udevadm settle to finish - wait_for_udevadm_settle # prevent restrating XBMC at reboot or shutdown LOCKDIR="/var/lock/" From 8e9b20afe66326d5d367ad59c4c07b8ad4026243 Mon Sep 17 00:00:00 2001 From: Stefan Saraev Date: Sun, 7 Jul 2013 19:24:36 +0300 Subject: [PATCH 61/61] xbmc: init: cosmetics to safe_shutdown --- packages/mediacenter/xbmc/init.d/93_xbmc | 38 +++++++++++------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/packages/mediacenter/xbmc/init.d/93_xbmc b/packages/mediacenter/xbmc/init.d/93_xbmc index 58d3224b79..05eb267fff 100644 --- a/packages/mediacenter/xbmc/init.d/93_xbmc +++ b/packages/mediacenter/xbmc/init.d/93_xbmc @@ -22,23 +22,25 @@ # # runlevels: openelec +# prevent restrating XBMC at reboot or shutdown + LOCKDIR="/var/lock/" + LOCKFILE="xbmc.disabled" + [ -f "$LOCKDIR/$LOCKFILE" ] && rm -f "$LOCKDIR/$LOCKFILE" & + # needed functions add_omit_pids() { omit_pids="$omit_pids -o $1" } - _shutdown_script () { + safe_shutdown () { + touch "$LOCKDIR/$LOCKFILE" SHUTDOWN="/storage/.config/shutdown.sh" if [ -f $SHUTDOWN ]; then - echo '!!! SHUTDOWN script detected !!!' | logger -t shutdown.sh + echo '!!! SHUTDOWN script detected !!!' | logger -t shutdown.sh $1 cat "$SHUTDOWN" | logger -t shutdown.sh - echo '!!! -End of shutdown script- !!!' | logger -t shutdown.sh + echo '!!! -End of shutdown script- !!!' | logger -t shutdown.sh $1 sh $SHUTDOWN $1 fi - } - - _safe_shutdown () { - _shutdown_script $1 add_omit_pids $(pidof connmand) add_omit_pids $(pidof dbus-daemon) killall5 -15 $omit_pids @@ -49,6 +51,11 @@ done sync umount -a >/dev/null 2>&1 + if [ $1 = "reboot" ]; then + reboot + elif [ $1 = "poweroff" ]; then + poweroff -f + fi } LIRCDEV="/var/run/lirc/lircd" @@ -94,11 +101,6 @@ fi wait_for_xorg -# prevent restrating XBMC at reboot or shutdown - LOCKDIR="/var/lock/" - LOCKFILE="xbmc.disabled" - [ -f "$LOCKDIR/$LOCKFILE" ] && rm -f "$LOCKDIR/$LOCKFILE" & - # starting XBMC usleep $XBMC_STARTDELAY while true; do @@ -112,19 +114,13 @@ fi case "$RET" in 0) - touch "$LOCKDIR/$LOCKFILE" - _safe_shutdown poweroff - poweroff -f + safe_shutdown poweroff ;; 64) - touch "$LOCKDIR/$LOCKFILE" - _safe_shutdown poweroff - poweroff -f + safe_shutdown poweroff ;; 66) - touch "$LOCKDIR/$LOCKFILE" - _safe_shutdown reboot - reboot + safe_shutdown reboot ;; 255) echo "Abnormal Exit. Exited with code $RET"